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:
parent
2b601fa3a0
commit
200a669dd2
2 changed files with 44 additions and 6 deletions
|
|
@ -1,4 +1,4 @@
|
||||||
# Copyright 2019,2023 NXP
|
# Copyright 2019,2023-2024 NXP
|
||||||
# Copyright (c) 2022, Basalte bv
|
# Copyright (c) 2022, Basalte bv
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
|
@ -105,6 +105,33 @@ config MCUX_ELCDIF_PXP_ROTATE_270
|
||||||
|
|
||||||
endchoice
|
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 # MCUX_ELCDIF_PXP
|
||||||
|
|
||||||
endif # DISPLAY_MCUX_ELCDIF
|
endif # DISPLAY_MCUX_ELCDIF
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2019-23, NXP
|
* Copyright 2019-24, NXP
|
||||||
* Copyright (c) 2022, Basalte bv
|
* Copyright (c) 2022, Basalte bv
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
@ -54,7 +54,7 @@ struct mcux_elcdif_data {
|
||||||
/* Tracks index of next active driver framebuffer */
|
/* Tracks index of next active driver framebuffer */
|
||||||
uint8_t next_idx;
|
uint8_t next_idx;
|
||||||
#ifdef CONFIG_MCUX_ELCDIF_PXP
|
#ifdef CONFIG_MCUX_ELCDIF_PXP
|
||||||
/* Given to when PXP completes rotation */
|
/* Given to when PXP completes operation */
|
||||||
struct k_sem pxp_done;
|
struct k_sem pxp_done;
|
||||||
#endif
|
#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
|
#ifdef CONFIG_MCUX_ELCDIF_PXP
|
||||||
if (full_fb) {
|
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_config pxp_dma = {0};
|
||||||
struct dma_block_config pxp_block = {0};
|
struct dma_block_config pxp_block = {0};
|
||||||
|
|
||||||
/* Source buffer is input to display_write, we will
|
/* 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];
|
dev_data->active_fb = dev_data->fb[dev_data->next_idx];
|
||||||
pxp_block.source_address = (uint32_t)buf;
|
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);
|
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.channel_direction = MEMORY_TO_MEMORY;
|
||||||
pxp_dma.source_data_size = desc->width * dev_data->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;
|
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);
|
k_sem_take(&dev_data->pxp_done, K_FOREVER);
|
||||||
} else {
|
} 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");
|
"framebuffer is provided");
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_MCUX_ELCDIF_PXP */
|
#endif /* CONFIG_MCUX_ELCDIF_PXP */
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue