drivers: display: display_mcux_elcdif: Add PXP flip feature

display_write() can leverage PXP to flip the image.

Signed-off-by: Derek Snell <derek.snell@nxp.com>
This commit is contained in:
Derek Snell 2024-07-22 16:23:50 -04:00 committed by Anas Nashif
parent 2b601fa3a0
commit 200a669dd2
2 changed files with 44 additions and 6 deletions

View file

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

View file

@ -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 */