diff --git a/drivers/display/Kconfig.mcux_elcdif b/drivers/display/Kconfig.mcux_elcdif index 44510e4bc30..6cfc98bc257 100644 --- a/drivers/display/Kconfig.mcux_elcdif +++ b/drivers/display/Kconfig.mcux_elcdif @@ -1,4 +1,4 @@ -# Copyright 2019,2023 NXP +# Copyright 2019,2023-2024 NXP # Copyright (c) 2022, Basalte bv # SPDX-License-Identifier: Apache-2.0 @@ -105,6 +105,33 @@ config MCUX_ELCDIF_PXP_ROTATE_270 endchoice +choice MCUX_ELCDIF_PXP_FLIP_DIRECTION + default MCUX_ELCDIF_PXP_FLIP_DISABLE + prompt "Flip direction of PXP" + help + Set flip direction of PXP. The ELCDIF cannot detect the correct + rotation angle based on the call to display_write, so the user should + configure it here. In order for PXP flip to work, calls to + display_write MUST supply a framebuffer equal in size to screen width + and height (without flip applied). Note that the width and + height settings of the screen in devicetree should not be modified + from their values in the default screen orientation when using this + functionality. + +config MCUX_ELCDIF_PXP_FLIP_DISABLE + bool "Do not flip display" + +config MCUX_ELCDIF_PXP_FLIP_HORIZONTAL + bool "Flip display horizontally" + +config MCUX_ELCDIF_PXP_FLIP_VERTICAL + bool "Flip display vertically" + +config MCUX_ELCDIF_PXP_FLIP_BOTH + bool "Flib display both horizontally and vertically" + +endchoice + endif # MCUX_ELCDIF_PXP endif # DISPLAY_MCUX_ELCDIF diff --git a/drivers/display/display_mcux_elcdif.c b/drivers/display/display_mcux_elcdif.c index 9c5785342d9..828fcf4314e 100644 --- a/drivers/display/display_mcux_elcdif.c +++ b/drivers/display/display_mcux_elcdif.c @@ -1,5 +1,5 @@ /* - * Copyright 2019-23, NXP + * Copyright 2019-24, NXP * Copyright (c) 2022, Basalte bv * * SPDX-License-Identifier: Apache-2.0 @@ -54,7 +54,7 @@ struct mcux_elcdif_data { /* Tracks index of next active driver framebuffer */ uint8_t next_idx; #ifdef CONFIG_MCUX_ELCDIF_PXP - /* Given to when PXP completes rotation */ + /* Given to when PXP completes operation */ struct k_sem pxp_done; #endif }; @@ -138,12 +138,12 @@ static int mcux_elcdif_write(const struct device *dev, const uint16_t x, const u #ifdef CONFIG_MCUX_ELCDIF_PXP if (full_fb) { - /* Configure PXP using DMA API, and rotate frame */ + /* Configure PXP using DMA API, and rotate/flip frame */ struct dma_config pxp_dma = {0}; struct dma_block_config pxp_block = {0}; /* Source buffer is input to display_write, we will - * place rotated output into a driver framebuffer. + * place modified output into a driver framebuffer. */ dev_data->active_fb = dev_data->fb[dev_data->next_idx]; pxp_block.source_address = (uint32_t)buf; @@ -171,6 +171,17 @@ static int mcux_elcdif_write(const struct device *dev, const uint16_t x, const u pxp_dma.dma_slot |= DMA_MCUX_PXP_CMD(DMA_MCUX_PXP_CMD_ROTATE_0); } + /* DMA linked_channel sets the flip direction */ + if (IS_ENABLED(CONFIG_MCUX_ELCDIF_PXP_FLIP_HORIZONTAL)) { + pxp_dma.linked_channel |= DMA_MCUX_PXP_FLIP(DMA_MCUX_PXP_FLIP_HORIZONTAL); + } else if (IS_ENABLED(CONFIG_MCUX_ELCDIF_PXP_FLIP_VERTICAL)) { + pxp_dma.linked_channel |= DMA_MCUX_PXP_FLIP(DMA_MCUX_PXP_FLIP_VERTICAL); + } else if (IS_ENABLED(CONFIG_MCUX_ELCDIF_PXP_FLIP_BOTH)) { + pxp_dma.linked_channel |= DMA_MCUX_PXP_FLIP(DMA_MCUX_PXP_FLIP_BOTH); + } else { + pxp_dma.linked_channel |= DMA_MCUX_PXP_FLIP(DMA_MCUX_PXP_FLIP_DISABLE); + } + pxp_dma.channel_direction = MEMORY_TO_MEMORY; pxp_dma.source_data_size = desc->width * dev_data->pixel_bytes; pxp_dma.dest_data_size = config->rgb_mode.panelWidth * dev_data->pixel_bytes; @@ -191,7 +202,7 @@ static int mcux_elcdif_write(const struct device *dev, const uint16_t x, const u } k_sem_take(&dev_data->pxp_done, K_FOREVER); } else { - LOG_WRN("PXP rotation will not work correctly unless a full sized " + LOG_WRN("PXP rotation/flip will not work correctly unless a full sized " "framebuffer is provided"); } #endif /* CONFIG_MCUX_ELCDIF_PXP */