Browse Source

drivers: display: ili9xxx: support display_read API

Add support for display_read API with ili9xxx controller. This
functionality is opt-in, since the required bitshifting makes the
read not very performant, and the implementation adds otherwise unused
code overhead.

Signed-off-by: Daniel DeGrasse <daniel.degrasse@nxp.com>
pull/72985/head
Daniel DeGrasse 1 year ago committed by Henrik Brix Andersen
parent
commit
f59156356d
  1. 9
      drivers/display/Kconfig.ili9xxx
  2. 138
      drivers/display/display_ili9xxx.c
  3. 3
      drivers/display/display_ili9xxx.h

9
drivers/display/Kconfig.ili9xxx

@ -10,6 +10,15 @@ config ILI9XXX @@ -10,6 +10,15 @@ config ILI9XXX
help
Hidden configuration entry for all ILI9XXX drivers.
config ILI9XXX_READ
bool "Allow display_read API with ILI9XXX"
help
Support display_read API with ILI9XXX controllers. This API is opt-in,
because it adds code overhead and is not very performant due to
the requirement to bitshift data read from the ILI9XXX. Note the
API only supports RGB565 mode.
config ILI9340
bool "ILI9340 display driver"
default y

138
drivers/display/display_ili9xxx.c

@ -21,6 +21,49 @@ struct ili9xxx_data { @@ -21,6 +21,49 @@ struct ili9xxx_data {
enum display_orientation orientation;
};
#ifdef CONFIG_ILI9XXX_READ
/* We set this LUT directly when reads are enabled,
* so that we can be sure the bitshift to convert GRAM data back
* to RGB565 will result in correct data
*/
const uint8_t ili9xxx_rgb_lut[] = {
0, 2, 4, 6,
8, 10, 12, 14,
16, 18, 20, 22,
24, 26, 28, 30,
32, 34, 36, 38,
40, 42, 44, 46,
48, 50, 52, 54,
56, 58, 60, 62,
0, 1, 2, 3,
4, 5, 6, 7,
8, 9, 10, 11,
12, 13, 14, 15,
16, 17, 18, 19,
20, 21, 22, 23,
24, 25, 26, 27,
28, 29, 30, 31,
32, 33, 34, 35,
36, 37, 38, 39,
40, 41, 42, 43,
44, 45, 46, 47,
48, 49, 50, 51,
52, 53, 54, 55,
56, 57, 58, 59,
60, 61, 62, 63,
0, 2, 4, 6,
8, 10, 12, 14,
16, 18, 20, 22,
24, 26, 28, 30,
32, 34, 36, 38,
40, 42, 44, 46,
48, 50, 52, 54,
56, 58, 60, 62
};
#endif
int ili9xxx_transmit(const struct device *dev, uint8_t cmd, const void *tx_data,
size_t tx_len)
{
@ -142,6 +185,93 @@ static int ili9xxx_write(const struct device *dev, const uint16_t x, @@ -142,6 +185,93 @@ static int ili9xxx_write(const struct device *dev, const uint16_t x,
return 0;
}
#ifdef CONFIG_ILI9XXX_READ
static int ili9xxx_read(const struct device *dev, const uint16_t x,
const uint16_t y,
const struct display_buffer_descriptor *desc, void *buf)
{
const struct ili9xxx_config *config = dev->config;
struct ili9xxx_data *data = dev->data;
struct display_buffer_descriptor mipi_desc;
int r;
uint32_t gram_data, nbr_of_reads;
uint16_t *read_data_start = (uint16_t *)buf;
if (data->pixel_format != PIXEL_FORMAT_RGB_565) {
/* Only RGB565 can be supported, see note below */
return -ENOTSUP;
}
__ASSERT(desc->width <= desc->pitch, "Pitch is smaller than width");
__ASSERT((desc->pitch * data->bytes_per_pixel * desc->height) <=
desc->buf_size,
"Output buffer to small");
LOG_DBG("Reading %dx%d (w,h) @ %dx%d (x,y)", desc->width, desc->height,
x, y);
r = ili9xxx_set_mem_area(dev, x, y, desc->width, desc->height);
if (r < 0) {
return r;
}
/*
* ILI9XXX stores all pixel data in graphics ram (GRAM) as 18 bit
* values. When using RGB565 pixel format, pixels are converted to
* 18 bit values via a lookup table. When using RGB888 format, the
* lower 2 bits of each pixel are simply dropped. When reading pixels,
* the response format will always look like so:
* | R[5:0] | x | x | G[5:0] | x | x | B[5:0] | x | x |
* Where x represents "don't care". The internal format of the
* ILI9XXX graphics RAM results in the following restrictions:
* - RGB888 mode can't be supported.
* - we can only read one pixel at once (since we need to do
* byte manipulation on the output)
*/
/* Setup MIPI descriptor to read 3 bytes (one pixel in GRAM) */
mipi_desc.width = 1;
mipi_desc.height = 1;
/* Per MIPI API, pitch must always match width */
mipi_desc.pitch = 1;
nbr_of_reads = desc->width * desc->height;
/* Initial read command should consist of RAMRD command, plus
* 8 dummy clock cycles
*/
uint8_t cmd[] = {ILI9XXX_RAMRD, 0xFF};
for (uint32_t read_cnt = 0; read_cnt < nbr_of_reads; read_cnt++) {
r = mipi_dbi_command_read(config->mipi_dev,
&config->dbi_config,
cmd, sizeof(cmd),
(uint8_t *)&gram_data, 3);
if (r < 0) {
return r;
}
/* Bitshift the graphics RAM data to RGB565.
* For more details on the formatting of this data,
* see "Read data through 4-line SPI mode" diagram
* on page 64 of datasheet.
*/
read_data_start[read_cnt] =
((gram_data & 0xF80000) >> 11) | /* Blue */
((gram_data & 0x1C00) << 3) | /* Green */
((gram_data & 0xE000) >> 13) | /* Green */
(gram_data & 0xF8); /* Red */
/* After first read, we should use read memory continue command */
cmd[0] = ILI9XXX_RAMRD_CONT;
}
return 0;
}
#endif
static int ili9xxx_display_blanking_off(const struct device *dev)
{
LOG_DBG("Turning display blanking off");
@ -321,6 +451,11 @@ static int ili9xxx_init(const struct device *dev) @@ -321,6 +451,11 @@ static int ili9xxx_init(const struct device *dev)
return r;
}
#ifdef CONFIG_ILI9XXX_READ
/* Set RGB LUT table to enable display read API */
ili9xxx_transmit(dev, ILI9XXX_RGBSET, ili9xxx_rgb_lut, sizeof(ili9xxx_rgb_lut));
#endif
k_sleep(K_MSEC(ILI9XXX_RESET_WAIT_TIME));
ili9xxx_display_blanking_on(dev);
@ -344,6 +479,9 @@ static const struct display_driver_api ili9xxx_api = { @@ -344,6 +479,9 @@ static const struct display_driver_api ili9xxx_api = {
.blanking_on = ili9xxx_display_blanking_on,
.blanking_off = ili9xxx_display_blanking_off,
.write = ili9xxx_write,
#ifdef CONFIG_ILI9XXX_READ
.read = ili9xxx_read,
#endif
.get_capabilities = ili9xxx_get_capabilities,
.set_pixel_format = ili9xxx_set_pixel_format,
.set_orientation = ili9xxx_set_orientation,

3
drivers/display/display_ili9xxx.h

@ -22,8 +22,11 @@ @@ -22,8 +22,11 @@
#define ILI9XXX_CASET 0x2a
#define ILI9XXX_PASET 0x2b
#define ILI9XXX_RAMWR 0x2c
#define ILI9XXX_RGBSET 0x2d
#define ILI9XXX_RAMRD 0x2e
#define ILI9XXX_MADCTL 0x36
#define ILI9XXX_PIXSET 0x3A
#define ILI9XXX_RAMRD_CONT 0x3e
/* MADCTL register fields. */
#define ILI9XXX_MADCTL_MY BIT(7U)

Loading…
Cancel
Save