From bddca6edd452feaeff6e95a64e25d554562dbe64 Mon Sep 17 00:00:00 2001 From: Phi Bang Nguyen Date: Tue, 13 Feb 2024 15:14:56 +0100 Subject: [PATCH 1/6] drivers: dma: pxp: Run clang-format Run clang-format before making changes Signed-off-by: Phi Bang Nguyen --- drivers/dma/dma_mcux_pxp.c | 61 ++++++++++------------- include/zephyr/drivers/dma/dma_mcux_pxp.h | 8 +-- 2 files changed, 31 insertions(+), 38 deletions(-) diff --git a/drivers/dma/dma_mcux_pxp.c b/drivers/dma/dma_mcux_pxp.c index ef6f9f90f2840..95ae1949a34bc 100644 --- a/drivers/dma/dma_mcux_pxp.c +++ b/drivers/dma/dma_mcux_pxp.c @@ -40,7 +40,7 @@ static void dma_mcux_pxp_irq_handler(const struct device *dev) PXP_ClearStatusFlags(config->base, kPXP_CompleteFlag); #ifdef CONFIG_HAS_MCUX_CACHE - DCACHE_InvalidateByRange((uint32_t) data->out_buf_addr, data->out_buf_size); + DCACHE_InvalidateByRange((uint32_t)data->out_buf_addr, data->out_buf_size); #endif if (data->dma_callback) { data->dma_callback(dev, data->user_data, 0, 0); @@ -49,7 +49,7 @@ static void dma_mcux_pxp_irq_handler(const struct device *dev) /* Configure a channel */ static int dma_mcux_pxp_configure(const struct device *dev, uint32_t channel, - struct dma_config *config) + struct dma_config *config) { const struct dma_mcux_pxp_config *dev_config = dev->config; struct dma_mcux_pxp_data *dev_data = dev->data; @@ -102,8 +102,8 @@ static int dma_mcux_pxp_configure(const struct device *dev, uint32_t channel, default: return -ENOTSUP; } - DCACHE_CleanByRange((uint32_t) config->head_block->source_address, - config->head_block->block_size); + DCACHE_CleanByRange((uint32_t)config->head_block->source_address, + config->head_block->block_size); /* * Some notes on how specific fields of the DMA config are used by @@ -127,15 +127,14 @@ static int dma_mcux_pxp_configure(const struct device *dev, uint32_t channel, output_buffer_cfg.buffer0Addr = config->head_block->dest_address; output_buffer_cfg.buffer1Addr = 0U; output_buffer_cfg.pitchBytes = config->dest_data_size; - output_buffer_cfg.width = (config->dest_data_size / bytes_per_pixel); + output_buffer_cfg.width = (config->dest_data_size / bytes_per_pixel); output_buffer_cfg.height = config->dest_burst_length; PXP_SetOutputBufferConfig(dev_config->base, &output_buffer_cfg); /* We only support a process surface that covers the full buffer */ - PXP_SetProcessSurfacePosition(dev_config->base, 0U, 0U, - output_buffer_cfg.width, output_buffer_cfg.height); + PXP_SetProcessSurfacePosition(dev_config->base, 0U, 0U, output_buffer_cfg.width, + output_buffer_cfg.height); /* Setup rotation */ - PXP_SetRotateConfig(dev_config->base, kPXP_RotateProcessSurface, - rotate, kPXP_FlipDisable); + PXP_SetRotateConfig(dev_config->base, kPXP_RotateProcessSurface, rotate, kPXP_FlipDisable); dev_data->ps_buf_addr = config->head_block->source_address; dev_data->ps_buf_size = config->head_block->block_size; @@ -151,7 +150,7 @@ static int dma_mcux_pxp_start(const struct device *dev, uint32_t channel) const struct dma_mcux_pxp_config *config = dev->config; struct dma_mcux_pxp_data *data = dev->data; #ifdef CONFIG_HAS_MCUX_CACHE - DCACHE_CleanByRange((uint32_t) data->ps_buf_addr, data->ps_buf_size); + DCACHE_CleanByRange((uint32_t)data->ps_buf_addr, data->ps_buf_size); #endif ARG_UNUSED(channel); @@ -178,29 +177,23 @@ static int dma_mcux_pxp_init(const struct device *dev) return 0; } -#define DMA_INIT(n) \ - static void dma_pxp_config_func##n(const struct device *dev) \ - { \ - IF_ENABLED(DT_INST_IRQ_HAS_IDX(n, 0), ( \ - IRQ_CONNECT(DT_INST_IRQN(n), \ - DT_INST_IRQ(n, priority), \ - dma_mcux_pxp_irq_handler, \ - DEVICE_DT_INST_GET(n), 0); \ - irq_enable(DT_INST_IRQ(n, irq)); \ - )) \ - } \ - \ - static const struct dma_mcux_pxp_config dma_config_##n = { \ - .base = (PXP_Type *)DT_INST_REG_ADDR(n), \ - .irq_config_func = dma_pxp_config_func##n, \ - }; \ - \ - static struct dma_mcux_pxp_data dma_data_##n; \ - \ - DEVICE_DT_INST_DEFINE(n, \ - &dma_mcux_pxp_init, NULL, \ - &dma_data_##n, &dma_config_##n, \ - PRE_KERNEL_1, CONFIG_DMA_INIT_PRIORITY, \ - &dma_mcux_pxp_api); +#define DMA_INIT(n) \ + static void dma_pxp_config_func##n(const struct device *dev) \ + { \ + IF_ENABLED(DT_INST_IRQ_HAS_IDX(n, 0), \ + (IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), \ + dma_mcux_pxp_irq_handler, DEVICE_DT_INST_GET(n), 0); \ + irq_enable(DT_INST_IRQ(n, irq));)) \ + } \ + \ + static const struct dma_mcux_pxp_config dma_config_##n = { \ + .base = (PXP_Type *)DT_INST_REG_ADDR(n), \ + .irq_config_func = dma_pxp_config_func##n, \ + }; \ + \ + static struct dma_mcux_pxp_data dma_data_##n; \ + \ + DEVICE_DT_INST_DEFINE(n, &dma_mcux_pxp_init, NULL, &dma_data_##n, &dma_config_##n, \ + PRE_KERNEL_1, CONFIG_DMA_INIT_PRIORITY, &dma_mcux_pxp_api); DT_INST_FOREACH_STATUS_OKAY(DMA_INIT) diff --git a/include/zephyr/drivers/dma/dma_mcux_pxp.h b/include/zephyr/drivers/dma/dma_mcux_pxp.h index 8c8c5feb0497c..6144db7023841 100644 --- a/include/zephyr/drivers/dma/dma_mcux_pxp.h +++ b/include/zephyr/drivers/dma/dma_mcux_pxp.h @@ -7,10 +7,10 @@ #ifndef ZEPHYR_INCLUDE_DRIVERS_DMA_MCUX_PXP_H_ #define ZEPHYR_INCLUDE_DRIVERS_DMA_MCUX_PXP_H_ -#define DMA_MCUX_PXP_CMD_MASK 0xE0 +#define DMA_MCUX_PXP_CMD_MASK 0xE0 #define DMA_MCUX_PXP_CMD_SHIFT 0x5 -#define DMA_MCUX_PXP_FMT_MASK 0x1F +#define DMA_MCUX_PXP_FMT_MASK 0x1F #define DMA_MCUX_PXP_FMT_SHIFT 0x0 /* @@ -29,8 +29,8 @@ #define DMA_MCUX_PXP_FMT(x) ((x << DMA_MCUX_PXP_FMT_SHIFT) & DMA_MCUX_PXP_FMT_MASK) #define DMA_MCUX_PXP_CMD(x) ((x << DMA_MCUX_PXP_CMD_SHIFT) & DMA_MCUX_PXP_CMD_MASK) -#define DMA_MCUX_PXP_CMD_ROTATE_0 0 -#define DMA_MCUX_PXP_CMD_ROTATE_90 1 +#define DMA_MCUX_PXP_CMD_ROTATE_0 0 +#define DMA_MCUX_PXP_CMD_ROTATE_90 1 #define DMA_MCUX_PXP_CMD_ROTATE_180 2 #define DMA_MCUX_PXP_CMD_ROTATE_270 3 From 028bcbe2679544db7d2465f084edab6b92506b8e Mon Sep 17 00:00:00 2001 From: Phi Bang Nguyen Date: Tue, 13 Feb 2024 15:19:06 +0100 Subject: [PATCH 2/6] drivers: dma: pxp: Add support for ARGB8888 format Add support for ARGB8888 pixel format as the camera pipeline on i.MX RT11xx could output images in this format Signed-off-by: Phi Bang Nguyen --- drivers/dma/dma_mcux_pxp.c | 5 +++++ include/zephyr/drivers/dma/dma_mcux_pxp.h | 5 +++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/dma/dma_mcux_pxp.c b/drivers/dma/dma_mcux_pxp.c index 95ae1949a34bc..88f8f39f34b3d 100644 --- a/drivers/dma/dma_mcux_pxp.c +++ b/drivers/dma/dma_mcux_pxp.c @@ -99,6 +99,11 @@ static int dma_mcux_pxp_configure(const struct device *dev, uint32_t channel, output_buffer_cfg.pixelFormat = kPXP_OutputPixelFormatRGB888; bytes_per_pixel = 3; break; + case DMA_MCUX_PXP_FMT_ARGB8888: + ps_buffer_cfg.pixelFormat = kPXP_PsPixelFormatARGB8888; + output_buffer_cfg.pixelFormat = kPXP_OutputPixelFormatARGB8888; + bytes_per_pixel = 4; + break; default: return -ENOTSUP; } diff --git a/include/zephyr/drivers/dma/dma_mcux_pxp.h b/include/zephyr/drivers/dma/dma_mcux_pxp.h index 6144db7023841..7cddab2c3ef36 100644 --- a/include/zephyr/drivers/dma/dma_mcux_pxp.h +++ b/include/zephyr/drivers/dma/dma_mcux_pxp.h @@ -34,7 +34,8 @@ #define DMA_MCUX_PXP_CMD_ROTATE_180 2 #define DMA_MCUX_PXP_CMD_ROTATE_270 3 -#define DMA_MCUX_PXP_FMT_RGB565 0 -#define DMA_MCUX_PXP_FMT_RGB888 1 +#define DMA_MCUX_PXP_FMT_RGB565 0 +#define DMA_MCUX_PXP_FMT_RGB888 1 +#define DMA_MCUX_PXP_FMT_ARGB8888 2 #endif /* ZEPHYR_INCLUDE_DRIVERS_DMA_MCUX_PXP_H_ */ From 2e41d3cdd4687b17a5cd3d094353545eca76cab6 Mon Sep 17 00:00:00 2001 From: Phi Bang Nguyen Date: Tue, 13 Feb 2024 15:23:46 +0100 Subject: [PATCH 3/6] drivers: display: elcdif: Run clang-format Run clang-format before making changes Signed-off-by: Phi Bang Nguyen --- drivers/display/display_mcux_elcdif.c | 193 +++++++++++--------------- 1 file changed, 81 insertions(+), 112 deletions(-) diff --git a/drivers/display/display_mcux_elcdif.c b/drivers/display/display_mcux_elcdif.c index 304638011f1e4..b6595966772d2 100644 --- a/drivers/display/display_mcux_elcdif.c +++ b/drivers/display/display_mcux_elcdif.c @@ -55,8 +55,8 @@ struct mcux_elcdif_data { }; #ifdef CONFIG_MCUX_ELCDIF_PXP -static void mcux_elcdif_pxp_callback(const struct device *dma_dev, - void *user_data, uint32_t channel, int ret) +static void mcux_elcdif_pxp_callback(const struct device *dma_dev, void *user_data, + uint32_t channel, int ret) { struct mcux_elcdif_data *data = user_data; @@ -64,10 +64,8 @@ static void mcux_elcdif_pxp_callback(const struct device *dma_dev, } #endif /* CONFIG_MCUX_ELCDIF_PXP */ -static int mcux_elcdif_write(const struct device *dev, const uint16_t x, - const uint16_t y, - const struct display_buffer_descriptor *desc, - const void *buf) +static int mcux_elcdif_write(const struct device *dev, const uint16_t x, const uint16_t y, + const struct display_buffer_descriptor *desc, const void *buf) { const struct mcux_elcdif_config *config = dev->config; struct mcux_elcdif_data *dev_data = dev->data; @@ -77,31 +75,24 @@ static int mcux_elcdif_write(const struct device *dev, const uint16_t x, int ret = 0; bool full_fb = false; - __ASSERT((config->pixel_bytes * desc->pitch * desc->height) <= - desc->buf_size, "Input buffer too small"); + __ASSERT((config->pixel_bytes * desc->pitch * desc->height) <= desc->buf_size, + "Input buffer too small"); LOG_DBG("W=%d, H=%d, @%d,%d", desc->width, desc->height, x, y); - - if ((x == 0) && (y == 0) && - (desc->width == config->rgb_mode.panelWidth) && - (desc->height == config->rgb_mode.panelHeight) && - (desc->pitch == desc->width)) { + if ((x == 0) && (y == 0) && (desc->width == config->rgb_mode.panelWidth) && + (desc->height == config->rgb_mode.panelHeight) && (desc->pitch == desc->width)) { /* We can use the display buffer directly, no need to copy it */ - LOG_DBG("Setting FB from %p->%p", - (void *) dev_data->active_fb, (void *) buf); + LOG_DBG("Setting FB from %p->%p", (void *)dev_data->active_fb, (void *)buf); dev_data->active_fb = buf; full_fb = true; - } else if ((x == 0) && (y == 0) && - (desc->width == config->rgb_mode.panelHeight) && - (desc->height == config->rgb_mode.panelWidth) && - (desc->pitch == desc->width) && - IS_ENABLED(CONFIG_MCUX_ELCDIF_PXP)) { + } else if ((x == 0) && (y == 0) && (desc->width == config->rgb_mode.panelHeight) && + (desc->height == config->rgb_mode.panelWidth) && (desc->pitch == desc->width) && + IS_ENABLED(CONFIG_MCUX_ELCDIF_PXP)) { /* With the PXP, we can rotate this display buffer to align * with output dimensions */ - LOG_DBG("Setting FB from %p->%p", - (void *) dev_data->active_fb, (void *) buf); + LOG_DBG("Setting FB from %p->%p", (void *)dev_data->active_fb, (void *)buf); dev_data->active_fb = buf; full_fb = true; } else { @@ -130,14 +121,14 @@ static int mcux_elcdif_write(const struct device *dev, const uint16_t x, dst += config->pixel_bytes * config->rgb_mode.panelWidth; } - LOG_DBG("Setting FB from %p->%p", (void *) dev_data->active_fb, - (void *) dev_data->fb[dev_data->next_idx]); + LOG_DBG("Setting FB from %p->%p", (void *)dev_data->active_fb, + (void *)dev_data->fb[dev_data->next_idx]); /* Set new active framebuffer */ dev_data->active_fb = dev_data->fb[dev_data->next_idx]; } #ifdef CONFIG_HAS_MCUX_CACHE - DCACHE_CleanByRange((uint32_t) dev_data->active_fb, config->fb_bytes); + DCACHE_CleanByRange((uint32_t)dev_data->active_fb, config->fb_bytes); #endif #ifdef CONFIG_MCUX_ELCDIF_PXP @@ -200,12 +191,10 @@ static int mcux_elcdif_write(const struct device *dev, const uint16_t x, #if CONFIG_MCUX_ELCDIF_FB_NUM != 0 /* Update index of active framebuffer */ - dev_data->next_idx = - (dev_data->next_idx + 1) % CONFIG_MCUX_ELCDIF_FB_NUM; + dev_data->next_idx = (dev_data->next_idx + 1) % CONFIG_MCUX_ELCDIF_FB_NUM; #endif /* Enable frame buffer completion interrupt */ - ELCDIF_EnableInterrupts(config->base, - kELCDIF_CurFrameDoneInterruptEnable); + ELCDIF_EnableInterrupts(config->base, kELCDIF_CurFrameDoneInterruptEnable); /* Wait for frame send to complete */ k_sem_take(&dev_data->sem, K_FOREVER); return ret; @@ -226,8 +215,7 @@ static int mcux_elcdif_display_blanking_on(const struct device *dev) } static int mcux_elcdif_set_pixel_format(const struct device *dev, - const enum display_pixel_format - pixel_format) + const enum display_pixel_format pixel_format) { const struct mcux_elcdif_config *config = dev->config; @@ -239,7 +227,7 @@ static int mcux_elcdif_set_pixel_format(const struct device *dev, } static int mcux_elcdif_set_orientation(const struct device *dev, - const enum display_orientation orientation) + const enum display_orientation orientation) { if (orientation == DISPLAY_ORIENTATION_NORMAL) { return 0; @@ -249,7 +237,7 @@ static int mcux_elcdif_set_orientation(const struct device *dev, } static void mcux_elcdif_get_capabilities(const struct device *dev, - struct display_capabilities *capabilities) + struct display_capabilities *capabilities) { const struct mcux_elcdif_config *config = dev->config; @@ -273,8 +261,7 @@ static void mcux_elcdif_isr(const struct device *dev) /* Disable frame completion interrupt, post to * sem to notify that frame send is complete. */ - ELCDIF_DisableInterrupts(config->base, - kELCDIF_CurFrameDoneInterruptEnable); + ELCDIF_DisableInterrupts(config->base, kELCDIF_CurFrameDoneInterruptEnable); k_sem_give(&dev_data->sem); } } @@ -309,7 +296,7 @@ static int mcux_elcdif_init(const struct device *dev) dev_data->fb[i] = config->fb_ptr + (config->fb_bytes * i); } - rgb_mode.bufferAddr = (uint32_t) config->fb_ptr; + rgb_mode.bufferAddr = (uint32_t)config->fb_ptr; dev_data->active_fb = config->fb_ptr; k_sem_init(&dev_data->sem, 0, 1); @@ -338,82 +325,64 @@ static const struct display_driver_api mcux_elcdif_api = { .set_orientation = mcux_elcdif_set_orientation, }; -#define MCUX_ELCDIF_PIXEL_BYTES(id) \ - (DISPLAY_BITS_PER_PIXEL(DT_INST_PROP(id, pixel_format)) / 8) - -#define MCUX_ELCDIF_DEVICE_INIT(id) \ - PINCTRL_DT_INST_DEFINE(id); \ - static void mcux_elcdif_config_func_##id(const struct device *dev); \ - static uint8_t __aligned(64) frame_buffer_##id[CONFIG_MCUX_ELCDIF_FB_NUM\ - * DT_INST_PROP(id, width) \ - * DT_INST_PROP(id, height) \ - * MCUX_ELCDIF_PIXEL_BYTES(id)]; \ - static const struct mcux_elcdif_config mcux_elcdif_config_##id = { \ - .base = (LCDIF_Type *) DT_INST_REG_ADDR(id), \ - .irq_config_func = mcux_elcdif_config_func_##id, \ - .rgb_mode = { \ - .panelWidth = DT_INST_PROP(id, width), \ - .panelHeight = DT_INST_PROP(id, height), \ - .hsw = DT_PROP(DT_INST_CHILD(id, display_timings), \ - hsync_len), \ - .hfp = DT_PROP(DT_INST_CHILD(id, display_timings), \ - hfront_porch), \ - .hbp = DT_PROP(DT_INST_CHILD(id, display_timings), \ - hback_porch), \ - .vsw = DT_PROP(DT_INST_CHILD(id, display_timings), \ - vsync_len), \ - .vfp = DT_PROP(DT_INST_CHILD(id, display_timings), \ - vfront_porch), \ - .vbp = DT_PROP(DT_INST_CHILD(id, display_timings), \ - vback_porch), \ - .polarityFlags = (DT_PROP(DT_INST_CHILD(id, \ - display_timings), hsync_active) ? \ - kELCDIF_HsyncActiveHigh : \ - kELCDIF_HsyncActiveLow) | \ - (DT_PROP(DT_INST_CHILD(id, \ - display_timings), vsync_active) ? \ - kELCDIF_VsyncActiveHigh : \ - kELCDIF_VsyncActiveLow) | \ - (DT_PROP(DT_INST_CHILD(id, \ - display_timings), de_active) ? \ - kELCDIF_DataEnableActiveHigh : \ - kELCDIF_DataEnableActiveLow) | \ - (DT_PROP(DT_INST_CHILD(id, \ - display_timings), pixelclk_active) ? \ - kELCDIF_DriveDataOnRisingClkEdge : \ - kELCDIF_DriveDataOnFallingClkEdge), \ - .dataBus = LCDIF_CTRL_LCD_DATABUS_WIDTH( \ - DT_INST_ENUM_IDX(id, data_bus_width)), \ - }, \ - .pixel_format = DT_INST_PROP(id, pixel_format), \ - .pixel_bytes = MCUX_ELCDIF_PIXEL_BYTES(id), \ - .fb_bytes = DT_INST_PROP(id, width) * DT_INST_PROP(id, height) \ - * MCUX_ELCDIF_PIXEL_BYTES(id), \ - .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(id), \ - .backlight_gpio = GPIO_DT_SPEC_INST_GET(id, backlight_gpios), \ - .fb_ptr = frame_buffer_##id, \ - IF_ENABLED(CONFIG_MCUX_ELCDIF_PXP, \ - (.pxp = DEVICE_DT_GET(DT_INST_PHANDLE(id, nxp_pxp)),)) \ - }; \ - static struct mcux_elcdif_data mcux_elcdif_data_##id = { \ - .next_idx = 0, \ - }; \ - DEVICE_DT_INST_DEFINE(id, \ - &mcux_elcdif_init, \ - NULL, \ - &mcux_elcdif_data_##id, \ - &mcux_elcdif_config_##id, \ - POST_KERNEL, \ - CONFIG_DISPLAY_INIT_PRIORITY, \ - &mcux_elcdif_api); \ - static void mcux_elcdif_config_func_##id(const struct device *dev) \ - { \ - IRQ_CONNECT(DT_INST_IRQN(id), \ - DT_INST_IRQ(id, priority), \ - mcux_elcdif_isr, \ - DEVICE_DT_INST_GET(id), \ - 0); \ - irq_enable(DT_INST_IRQN(id)); \ +#define MCUX_ELCDIF_PIXEL_BYTES(id) (DISPLAY_BITS_PER_PIXEL(DT_INST_PROP(id, pixel_format)) / 8) + +#define MCUX_ELCDIF_DEVICE_INIT(id) \ + PINCTRL_DT_INST_DEFINE(id); \ + static void mcux_elcdif_config_func_##id(const struct device *dev); \ + static uint8_t __aligned(64) \ + frame_buffer_##id[CONFIG_MCUX_ELCDIF_FB_NUM * DT_INST_PROP(id, width) * \ + DT_INST_PROP(id, height) * MCUX_ELCDIF_PIXEL_BYTES(id)]; \ + static const struct mcux_elcdif_config mcux_elcdif_config_##id = { \ + .base = (LCDIF_Type *)DT_INST_REG_ADDR(id), \ + .irq_config_func = mcux_elcdif_config_func_##id, \ + .rgb_mode = \ + { \ + .panelWidth = DT_INST_PROP(id, width), \ + .panelHeight = DT_INST_PROP(id, height), \ + .hsw = DT_PROP(DT_INST_CHILD(id, display_timings), hsync_len), \ + .hfp = DT_PROP(DT_INST_CHILD(id, display_timings), hfront_porch), \ + .hbp = DT_PROP(DT_INST_CHILD(id, display_timings), hback_porch), \ + .vsw = DT_PROP(DT_INST_CHILD(id, display_timings), vsync_len), \ + .vfp = DT_PROP(DT_INST_CHILD(id, display_timings), vfront_porch), \ + .vbp = DT_PROP(DT_INST_CHILD(id, display_timings), vback_porch), \ + .polarityFlags = \ + (DT_PROP(DT_INST_CHILD(id, display_timings), hsync_active) \ + ? kELCDIF_HsyncActiveHigh \ + : kELCDIF_HsyncActiveLow) | \ + (DT_PROP(DT_INST_CHILD(id, display_timings), vsync_active) \ + ? kELCDIF_VsyncActiveHigh \ + : kELCDIF_VsyncActiveLow) | \ + (DT_PROP(DT_INST_CHILD(id, display_timings), de_active) \ + ? kELCDIF_DataEnableActiveHigh \ + : kELCDIF_DataEnableActiveLow) | \ + (DT_PROP(DT_INST_CHILD(id, display_timings), \ + pixelclk_active) \ + ? kELCDIF_DriveDataOnRisingClkEdge \ + : kELCDIF_DriveDataOnFallingClkEdge), \ + .dataBus = LCDIF_CTRL_LCD_DATABUS_WIDTH( \ + DT_INST_ENUM_IDX(id, data_bus_width)), \ + }, \ + .pixel_format = DT_INST_PROP(id, pixel_format), \ + .pixel_bytes = MCUX_ELCDIF_PIXEL_BYTES(id), \ + .fb_bytes = DT_INST_PROP(id, width) * DT_INST_PROP(id, height) * \ + MCUX_ELCDIF_PIXEL_BYTES(id), \ + .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(id), \ + .backlight_gpio = GPIO_DT_SPEC_INST_GET(id, backlight_gpios), \ + .fb_ptr = frame_buffer_##id, \ + IF_ENABLED(CONFIG_MCUX_ELCDIF_PXP, \ + (.pxp = DEVICE_DT_GET(DT_INST_PHANDLE(id, nxp_pxp)),))}; \ + static struct mcux_elcdif_data mcux_elcdif_data_##id = { \ + .next_idx = 0, \ + }; \ + DEVICE_DT_INST_DEFINE(id, &mcux_elcdif_init, NULL, &mcux_elcdif_data_##id, \ + &mcux_elcdif_config_##id, POST_KERNEL, CONFIG_DISPLAY_INIT_PRIORITY, \ + &mcux_elcdif_api); \ + static void mcux_elcdif_config_func_##id(const struct device *dev) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(id), DT_INST_IRQ(id, priority), mcux_elcdif_isr, \ + DEVICE_DT_INST_GET(id), 0); \ + irq_enable(DT_INST_IRQN(id)); \ } DT_INST_FOREACH_STATUS_OKAY(MCUX_ELCDIF_DEVICE_INIT) From 852738980f367f415e2bf8f29acefc7da14d3994 Mon Sep 17 00:00:00 2001 From: Phi Bang Nguyen Date: Tue, 13 Feb 2024 15:25:53 +0100 Subject: [PATCH 4/6] drivers: display: elcdif: Add support for ARGB8888 format Add support for ARGB8888 pixel format as the camera pipeline on i.MX RT11xx could output images in this format Signed-off-by: Phi Bang Nguyen --- drivers/display/display_mcux_elcdif.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/display/display_mcux_elcdif.c b/drivers/display/display_mcux_elcdif.c index b6595966772d2..a4dd3ce1c0bbf 100644 --- a/drivers/display/display_mcux_elcdif.c +++ b/drivers/display/display_mcux_elcdif.c @@ -27,6 +27,8 @@ LOG_MODULE_REGISTER(display_mcux_elcdif, CONFIG_DISPLAY_LOG_LEVEL); +static const uint32_t supported_fmts = PIXEL_FORMAT_BGR_565 | PIXEL_FORMAT_ARGB_8888; + struct mcux_elcdif_config { LCDIF_Type *base; void (*irq_config_func)(const struct device *dev); @@ -150,6 +152,8 @@ static int mcux_elcdif_write(const struct device *dev, const uint16_t x, const u pxp_dma.dma_slot = DMA_MCUX_PXP_FMT(DMA_MCUX_PXP_FMT_RGB565); } else if (config->pixel_format == PIXEL_FORMAT_RGB_888) { pxp_dma.dma_slot = DMA_MCUX_PXP_FMT(DMA_MCUX_PXP_FMT_RGB888); + } else if (config->pixel_format == PIXEL_FORMAT_ARGB_8888) { + pxp_dma.dma_slot = DMA_MCUX_PXP_FMT(DMA_MCUX_PXP_FMT_ARGB8888); } else { /* Cannot rotate */ return -ENOTSUP; @@ -244,7 +248,7 @@ static void mcux_elcdif_get_capabilities(const struct device *dev, memset(capabilities, 0, sizeof(struct display_capabilities)); capabilities->x_resolution = config->rgb_mode.panelWidth; capabilities->y_resolution = config->rgb_mode.panelHeight; - capabilities->supported_pixel_formats = config->pixel_format; + capabilities->supported_pixel_formats = supported_fmts; capabilities->current_pixel_format = config->pixel_format; capabilities->current_orientation = DISPLAY_ORIENTATION_NORMAL; } @@ -289,6 +293,8 @@ static int mcux_elcdif_init(const struct device *dev) rgb_mode.pixelFormat = kELCDIF_PixelFormatRGB565; } else if (config->pixel_format == PIXEL_FORMAT_RGB_888) { rgb_mode.pixelFormat = kELCDIF_PixelFormatRGB888; + } else if (config->pixel_format == PIXEL_FORMAT_ARGB_8888) { + rgb_mode.pixelFormat = kELCDIF_PixelFormatXRGB8888; } for (int i = 0; i < CONFIG_MCUX_ELCDIF_FB_NUM; i++) { From 6ea6b2146ec4696c97dd16c82a81ded243f06e24 Mon Sep 17 00:00:00 2001 From: Phi Bang Nguyen Date: Mon, 19 Feb 2024 18:55:27 +0100 Subject: [PATCH 5/6] 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 --- drivers/display/Kconfig.mcux_elcdif | 10 +++ drivers/display/display_mcux_elcdif.c | 111 ++++++++++++++------------ 2 files changed, 70 insertions(+), 51 deletions(-) diff --git a/drivers/display/Kconfig.mcux_elcdif b/drivers/display/Kconfig.mcux_elcdif index 7bf2ba2862422..43f90374380a7 100644 --- a/drivers/display/Kconfig.mcux_elcdif +++ b/drivers/display/Kconfig.mcux_elcdif @@ -32,6 +32,16 @@ config MCUX_ELCDIF_FB_NUM implications of this concern you, leave at least one driver framebuffer enabled. +config MCUX_ELCDIF_FB_SIZE + int "Framebuffer size required by the eLCDIF driver" + default 3686400 + help + eLCDIF driver allocates framebuffers to support partial display updates. + The framebuffer size is computed as : panel_width * panel_height * bpp. + The default value is set to afford for a default resolution of 1280x720 and + 4-bytes pixel format, e.g. ARGB8888. Applications should change this value + according to the actual used resolution and format to optimize the heap size. + config MCUX_ELCDIF_PXP bool "Use PXP for display rotation" depends on MCUX_PXP diff --git a/drivers/display/display_mcux_elcdif.c b/drivers/display/display_mcux_elcdif.c index a4dd3ce1c0bbf..e4b45f89d40dd 100644 --- a/drivers/display/display_mcux_elcdif.c +++ b/drivers/display/display_mcux_elcdif.c @@ -27,18 +27,17 @@ LOG_MODULE_REGISTER(display_mcux_elcdif, CONFIG_DISPLAY_LOG_LEVEL); +/* Define the heap size. 512 bytes of padding are included for kernel heap structures */ +K_HEAP_DEFINE(display_heap, CONFIG_MCUX_ELCDIF_FB_NUM * CONFIG_MCUX_ELCDIF_FB_SIZE + 512); + static const uint32_t supported_fmts = PIXEL_FORMAT_BGR_565 | PIXEL_FORMAT_ARGB_8888; struct mcux_elcdif_config { LCDIF_Type *base; void (*irq_config_func)(const struct device *dev); elcdif_rgb_mode_config_t rgb_mode; - enum display_pixel_format pixel_format; - size_t pixel_bytes; - size_t fb_bytes; const struct pinctrl_dev_config *pincfg; const struct gpio_dt_spec backlight_gpio; - uint8_t *fb_ptr; const struct device *pxp; }; @@ -47,6 +46,10 @@ struct mcux_elcdif_data { const uint8_t *active_fb; /* Pointers to driver allocated framebuffers */ uint8_t *fb[CONFIG_MCUX_ELCDIF_FB_NUM]; + enum display_pixel_format pixel_format; + size_t pixel_bytes; + size_t fb_bytes; + elcdif_rgb_mode_config_t rgb_mode; struct k_sem sem; /* Tracks index of next active driver framebuffer */ uint8_t next_idx; @@ -77,7 +80,7 @@ static int mcux_elcdif_write(const struct device *dev, const uint16_t x, const u int ret = 0; bool full_fb = false; - __ASSERT((config->pixel_bytes * desc->pitch * desc->height) <= desc->buf_size, + __ASSERT((dev_data->pixel_bytes * desc->pitch * desc->height) <= desc->buf_size, "Input buffer too small"); 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 */ src = dev_data->active_fb; dst = dev_data->fb[dev_data->next_idx]; - memcpy(dst, src, config->fb_bytes); + memcpy(dst, src, dev_data->fb_bytes); } /* Now, write the display update into active framebuffer */ src = buf; dst = dev_data->fb[dev_data->next_idx]; - dst += config->pixel_bytes * (y * config->rgb_mode.panelWidth + x); + dst += dev_data->pixel_bytes * (y * config->rgb_mode.panelWidth + x); for (h_idx = 0; h_idx < desc->height; h_idx++) { - memcpy(dst, src, config->pixel_bytes * desc->width); - src += config->pixel_bytes * desc->pitch; - dst += config->pixel_bytes * config->rgb_mode.panelWidth; + memcpy(dst, src, dev_data->pixel_bytes * desc->width); + src += dev_data->pixel_bytes * desc->pitch; + dst += dev_data->pixel_bytes * config->rgb_mode.panelWidth; } 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 } #ifdef CONFIG_HAS_MCUX_CACHE - DCACHE_CleanByRange((uint32_t)dev_data->active_fb, config->fb_bytes); + DCACHE_CleanByRange((uint32_t)dev_data->active_fb, dev_data->fb_bytes); #endif #ifdef CONFIG_MCUX_ELCDIF_PXP @@ -148,11 +151,11 @@ static int mcux_elcdif_write(const struct device *dev, const uint16_t x, const u pxp_block.block_size = desc->buf_size; /* DMA slot sets pixel format and rotation angle */ - if (config->pixel_format == PIXEL_FORMAT_BGR_565) { + if (dev_data->pixel_format == PIXEL_FORMAT_BGR_565) { pxp_dma.dma_slot = DMA_MCUX_PXP_FMT(DMA_MCUX_PXP_FMT_RGB565); - } else if (config->pixel_format == PIXEL_FORMAT_RGB_888) { + } else if (dev_data->pixel_format == PIXEL_FORMAT_RGB_888) { pxp_dma.dma_slot = DMA_MCUX_PXP_FMT(DMA_MCUX_PXP_FMT_RGB888); - } else if (config->pixel_format == PIXEL_FORMAT_ARGB_8888) { + } else if (dev_data->pixel_format == PIXEL_FORMAT_ARGB_8888) { pxp_dma.dma_slot = DMA_MCUX_PXP_FMT(DMA_MCUX_PXP_FMT_ARGB8888); } else { /* Cannot rotate */ @@ -169,8 +172,8 @@ static int mcux_elcdif_write(const struct device *dev, const uint16_t x, const u } pxp_dma.channel_direction = MEMORY_TO_MEMORY; - pxp_dma.source_data_size = desc->width * config->pixel_bytes; - pxp_dma.dest_data_size = config->rgb_mode.panelWidth * config->pixel_bytes; + pxp_dma.source_data_size = desc->width * dev_data->pixel_bytes; + pxp_dma.dest_data_size = config->rgb_mode.panelWidth * dev_data->pixel_bytes; /* Burst lengths are heights of source/dest buffer in pixels */ pxp_dma.source_burst_length = desc->height; pxp_dma.dest_burst_length = config->rgb_mode.panelHeight; @@ -221,13 +224,42 @@ static int mcux_elcdif_display_blanking_on(const struct device *dev) static int mcux_elcdif_set_pixel_format(const struct device *dev, const enum display_pixel_format pixel_format) { + struct mcux_elcdif_data *dev_data = dev->data; const struct mcux_elcdif_config *config = dev->config; - if (pixel_format == config->pixel_format) { - return 0; + if (!(pixel_format & supported_fmts)) { + LOG_ERR("Unsupported pixel format"); + return -ENOTSUP; } - LOG_ERR("Pixel format change not implemented"); - return -ENOTSUP; + + dev_data->pixel_format = pixel_format; + dev_data->pixel_bytes = DISPLAY_BITS_PER_PIXEL(pixel_format) / 8; + dev_data->fb_bytes = + config->rgb_mode.panelWidth * config->rgb_mode.panelHeight * dev_data->pixel_bytes; + + for (int i = 0; i < CONFIG_MCUX_ELCDIF_FB_NUM; i++) { + k_heap_free(&display_heap, dev_data->fb[i]); + dev_data->fb[i] = + k_heap_aligned_alloc(&display_heap, 64, dev_data->fb_bytes, K_FOREVER); + if (dev_data->fb[i] == NULL) { + LOG_ERR("Could not allocate memory for framebuffers"); + return -ENOMEM; + } + memset(dev_data->fb[i], 0, dev_data->fb_bytes); + } + + dev_data->rgb_mode = config->rgb_mode; + if (pixel_format == PIXEL_FORMAT_BGR_565) { + dev_data->rgb_mode.pixelFormat = kELCDIF_PixelFormatRGB565; + } else if (pixel_format == PIXEL_FORMAT_RGB_888) { + dev_data->rgb_mode.pixelFormat = kELCDIF_PixelFormatRGB888; + } else if (pixel_format == PIXEL_FORMAT_ARGB_8888) { + dev_data->rgb_mode.pixelFormat = kELCDIF_PixelFormatXRGB8888; + } + + ELCDIF_RgbModeSetPixelFormat(config->base, dev_data->rgb_mode.pixelFormat); + + return 0; } static int mcux_elcdif_set_orientation(const struct device *dev, @@ -249,7 +281,7 @@ static void mcux_elcdif_get_capabilities(const struct device *dev, capabilities->x_resolution = config->rgb_mode.panelWidth; capabilities->y_resolution = config->rgb_mode.panelHeight; capabilities->supported_pixel_formats = supported_fmts; - capabilities->current_pixel_format = config->pixel_format; + capabilities->current_pixel_format = ((struct mcux_elcdif_data *)dev->data)->pixel_format; capabilities->current_orientation = DISPLAY_ORIENTATION_NORMAL; } @@ -286,25 +318,6 @@ static int mcux_elcdif_init(const struct device *dev) return err; } - elcdif_rgb_mode_config_t rgb_mode = config->rgb_mode; - - /* Set the Pixel format */ - if (config->pixel_format == PIXEL_FORMAT_BGR_565) { - rgb_mode.pixelFormat = kELCDIF_PixelFormatRGB565; - } else if (config->pixel_format == PIXEL_FORMAT_RGB_888) { - rgb_mode.pixelFormat = kELCDIF_PixelFormatRGB888; - } else if (config->pixel_format == PIXEL_FORMAT_ARGB_8888) { - rgb_mode.pixelFormat = kELCDIF_PixelFormatXRGB8888; - } - - for (int i = 0; i < CONFIG_MCUX_ELCDIF_FB_NUM; i++) { - /* Record pointers to each driver framebuffer */ - dev_data->fb[i] = config->fb_ptr + (config->fb_bytes * i); - } - - rgb_mode.bufferAddr = (uint32_t)config->fb_ptr; - dev_data->active_fb = config->fb_ptr; - k_sem_init(&dev_data->sem, 0, 1); #ifdef CONFIG_MCUX_ELCDIF_PXP k_sem_init(&dev_data->pxp_done, 0, 1); @@ -316,7 +329,12 @@ static int mcux_elcdif_init(const struct device *dev) config->irq_config_func(dev); - ELCDIF_RgbModeInit(config->base, &rgb_mode); + /* Set default pixel format obtained from device tree */ + mcux_elcdif_set_pixel_format(dev, dev_data->pixel_format); + + dev_data->active_fb = dev_data->fb[0]; + + ELCDIF_RgbModeInit(config->base, &dev_data->rgb_mode); ELCDIF_RgbModeStart(config->base); return 0; @@ -331,14 +349,9 @@ static const struct display_driver_api mcux_elcdif_api = { .set_orientation = mcux_elcdif_set_orientation, }; -#define MCUX_ELCDIF_PIXEL_BYTES(id) (DISPLAY_BITS_PER_PIXEL(DT_INST_PROP(id, pixel_format)) / 8) - #define MCUX_ELCDIF_DEVICE_INIT(id) \ PINCTRL_DT_INST_DEFINE(id); \ static void mcux_elcdif_config_func_##id(const struct device *dev); \ - static uint8_t __aligned(64) \ - frame_buffer_##id[CONFIG_MCUX_ELCDIF_FB_NUM * DT_INST_PROP(id, width) * \ - DT_INST_PROP(id, height) * MCUX_ELCDIF_PIXEL_BYTES(id)]; \ static const struct mcux_elcdif_config mcux_elcdif_config_##id = { \ .base = (LCDIF_Type *)DT_INST_REG_ADDR(id), \ .irq_config_func = mcux_elcdif_config_func_##id, \ @@ -369,17 +382,13 @@ static const struct display_driver_api mcux_elcdif_api = { .dataBus = LCDIF_CTRL_LCD_DATABUS_WIDTH( \ DT_INST_ENUM_IDX(id, data_bus_width)), \ }, \ - .pixel_format = DT_INST_PROP(id, pixel_format), \ - .pixel_bytes = MCUX_ELCDIF_PIXEL_BYTES(id), \ - .fb_bytes = DT_INST_PROP(id, width) * DT_INST_PROP(id, height) * \ - MCUX_ELCDIF_PIXEL_BYTES(id), \ .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(id), \ .backlight_gpio = GPIO_DT_SPEC_INST_GET(id, backlight_gpios), \ - .fb_ptr = frame_buffer_##id, \ IF_ENABLED(CONFIG_MCUX_ELCDIF_PXP, \ (.pxp = DEVICE_DT_GET(DT_INST_PHANDLE(id, nxp_pxp)),))}; \ static struct mcux_elcdif_data mcux_elcdif_data_##id = { \ .next_idx = 0, \ + .pixel_format = DT_INST_PROP(id, pixel_format), \ }; \ DEVICE_DT_INST_DEFINE(id, &mcux_elcdif_init, NULL, &mcux_elcdif_data_##id, \ &mcux_elcdif_config_##id, POST_KERNEL, CONFIG_DISPLAY_INIT_PRIORITY, \ From 7350bf2581c20a7cce8acec277298966eb4381f8 Mon Sep 17 00:00:00 2001 From: Phi Bang Nguyen Date: Wed, 21 Feb 2024 23:09:26 +0100 Subject: [PATCH 6/6] samples: drivers: display: Modify heap size configs for RT595 & RT1170 The heap size for i.MX RT1170 is way too much while for i.MX RT595, it is too small to afford for 4-bytes formats, e.g. ARGB8888. Signed-off-by: Phi Bang Nguyen --- .../display/boards/mimxrt1170_evk_mimxrt1176_cm7_A.conf | 5 ++++- .../display/boards/mimxrt1170_evk_mimxrt1176_cm7_B.conf | 2 +- samples/drivers/display/boards/mimxrt1170_evkb_cm7.conf | 5 ++++- .../display/boards/mimxrt595_evk_mimxrt595s_cm33.conf | 8 ++++---- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/samples/drivers/display/boards/mimxrt1170_evk_mimxrt1176_cm7_A.conf b/samples/drivers/display/boards/mimxrt1170_evk_mimxrt1176_cm7_A.conf index d5fb0e239e3a5..af2acc5acf0de 100644 --- a/samples/drivers/display/boards/mimxrt1170_evk_mimxrt1176_cm7_A.conf +++ b/samples/drivers/display/boards/mimxrt1170_evk_mimxrt1176_cm7_A.conf @@ -4,4 +4,7 @@ # SPDX-License-Identifier: Apache-2.0 # -CONFIG_HEAP_MEM_POOL_SIZE=4194304 +# Sample will allocate buffer equal to: (panelwidth / 8) * (panelwidth / 4) * pixel depth. For a +# 1280x720 display in a 32-bpp format (e.g. ARGB8888), this is (720 / 8) * (720 / 4) * 4 = 64800 +# bytes. We include 128 bytes of padding for kernel heap structures +CONFIG_HEAP_MEM_POOL_SIZE=64928 diff --git a/samples/drivers/display/boards/mimxrt1170_evk_mimxrt1176_cm7_B.conf b/samples/drivers/display/boards/mimxrt1170_evk_mimxrt1176_cm7_B.conf index 072545354b964..0fbbef94c32ac 100644 --- a/samples/drivers/display/boards/mimxrt1170_evk_mimxrt1176_cm7_B.conf +++ b/samples/drivers/display/boards/mimxrt1170_evk_mimxrt1176_cm7_B.conf @@ -4,4 +4,4 @@ # SPDX-License-Identifier: Apache-2.0 # -CONFIG_HEAP_MEM_POOL_SIZE=4194304 +CONFIG_HEAP_MEM_POOL_SIZE=64928 diff --git a/samples/drivers/display/boards/mimxrt1170_evkb_cm7.conf b/samples/drivers/display/boards/mimxrt1170_evkb_cm7.conf index 072545354b964..c8e665357ca37 100644 --- a/samples/drivers/display/boards/mimxrt1170_evkb_cm7.conf +++ b/samples/drivers/display/boards/mimxrt1170_evkb_cm7.conf @@ -4,4 +4,7 @@ # SPDX-License-Identifier: Apache-2.0 # -CONFIG_HEAP_MEM_POOL_SIZE=4194304 +# Sample will allocate buffer equal to: (panelwidth / 8) * (panelwidth / 4) * pixel depth. For a +# 1280x720 display in a 32-bpp format (e.g. ARGB8888), this is (720 / 8) * (720 / 4) * 4 = 64800 +# bytes. We include 128 bytes of padding for kernel heap structures +CONFIG_HEAP_MEM_POOL_SIZE=64928 diff --git a/samples/drivers/display/boards/mimxrt595_evk_mimxrt595s_cm33.conf b/samples/drivers/display/boards/mimxrt595_evk_mimxrt595s_cm33.conf index 06ab28637ed8d..c8e665357ca37 100644 --- a/samples/drivers/display/boards/mimxrt595_evk_mimxrt595s_cm33.conf +++ b/samples/drivers/display/boards/mimxrt595_evk_mimxrt595s_cm33.conf @@ -4,7 +4,7 @@ # SPDX-License-Identifier: Apache-2.0 # -# Sample will allocate buffer equal to: (height / 8) * (height / 4) * pixel depth -# For the 1280x720 16 bit display, this is (720 / 8) * (720 / 4) * 2 = 32400 bytes -# We include 128 bytes of padding for kernel heap structures -CONFIG_HEAP_MEM_POOL_SIZE=32528 +# Sample will allocate buffer equal to: (panelwidth / 8) * (panelwidth / 4) * pixel depth. For a +# 1280x720 display in a 32-bpp format (e.g. ARGB8888), this is (720 / 8) * (720 / 4) * 4 = 64800 +# bytes. We include 128 bytes of padding for kernel heap structures +CONFIG_HEAP_MEM_POOL_SIZE=64928