diff --git a/drivers/display/CMakeLists.txt b/drivers/display/CMakeLists.txt index b1b81d99e1764..7d55a548dac14 100644 --- a/drivers/display/CMakeLists.txt +++ b/drivers/display/CMakeLists.txt @@ -25,6 +25,7 @@ zephyr_library_sources_ifdef(CONFIG_SSD16XX ssd16xx.c) zephyr_library_sources_ifdef(CONFIG_SSD1322 ssd1322.c) zephyr_library_sources_ifdef(CONFIG_SSD1331 display_ssd1331.c) zephyr_library_sources_ifdef(CONFIG_SSD1351 display_ssd1351.c) +zephyr_library_sources_ifdef(CONFIG_ST730X display_st730x.c) zephyr_library_sources_ifdef(CONFIG_ST75256 display_st75256.c) zephyr_library_sources_ifdef(CONFIG_ST7567 display_st7567.c) zephyr_library_sources_ifdef(CONFIG_ST7789V display_st7789v.c) diff --git a/drivers/display/Kconfig b/drivers/display/Kconfig index 7e9ae5fa713d7..45c50727ca462 100644 --- a/drivers/display/Kconfig +++ b/drivers/display/Kconfig @@ -35,6 +35,7 @@ source "drivers/display/Kconfig.ssd1322" source "drivers/display/Kconfig.ssd1331" source "drivers/display/Kconfig.ssd1351" source "drivers/display/Kconfig.ssd1363" +source "drivers/display/Kconfig.st730x" source "drivers/display/Kconfig.st75256" source "drivers/display/Kconfig.st7567" source "drivers/display/Kconfig.st7735r" diff --git a/drivers/display/Kconfig.st730x b/drivers/display/Kconfig.st730x new file mode 100644 index 0000000000000..03879012e2363 --- /dev/null +++ b/drivers/display/Kconfig.st730x @@ -0,0 +1,26 @@ +# Copyright (c) 2025 MASSDRIVER EI (massdriver.space) +# SPDX-License-Identifier: Apache-2.0 + +config ST730X + bool "ST730x display driver" + default y + depends on DT_HAS_SITRONIX_ST7305_ENABLED || DT_HAS_SITRONIX_ST7306_ENABLED + select MIPI_DBI + help + Enable driver for ST730X series display controllers. + +if ST730X + +config ST730X_CONV_BUFFER_LINE_CNT + int "Size of the conversion buffer in lines" + default 8 + range 1 1024 + help + Size of the conversion buffer in lines. + +config ST730X_POWERMODE_LOW + bool "Use low power mode and not high power mode" + help + Enable this to use lower framerate LPM (Low Power Mode). + +endif # ST730X diff --git a/drivers/display/display_st730x.c b/drivers/display/display_st730x.c new file mode 100644 index 0000000000000..0337e5f5ca136 --- /dev/null +++ b/drivers/display/display_st730x.c @@ -0,0 +1,561 @@ +/* + * Copyright (c) 2025 MASSDRIVER EI (massdriver.space) + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +LOG_MODULE_REGISTER(st730x, CONFIG_DISPLAY_LOG_LEVEL); + +#include +#include +#include +#include +#include +#include +#include + +/* Registers */ +#define ST730X_SLEEP_IN 0x10 +#define ST730X_SLEEP_OUT 0x11 +#define ST730X_SET_NORMAL_DISPLAY 0x20 +#define ST730X_SET_REVERSE_DISPLAY 0x21 +#define ST730X_DISPLAY_OFF 0x28 +#define ST730X_DISPLAY_ON 0x29 +#define ST730X_SET_COLUMN_ADDR 0x2A +#define ST730X_SET_ROW_ADDR 0x2B +#define ST730X_WRITE 0x2C +#define ST730X_READ 0x2E +#define ST730X_TEARING_OUT 0x35 +#define ST730X_TEARING_OUT_VBLANK 0x00 +#define ST730X_TEARING_OUT_VHBLANK 0x01 +#define ST730X_MADCTL 0x36 +#define ST730X_HPM 0x38 +#define ST730X_LPM 0x39 +#define ST730X_DTFORM 0x3A +#define ST730X_DTFORM_4W_24B 0x10 +#define ST730X_DTFORM_3W_24B 0x11 +#define ST730X_GATESET 0xB0 +#define ST730X_FIRSTGATE 0xB1 +#define ST730X_FRAMERATE 0xB2 +#define ST730X_HPM_GATE_WAVEFORM 0xB3 +#define ST730X_LPM_GATE_WAVEFORM 0xB4 +#define ST730X_SOURCE_EQ_EN 0xB7 +#define ST730X_SOURCE_EQ_EN_ENABLE 0x13 +#define ST730X_SOURCE_EQ_EN_DISABLE 0x03 +#define ST730X_PNLSET 0xB8 +#define ST730X_GAMAMS 0xB9 +#define ST730X_CLEAR_RAM 0xBB +#define ST730X_CLEAR_RAM_ENABLE 0xCF +#define ST730X_CLEAR_RAM_DISABLE 0x4F +#define ST730X_GAMAMS_MONO 0x20 +#define ST730X_GAMAMS_4GS 0x00 +#define ST730X_GATE_VOLTAGE 0xC0 +#define ST730X_VSH 0xC1 +#define ST730X_VSL 0xC2 +#define ST730X_VSHN 0xC4 +#define ST730X_VSLN 0xC5 +#define ST730X_VSHLSEL 0xC9 +#define ST730X_AUTOPWRDOWN 0xD0 +#define ST730X_AUTOPWRDOWN_ON 0xFF +#define ST730X_AUTOPWRDOWN_OFF 0x7F +#define ST730X_BOOSTER_EN 0xD1 +#define ST730X_BOOSTER_EN_ENABLE 0x01 +#define ST730X_BOOSTER_EN_DISABLE 0x00 +#define ST730X_NVM_LOAD 0xD6 +#define ST730X_OSC_SETTINGS 0xD8 +#define ST730X_OSC_SETTINGS_BYTE2 0xE9 + +#define ST730X_RESET_DELAY 100 +#define ST730X_SLEEP_DELAY 100 + +#ifdef CONFIG_ST730X_POWERMODE_LOW +#define ST730X_POWER_MODE ST730X_LPM +#else +#define ST730X_POWER_MODE ST730X_HPM +#endif + +/* ST730x controllers have a evil data format + * where the pixels are ordered at each address as such: + * p1 p3 p5 p7 + * p2 p4 p6 p8 + */ + +struct st730x_specific { + uint8_t column_offset; +}; + +struct st730x_config { + const struct device *mipi_dev; + const struct mipi_dbi_config dbi_config; + const struct st730x_specific *specifics; + uint16_t height; + uint16_t width; + uint16_t start_line; + uint16_t start_column; + uint8_t nvm_load[2]; + uint8_t gate_voltages[2]; + uint8_t vsh[4]; + uint8_t vsl[4]; + uint8_t vshn[4]; + uint8_t vsln[4]; + uint8_t osc_settings; + uint8_t framerate; + uint8_t multiplex_ratio; + uint8_t source_voltage; + uint8_t remap_value; + uint8_t panel_settings; + uint8_t hpm_gate_waveform[10]; + uint8_t lpm_gate_waveform[8]; + bool color_inversion; + uint8_t *conversion_buf; + size_t conversion_buf_size; +}; + +static int st730x_resume(const struct device *dev) +{ + const struct st730x_config *config = dev->config; + int err; + + err = mipi_dbi_command_write(config->mipi_dev, &config->dbi_config, ST730X_SLEEP_OUT, + NULL, 0); + if (err < 0) { + return err; + } + k_msleep(ST730X_SLEEP_DELAY); + + /* Also enable display */ + err = mipi_dbi_command_write(config->mipi_dev, &config->dbi_config, ST730X_DISPLAY_ON, + NULL, 0); + if (err < 0) { + return err; + } + + return mipi_dbi_release(config->mipi_dev, &config->dbi_config); +} + +static int st730x_suspend(const struct device *dev) +{ + const struct st730x_config *config = dev->config; + int err; + + err = mipi_dbi_command_write(config->mipi_dev, &config->dbi_config, ST730X_SLEEP_IN, + NULL, 0); + if (err < 0) { + return err; + } + k_msleep(ST730X_SLEEP_DELAY); + + return mipi_dbi_release(config->mipi_dev, &config->dbi_config); +} + +static inline int st730x_set_hardware_config(const struct device *dev) +{ + const struct st730x_config *config = dev->config; + int err; + uint8_t tmp[2]; + + err = mipi_dbi_command_write(config->mipi_dev, &config->dbi_config, + ST730X_NVM_LOAD, config->nvm_load, 2); + if (err < 0) { + return err; + } + + tmp[0] = ST730X_BOOSTER_EN_ENABLE; + err = mipi_dbi_command_write(config->mipi_dev, &config->dbi_config, ST730X_BOOSTER_EN, tmp, + 1); + if (err < 0) { + return err; + } + + err = mipi_dbi_command_write(config->mipi_dev, &config->dbi_config, + ST730X_GATE_VOLTAGE, config->gate_voltages, 2); + if (err < 0) { + return err; + } + + err = mipi_dbi_command_write(config->mipi_dev, &config->dbi_config, + ST730X_VSH, config->vsh, 4); + if (err < 0) { + return err; + } + + err = mipi_dbi_command_write(config->mipi_dev, &config->dbi_config, + ST730X_VSL, config->vsl, 4); + if (err < 0) { + return err; + } + + err = mipi_dbi_command_write(config->mipi_dev, &config->dbi_config, + ST730X_VSHN, config->vshn, 4); + if (err < 0) { + return err; + } + + err = mipi_dbi_command_write(config->mipi_dev, &config->dbi_config, + ST730X_VSLN, config->vsln, 4); + if (err < 0) { + return err; + } + + tmp[0] = config->osc_settings; + tmp[1] = ST730X_OSC_SETTINGS_BYTE2; + err = mipi_dbi_command_write(config->mipi_dev, &config->dbi_config, + ST730X_OSC_SETTINGS, tmp, 2); + if (err < 0) { + return err; + } + + err = mipi_dbi_command_write(config->mipi_dev, &config->dbi_config, + ST730X_FRAMERATE, &config->framerate, 1); + if (err < 0) { + return err; + } + + err = mipi_dbi_command_write(config->mipi_dev, &config->dbi_config, + ST730X_HPM_GATE_WAVEFORM, config->hpm_gate_waveform, 10); + if (err < 0) { + return err; + } + + err = mipi_dbi_command_write(config->mipi_dev, &config->dbi_config, + ST730X_LPM_GATE_WAVEFORM, config->lpm_gate_waveform, 8); + if (err < 0) { + return err; + } + + tmp[0] = ST730X_SOURCE_EQ_EN_ENABLE; + err = mipi_dbi_command_write(config->mipi_dev, &config->dbi_config, + ST730X_SOURCE_EQ_EN, tmp, 1); + if (err < 0) { + return err; + } + + err = mipi_dbi_command_write(config->mipi_dev, &config->dbi_config, + ST730X_GATESET, &config->multiplex_ratio, 1); + if (err < 0) { + return err; + } + + err = mipi_dbi_command_write(config->mipi_dev, &config->dbi_config, + ST730X_VSHLSEL, &config->source_voltage, 1); + if (err < 0) { + return err; + } + + err = mipi_dbi_command_write(config->mipi_dev, &config->dbi_config, + ST730X_MADCTL, &config->remap_value, 1); + if (err < 0) { + return err; + } + + tmp[0] = ST730X_DTFORM_3W_24B; + err = mipi_dbi_command_write(config->mipi_dev, &config->dbi_config, + ST730X_DTFORM, tmp, 1); + if (err < 0) { + return err; + } + + tmp[0] = ST730X_GAMAMS_MONO; + err = mipi_dbi_command_write(config->mipi_dev, &config->dbi_config, + ST730X_GAMAMS, tmp, 1); + if (err < 0) { + return err; + } + + err = mipi_dbi_command_write(config->mipi_dev, &config->dbi_config, + ST730X_PNLSET, &config->panel_settings, 1); + if (err < 0) { + return err; + } + + tmp[0] = ST730X_TEARING_OUT_VBLANK; + err = mipi_dbi_command_write(config->mipi_dev, &config->dbi_config, + ST730X_TEARING_OUT, tmp, 1); + if (err < 0) { + return err; + } + + tmp[0] = ST730X_AUTOPWRDOWN_ON; + err = mipi_dbi_command_write(config->mipi_dev, &config->dbi_config, + ST730X_AUTOPWRDOWN, tmp, 1); + if (err < 0) { + return err; + } + + tmp[0] = (config->start_line & 0x100) >> 8; + tmp[1] = config->start_line & 0xFF; + err = mipi_dbi_command_write(config->mipi_dev, &config->dbi_config, + ST730X_FIRSTGATE, tmp, 2); + if (err < 0) { + return err; + } + + return mipi_dbi_command_write(config->mipi_dev, &config->dbi_config, + ST730X_POWER_MODE, NULL, 0); +} + +/* Convert what the conversion buffer can hold to the st730x format */ +static int st730x_convert(const struct device *dev, const uint8_t *buf, uint32_t offset, + const struct display_buffer_descriptor *desc) +{ + const struct st730x_config *config = dev->config; + uint32_t vertical_offset = desc->width / 8; + uint32_t i = 0; + uint32_t ipos, ipos_zeroed; + uint32_t max_lines = (config->conversion_buf_size / (desc->width / 8)) & ~0x1; + + if (max_lines < 2) { + LOG_ERR("Buffer too small, cannot convert"); + return -EINVAL; + } + + for (; (offset + i) < desc->height && i < max_lines; i += 2) { + ipos = (offset + i) * vertical_offset; + ipos_zeroed = i * vertical_offset / 2; + for (uint32_t j = 0; j < desc->width / 8 ; j++) { + config->conversion_buf[(ipos_zeroed + j) * 2 + 1] = + (buf[ipos + j + vertical_offset] & 0x80) >> 7 + | (buf[ipos + j] & 0x80) >> 6 + | (buf[ipos + j + vertical_offset] & 0x40) >> 4 + | (buf[ipos + j] & 0x40) >> 3 + | (buf[ipos + j + vertical_offset] & 0x20) >> 1 + | (buf[ipos + j] & 0x20) + | (buf[ipos + j + vertical_offset] & 0x10) << 2 + | (buf[ipos + j] & 0x10) << 3; + config->conversion_buf[(ipos_zeroed + j) * 2+0] = + (buf[ipos + j + vertical_offset] & 0x8) >> 3 + | (buf[ipos + j] & 0x8) >> 2 + | (buf[ipos + j + vertical_offset] & 0x4) + | (buf[ipos + j] & 0x4) << 1 + | (buf[ipos + j + vertical_offset] & 0x2) << 3 + | (buf[ipos + j] & 0x2) << 4 + | (buf[ipos + j + vertical_offset] & 0x1) << 6 + | (buf[ipos + j] & 0x1) << 7; + } + } + + return i; +} + +static int st730x_write(const struct device *dev, const uint16_t x, const uint16_t y, + const struct display_buffer_descriptor *desc, const void *buf) +{ + const struct st730x_config *config = dev->config; + int err; + size_t buf_len; + uint32_t processed = 0; + int i; + struct display_buffer_descriptor mipi_desc = *desc; + uint8_t x_start = config->specifics->column_offset + (config->start_column + x) / 12; + uint8_t x_end = config->specifics->column_offset + + (config->start_column + x + desc->width) / 12 - 1; + uint8_t x_position[] = {x_start, x_end}; + uint8_t y_position[] = {y / 2, (y + desc->height) / 2 - 1}; + + if (desc->pitch != desc->width) { + LOG_ERR("Pitch is not width"); + return -EINVAL; + } + + buf_len = MIN(desc->buf_size, desc->height * desc->width / 8); + if (buf == NULL || buf_len == 0U) { + LOG_ERR("Display buffer is not available"); + return -EINVAL; + } + + if (x % 12 || desc->width % 12) { + LOG_ERR("X coordinate and size must be aligned by 12 pixels"); + return -EINVAL; + } + + if (y % 2 || desc->height % 2) { + LOG_ERR("Y coordinate and size must be aligned by 2 pixels"); + return -EINVAL; + } + + LOG_DBG("x %u, y %u, pitch %u, width %u, height %u, buf_len %u", x, y, desc->pitch, + desc->width, desc->height, buf_len); + + err = mipi_dbi_command_write(config->mipi_dev, &config->dbi_config, ST730X_SET_COLUMN_ADDR, + x_position, 2); + if (err < 0) { + return err; + } + + err = mipi_dbi_command_write(config->mipi_dev, &config->dbi_config, ST730X_SET_ROW_ADDR, + y_position, 2); + if (err < 0) { + return err; + } + + err = mipi_dbi_command_write(config->mipi_dev, &config->dbi_config, ST730X_WRITE, NULL, 0); + if (err < 0) { + return err; + } + + while (desc->height > processed) { + i = st730x_convert(dev, buf, processed, desc); + + if (i < 0) { + return i; + } + + mipi_desc.buf_size = i * desc->width / 8; + mipi_desc.width = desc->width; + mipi_desc.height = i; + + err = mipi_dbi_write_display(config->mipi_dev, &config->dbi_config, + config->conversion_buf, &mipi_desc, + PIXEL_FORMAT_MONO01); + if (err < 0) { + return err; + } + processed += i; + } + + return mipi_dbi_release(config->mipi_dev, &config->dbi_config); +} + +static void st730x_get_capabilities(const struct device *dev, struct display_capabilities *caps) +{ + const struct st730x_config *config = dev->config; + + memset(caps, 0, sizeof(struct display_capabilities)); + caps->x_resolution = config->width; + caps->y_resolution = config->height; + caps->supported_pixel_formats = PIXEL_FORMAT_MONO01; + caps->current_pixel_format = PIXEL_FORMAT_MONO01; + caps->screen_info = 0; +} + +static int st730x_set_pixel_format(const struct device *dev, const enum display_pixel_format pf) +{ + if (pf == PIXEL_FORMAT_MONO01) { + return 0; + } + LOG_ERR("Unsupported pixel format"); + + return -ENOTSUP; +} + +static int st730x_init_device(const struct device *dev) +{ + const struct st730x_config *config = dev->config; + int err; + + err = st730x_suspend(dev); + if (err < 0) { + return err; + } + + err = st730x_set_hardware_config(dev); + if (err < 0) { + return err; + } + + err = mipi_dbi_command_write(config->mipi_dev, &config->dbi_config, + config->color_inversion ? ST730X_SET_REVERSE_DISPLAY + : ST730X_SET_NORMAL_DISPLAY, + NULL, 0); + if (err < 0) { + return err; + } + + err = st730x_resume(dev); + if (err < 0) { + return err; + } + + return mipi_dbi_release(config->mipi_dev, &config->dbi_config); +} + +static int st730x_init(const struct device *dev) +{ + const struct st730x_config *config = dev->config; + int err; + + LOG_DBG("Initializing device"); + + if (!device_is_ready(config->mipi_dev)) { + LOG_ERR("MIPI Device not ready!"); + return -EINVAL; + } + + err = mipi_dbi_reset(config->mipi_dev, ST730X_RESET_DELAY); + if (err < 0) { + LOG_ERR("Failed to reset device!"); + return err; + } + + err = st730x_init_device(dev); + if (err < 0) { + LOG_ERR("Failed to initialize device! %d", err); + return err; + } + + return 0; +} + +static DEVICE_API(display, st730x_driver_api) = { + .blanking_on = st730x_suspend, + .blanking_off = st730x_resume, + .write = st730x_write, + .get_capabilities = st730x_get_capabilities, + .set_pixel_format = st730x_set_pixel_format, +}; + +#if DT_HAS_COMPAT_STATUS_OKAY(sitronix_st7305) +static const struct st730x_specific st7305_specifics = { + .column_offset = 19, +}; +#endif + +#if DT_HAS_COMPAT_STATUS_OKAY(sitronix_st7306) +static const struct st730x_specific st7306_specifics = { + .column_offset = 0, +}; +#endif + +#define ST730X_WORD_SIZE(inst) \ + ((DT_STRING_UPPER_TOKEN(inst, mipi_mode) == MIPI_DBI_MODE_SPI_4WIRE) ? SPI_WORD_SET(8) \ + : SPI_WORD_SET(9)) + +#define ST730X_CONV_BUFFER_SIZE(node_id) \ + ROUND_UP(DT_PROP(node_id, width) * CONFIG_ST730X_CONV_BUFFER_LINE_CNT, \ + DT_PROP(node_id, width)) + +#define ST730X_DEFINE_MIPI(node_id, specifics_ptr) \ + static uint8_t conversion_buf##node_id[ST730X_CONV_BUFFER_SIZE(node_id)]; \ + static const struct st730x_config config##node_id = { \ + .mipi_dev = DEVICE_DT_GET(DT_PARENT(node_id)), \ + .dbi_config = MIPI_DBI_CONFIG_DT( \ + node_id, ST730X_WORD_SIZE(node_id) | SPI_OP_MODE_MASTER, 0), \ + .height = DT_PROP(node_id, height), \ + .width = DT_PROP(node_id, width), \ + .start_line = DT_PROP(node_id, start_line), \ + .start_column = DT_PROP(node_id, start_column), \ + .nvm_load = DT_PROP(node_id, nvm_load), \ + .gate_voltages = DT_PROP(node_id, gate_voltages), \ + .vsh = DT_PROP(node_id, vsh), \ + .vsl = DT_PROP(node_id, vsl), \ + .vshn = DT_PROP(node_id, vshn), \ + .vsln = DT_PROP(node_id, vsln), \ + .osc_settings = DT_PROP(node_id, osc_settings), \ + .framerate = DT_PROP(node_id, framerate), \ + .multiplex_ratio = DT_PROP(node_id, multiplex_ratio), \ + .source_voltage = DT_PROP(node_id, source_voltage), \ + .remap_value = DT_PROP(node_id, remap_value), \ + .panel_settings = DT_PROP(node_id, panel_settings), \ + .hpm_gate_waveform = DT_PROP(node_id, hpm_gate_waveform), \ + .lpm_gate_waveform = DT_PROP(node_id, lpm_gate_waveform), \ + .color_inversion = DT_PROP(node_id, inversion_on), \ + .specifics = specifics_ptr, \ + .conversion_buf = conversion_buf##node_id, \ + .conversion_buf_size = sizeof(conversion_buf##node_id), \ + }; \ + DEVICE_DT_DEFINE(node_id, st730x_init, NULL, NULL, &config##node_id, \ + POST_KERNEL, CONFIG_DISPLAY_INIT_PRIORITY, &st730x_driver_api); + +DT_FOREACH_STATUS_OKAY_VARGS(sitronix_st7305, ST730X_DEFINE_MIPI, &st7305_specifics) +DT_FOREACH_STATUS_OKAY_VARGS(sitronix_st7306, ST730X_DEFINE_MIPI, &st7306_specifics) diff --git a/dts/bindings/display/sitronix,st7305.yaml b/dts/bindings/display/sitronix,st7305.yaml new file mode 100644 index 0000000000000..562c7a650db80 --- /dev/null +++ b/dts/bindings/display/sitronix,st7305.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2025 MASSDRIVER EI (massdriver.space) +# SPDX-License-Identifier: Apache-2.0 + +description: Sitronix ST7305 Monochrome 264x320 display controller + +compatible: "sitronix,st7305" + +include: sitronix,st730x-common.yaml diff --git a/dts/bindings/display/sitronix,st7306.yaml b/dts/bindings/display/sitronix,st7306.yaml new file mode 100644 index 0000000000000..4d45265b894b9 --- /dev/null +++ b/dts/bindings/display/sitronix,st7306.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2025 MASSDRIVER EI (massdriver.space) +# SPDX-License-Identifier: Apache-2.0 + +description: Sitronix ST7306 multi-mode 720x480(Monochrome) display controller + +compatible: "sitronix,st7306" + +include: sitronix,st730x-common.yaml diff --git a/dts/bindings/display/sitronix,st730x-common.yaml b/dts/bindings/display/sitronix,st730x-common.yaml new file mode 100644 index 0000000000000..8c2582952b5b9 --- /dev/null +++ b/dts/bindings/display/sitronix,st730x-common.yaml @@ -0,0 +1,133 @@ +# Copyright (c) 2025 MASSDRIVER EI (massdriver.space) +# SPDX-License-Identifier: Apache-2.0 + +title: Sitronix ST730x display controllers common properties + +description: | + The ST730x display controllers are mostly monochrome low power LCD controllers. + These displays have extreme clarity and contrast, and refresh rate up to 51 Hz. + They use a unusual data format that requires conversion from standard ones, and + necessitate rounding X axis values to 12, including width which sometimes need + to be rounded to the next multiple of 12 to fill the display. + +include: [mipi-dbi-spi-device.yaml, display-controller.yaml] + +properties: + start-line: + type: int + required: true + description: Start line (first gate) of display RAM to be displayed. + + start-column: + type: int + required: true + description: Start column of display RAM to be displayed. Must be multiple of 12. + + nvm-load: + type: uint8-array + required: true + description: NVM Load settings, 2 bytes. + + gate-voltages: + type: uint8-array + required: true + description: Gate Voltages, 5 bits each, 2 bytes. + + vsh: + type: uint8-array + required: true + description: High positive voltage in different modes. 4 bytes. + On LCDs the high and low voltages affect contrast. + + vsl: + type: uint8-array + required: true + description: Low positive voltage in different modes. 4 bytes. + On LCDs the high and low voltages affect contrast. + + vshn: + type: uint8-array + required: true + description: High negative voltage in different modes. 4 bytes. + On LCDs the high and low voltages affect contrast. + + vsln: + type: uint8-array + required: true + description: Low negative voltage in different modes. 4 bytes. + On LCDs the high and low voltages affect contrast. + + osc-settings: + type: int + required: true + description: | + Oscillator settings, 1 byte such as: + - [7]: enabled or disabled + - [5][2-1]: Max framerate: 000 = 51Hz, 111 = 32Hz + - [6][4-3][0]: 0 + + framerate: + type: int + required: true + description: | + Framerate settings, 1 byte such as: + - [4]: High power mode framerate, max framerate is 000, 0=25.5Hz, 1=51Hz, else 0=16Hz, 1=32Hz. + - [2-0]: Low power mode framerate, 0:0.25Hz, 1:0.5Hz, 2:1Hz, 3:2hz, 4:4Hz, 5:8Hz. + + multiplex-ratio: + type: int + required: true + description: Specify how many gate lines the display uses times 4, so typically y-size / 4; + + source-voltage: + type: int + required: true + description: | + Source voltage selection [1-0]: + - 00: VSHPA1/ VSLPA1/ VSHNA1/ VSLNA1 + - 01: VSHPA2/ VSLPA2/ VSHNA2/ VSLNA2 + - 10: VSHPA3/ VSLPA3/ VSHNA3/ VSLNA3 + - 11: VSHPA4/ VSLPA4/ VSHNA4/ VSLNA4 + + remap-value: + type: int + required: true + description: | + Remap memory data access and so flip the display: + - [7]: Page address order flip + - [6]: Column address order flip + - [5]: Page/Column order flip + - [3]: Data output order flip + - [2]: Gate scan order flip + + panel-settings: + type: int + required: true + description: | + Set panel and gate layout: + - [7][4]: 0 + - [6-5]: Column dot inversion: 00: Column inversion, 01: 1-Dot inversion, 10: 2-Dot inversion + - [3-2]: Gate scan mode: 00: 2 line interval, 01: 1 line interval, 10: frame interval + - [1-0]: Panel layout: 00: 2 line interlace, 01: 1 line interlace, 10: no interlacing + + hpm-gate-waveform: + type: uint8-array + default: [0xE5, 0xF6, 0x05, 0x46, 0x77, 0x77, 0x77, 0x77, 0x76, 0x45] + description: | + Waveform used to drive LCD in high power mode. 10 bytes total: + - 1 byte: 0xA5 (disable) or 0xE5 (enable), tells if waveform is enabled or disabled + - 1 byte: 0xF6 + - 8 bytes: [7][3]: 0, [6-4]: GPCHPUx, [2-0]: GPCHPUx+1. Please See datasheet. + The default is the default values of the controller. + + lpm-gate-waveform: + type: uint8-array + default: [0x05, 0x46, 0x77, 0x77, 0x77, 0x77, 0x76, 0x45] + description: | + Waveform used to drive LCD in low power mode. 8 bytes total: + - 8 bytes: [7][3]: 0, [6-4]: GPCLPUx, [2-0]: GPCLPUx+1. Please See datasheet. + The default is the default values of the controller. + + inversion-on: + type: boolean + description: Turn on display color inverting diff --git a/tests/drivers/build_all/display/app.overlay b/tests/drivers/build_all/display/app.overlay index 99de4a9a12c30..21c0e850c68b5 100644 --- a/tests/drivers/build_all/display/app.overlay +++ b/tests/drivers/build_all/display/app.overlay @@ -273,6 +273,52 @@ phase-length = <0x0>; mipi-mode = "MIPI_DBI_MODE_SPI_4WIRE"; }; + + test_mipi_dbi_st7305: st7305@16 { + compatible = "sitronix,st7305"; + mipi-max-frequency = <10000000>; + reg = <16>; + width = <168>; + height = <384>; + start-line = <0>; + start-column = <48>; + nvm-load = [17 02]; + gate-voltages = [11 04]; + vsh = [41 41 41 41]; + vsl = [19 19 19 19]; + vshn = [41 41 41 41]; + vsln = [19 19 19 19]; + osc-settings = <0xA6>; + framerate = <0x5>; + multiplex-ratio = <0x64>; + source-voltage = <0x0>; + remap-value = <0x40>; + panel-settings = <0x29>; + mipi-mode = "MIPI_DBI_MODE_SPI_4WIRE"; + }; + + test_mipi_dbi_st7306: st7306@17 { + compatible = "sitronix,st7306"; + mipi-max-frequency = <10000000>; + reg = <17>; + width = <312>; + height = <400>; + start-line = <0>; + start-column = <216>; + nvm-load = [17 02]; + gate-voltages = [11 04]; + vsh = [41 41 41 41]; + vsl = [19 19 19 19]; + vshn = [41 41 41 41]; + vsln = [19 19 19 19]; + osc-settings = <0x80>; + framerate = <0x05>; + multiplex-ratio = <0x64>; + source-voltage = <0x0>; + remap-value = <0x4>; + panel-settings = <0x29>; + mipi-mode = "MIPI_DBI_MODE_SPI_4WIRE"; + }; }; test_mipi_dbi_xfr_16bit_write_only {