diff --git a/boards/shields/seeed_xiao_round_display/seeed_xiao_round_display.overlay b/boards/shields/seeed_xiao_round_display/seeed_xiao_round_display.overlay index dab060bb604..d4a3ad1329e 100644 --- a/boards/shields/seeed_xiao_round_display/seeed_xiao_round_display.overlay +++ b/boards/shields/seeed_xiao_round_display/seeed_xiao_round_display.overlay @@ -27,6 +27,26 @@ aliases { rtc = &pcf8563_xiao_round_display; }; + + xiao_round_display_mipi_dbi { + compatible = "zephyr,mipi-dbi-spi"; + spi-dev = <&xiao_spi>; + dc-gpios = <&xiao_d 3 GPIO_ACTIVE_HIGH>; + write-only; + #address-cells = <1>; + #size-cells = <0>; + + gc9a01_xiao_round_display: gc9a01@0 { + status = "okay"; + compatible = "galaxycore,gc9x01x"; + reg = <0>; + mipi-max-frequency = ; + pixel-format = ; + width = <240>; + height = <240>; + display-inversion; + }; + }; }; &xiao_adc { @@ -62,18 +82,6 @@ status = "okay"; cs-gpios = <&xiao_d 1 GPIO_ACTIVE_LOW>, <&xiao_d 2 GPIO_ACTIVE_LOW>; - gc9a01_xiao_round_display: gc9a01@0 { - status = "okay"; - compatible = "galaxycore,gc9x01x"; - reg = <0>; - spi-max-frequency = ; - cmd-data-gpios = <&xiao_d 3 GPIO_ACTIVE_HIGH>; - pixel-format = ; - width = <240>; - height = <240>; - display-inversion; - }; - sdhc_xiao_round_display: sdhc@1 { compatible = "zephyr,sdhc-spi-slot"; reg = <1>; diff --git a/boards/waveshare/esp32s3_touch_lcd_1_28/esp32s3_touch_lcd_1_28_esp32s3_procpu.dts b/boards/waveshare/esp32s3_touch_lcd_1_28/esp32s3_touch_lcd_1_28_esp32s3_procpu.dts index f6a62874fe5..cb4bd891f61 100644 --- a/boards/waveshare/esp32s3_touch_lcd_1_28/esp32s3_touch_lcd_1_28_esp32s3_procpu.dts +++ b/boards/waveshare/esp32s3_touch_lcd_1_28/esp32s3_touch_lcd_1_28_esp32s3_procpu.dts @@ -56,6 +56,28 @@ pwms = <&ledc0 0 PWM_HZ(250) PWM_POLARITY_NORMAL>; }; }; + + /* MIPI DBI */ + mipi_dbi { + compatible = "zephyr,mipi-dbi-spi"; + spi-dev = <&spi2>; + dc-gpios = <&gpio0 8 GPIO_ACTIVE_HIGH>; + reset-gpios = <&gpio0 14 GPIO_ACTIVE_LOW>; + write-only; + #address-cells = <1>; + #size-cells = <0>; + + gc9a01: gc9a01@0 { + status = "okay"; + compatible = "galaxycore,gc9x01x"; + reg = <0>; + mipi-max-frequency = <100000000>; + pixel-format = ; + display-inversion; + width = <240>; + height = <240>; + }; + }; }; &flash0 { @@ -146,19 +168,6 @@ pinctrl-0 = <&spim2_default>; pinctrl-names = "default"; cs-gpios = <&gpio0 9 GPIO_ACTIVE_LOW>; - - gc9a01: gc9a01@0 { - status = "okay"; - compatible = "galaxycore,gc9x01x"; - reg = <0>; - spi-max-frequency = <100000000>; - cmd-data-gpios = <&gpio0 8 GPIO_ACTIVE_HIGH>; - reset-gpios = <&gpio0 14 GPIO_ACTIVE_LOW>; - pixel-format = ; - display-inversion; - width = <240>; - height = <240>; - }; }; &trng0 { diff --git a/drivers/display/Kconfig.gc9x01x b/drivers/display/Kconfig.gc9x01x index aba24c445f1..650b0de9191 100644 --- a/drivers/display/Kconfig.gc9x01x +++ b/drivers/display/Kconfig.gc9x01x @@ -5,6 +5,6 @@ config GC9X01X bool "GC9X01X display driver" default y depends on DT_HAS_GALAXYCORE_GC9X01X_ENABLED - select SPI + select MIPI_DBI help Enable driver for GC9X01X display driver. diff --git a/drivers/display/display_gc9x01x.c b/drivers/display/display_gc9x01x.c index 1d432d3f355..963e0dbe7a6 100644 --- a/drivers/display/display_gc9x01x.c +++ b/drivers/display/display_gc9x01x.c @@ -10,8 +10,7 @@ #include #include -#include -#include +#include #include #include #include @@ -19,12 +18,6 @@ #include LOG_MODULE_REGISTER(display_gc9x01x, CONFIG_DISPLAY_LOG_LEVEL); -/* Command/data GPIO level for commands. */ -#define GC9X01X_GPIO_LEVEL_CMD 0U - -/* Command/data GPIO level for data. */ -#define GC9X01X_GPIO_LEVEL_DATA 1U - /* Maximum number of default init registers */ #define GC9X01X_NUM_DEFAULT_INIT_REGS 12U @@ -37,9 +30,8 @@ struct gc9x01x_data { /* Configuration data struct.*/ struct gc9x01x_config { - struct spi_dt_spec spi; - struct gpio_dt_spec cmd_data; - struct gpio_dt_spec reset; + const struct device *mipi_dev; + struct mipi_dbi_config dbi_config; uint8_t pixel_format; uint16_t orientation; uint16_t x_resolution; @@ -229,35 +221,9 @@ static int gc9x01x_transmit(const struct device *dev, uint8_t cmd, const void *t size_t tx_len) { const struct gc9x01x_config *config = dev->config; - int ret; - struct spi_buf tx_buf = {.buf = &cmd, .len = 1U}; - struct spi_buf_set tx_bufs = {.buffers = &tx_buf, .count = 1U}; - - ret = gpio_pin_set_dt(&config->cmd_data, GC9X01X_GPIO_LEVEL_CMD); - if (ret < 0) { - return ret; - } - ret = spi_write_dt(&config->spi, &tx_bufs); - if (ret < 0) { - return ret; - } - - /* send data (if any) */ - if (tx_data != NULL) { - tx_buf.buf = (void *)tx_data; - tx_buf.len = tx_len; - - ret = gpio_pin_set_dt(&config->cmd_data, GC9X01X_GPIO_LEVEL_DATA); - if (ret < 0) { - return ret; - } - ret = spi_write_dt(&config->spi, &tx_bufs); - if (ret < 0) { - return ret; - } - } - return 0; + return mipi_dbi_command_write(config->mipi_dev, &config->dbi_config, + cmd, tx_data, tx_len); } static int gc9x01x_regs_init(const struct device *dev) @@ -266,6 +232,10 @@ static int gc9x01x_regs_init(const struct device *dev) const struct gc9x01x_regs *regs = config->regs; int ret; + if (!device_is_ready(config->mipi_dev)) { + return -ENODEV; + } + /* Enable inter-command mode */ ret = gc9x01x_transmit(dev, GC9X01X_CMD_INREGEN1, NULL, 0); if (ret < 0) { @@ -371,17 +341,15 @@ static int gc9x01x_enter_sleep(const struct device *dev) static int gc9x01x_hw_reset(const struct device *dev) { const struct gc9x01x_config *config = dev->config; + int ret; - if (config->reset.port == NULL) { - return -ENODEV; + ret = mipi_dbi_reset(config->mipi_dev, 100); + if (ret < 0) { + return ret; } - - gpio_pin_set_dt(&config->reset, 1U); - k_msleep(100); - gpio_pin_set_dt(&config->reset, 0U); k_msleep(10); - return 0; + return ret; } static int gc9x01x_display_blanking_off(const struct device *dev) @@ -492,38 +460,8 @@ static int gc9x01x_configure(const struct device *dev) static int gc9x01x_init(const struct device *dev) { - const struct gc9x01x_config *config = dev->config; int ret; - if (!spi_is_ready_dt(&config->spi)) { - LOG_ERR("SPI device is not ready"); - return -ENODEV; - } - - if (!gpio_is_ready_dt(&config->cmd_data)) { - LOG_ERR("Command/Data GPIO device not ready"); - return -ENODEV; - } - - ret = gpio_pin_configure_dt(&config->cmd_data, GPIO_OUTPUT); - if (ret < 0) { - LOG_ERR("Could not configure command/data GPIO (%d)", ret); - return ret; - } - - if (config->reset.port != NULL) { - if (!device_is_ready(config->reset.port)) { - LOG_ERR("Reset GPIO device not ready"); - return -ENODEV; - } - - ret = gpio_pin_configure_dt(&config->reset, GPIO_OUTPUT_INACTIVE); - if (ret < 0) { - LOG_ERR("Could not configure reset GPIO (%d)", ret); - return ret; - } - } - gc9x01x_hw_reset(dev); gc9x01x_display_blanking_on(dev); @@ -573,8 +511,7 @@ static int gc9x01x_write(const struct device *dev, const uint16_t x, const uint1 struct gc9x01x_data *data = dev->data; int ret; const uint8_t *write_data_start = (const uint8_t *)buf; - struct spi_buf tx_buf; - struct spi_buf_set tx_bufs; + struct display_buffer_descriptor mipi_desc; uint16_t write_cnt; uint16_t nbr_of_writes; uint16_t write_h; @@ -592,26 +529,30 @@ static int gc9x01x_write(const struct device *dev, const uint16_t x, const uint1 if (desc->pitch > desc->width) { write_h = 1U; nbr_of_writes = desc->height; + mipi_desc.height = 1; + mipi_desc.buf_size = desc->pitch * data->bytes_per_pixel; } else { write_h = desc->height; + mipi_desc.height = desc->height; + mipi_desc.buf_size = desc->width * data->bytes_per_pixel * write_h; nbr_of_writes = 1U; } - ret = gc9x01x_transmit(dev, GC9X01X_CMD_MEMWR, write_data_start, - desc->width * data->bytes_per_pixel * write_h); + mipi_desc.width = desc->width; + /* Per MIPI API, pitch must always match width */ + mipi_desc.pitch = desc->width; + + ret = gc9x01x_transmit(dev, GC9X01X_CMD_MEMWR, NULL, 0); if (ret < 0) { return ret; } - tx_bufs.buffers = &tx_buf; - tx_bufs.count = 1U; - - write_data_start += desc->pitch * data->bytes_per_pixel; - for (write_cnt = 1U; write_cnt < nbr_of_writes; ++write_cnt) { - tx_buf.buf = (void *)write_data_start; - tx_buf.len = desc->width * data->bytes_per_pixel * write_h; - - ret = spi_write_dt(&config->spi, &tx_bufs); + for (write_cnt = 0U; write_cnt < nbr_of_writes; ++write_cnt) { + ret = mipi_dbi_write_display(config->mipi_dev, + &config->dbi_config, + write_data_start, + &mipi_desc, + data->pixel_format); if (ret < 0) { return ret; } @@ -679,9 +620,13 @@ static const struct display_driver_api gc9x01x_api = { #define GC9X01X_INIT(inst) \ GC9X01X_REGS_INIT(inst); \ static const struct gc9x01x_config gc9x01x_config_##inst = { \ - .spi = SPI_DT_SPEC_INST_GET(inst, SPI_OP_MODE_MASTER | SPI_WORD_SET(8), 0), \ - .cmd_data = GPIO_DT_SPEC_INST_GET(inst, cmd_data_gpios), \ - .reset = GPIO_DT_SPEC_INST_GET_OR(inst, reset_gpios, {0}), \ + .mipi_dev = DEVICE_DT_GET(DT_INST_PARENT(inst)), \ + .dbi_config = { \ + .mode = MIPI_DBI_MODE_SPI_4WIRE, \ + .config = MIPI_DBI_SPI_CONFIG_DT_INST(inst, \ + SPI_OP_MODE_MASTER | \ + SPI_WORD_SET(8), 0), \ + }, \ .pixel_format = DT_INST_PROP(inst, pixel_format), \ .orientation = DT_INST_ENUM_IDX(inst, orientation), \ .x_resolution = DT_INST_PROP(inst, width), \ diff --git a/dts/bindings/display/galaxycore,gc9x01x.yaml b/dts/bindings/display/galaxycore,gc9x01x.yaml index bc85c652b06..7867de55a0d 100644 --- a/dts/bindings/display/galaxycore,gc9x01x.yaml +++ b/dts/bindings/display/galaxycore,gc9x01x.yaml @@ -29,23 +29,9 @@ description: | compatible: "galaxycore,gc9x01x" -include: [spi-device.yaml, display-controller.yaml, lcd-controller.yaml] +include: [mipi-dbi-spi-device.yaml, display-controller.yaml, lcd-controller.yaml] properties: - reset-gpios: - type: phandle-array - description: | - RESET pin of the GC9X01X. - If connected directly the MCU pin should be configured - as active low. - - cmd-data-gpios: - type: phandle-array - required: true - description: | - Data/Command pin of the GC9X01X is to be configured - high(1) for data, low(0) for command. - orientation: type: string default: "normal" diff --git a/tests/drivers/build_all/display/app.overlay b/tests/drivers/build_all/display/app.overlay index a30348fcf0d..b17b02e8d7b 100644 --- a/tests/drivers/build_all/display/app.overlay +++ b/tests/drivers/build_all/display/app.overlay @@ -125,6 +125,16 @@ tcon = <0x22>; }; }; + + test_spi_gc9x01x: gc9x01x@6 { + compatible = "galaxycore,gc9x01x"; + reg = <6>; + mipi-max-frequency = <100000000>; + pixel-format = <16>; + + width = <240>; + height = <240>; + }; }; @@ -136,21 +146,12 @@ status = "okay"; clock-frequency = <2000000>; - /* one entry for every devices at spi.dtsi */ + /* one entry for every device. Note that this must + * include MIPI DBI devices as well. + */ cs-gpios = <&test_gpio 0 0 &test_gpio 0 1 &test_gpio 0 2 - &test_gpio 0 3 &test_gpio 0 4 &test_gpio 0 5>; - - test_spi_gc9x01x: gc9x01x@1 { - compatible = "galaxycore,gc9x01x"; - reg = <1>; - spi-max-frequency = <100000000>; - cmd-data-gpios = <&test_gpio 1 0>; - reset-gpios = <&test_gpio 2 0>; - pixel-format = <16>; - - width = <240>; - height = <240>; - }; + &test_gpio 0 3 &test_gpio 0 4 &test_gpio 0 5 + &test_gpio 0 6>; test_led_strip_0: lpd8806@2 { compatible = "greeled,lpd8806";