Skip to content

Commit 080f26f

Browse files
ngphibangfabiobaltieri
authored andcommitted
drivers: display: elcdif: Implement set_format API
Implement the set_format API so that applications can change format at runtime instead of using the predefined one in the device tree. Signed-off-by: Phi Bang Nguyen <[email protected]>
1 parent f5e970d commit 080f26f

File tree

2 files changed

+70
-51
lines changed

2 files changed

+70
-51
lines changed

drivers/display/Kconfig.mcux_elcdif

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,16 @@ config MCUX_ELCDIF_FB_NUM
3232
implications of this concern you, leave at least one driver
3333
framebuffer enabled.
3434

35+
config MCUX_ELCDIF_FB_SIZE
36+
int "Framebuffer size required by the eLCDIF driver"
37+
default 3686400
38+
help
39+
eLCDIF driver allocates framebuffers to support partial display updates.
40+
The framebuffer size is computed as : panel_width * panel_height * bpp.
41+
The default value is set to afford for a default resolution of 1280x720 and
42+
4-bytes pixel format, e.g. ARGB8888. Applications should change this value
43+
according to the actual used resolution and format to optimize the heap size.
44+
3545
config MCUX_ELCDIF_PXP
3646
bool "Use PXP for display rotation"
3747
depends on MCUX_PXP

drivers/display/display_mcux_elcdif.c

Lines changed: 60 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -27,18 +27,17 @@
2727

2828
LOG_MODULE_REGISTER(display_mcux_elcdif, CONFIG_DISPLAY_LOG_LEVEL);
2929

30+
/* Define the heap size. 512 bytes of padding are included for kernel heap structures */
31+
K_HEAP_DEFINE(display_heap, CONFIG_MCUX_ELCDIF_FB_NUM * CONFIG_MCUX_ELCDIF_FB_SIZE + 512);
32+
3033
static const uint32_t supported_fmts = PIXEL_FORMAT_BGR_565 | PIXEL_FORMAT_ARGB_8888;
3134

3235
struct mcux_elcdif_config {
3336
LCDIF_Type *base;
3437
void (*irq_config_func)(const struct device *dev);
3538
elcdif_rgb_mode_config_t rgb_mode;
36-
enum display_pixel_format pixel_format;
37-
size_t pixel_bytes;
38-
size_t fb_bytes;
3939
const struct pinctrl_dev_config *pincfg;
4040
const struct gpio_dt_spec backlight_gpio;
41-
uint8_t *fb_ptr;
4241
const struct device *pxp;
4342
};
4443

