@ -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 ,