diff --git a/drivers/display/CMakeLists.txt b/drivers/display/CMakeLists.txt index 88365c2a31a744..b17d6670311308 100644 --- a/drivers/display/CMakeLists.txt +++ b/drivers/display/CMakeLists.txt @@ -8,6 +8,7 @@ zephyr_sources_ifdef(CONFIG_SDL_DISPLAY display_sdl.c) zephyr_sources_ifdef(CONFIG_DUMMY_DISPLAY display_dummy.c) zephyr_sources_ifdef(CONFIG_FRAMEBUF_DISPLAY display_framebuf.c) zephyr_sources_ifdef(CONFIG_ILI9340 display_ili9340.c) +zephyr_sources_ifdef(CONFIG_ST7789V display_st7789v.c) zephyr_sources_ifdef(CONFIG_MICROBIT_DISPLAY mb_display.c @@ -20,3 +21,7 @@ zephyr_sources_ifdef(CONFIG_ILI9340_LCD_ADAFRUIT_1480 zephyr_sources_ifdef(CONFIG_ILI9340_LCD_SEEED_TFTV2 display_ili9340_seeed_tftv2.c ) + +zephyr_sources_ifdef(CONFIG_ST7789V_LCD_TL019FQV01 + display_st7789v_tl019fqv01.c +) diff --git a/drivers/display/Kconfig b/drivers/display/Kconfig index bc79f349102d50..2dd9da71e3a786 100644 --- a/drivers/display/Kconfig +++ b/drivers/display/Kconfig @@ -24,6 +24,7 @@ source "drivers/display/Kconfig.ili9340" source "drivers/display/Kconfig.sdl" source "drivers/display/Kconfig.ssd1306" source "drivers/display/Kconfig.ssd16xx" +source "drivers/display/Kconfig.st7789v" source "drivers/display/Kconfig.dummy" config FRAMEBUF_DISPLAY diff --git a/drivers/display/Kconfig.st7789v b/drivers/display/Kconfig.st7789v new file mode 100644 index 00000000000000..71fea4d9866b0f --- /dev/null +++ b/drivers/display/Kconfig.st7789v @@ -0,0 +1,68 @@ +# Kconfig - ST7789V display driver configuration options + +# +# Copyright (c) 2019 Marc Reilly +# +# SPDX-License-Identifier: Apache-2.0 +# + +menuconfig ST7789V + bool "ST7789V display driver" + depends on SPI + help + Enable driver for ST7789V display driver. + +if ST7789V + +choice + prompt "LCD" + help + Specify the type of LCD connected to the ST7789V display controller. + +config ST7789V_LCD_TL019FQV01 + bool "TDO TL019FQV01" + +endchoice + +choice + prompt "Color pixel format" + default ST7789V_RGB565 + help + Specify the color pixel format for the ST7789V display controller. + +config ST7789V_RGB888 + bool "RGB888" + +config ST7789V_RGB565 + bool "RGB565" + +endchoice + +if ST7789V_RGB565 +config ST7789V_SWAP_PIXEL_LCD_ENDIANNESS + bool "Swap pixel endianness at LCD" + help + Pixel data bytes are swapped when being blitted to the LCD. + Note that this isn't just a swap of RGB <--> BGR, (if the endianness is + swapped then the 3 lowest bits of G are sent first/last). + You may want to enable this if you are using lvgl and your colors + don't look right. + +config ST7789V_REVERSE_LCD_RGB_ORDER + bool "Reverse draw order of controller ram to LCD" + help + This reverses the order that the controller draws RGB to the LCD. + +config ST7789V_REVERSE_X + bool "Reverse X axis" + help + Address pixels from right to left. + +config ST7789V_REVERSE_Y + bool "Reverse Y axis" + help + Address pixels from bottom to top. + +endif #ST7789V_RGB565 + +endif #ST7789V diff --git a/drivers/display/display_st7789v.c b/drivers/display/display_st7789v.c new file mode 100644 index 00000000000000..c652a6139352d7 --- /dev/null +++ b/drivers/display/display_st7789v.c @@ -0,0 +1,368 @@ +/* + * Copyright (c) 2017 Jan Van Winkel + * Copyright (c) 2019 Nordic Semiconductor ASA + * Copyright (c) 2019 Marc Reilly + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "display_st7789v.h" + +#include +#include +#include +#include +#include + +#define LOG_LEVEL CONFIG_DISPLAY_LOG_LEVEL +#include +LOG_MODULE_REGISTER(display_st7789v); + +#define ST7789V_CS_PIN DT_INST_0_SITRONIX_ST7789V_CS_GPIOS_PIN +#define ST7789V_CMD_DATA_PIN DT_INST_0_SITRONIX_ST7789V_CMD_DATA_GPIOS_PIN +#define ST7789V_RESET_PIN DT_INST_0_SITRONIX_ST7789V_RESET_GPIOS_PIN + +struct st7789v_data { + struct device *spi_dev; + struct spi_config spi_config; +#ifdef DT_INST_0_SITRONIX_ST7789V_CS_GPIOS_CONTROLLER + struct spi_cs_control cs_ctrl; +#endif + +#ifdef DT_INST_0_SITRONIX_ST7789V_RESET_GPIOS_CONTROLLER + struct device *reset_gpio; +#endif + struct device *cmd_data_gpio; + + u16_t height; + u16_t width; + u16_t x_offset; + u16_t y_offset; +}; + +#ifdef CONFIG_ST7789V_RGB565 +#define ST7789V_PIXEL_SIZE 2u +#else +#define ST7789V_PIXEL_SIZE 3u +#endif + +static int st7789v_blanking_off(const struct device *dev); +static int st7789v_blanking_on(const struct device *dev); + +void st7789v_set_lcd_margins(struct st7789v_data *data, + u16_t x_offset, u16_t y_offset) +{ + data->x_offset = x_offset; + data->y_offset = y_offset; +} + +static void st7789v_set_cmd(struct st7789v_data *data, int is_cmd) +{ + gpio_pin_write(data->cmd_data_gpio, ST7789V_CMD_DATA_PIN, !is_cmd); +} + +void st7789v_transmit(struct st7789v_data *data, u8_t cmd, + u8_t *tx_data, size_t tx_count) +{ + struct spi_buf tx_buf = { .buf = &cmd, .len = 1 }; + struct spi_buf_set tx_bufs = { .buffers = &tx_buf, .count = 1 }; + + st7789v_set_cmd(data, true); + spi_write(data->spi_dev, &data->spi_config, &tx_bufs); + + if (tx_data != NULL) { + tx_buf.buf = tx_data; + tx_buf.len = tx_count; + st7789v_set_cmd(data, false); + spi_write(data->spi_dev, &data->spi_config, &tx_bufs); + } +} + +static void st7789v_exit_sleep(struct st7789v_data *data) +{ + st7789v_transmit(data, ST7789V_CMD_SLEEP_OUT, NULL, 0); + k_sleep(120); +} + +static void st7789v_reset_display(struct st7789v_data *data) +{ + LOG_DBG("Resetting display"); +#ifdef DT_INST_0_SITRONIX_ST7789V_RESET_GPIOS_CONTROLLER + gpio_pin_write(data->reset_gpio, ST7789V_RESET_PIN, 1); + k_sleep(1); + gpio_pin_write(data->reset_gpio, ST7789V_RESET_PIN, 0); + k_sleep(6); + gpio_pin_write(data->reset_gpio, ST7789V_RESET_PIN, 1); + k_sleep(20); +#else + st7789v_transmit(p_st7789v, ST7789V_CMD_SW_RESET, NULL, 0); + k_sleep(5); +#endif +} + +int st7789v_init(struct device *dev) +{ + struct st7789v_data *data = (struct st7789v_data *)dev->driver_data; + + data->spi_dev = device_get_binding(DT_INST_0_SITRONIX_ST7789V_BUS_NAME); + if (data->spi_dev == NULL) { + LOG_ERR("Could not get SPI device for LCD"); + return -EPERM; + } + + data->spi_config.frequency = DT_INST_0_SITRONIX_ST7789V_SPI_MAX_FREQUENCY; + data->spi_config.operation = SPI_OP_MODE_MASTER | SPI_WORD_SET(8); + data->spi_config.slave = DT_INST_0_SITRONIX_ST7789V_BASE_ADDRESS; + +#ifdef DT_INST_0_SITRONIX_ST7789V_CS_GPIOS_CONTROLLER + data->cs_ctrl.gpio_dev = + device_get_binding(DT_INST_0_SITRONIX_ST7789V_CS_GPIOS_CONTROLLER); + data->cs_ctrl.gpio_pin = DT_INST_0_SITRONIX_ST7789V_CS_GPIOS_PIN; + data->cs_ctrl.delay = 0U; + data->spi_config.cs = &(data->cs_ctrl); +#else + data->spi_config.cs = NULL; +#endif + +#ifdef DT_INST_0_SITRONIX_ST7789V_RESET_GPIOS_CONTROLLER + data->reset_gpio = + device_get_binding(DT_INST_0_SITRONIX_ST7789V_RESET_GPIOS_CONTROLLER); + if (data->reset_gpio == NULL) { + LOG_ERR("Could not get GPIO port for display reset"); + return -EPERM; + } + + if (gpio_pin_configure(data->reset_gpio, ST7789V_RESET_PIN, GPIO_DIR_OUT)) { + LOG_ERR("Couldn't configure reset pin"); + return -EIO; + } +#endif + + data->cmd_data_gpio = + device_get_binding(DT_INST_0_SITRONIX_ST7789V_CMD_DATA_GPIOS_CONTROLLER); + if (data->cmd_data_gpio == NULL) { + LOG_ERR("Could not get GPIO port for cmd/DATA port"); + return -EPERM; + } + if (gpio_pin_configure(data->cmd_data_gpio, ST7789V_CMD_DATA_PIN, + GPIO_DIR_OUT)) { + LOG_ERR("Couldn't configure cmd/DATA pin"); + return -EIO; + } + + data->width = 240; + data->height = 320; + data->x_offset = 0; + data->y_offset = 0; + +#ifdef DT_INST_0_SITRONIX_ST7789V_WIDTH + data->width = DT_INST_0_SITRONIX_ST7789V_WIDTH; +#endif +#ifdef DT_INST_0_SITRONIX_ST7789V_HEIGHT + data->height = DT_INST_0_SITRONIX_ST7789V_HEIGHT; +#endif + + st7789v_reset_display(data); + + st7789v_blanking_on(dev); + + st7789v_lcd_init(data); + + st7789v_exit_sleep(data); + + return 0; +} + +int st7789v_cmd_read8(struct st7789v_data *data, int cmd, u8_t *pRet) +{ + u8_t sendbuff[4]; + + sendbuff[0] = cmd; + + const struct spi_buf tx_buf[2] = { + { .buf = sendbuff, .len = 1 }, + { .buf = 0, .len = 1 }, + }; + const struct spi_buf rx_buf[2] = { + { .buf = 0, .len = 1 }, + { .buf = pRet, .len = 1 } + }; + struct spi_buf_set tx_bufs = { .buffers = tx_buf, .count = 2 }; + struct spi_buf_set rx_bufs = { .buffers = rx_buf, .count = 2 }; + + st7789v_set_cmd(data, 1); + int ret = spi_transceive(data->spi_dev, &data->spi_config, &tx_bufs, + &rx_bufs); + st7789v_set_cmd(data, 0); + + return ret; +} + +static int st7789v_blanking_on(const struct device *dev) +{ + struct st7789v_data *driver = (struct st7789v_data *)dev->driver_data; + + st7789v_transmit(driver, ST7789V_CMD_DISP_OFF, NULL, 0); + return 0; +} + +static int st7789v_blanking_off(const struct device *dev) +{ + struct st7789v_data *driver = (struct st7789v_data *)dev->driver_data; + + st7789v_transmit(driver, ST7789V_CMD_DISP_ON, NULL, 0); + return 0; +} + +static int st7789v_read(const struct device *dev, + const u16_t x, + const u16_t y, + const struct display_buffer_descriptor *desc, + void *buf) +{ + return -ENOTSUP; +} + +static void st7789v_set_mem_area(struct st7789v_data *data, const u16_t x, + const u16_t y, const u16_t w, const u16_t h) +{ + u16_t spi_data[2]; + + u16_t ram_x = x + data->x_offset; + u16_t ram_y = y + data->y_offset; + + spi_data[0] = sys_cpu_to_be16(ram_x); + spi_data[1] = sys_cpu_to_be16(ram_x + w - 1); + st7789v_transmit(data, ST7789V_CMD_CASET, (u8_t *)&spi_data[0], 4); + + spi_data[0] = sys_cpu_to_be16(ram_y); + spi_data[1] = sys_cpu_to_be16(ram_y + h - 1); + st7789v_transmit(data, ST7789V_CMD_RASET, (u8_t *)&spi_data[0], 4); +} + +static int st7789v_write(const struct device *dev, + const u16_t x, + const u16_t y, + const struct display_buffer_descriptor *desc, + const void *buf) +{ + struct st7789v_data *data = (struct st7789v_data *)dev->driver_data; + const u8_t *write_data_start = (u8_t *) buf; + struct spi_buf tx_buf; + struct spi_buf_set tx_bufs; + u16_t write_cnt; + u16_t nbr_of_writes; + u16_t write_h; + + __ASSERT(desc->width <= desc->pitch, "Pitch is smaller then width"); + __ASSERT((desc->pitch * ST7789V_PIXEL_SIZE * desc->height) <= desc->buf_size, + "Input buffer to small"); + + LOG_DBG("Writing %dx%d (w,h) @ %dx%d (x,y)", + desc->width, desc->height, x, y); + st7789v_set_mem_area(data, x, y, desc->width, desc->height); + + if (desc->pitch > desc->width) { + write_h = 1U; + nbr_of_writes = desc->height; + } else { + write_h = desc->height; + nbr_of_writes = 1U; + } + + st7789v_transmit(data, ST7789V_CMD_RAMWR, + (void *) write_data_start, + desc->width * ST7789V_PIXEL_SIZE * write_h); + + tx_bufs.buffers = &tx_buf; + tx_bufs.count = 1; + + write_data_start += (desc->pitch * ST7789V_PIXEL_SIZE); + for (write_cnt = 1U; write_cnt < nbr_of_writes; ++write_cnt) { + tx_buf.buf = (void *)write_data_start; + tx_buf.len = desc->width * ST7789V_PIXEL_SIZE * write_h; + spi_write(data->spi_dev, &data->spi_config, &tx_bufs); + write_data_start += (desc->pitch * ST7789V_PIXEL_SIZE); + } + + return 0; +} + +void *st7789v_get_framebuffer(const struct device *dev) +{ + return NULL; +} + +int st7789v_set_brightness(const struct device *dev, + const u8_t brightness) +{ + return -ENOTSUP; +} + +int st7789v_set_contrast(const struct device *dev, + const u8_t contrast) +{ + return -ENOTSUP; +} + +void st7789v_get_capabilities(const struct device *dev, + struct display_capabilities *capabilities) +{ + struct st7789v_data *data = (struct st7789v_data *)dev->driver_data; + + memset(capabilities, 0, sizeof(struct display_capabilities)); + capabilities->x_resolution = data->width; + capabilities->y_resolution = data->height; + +#ifdef CONFIG_ST7789V_RGB565 + capabilities->supported_pixel_formats = PIXEL_FORMAT_RGB_565; + capabilities->current_pixel_format = PIXEL_FORMAT_RGB_565; +#else + capabilities->supported_pixel_formats = PIXEL_FORMAT_RGB_888; + capabilities->current_pixel_format = PIXEL_FORMAT_RGB_888; +#endif + capabilities->current_orientation = DISPLAY_ORIENTATION_NORMAL; +} + +int st7789v_set_pixel_format(const struct device *dev, + const enum display_pixel_format pixel_format) +{ +#ifdef CONFIG_ST7789V_RGB565 + if (pixel_format == PIXEL_FORMAT_RGB_565) { +#else + if (pixel_format == PIXEL_FORMAT_RGB_888) { +#endif + return 0; + } + LOG_ERR("Pixel format change not implemented"); + return -ENOTSUP; +} + +int st7789v_set_orientation(const struct device *dev, + const enum display_orientation orientation) +{ + if (orientation == DISPLAY_ORIENTATION_NORMAL) { + return 0; + } + LOG_ERR("Changing display orientation not implemented"); + return -ENOTSUP; +} + +static const struct display_driver_api st7789v_api = { + .blanking_on = st7789v_blanking_on, + .blanking_off = st7789v_blanking_off, + .write = st7789v_write, + .read = st7789v_read, + .get_framebuffer = st7789v_get_framebuffer, + .set_brightness = st7789v_set_brightness, + .set_contrast = st7789v_set_contrast, + .get_capabilities = st7789v_get_capabilities, + .set_pixel_format = st7789v_set_pixel_format, + .set_orientation = st7789v_set_orientation, +}; + +static struct st7789v_data st7789v_data; + +DEVICE_AND_API_INIT(st7789v, DT_INST_0_SITRONIX_ST7789V_LABEL, &st7789v_init, + &st7789v_data, NULL, APPLICATION, + CONFIG_APPLICATION_INIT_PRIORITY, &st7789v_api); diff --git a/drivers/display/display_st7789v.h b/drivers/display/display_st7789v.h new file mode 100644 index 00000000000000..610d4c4c1d8d1c --- /dev/null +++ b/drivers/display/display_st7789v.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2019 Marc Reilly + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ST7789V_DISPLAY_DRIVER_H__ +#define ST7789V_DISPLAY_DRIVER_H__ + +#include + +#define ST7789V_CMD_SW_RESET 0x01 + +#define ST7789V_CMD_SLEEP_IN 0x10 +#define ST7789V_CMD_SLEEP_OUT 0x11 +#define ST7789V_CMD_INV_OFF 0x20 +#define ST7789V_CMD_INV_ON 0x21 +#define ST7789V_CMD_GAMSET 0x26 +#define ST7789V_CMD_DISP_OFF 0x28 +#define ST7789V_CMD_DISP_ON 0x29 + +#define ST7789V_CMD_CASET 0x2a +#define ST7789V_CMD_RASET 0x2b +#define ST7789V_CMD_RAMWR 0x2c + +#define ST7789V_CMD_MADCTL 0x36 +#define ST7789V_MADCTL_MY_TOP_TO_BOTTOM 0x00 +#define ST7789V_MADCTL_MY_BOTTOM_TO_TOP 0x80 +#define ST7789V_MADCTL_MX_LEFT_TO_RIGHT 0x00 +#define ST7789V_MADCTL_MX_RIGHT_TO_LEFT 0x40 +#define ST7789V_MADCTL_MV_REVERSE_MODE 0x20 +#define ST7789V_MADCTL_MV_NORMAL_MODE 0x00 +#define ST7789V_MADCTL_ML 0x10 +#define ST7789V_MADCTL_RBG 0x00 +#define ST7789V_MADCTL_BGR 0x08 +#define ST7789V_MADCTL_MH_LEFT_TO_RIGHT 0x00 +#define ST7789V_MADCTL_MH_RIGHT_TO_LEFT 0x04 + +#define ST7789V_CMD_COLMOD 0x3a +#define ST7789V_COLMOD_RGB_65K (0x5 << 4) +#define ST7789V_COLMOD_RGB_262K (0x6 << 4) +#define ST7789V_COLMOD_FMT_12bit (3) +#define ST7789V_COLMOD_FMT_16bit (5) +#define ST7789V_COLMOD_FMT_18bit (6) + +#define ST7789V_CMD_RAMCTRL 0xb0 +#define ST7789V_CMD_RGBCTRL 0xb1 +#define ST7789V_CMD_PORCTRL 0xb2 +#define ST7789V_CMD_CMD2EN 0xdf +#define ST7789V_CMD_DGMEN 0xba +#define ST7789V_CMD_GCTRL 0xb7 +#define ST7789V_CMD_VCOMS 0xbb + +#define ST7789V_CMD_LCMCTRL 0xc0 +#define ST7789V_LCMCTRL_XMY 0x40 +#define ST7789V_LCMCTRL_XBGR 0x20 +#define ST7789V_LCMCTRL_XINV 0x10 +#define ST7789V_LCMCTRL_XMX 0x08 +#define ST7789V_LCMCTRL_XMH 0x04 +#define ST7789V_LCMCTRL_XMV 0x02 + +#define ST7789V_CMD_VDVVRHEN 0xc2 +#define ST7789V_CMD_VRH 0xc3 +#define ST7789V_CMD_VDS 0xc4 +#define ST7789V_CMD_FRCTRL2 0xc6 +#define ST7789V_CMD_PWCTRL1 0xd0 + +#define ST7789V_CMD_PVGAMCTRL 0xe0 +#define ST7789V_CMD_NVGAMCTRL 0xe1 + +struct st7789v_data; + +void st7789v_set_lcd_margins(struct st7789v_data *data, + u16_t x_offset, u16_t y_offset); + +void st7789v_lcd_init(struct st7789v_data *data); + +void st7789v_transmit(struct st7789v_data *data, u8_t cmd, + u8_t *tx_data, size_t tx_count); + +#endif diff --git a/drivers/display/display_st7789v_tl019fqv01.c b/drivers/display/display_st7789v_tl019fqv01.c new file mode 100644 index 00000000000000..9ca61dfcf481e1 --- /dev/null +++ b/drivers/display/display_st7789v_tl019fqv01.c @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2019 Marc Reilly + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "display_st7789v.h" +#include +#include + +void st7789v_lcd_init(struct st7789v_data *p_st7789v) +{ + /* the LCD itself is smaller than the area of the ram on + * the controller. In its 'natural' orientation the LCD is + * 170 columns and 320 rows which is centered in the controller + * RAM area (so the LCD actually starts at column 35). + * We switch the rows/column addressing around so that the + * display is 320x170, and so the effective LCD is offset + * by 35 "rows". + */ + st7789v_set_lcd_margins(p_st7789v, 0, 35); + + u8_t cmd; + u8_t data[14]; + + cmd = ST7789V_CMD_PORCTRL; + data[0] = 0x0c; + data[1] = 0x0c; + data[2] = 0x00; + data[3] = 0x33; + data[4] = 0x33; + st7789v_transmit(p_st7789v, cmd, data, 5); + + cmd = ST7789V_CMD_CMD2EN; + data[0] = 0x5a; + data[1] = 0x69; + data[2] = 0x02; + data[3] = 0x01; + st7789v_transmit(p_st7789v, cmd, data, 4); + + cmd = ST7789V_CMD_DGMEN; + data[0] = 0x00; + st7789v_transmit(p_st7789v, cmd, data, 1); + + cmd = ST7789V_CMD_GCTRL; + data[0] = 0x35; + st7789v_transmit(p_st7789v, cmd, data, 1); + + cmd = ST7789V_CMD_VCOMS; + data[0] = 0x2b; + st7789v_transmit(p_st7789v, cmd, data, 1); + +#if CONFIG_ST7789V_REVERSE_LCD_RGB_ORDER + cmd = ST7789V_CMD_LCMCTRL; + data[0] = ST7789V_LCMCTRL_XBGR; + st7789v_transmit(p_st7789v, cmd, data, 1); +#endif + + cmd = ST7789V_CMD_VDVVRHEN; + data[0] = 0x01; + st7789v_transmit(p_st7789v, cmd, data, 1); + + cmd = ST7789V_CMD_VRH; + data[0] = 0x0f; + st7789v_transmit(p_st7789v, cmd, data, 1); + + cmd = ST7789V_CMD_VDS; + data[0] = 0x20; + st7789v_transmit(p_st7789v, cmd, data, 1); + + cmd = ST7789V_CMD_FRCTRL2; + data[0] = 0x0f; + st7789v_transmit(p_st7789v, cmd, data, 1); + + cmd = ST7789V_CMD_PWCTRL1; + data[0] = 0x52; + data[1] = (0x2 << 6) | (0x2 << 4) | 0x01; + st7789v_transmit(p_st7789v, cmd, data, 2); + + cmd = ST7789V_CMD_MADCTL; + data[0] = ST7789V_MADCTL_MV_REVERSE_MODE; +#ifdef CONFIG_ST7789V_REVERSE_X + data[0] |= ST7789V_MADCTL_MX_RIGHT_TO_LEFT; +#endif +#ifdef CONFIG_ST7789V_REVERSE_Y + data[0] |= ST7789V_MADCTL_MY_BOTTOM_TO_TOP; +#endif + st7789v_transmit(p_st7789v, cmd, data, 1); + + cmd = ST7789V_CMD_COLMOD; +#ifdef CONFIG_ST7789V_RGB565 + data[0] = ST7789V_COLMOD_RGB_65K + | ST7789V_COLMOD_FMT_16bit; +#else + data[0] = ST7789V_COLMOD_RGB_262K + | ST7789V_COLMOD_FMT_18bit; +#endif + st7789v_transmit(p_st7789v, cmd, data, 1); + + cmd = ST7789V_CMD_INV_ON; + st7789v_transmit(p_st7789v, cmd, NULL, 0); + + cmd = ST7789V_CMD_GAMSET; + data[0] = 0x01U; + st7789v_transmit(p_st7789v, cmd, data, 1); + + cmd = ST7789V_CMD_PVGAMCTRL; + data[0] = 0xD0 | 0x00; /* v63 | V0 */ + data[1] = 0x00; /* v1 */ + data[2] = 0x02; /* v2 */ + data[3] = 0x07; /* v4 */ + data[4] = 0x0B; /* V6 */ + data[5] = (0x01 << 4) | 0x0a; /* J0 | V13 */ + data[6] = 0x31; /* V2 */ + data[7] = (0x5 << 4) | 0x4; /* V36 | V27 */ + data[8] = 0x40; /* V43 */ + data[9] = (0x02 << 4) | 0x09; /* J1 | V50 */ + data[10] = 0x12; /* V57 */ + data[11] = 0x12; /* V59 */ + data[12] = 0x12; /* V61 */ + data[13] = 0x17; /* V62 */ + st7789v_transmit(p_st7789v, cmd, data, 14); + + cmd = ST7789V_CMD_NVGAMCTRL; + data[0] = (0xd << 4) | 0x00; /* V63 | V0 */ + data[1] = 0x00; /* v1 */ + data[2] = 0x02; /* v2 */ + data[3] = 0x07; /* v4 */ + data[4] = 0x05; /* V6 */ + data[5] = (0x01 << 4) | 0x05; /* J0 | V13 */ + data[6] = 0x2D; /* V20 */ + data[7] = (0x4 << 4) | 0x4; /* V36 | V27 */ + data[8] = 0x44; /* V43 */ + data[9] = (0x01 << 4) | 0x0c; /* J1 | V50 */ + data[10] = 0x18; /* V57 */ + data[11] = 0x16; /* V59 */ + data[12] = 0x1c; /* V61 */ + data[13] = 0x1d; /* V62 */ + st7789v_transmit(p_st7789v, cmd, data, 14); + + cmd = ST7789V_CMD_RAMCTRL; + data[0] = 0x00; + data[1] = (0x3 << 6) | (0x3u << 4); +#if CONFIG_ST7789V_SWAP_PIXEL_LCD_ENDIANNESS + data[1] |= 0x08; +#endif + st7789v_transmit(p_st7789v, cmd, data, 2); + + cmd = ST7789V_CMD_RGBCTRL; + data[0] = 0x80 | (0x2 << 5) | 0xd; + data[1] = 0x08; + data[2] = 0x14; + st7789v_transmit(p_st7789v, cmd, data, 3); +} diff --git a/dts/bindings/display/sitronix,st7789v.yaml b/dts/bindings/display/sitronix,st7789v.yaml new file mode 100644 index 00000000000000..f369e217ee5c7a --- /dev/null +++ b/dts/bindings/display/sitronix,st7789v.yaml @@ -0,0 +1,45 @@ +# +# Copyright (c) 2019, Marc Reilly +# +# SPDX-License-Identifier: Apache-2.0 +# + +title: ST7789V 320x240 Display Controller + +description: > + This is a representation of the ST7789V 320x240 Display Controller + +inherits: + !include spi-device.yaml + +properties: + compatible: + constraint: "sitronix,st7789v" + + reset-gpios: + type: compound + category: required + + cmd-data-gpios: + type: compound + category: required + + height: + type: int + category: required + description: Height in pixels of the panel driven by the controller + + width: + type: int + category: required + description: Width in pixels of the panel driven by the controller + + x-offset: + type: int + category: optional + description: The column offset in pixels of the LCD to the controller memory + + y-offset: + type: int + category: optional + description: The row offset in pixels of the LCD to the controller memory