drivers: display: st7796: Update the logic to invert RGB and BGR

1. Add a property for panels where the RGB is displayed as BGR.
2. Add a check for 8080 8-bit mode and invert RGB and BGR for
   this case.

Signed-off-by: Mahesh Mahadevan <mahesh.mahadevan@nxp.com>
This commit is contained in:
Mahesh Mahadevan 2024-05-09 13:03:22 -05:00 committed by Anas Nashif
parent 6236779d32
commit 3dd5ffe20a
2 changed files with 60 additions and 12 deletions

View file

@ -46,6 +46,7 @@ struct st7796s_config {
uint8_t pgc[14]; /* Positive gamma control */
uint8_t ngc[14]; /* Negative gamma control */
uint8_t madctl; /* Memory data access control */
bool rgb_is_inverted;
};
static int st7796s_send_cmd(const struct device *dev,
@ -92,6 +93,52 @@ static int st7796s_blanking_off(const struct device *dev)
return st7796s_send_cmd(dev, ST7796S_CMD_DISPON, NULL, 0);
}
static int st7796s_get_pixelfmt(const struct device *dev)
{
const struct st7796s_config *config = dev->config;
/*
* Invert the pixel format for 8-bit 8080 Parallel Interface.
*
* Zephyr uses big endian byte order when the pixel format has
* multiple bytes.
*
* For RGB565, Red is placed in byte 1 and Blue in byte 0.
* For BGR565, Red is placed in byte 0 and Blue in byte 1.
*
* This is not an issue when using a 16-bit interface.
* For RGB565, this would map to Red being in D[11:15] and
* Blue in D[0:4] and vice versa for BGR565.
*
* However this is an issue when using a 8-bit interface.
* For RGB565, Blue is placed in byte 0 as mentioned earlier.
* However the controller expects Red to be in D[3:7] of byte 0.
*
* Hence we report pixel format as RGB when MADCTL setting is BGR
* and vice versa.
*/
if (config->dbi_config.mode == MIPI_DBI_MODE_8080_BUS_8_BIT) {
if (config->madctl & ST7796S_MADCTL_BGR) {
return PIXEL_FORMAT_RGB_565;
} else {
return PIXEL_FORMAT_BGR_565;
}
}
/*
* Invert the pixel format if rgb_is_inverted is enabled.
* Report pixel format as the same format set in the MADCTL
* if rgb_is_inverted is disabled.
* Report pixel format as RGB if MADCTL setting is BGR and vice versa
* if rgb_is_inverted is enabled.
* It is a workaround for supporting buggy modules that display RGB as BGR.
*/
if (!(config->madctl & ST7796S_MADCTL_BGR) != !config->rgb_is_inverted) {
return PIXEL_FORMAT_BGR_565;
} else {
return PIXEL_FORMAT_RGB_565;
}
}
static int st7796s_write(const struct device *dev,
const uint16_t x,
@ -118,12 +165,7 @@ static int st7796s_write(const struct device *dev,
return ret;
}
if (config->madctl & ST7796S_MADCTL_BGR) {
/* Zephyr treats RGB565 as BGR565 */
pixfmt = PIXEL_FORMAT_RGB_565;
} else {
pixfmt = PIXEL_FORMAT_BGR_565;
}
pixfmt = st7796s_get_pixelfmt(dev);
return mipi_dbi_write_display(config->mipi_dbi,
&config->dbi_config, buf,
@ -137,12 +179,8 @@ static void st7796s_get_capabilities(const struct device *dev,
memset(capabilities, 0, sizeof(struct display_capabilities));
if (config->madctl & ST7796S_MADCTL_BGR) {
/* Zephyr treats RGB565 as BGR565 */
capabilities->current_pixel_format = PIXEL_FORMAT_RGB_565;
} else {
capabilities->current_pixel_format = PIXEL_FORMAT_BGR_565;
}
capabilities->current_pixel_format = st7796s_get_pixelfmt(dev);
capabilities->x_resolution = config->width;
capabilities->y_resolution = config->height;
capabilities->current_orientation = DISPLAY_ORIENTATION_NORMAL;
@ -339,6 +377,7 @@ static const struct display_driver_api st7796s_api = {
.pgc = DT_INST_PROP(n, pgc), \
.ngc = DT_INST_PROP(n, ngc), \
.madctl = DT_INST_PROP(n, madctl), \
.rgb_is_inverted = DT_INST_PROP(n, rgb_is_inverted), \
}; \
\
DEVICE_DT_INST_DEFINE(n, st7796s_init, \

View file

@ -104,3 +104,12 @@ properties:
- "2-dot"
description: |
Display inversion control mode.
rgb-is-inverted:
type: boolean
description: |
Inverting color format order (RGB->BGR or BGR->RGB)
In the case of enabling this option, API reports pixel-format in capabilities
as the inverted value of the RGB pixel-format specified in MADCTL.
This option is convenient for supporting displays with bugs
where the actual color is different from the pixel format of MADCTL.