diff --git a/boards/shields/st7735r/st7735r_ada_160x128.overlay b/boards/shields/st7735r/st7735r_ada_160x128.overlay index 42d7cd89060..d769b9a1a4d 100644 --- a/boards/shields/st7735r/st7735r_ada_160x128.overlay +++ b/boards/shields/st7735r/st7735r_ada_160x128.overlay @@ -4,38 +4,48 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include + / { chosen { zephyr,display = &st7735r_st7735r_ada_160x128; }; + + mipi_dbi_st7735r_ada_160x128 { + compatible = "zephyr,mipi-dbi-spi"; + spi-dev = <&arduino_spi>; + dc-gpios = <&arduino_header 15 GPIO_ACTIVE_HIGH>; /* D9 */ + reset-gpios = <&arduino_header 14 GPIO_ACTIVE_LOW>; /* D8 */ + #address-cells = <1>; + #size-cells = <0>; + + st7735r_st7735r_ada_160x128: st7735r@0 { + compatible = "sitronix,st7735r"; + mipi-max-frequency = <20000000>; + mipi-mode = ; + reg = <0>; + width = <160>; + height = <128>; + x-offset = <0>; + y-offset = <0>; + madctl = <0x60>; + colmod = <0x55>; + vmctr1 = <0x0e>; + pwctr1 = [a2 02 84]; + pwctr2 = [c5]; + pwctr3 = [0a 00]; + pwctr4 = [8a 2a]; + pwctr5 = [8a ee]; + frmctr1 = [01 2c 2d]; + frmctr2 = [01 2c 2d]; + frmctr3 = [01 2c 2d 01 2c 2d]; + gamctrp1 = [02 1c 07 12 37 32 29 2d 29 25 2b 39 00 01 03 10]; + gamctrn1 = [03 1d 07 06 2e 2c 29 2d 2e 2e 37 3f 00 00 02 10]; + }; + }; }; &arduino_spi { status = "okay"; cs-gpios = <&arduino_header 16 GPIO_ACTIVE_LOW>; /* D10 */ - - st7735r_st7735r_ada_160x128: st7735r@0 { - compatible = "sitronix,st7735r"; - spi-max-frequency = <20000000>; - reg = <0>; - cmd-data-gpios = <&arduino_header 15 GPIO_ACTIVE_LOW>; /* D9 */ - reset-gpios = <&arduino_header 14 GPIO_ACTIVE_LOW>; /* D8 */ - width = <160>; - height = <128>; - x-offset = <0>; - y-offset = <0>; - madctl = <0x60>; - colmod = <0x55>; - vmctr1 = <0x0e>; - pwctr1 = [a2 02 84]; - pwctr2 = [c5]; - pwctr3 = [0a 00]; - pwctr4 = [8a 2a]; - pwctr5 = [8a ee]; - frmctr1 = [01 2c 2d]; - frmctr2 = [01 2c 2d]; - frmctr3 = [01 2c 2d 01 2c 2d]; - gamctrp1 = [02 1c 07 12 37 32 29 2d 29 25 2b 39 00 01 03 10]; - gamctrn1 = [03 1d 07 06 2e 2c 29 2d 2e 2e 37 3f 00 00 02 10]; - }; }; diff --git a/boards/sipeed/longan_nano/longan_nano-common.dtsi b/boards/sipeed/longan_nano/longan_nano-common.dtsi index 6d272ddd53d..c5e9202e94f 100644 --- a/boards/sipeed/longan_nano/longan_nano-common.dtsi +++ b/boards/sipeed/longan_nano/longan_nano-common.dtsi @@ -5,6 +5,7 @@ */ #include +#include / { chosen { @@ -65,6 +66,50 @@ sw0 = &button_boot0; watchdog0 = &fwdgt; }; + + mipi_dbi { + compatible = "zephyr,mipi-dbi-spi"; + reset-gpios = <&gpiob 1 GPIO_ACTIVE_LOW>; + dc-gpios = <&gpiob 0 GPIO_ACTIVE_HIGH>; + spi-dev = <&spi0>; + write-only; + #address-cells = <1>; + #size-cells = <0>; + + /* longan nano has LCD with st7735s controller. + * It can use with st7735r driver. + */ + lcd0: lcd@0 { + compatible = "sitronix,st7735r"; + reg = <0>; + status = "okay"; + width = <160>; + height = <80>; + inversion-on; + rgb-is-inverted; + x-offset = <1>; + y-offset = <26>; + pwctr1 = [62 02 04]; + pwctr2 = [C0]; + pwctr3 = [0D 00]; + pwctr4 = [8D 6A]; + pwctr5 = [8D EE]; + invctr = <3>; + frmctr1 = [05 3A 3A]; + frmctr2 = [05 3A 3A]; + frmctr3 = [05 3A 3A 05 3A 3A]; + vmctr1 = <14>; + gamctrp1 = [10 0E 02 03 0E 07 02 07 0A 12 27 37 00 0D 0E 10]; + gamctrn1 = [10 0E 03 03 0F 06 02 08 0A 13 26 36 00 0D 0E 10]; + colmod = <5>; + madctl = <120>; + caset = [00 01 00 a0]; + raset = [00 1a 00 69]; + + mipi-mode = ; + mipi-max-frequency = <4000000>; + }; + }; }; &gpioa { @@ -109,41 +154,6 @@ pinctrl-names = "default"; cs-gpios = <&gpiob 2 GPIO_ACTIVE_LOW>; - - /* longan nano has LCD with st7735s controller. - * It can use with st7735r driver. - */ - lcd0: lcd@0 { - compatible = "sitronix,st7735r"; - reg = <0>; - status = "okay"; - reset-gpios = <&gpiob 1 GPIO_ACTIVE_LOW>; - cmd-data-gpios = <&gpiob 0 GPIO_ACTIVE_LOW>; - width = <160>; - height = <80>; - inversion-on; - rgb-is-inverted; - x-offset = <1>; - y-offset = <26>; - pwctr1 = [62 02 04]; - pwctr2 = [C0]; - pwctr3 = [0D 00]; - pwctr4 = [8D 6A]; - pwctr5 = [8D EE]; - invctr = <3>; - frmctr1 = [05 3A 3A]; - frmctr2 = [05 3A 3A]; - frmctr3 = [05 3A 3A 05 3A 3A]; - vmctr1 = <14>; - gamctrp1 = [10 0E 02 03 0E 07 02 07 0A 12 27 37 00 0D 0E 10]; - gamctrn1 = [10 0E 03 03 0F 06 02 08 0A 13 26 36 00 0D 0E 10]; - colmod = <5>; - madctl = <120>; - caset = [00 01 00 a0]; - raset = [00 1a 00 69]; - - spi-max-frequency = <4000000>; - }; }; &spi1 { diff --git a/drivers/display/Kconfig.st7735r b/drivers/display/Kconfig.st7735r index 94153eca585..387665ace45 100644 --- a/drivers/display/Kconfig.st7735r +++ b/drivers/display/Kconfig.st7735r @@ -7,6 +7,6 @@ config ST7735R bool "ST7735R/ST7735S display driver" default y depends on DT_HAS_SITRONIX_ST7735R_ENABLED - select SPI + select MIPI_DBI help Enable driver for ST7735R/ST7735S display driver. diff --git a/drivers/display/display_st7735r.c b/drivers/display/display_st7735r.c index 88c282d89f8..1626cb5204b 100644 --- a/drivers/display/display_st7735r.c +++ b/drivers/display/display_st7735r.c @@ -5,6 +5,7 @@ * Copyright (c) 2019 PHYTEC Messtechnik GmbH * Copyright (c) 2020 Endian Technologies AB * Copyright (c) 2020 Kim Bøndergaard + * Copyright 2024 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -14,7 +15,7 @@ #include "display_st7735r.h" #include -#include +#include #include #include #include @@ -23,15 +24,14 @@ #include LOG_MODULE_REGISTER(display_st7735r, CONFIG_DISPLAY_LOG_LEVEL); -#define ST7735R_RESET_TIME K_MSEC(1) +#define ST7735R_RESET_TIME 1 #define ST7735R_EXIT_SLEEP_TIME K_MSEC(120) #define ST7735R_PIXEL_SIZE 2u struct st7735r_config { - struct spi_dt_spec bus; - struct gpio_dt_spec cmd_data; - struct gpio_dt_spec reset; + const struct device *mipi_dev; + const struct mipi_dbi_config dbi_config; uint16_t height; uint16_t width; uint8_t madctl; @@ -68,38 +68,13 @@ static void st7735r_set_lcd_margins(const struct device *dev, data->y_offset = y_offset; } -static void st7735r_set_cmd(const struct device *dev, int is_cmd) -{ - const struct st7735r_config *config = dev->config; - - gpio_pin_set_dt(&config->cmd_data, is_cmd); -} - static int st7735r_transmit_hold(const struct device *dev, uint8_t cmd, const uint8_t *tx_data, size_t tx_count) { const struct st7735r_config *config = dev->config; - struct spi_buf tx_buf = { .buf = &cmd, .len = 1 }; - struct spi_buf_set tx_bufs = { .buffers = &tx_buf, .count = 1 }; - int ret; - st7735r_set_cmd(dev, 1); - ret = spi_write_dt(&config->bus, &tx_bufs); - if (ret < 0) { - return ret; - } - - if (tx_data != NULL) { - tx_buf.buf = (void *)tx_data; - tx_buf.len = tx_count; - st7735r_set_cmd(dev, 0); - ret = spi_write_dt(&config->bus, &tx_bufs); - if (ret < 0) { - return ret; - } - } - - return 0; + return mipi_dbi_command_write(config->mipi_dev, &config->dbi_config, + cmd, tx_data, tx_count); } static int st7735r_transmit(const struct device *dev, uint8_t cmd, @@ -109,7 +84,7 @@ static int st7735r_transmit(const struct device *dev, uint8_t cmd, int ret; ret = st7735r_transmit_hold(dev, cmd, tx_data, tx_count); - spi_release_dt(&config->bus); + mipi_dbi_release(config->mipi_dev, &config->dbi_config); return ret; } @@ -133,11 +108,8 @@ static int st7735r_reset_display(const struct device *dev) int ret; LOG_DBG("Resetting display"); - if (config->reset.port != NULL) { - gpio_pin_set_dt(&config->reset, 1); - k_sleep(ST7735R_RESET_TIME); - gpio_pin_set_dt(&config->reset, 0); - } else { + ret = mipi_dbi_reset(config->mipi_dev, ST7735R_RESET_TIME); + if (ret != 0) { ret = st7735r_transmit(dev, ST7735R_CMD_SW_RESET, NULL, 0); if (ret < 0) { return ret; @@ -204,12 +176,12 @@ static int st7735r_write(const struct device *dev, { const struct st7735r_config *config = dev->config; const uint8_t *write_data_start = (uint8_t *) buf; - struct spi_buf tx_buf; - struct spi_buf_set tx_bufs; uint16_t write_cnt; uint16_t nbr_of_writes; uint16_t write_h; int ret; + enum display_pixel_format fmt; + struct display_buffer_descriptor mipi_desc; __ASSERT(desc->width <= desc->pitch, "Pitch is smaller than width"); __ASSERT((desc->pitch * ST7735R_PIXEL_SIZE * desc->height) @@ -225,9 +197,24 @@ static int st7735r_write(const struct device *dev, if (desc->pitch > desc->width) { write_h = 1U; nbr_of_writes = desc->height; + mipi_desc.height = 1; + mipi_desc.buf_size = desc->pitch * ST7735R_PIXEL_SIZE; } else { write_h = desc->height; nbr_of_writes = 1U; + mipi_desc.height = desc->height; + mipi_desc.buf_size = desc->width * ST7735R_PIXEL_SIZE * write_h; + } + + mipi_desc.width = desc->width; + /* Per MIPI API, pitch must always match width */ + mipi_desc.pitch = desc->width; + + + if (!(config->madctl & ST7735R_MADCTL_BGR) != !config->rgb_is_inverted) { + fmt = PIXEL_FORMAT_BGR_565; + } else { + fmt = PIXEL_FORMAT_RGB_565; } ret = st7735r_transmit_hold(dev, ST7735R_CMD_RAMWR, @@ -237,14 +224,13 @@ static int st7735r_write(const struct device *dev, goto out; } - tx_bufs.buffers = &tx_buf; - tx_bufs.count = 1; - write_data_start += (desc->pitch * ST7735R_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 * ST7735R_PIXEL_SIZE * write_h; - ret = spi_write_dt(&config->bus, &tx_bufs); + ret = mipi_dbi_write_display(config->mipi_dev, + &config->dbi_config, + write_data_start, + &mipi_desc, + fmt); if (ret < 0) { goto out; } @@ -254,7 +240,7 @@ static int st7735r_write(const struct device *dev, ret = 0; out: - spi_release_dt(&config->bus); + mipi_dbi_release(config->mipi_dev, &config->dbi_config); return ret; } @@ -445,36 +431,11 @@ static int st7735r_init(const struct device *dev) const struct st7735r_config *config = dev->config; int ret; - if (!spi_is_ready_dt(&config->bus)) { - LOG_ERR("SPI bus %s not ready", config->bus.bus->name); + if (!device_is_ready(config->mipi_dev)) { + LOG_ERR("MIPI bus %s not ready", config->mipi_dev->name); return -ENODEV; } - if (config->reset.port != NULL) { - if (!gpio_is_ready_dt(&config->reset)) { - LOG_ERR("Reset GPIO port for display not ready"); - return -ENODEV; - } - - ret = gpio_pin_configure_dt(&config->reset, - GPIO_OUTPUT_INACTIVE); - if (ret) { - LOG_ERR("Couldn't configure reset pin"); - return ret; - } - } - - if (!gpio_is_ready_dt(&config->cmd_data)) { - LOG_ERR("cmd/DATA GPIO port not ready"); - return -ENODEV; - } - - ret = gpio_pin_configure_dt(&config->cmd_data, GPIO_OUTPUT); - if (ret) { - LOG_ERR("Couldn't configure cmd/DATA pin"); - return ret; - } - ret = st7735r_reset_display(dev); if (ret < 0) { LOG_ERR("Couldn't reset display"); @@ -530,11 +491,13 @@ static const struct display_driver_api st7735r_api = { #define ST7735R_INIT(inst) \ const static struct st7735r_config st7735r_config_ ## inst = { \ - .bus = SPI_DT_SPEC_INST_GET( \ - inst, SPI_OP_MODE_MASTER | SPI_WORD_SET(8) | \ - SPI_HOLD_ON_CS | SPI_LOCK_ON, 0), \ - .cmd_data = GPIO_DT_SPEC_INST_GET(inst, cmd_data_gpios), \ - .reset = GPIO_DT_SPEC_INST_GET_OR(inst, reset_gpios, {}), \ + .mipi_dev = DEVICE_DT_GET(DT_INST_PARENT(inst)), \ + .dbi_config = MIPI_DBI_CONFIG_DT_INST(inst, \ + SPI_OP_MODE_MASTER | \ + ((DT_INST_PROP(inst, mipi_mode) == \ + MIPI_DBI_MODE_SPI_4WIRE) ? SPI_WORD_SET(8) : \ + SPI_WORD_SET(9)) | \ + SPI_HOLD_ON_CS | SPI_LOCK_ON, 0), \ .width = DT_INST_PROP(inst, width), \ .height = DT_INST_PROP(inst, height), \ .madctl = DT_INST_PROP(inst, madctl), \ diff --git a/dts/bindings/display/sitronix,st7735r.yaml b/dts/bindings/display/sitronix,st7735r.yaml index 90ead2b8731..bc94281e829 100644 --- a/dts/bindings/display/sitronix,st7735r.yaml +++ b/dts/bindings/display/sitronix,st7735r.yaml @@ -5,26 +5,9 @@ description: ST7735R/ST7735S 160x128 (max) display controller compatible: "sitronix,st7735r" -include: [spi-device.yaml, display-controller.yaml] +include: [mipi-dbi-spi-device.yaml, display-controller.yaml] properties: - reset-gpios: - type: phandle-array - description: RESET pin. - - The RESET pin of ST7735R is active low. - If connected directly the MCU pin should be configured - as active low. - - cmd-data-gpios: - type: phandle-array - required: true - description: D/CX pin. - - The D/CX pin of ST7735R is active low (transmission command byte). - If connected directly the MCU pin should be configured - as active low. - x-offset: type: int required: true