@@ -47,6 +46,10 @@ struct mcux_elcdif_data {
4746
const uint8_t *active_fb;
4847
/* Pointers to driver allocated framebuffers */
4948
uint8_t *fb[CONFIG_MCUX_ELCDIF_FB_NUM];
49+
enum display_pixel_format pixel_format;
50+
size_t pixel_bytes;
51+
size_t fb_bytes;
52+
elcdif_rgb_mode_config_t rgb_mode;
5053
struct k_sem sem;
5154
/* Tracks index of next active driver framebuffer */
5255
uint8_t next_idx;
@@ -77,7 +80,7 @@ static int mcux_elcdif_write(const struct device *dev, const uint16_t x, const u
7780
int ret = 0;
7881
bool full_fb = false;
7982

80-
__ASSERT((config->pixel_bytes * desc->pitch * desc->height) <= desc->buf_size,
83+
__ASSERT((dev_data->pixel_bytes * desc->pitch * desc->height) <= desc->buf_size,
8184
"Input buffer too small");
8285

8386
LOG_DBG("W=%d, H=%d, @%d,%d", desc->width, desc->height, x, y);
@@ -110,17 +113,17 @@ static int mcux_elcdif_write(const struct device *dev, const uint16_t x, const u
110113
*/
111114
src = dev_data->active_fb;
112115
dst = dev_data->fb[dev_data->next_idx];
113-
memcpy(dst, src, config->fb_bytes);
116+
memcpy(dst, src, dev_data->fb_bytes);
114117
}
115118
/* Now, write the display update into active framebuffer */
116119
src = buf;
117120
dst = dev_data->fb[dev_data->next_idx];
118-
dst += config->pixel_bytes * (y * config->rgb_mode.panelWidth + x);
121+
dst += dev_data->pixel_bytes * (y * config->rgb_mode.panelWidth + x);
119122

120123
for (h_idx = 0; h_idx < desc->height; h_idx++) {
121-
memcpy(dst, src, config->pixel_bytes * desc->width);
122-
src += config->pixel_bytes * desc->pitch;
123-
dst += config->pixel_bytes * config->rgb_mode.panelWidth;
124+
memcpy(dst, src, dev_data->pixel_bytes * desc->width);
125+
src += dev_data->pixel_bytes * desc->pitch;
126+
dst += dev_data->pixel_bytes * config->rgb_mode.panelWidth;
124127
}
125128

126129
LOG_DBG("Setting FB from %p->%p", (void *)dev_data->active_fb,
@@ -130,7 +133,7 @@ static int mcux_elcdif_write(const struct device *dev, const uint16_t x, const u
130133
}
131134

132135
#ifdef CONFIG_HAS_MCUX_CACHE
133-
DCACHE_CleanByRange((uint32_t)dev_data->active_fb, config->fb_bytes);
136+
DCACHE_CleanByRange((uint32_t)dev_data->active_fb, dev_data->fb_bytes);
134137
#endif
135138

136139
#ifdef CONFIG_MCUX_ELCDIF_PXP
@@ -148,11 +151,11 @@ static int mcux_elcdif_write(const struct device *dev, const uint16_t x, const u
148151
pxp_block.block_size = desc->buf_size;
149152

150153
/* DMA slot sets pixel format and rotation angle */
151-
if (config->pixel_format == PIXEL_FORMAT_BGR_565) {
154+
if (dev_data->pixel_format == PIXEL_FORMAT_BGR_565) {
152155
pxp_dma.dma_slot = DMA_MCUX_PXP_FMT(DMA_MCUX_PXP_FMT_RGB565);
153-
} else if (config->pixel_format == PIXEL_FORMAT_RGB_888) {
156+
} else if (dev_data->pixel_format == PIXEL_FORMAT_RGB_888) {
154157
pxp_dma.dma_slot = DMA_MCUX_PXP_FMT(DMA_MCUX_PXP_FMT_RGB888);
155-
} else if (config->pixel_format == PIXEL_FORMAT_ARGB_8888) {
158+
} else if (dev_data->pixel_format == PIXEL_FORMAT_ARGB_8888) {
156159
pxp_dma.dma_slot = DMA_MCUX_PXP_FMT(DMA_MCUX_PXP_FMT_ARGB8888);
157160
} else {
158161
/* Cannot rotate */
@@ -169,8 +172,8 @@ static int mcux_elcdif_write(const struct device *dev, const uint16_t x, const u
169172
}
170173

171174
pxp_dma.channel_direction = MEMORY_TO_MEMORY;
172-
pxp_dma.source_data_size = desc->width * config->pixel_bytes;
173-
pxp_dma.dest_data_size = config->rgb_mode.panelWidth * config->pixel_bytes;
175+
pxp_dma.source_data_size = desc->width * dev_data->pixel_bytes;
176+
pxp_dma.dest_data_size = config->rgb_mode.panelWidth * dev_data->pixel_bytes;
174177
/* Burst lengths are heights of source/dest buffer in pixels */
175178
pxp_dma.source_burst_length = desc->height;
176179
pxp_dma.dest_burst_length = config->rgb_mode.panelHeight;
@@ -221,13 +224,42 @@ static int mcux_elcdif_display_blanking_on(const struct device *dev)
221224
static int mcux_elcdif_set_pixel_format(const struct device *dev,
222225
const enum display_pixel_format pixel_format)
223226
{
227+
struct mcux_elcdif_data *dev_data = dev->data;
224228
const struct mcux_elcdif_config *config = dev->config;
225229

226-
if (pixel_format == config->pixel_format) {
227-
return 0;
230+
if (!(pixel_format & supported_fmts)) {
231+
LOG_ERR("Unsupported pixel format");
232+
return -ENOTSUP;
228233
}
229-
LOG_ERR("Pixel format change not implemented");
230-
return -ENOTSUP;
234+
235+
dev_data->pixel_format = pixel_format;
236+
dev_data->pixel_bytes = DISPLAY_BITS_PER_PIXEL(pixel_format) / 8;
237+
dev_data->fb_bytes =
238+
config->rgb_mode.panelWidth * config->rgb_mode.panelHeight * dev_data->pixel_bytes;
239+
240+
for (int i = 0; i < CONFIG_MCUX_ELCDIF_FB_NUM; i++) {
241+
k_heap_free(&display_heap, dev_data->fb[i]);
242+
dev_data->fb[i] =
243+
k_heap_aligned_alloc(&display_heap, 64, dev_data->fb_bytes, K_FOREVER);
244+
if (dev_data->fb[i] == NULL) {
245+
LOG_ERR("Could not allocate memory for framebuffers");
246+
return -ENOMEM;
247+
}
248+
memset(dev_data->fb[i], 0, dev_data->fb_bytes);
249+
}
250+
251+
dev_data->rgb_mode = config->rgb_mode;
252+
if (pixel_format == PIXEL_FORMAT_BGR_565) {
253+
dev_data->rgb_mode.pixelFormat = kELCDIF_PixelFormatRGB565;
254+
} else if (pixel_format == PIXEL_FORMAT_RGB_888) {
255+
dev_data->rgb_mode.pixelFormat = kELCDIF_PixelFormatRGB888;
256+
} else if (pixel_format == PIXEL_FORMAT_ARGB_8888) {
257+
dev_data->rgb_mode.pixelFormat = kELCDIF_PixelFormatXRGB8888;
258+
}
259+
260+
ELCDIF_RgbModeSetPixelFormat(config->base, dev_data->rgb_mode.pixelFormat);
261+
262+
return 0;
231263
}
232264

233265
static int mcux_elcdif_set_orientation(const struct device *dev,
@@ -249,7 +281,7 @@ static void mcux_elcdif_get_capabilities(const struct device *dev,
249281
capabilities->x_resolution = config->rgb_mode.panelWidth;
250282
capabilities->y_resolution = config->rgb_mode.panelHeight;
251283
capabilities->supported_pixel_formats = supported_fmts;
252-
capabilities->current_pixel_format = config->pixel_format;
284+
capabilities->current_pixel_format = ((struct mcux_elcdif_data *)dev->data)->pixel_format;
253285
capabilities->current_orientation = DISPLAY_ORIENTATION_NORMAL;
254286
}
255287

@@ -286,25 +318,6 @@ static int mcux_elcdif_init(const struct device *dev)
286318
return err;
287319
}
288320

289-
elcdif_rgb_mode_config_t rgb_mode = config->rgb_mode;
290-
291-
/* Set the Pixel format */
292-
if (config->pixel_format == PIXEL_FORMAT_BGR_565) {
293-
rgb_mode.pixelFormat = kELCDIF_PixelFormatRGB565;
294-
} else if (config->pixel_format == PIXEL_FORMAT_RGB_888) {
295-
rgb_mode.pixelFormat = kELCDIF_PixelFormatRGB888;
296-
} else if (config->pixel_format == PIXEL_FORMAT_ARGB_8888) {
297-
rgb_mode.pixelFormat = kELCDIF_PixelFormatXRGB8888;
298-
}
299-
300-
for (int i = 0; i < CONFIG_MCUX_ELCDIF_FB_NUM; i++) {
301-
/* Record pointers to each driver framebuffer */
302-
dev_data->fb[i] = config->fb_ptr + (config->fb_bytes * i);
303-
}
304-
305-
rgb_mode.bufferAddr = (uint32_t)config->fb_ptr;
306-
dev_data->active_fb = config->fb_ptr;
307-
308321
k_sem_init(&dev_data->sem, 0, 1);
309322
#ifdef CONFIG_MCUX_ELCDIF_PXP
310323
k_sem_init(&dev_data->pxp_done, 0, 1);
@@ -316,7 +329,12 @@ static int mcux_elcdif_init(const struct device *dev)
316329

317330
config->irq_config_func(dev);
318331

319-
ELCDIF_RgbModeInit(config->base, &rgb_mode);
332+
/* Set default pixel format obtained from device tree */
333+
mcux_elcdif_set_pixel_format(dev, dev_data->pixel_format);
334+
335+
dev_data->active_fb = dev_data->fb[0];
336+
337+
ELCDIF_RgbModeInit(config->base, &dev_data->rgb_mode);
320338
ELCDIF_RgbModeStart(config->base);
321339

322340
return 0;
@@ -331,14 +349,9 @@ static const struct display_driver_api mcux_elcdif_api = {
331349
.set_orientation = mcux_elcdif_set_orientation,
332350
};
333351

334-
#define MCUX_ELCDIF_PIXEL_BYTES(id) (DISPLAY_BITS_PER_PIXEL(DT_INST_PROP(id, pixel_format)) / 8)
335-
336352
#define MCUX_ELCDIF_DEVICE_INIT(id) \
337353
PINCTRL_DT_INST_DEFINE(id); \
338354
static void mcux_elcdif_config_func_##id(const struct device *dev); \
339-
static uint8_t __aligned(64) \
340-
frame_buffer_##id[CONFIG_MCUX_ELCDIF_FB_NUM * DT_INST_PROP(id, width) * \
341-
DT_INST_PROP(id, height) * MCUX_ELCDIF_PIXEL_BYTES(id)]; \
342355
static const struct mcux_elcdif_config mcux_elcdif_config_##id = { \
343356
.base = (LCDIF_Type *)DT_INST_REG_ADDR(id), \
344357
.irq_config_func = mcux_elcdif_config_func_##id, \
@@ -369,17 +382,13 @@ static const struct display_driver_api mcux_elcdif_api = {
369382
.dataBus = LCDIF_CTRL_LCD_DATABUS_WIDTH( \
370383
DT_INST_ENUM_IDX(id, data_bus_width)), \
371384
}, \
372-
.pixel_format = DT_INST_PROP(id, pixel_format), \
373-
.pixel_bytes = MCUX_ELCDIF_PIXEL_BYTES(id), \
374-
.fb_bytes = DT_INST_PROP(id, width) * DT_INST_PROP(id, height) * \
375-
MCUX_ELCDIF_PIXEL_BYTES(id), \
376385
.pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(id), \
377386
.backlight_gpio = GPIO_DT_SPEC_INST_GET(id, backlight_gpios), \
378-
.fb_ptr = frame_buffer_##id, \
379387
IF_ENABLED(CONFIG_MCUX_ELCDIF_PXP, \
380388
(.pxp = DEVICE_DT_GET(DT_INST_PHANDLE(id, nxp_pxp)),))}; \
381389
static struct mcux_elcdif_data mcux_elcdif_data_##id = { \
382390
.next_idx = 0, \
391+
.pixel_format = DT_INST_PROP(id, pixel_format), \
383392
}; \
384393
DEVICE_DT_INST_DEFINE(id, &mcux_elcdif_init, NULL, &mcux_elcdif_data_##id, \
385394
&mcux_elcdif_config_##id, POST_KERNEL, CONFIG_DISPLAY_INIT_PRIORITY, \

0 commit comments

Comments
 (0)