diff --git a/arch/arm/src/stm32/Kconfig b/arch/arm/src/stm32/Kconfig index 4cfa51a0cfd..93e2cbfcd42 100644 --- a/arch/arm/src/stm32/Kconfig +++ b/arch/arm/src/stm32/Kconfig @@ -8176,8 +8176,8 @@ config STM32_LTDC_FB_BASE config STM32_LTDC_FB_SIZE int "Framebuffer memory size (bytes)" default 0 - ---help--- - Must be the whole size of the active LTDC layer. + ---help--- + Must be the whole size of the active LTDC layer. config STM32_LTDC_L1_CHROMAKEYEN bool "Enable chromakey support for layer 1" diff --git a/arch/arm/src/stm32/stm32_ltdc.h b/arch/arm/src/stm32/stm32_ltdc.h index e37cb7d6335..d4b16e728fe 100644 --- a/arch/arm/src/stm32/stm32_ltdc.h +++ b/arch/arm/src/stm32/stm32_ltdc.h @@ -49,22 +49,6 @@ #include #include -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - -/**************************************************************************** - * Public Types - ****************************************************************************/ - -/**************************************************************************** - * Public Data - ****************************************************************************/ - -/**************************************************************************** - * Inline Functions - ****************************************************************************/ - /**************************************************************************** * Public Functions ****************************************************************************/ diff --git a/arch/arm/src/stm32f7/Kconfig b/arch/arm/src/stm32f7/Kconfig index 4f07188d097..21d321f2268 100644 --- a/arch/arm/src/stm32f7/Kconfig +++ b/arch/arm/src/stm32f7/Kconfig @@ -1317,6 +1317,8 @@ config STM32F7_DSIHOST config STM32F7_DMA2D bool "DMA2D" default n + select FB + select FB_OVERLAY depends on STM32F7_HAVE_DMA2D ---help--- The STM32 DMA2D is an Chrom-Art Accelerator for image manipulation @@ -1379,6 +1381,7 @@ config STM32F7_LPTIM1 config STM32F7_LTDC bool "LTDC" default n + select FB depends on STM32F7_HAVE_LTDC ---help--- The STM32 LTDC is an LCD-TFT Display Controller available on @@ -4881,12 +4884,6 @@ if STM32F7_LTDC menu "LTDC Configuration" -config STM32F7_LTDC_INTERFACE - bool "LTDC interface support" - default n - ---help--- - Enable the ltdc interface to support ltdc layer control. - config STM32F7_LTDC_USE_DSI bool "Use DSI as display connection" default n @@ -4942,6 +4939,7 @@ config STM32F7_LTDC_DITHER_BLUE config STM32F7_LTDC_FB_BASE hex "Framebuffer memory start address" + default 0 ---help--- If you are using the LTDC, then you must provide the address of the start of the framebuffer. This address will typically @@ -4950,6 +4948,20 @@ config STM32F7_LTDC_FB_BASE config STM32F7_LTDC_FB_SIZE int "Framebuffer memory size (bytes)" default 0 + ---help--- + Must be the whole size of the active LTDC layer. + +config STM32F7_LTDC_L1_CHROMAKEYEN + bool "Enable chromakey support for layer 1" + default y + +config STM32F7_LTDC_L1_CHROMAKEY + hex "Layer L1 initial chroma key" + default 0x00000000 + +config STM32F7_LTDC_L1_COLOR + hex "Layer L1 default color" + default 0x00000000 choice prompt "Layer 1 color format" @@ -4957,27 +4969,35 @@ choice config STM32F7_LTDC_L1_L8 bool "8 bpp L8 (8-bit CLUT)" + depends on FB_CMAP config STM32F7_LTDC_L1_AL44 bool "8 bpp AL44 (4-bit alpha + 4-bit CLUT)" + depends on FB_CMAP config STM32F7_LTDC_L1_AL88 bool "16 bpp AL88 (8-bit alpha + 8-bit CLUT)" + depends on FB_CMAP config STM32F7_LTDC_L1_RGB565 bool "16 bpp RGB 565" + depends on !FB_CMAP config STM32F7_LTDC_L1_ARGB4444 bool "16 bpp ARGB 4444" + depends on !FB_CMAP config STM32F7_LTDC_L1_ARGB1555 bool "16 bpp ARGB 1555" + depends on !FB_CMAP config STM32F7_LTDC_L1_RGB888 bool "24 bpp RGB 888" + depends on !FB_CMAP config STM32F7_LTDC_L1_ARGB8888 bool "32 bpp ARGB 8888" + depends on !FB_CMAP endchoice # Layer 1 color format @@ -4987,40 +5007,58 @@ config STM32F7_LTDC_L2 if STM32F7_LTDC_L2 +config STM32F7_LTDC_L2_COLOR + hex "Layer L2 default color" + default 0x00000000 + +config STM32F7_LTDC_L2_CHROMAKEYEN + bool "Enable chromakey support for layer 2" + default y + +config STM32F7_LTDC_L2_CHROMAKEY + hex "Layer L2 initial chroma key" + default 0x00000000 + choice prompt "Layer 2 (top layer) color format" default STM32F7_LTDC_L2_RGB565 config STM32F7_LTDC_L2_L8 + depends on STM32F7_LTDC_L1_L8 bool "8 bpp L8 (8-bit CLUT)" config STM32F7_LTDC_L2_AL44 + depends on STM32F7_LTDC_L1_AL44 bool "8 bpp AL44 (4-bit alpha + 4-bit CLUT)" config STM32F7_LTDC_L2_AL88 + depends on STM32F7_LTDC_L1_AL88 bool "16 bpp AL88 (8-bit alpha + 8-bit CLUT)" config STM32F7_LTDC_L2_RGB565 + depends on STM32F7_LTDC_L1_RGB565 bool "16 bpp RGB 565" config STM32F7_LTDC_L2_ARGB4444 + depends on STM32F7_LTDC_L1_ARGB4444 bool "16 bpp ARGB 4444" config STM32F7_LTDC_L2_ARGB1555 + depends on STM32F7_LTDC_L1_ARGB1555 bool "16 bpp ARGB 1555" config STM32F7_LTDC_L2_RGB888 + depends on STM32F7_LTDC_L1_RGB888 bool "24 bpp RGB 888" config STM32F7_LTDC_L2_ARGB8888 + depends on STM32F7_LTDC_L1_ARGB8888 bool "32 bpp ARGB 8888" endchoice # Layer 2 color format endif # STM32F7_LTDC_L2 -if STM32F7_LTDC_L1_L8 || STM32F7_LTDC_L2_L8 - config FB_CMAP bool "Enable color map support" default y @@ -5030,12 +5068,11 @@ config FB_CMAP config FB_TRANSPARENCY bool "Enable transparency color map support" default y + depends on FB_CMAP ---help--- Enabling transparency color map support is neccessary for ltdc L8 format. -endif - config STM32F7_LTDC_REGDEBUG bool "Enable LTDC register value debug messages" default n @@ -5053,49 +5090,93 @@ if STM32F7_DMA2D menu "DMA2D Configuration" config STM32F7_DMA2D_NLAYERS - int "Number DMA2D layers" - default 2 + int "Number DMA2D overlays" + default 1 + range 1 256 ---help--- - Number of allocatable DMA2D layers except the LTDC layer. + Number of supported DMA2D layer. + +config STM32F7_DMA2D_LAYER_SHARED + bool "Overlays shared memory region" + default n + ---help--- + Several overlays can share the same memory region. + Setup a whole memory area (usually multiple size of the visible screen) + allows image preprocessing before they become visible by blit operation. + +config STM32F7_DMA2D_LAYER_PPLINE + int "Pixel per line" + default 1 + range 1 65535 + ---help--- + If you are using the DMA2D, then you must provide the pixel per line or + width of the overlay. + +config STM32F7_DMA2D_FB_BASE + hex "Framebuffer memory start address" + default 0 + ---help--- + If you are using the DMA2D, then you must provide the address + of the start of the DMA2D overlays framebuffer. This address will typically + be in the SRAM or SDRAM memory region of the FSMC. + +config STM32F7_DMA2D_FB_SIZE + int "Framebuffer memory size (bytes)" + default 0 + ---help--- + Must be the whole size of all DMA2D overlays. menu "Supported pixel format" config STM32F7_DMA2D_L8 - depends on FB_CMAP + depends on FB_CMAP && STM32F7_LTDC_L1_L8 bool "8 bpp L8 (8-bit CLUT)" default y config STM32F7_DMA2D_AL44 - depends on FB_CMAP + depends on FB_CMAP && STM32F7_LTDC_L1_AL44 bool "8 bpp AL44 (4-bit alpha + 4-bit CLUT)" - default n + default y config STM32F7_DMA2D_AL88 - depends on FB_CMAP + depends on FB_CMAP && STM32F7_LTDC_L1_AL88 bool "16 bpp AL88 (8-bit alpha + 8-bit CLUT)" - default n + default y config STM32F7_DMA2D_RGB565 bool "16 bpp RGB 565" + depends on STM32F7_LTDC_L1_RGB565 default y config STM32F7_DMA2D_ARGB4444 bool "16 bpp ARGB 4444" - default n + depends on STM32F7_LTDC_L1_ARGB4444 + default y config STM32F7_DMA2D_ARGB1555 bool "16 bpp ARGB 1555" - default n + depends on STM32F7_LTDC_L1_ARGB15555 + default y config STM32F7_DMA2D_RGB888 bool "24 bpp RGB 888" + depends on STM32F7_LTDC_L1_RGB888 default y config STM32F7_DMA2D_ARGB8888 bool "32 bpp ARGB 8888" - default n + depends on STM32F7_LTDC_L1_ARGB8888 + default y endmenu + +config STM32F7_DMA2D_REGDEBUG + bool "DMA2D Register level debug" + depends on DEBUG_INFO && DEBUG_LCD + default n + ---help--- + Output detailed register-level DMA2D device debug information. + endmenu endif # STM32F7_DMA2D diff --git a/arch/arm/src/stm32f7/chip/stm32_dma2d.h b/arch/arm/src/stm32f7/chip/stm32_dma2d.h index 7a44561a1db..e21130b73d6 100644 --- a/arch/arm/src/stm32f7/chip/stm32_dma2d.h +++ b/arch/arm/src/stm32f7/chip/stm32_dma2d.h @@ -1,5 +1,5 @@ /**************************************************************************** - * arch/arm/src/stm32/chip/stm32_dma2d.h + * arch/arm/src/stm32f7/chip/stm32_dma2d.h * * Copyright (C) 2014-2015 Marco Krahl. All rights reserved. * Author: Marco Krahl @@ -33,8 +33,8 @@ * ****************************************************************************/ -#ifndef __ARCH_ARM_SRC_STM32_CHIP_STM32_DMA2D_H -#define __ARCH_ARM_SRC_STM32_CHIP_STM32_DMA2D_H +#ifndef __ARCH_ARM_SRC_STM32F7_CHIP_STM32_DMA2D_H +#define __ARCH_ARM_SRC_STM32F7_CHIP_STM32_DMA2D_H /**************************************************************************** * Included Files @@ -70,29 +70,29 @@ #define STM32_DMA2D_OOR_OFFSET 0x0040 /* DMA2D Output Offset Register */ #define STM32_DMA2D_NLR_OFFSET 0x0044 /* DMA2D Number Of Line Register */ #define STM32_DMA2D_LWR_OFFSET 0x0048 /* DMA2D Line Watermark Register */ -#define STM32_DMA2D_AMTCR_OFFSET 0x004C /* DMA2D AHB Master Time Configuration Register */ +#define STM32_DMA2D_AMTCR_OFFSET 0x004c /* DMA2D AHB Master Time Configuration Register */ /* DMA2D Register Addresses **************************************************/ -#define STM32_DMA2D_CR (STM32_DMA2D_BASE+STM32_DMA2D_CR_OFFSET) -#define STM32_DMA2D_ISR (STM32_DMA2D_BASE+STM32_DMA2D_ISR_OFFSET) -#define STM32_DMA2D_IFCR (STM32_DMA2D_BASE+STM32_DMA2D_IFCR_OFFSET) -#define STM32_DMA2D_FGMAR (STM32_DMA2D_BASE+STM32_DMA2D_FGMAR_OFFSET) -#define STM32_DMA2D_FGOR (STM32_DMA2D_BASE+STM32_DMA2D_FGOR_OFFSET) -#define STM32_DMA2D_BGMAR (STM32_DMA2D_BASE+STM32_DMA2D_BGMAR_OFFSET) -#define STM32_DMA2D_BGOR (STM32_DMA2D_BASE+STM32_DMA2D_BGOR_OFFSET) -#define STM32_DMA2D_FGPFCCR (STM32_DMA2D_BASE+STM32_DMA2D_FGPFCCR_OFFSET) -#define STM32_DMA2D_FGCOLR (STM32_DMA2D_BASE+STM32_DMA2D_FGCOLR_OFFSET) -#define STM32_DMA2D_BGPFCCR (STM32_DMA2D_BASE+STM32_DMA2D_BGPFCCR_OFFSET) -#define STM32_DMA2D_BGCOLR (STM32_DMA2D_BASE+STM32_DMA2D_BGCOLR_OFFSET) -#define STM32_DMA2D_FGCMAR (STM32_DMA2D_BASE+STM32_DMA2D_FGCMAR_OFFSET) -#define STM32_DMA2D_BGCMAR (STM32_DMA2D_BASE+STM32_DMA2D_BGCMAR_OFFSET) -#define STM32_DMA2D_OPFCCR (STM32_DMA2D_BASE+STM32_DMA2D_OPFCCR_OFFSET) -#define STM32_DMA2D_OCOLR (STM32_DMA2D_BASE+STM32_DMA2D_OCOLR_OFFSET) -#define STM32_DMA2D_OMAR (STM32_DMA2D_BASE+STM32_DMA2D_OMAR_OFFSET) -#define STM32_DMA2D_OOR (STM32_DMA2D_BASE+STM32_DMA2D_OOR_OFFSET) -#define STM32_DMA2D_NLR (STM32_DMA2D_BASE+STM32_DMA2D_NLR_OFFSET) -#define STM32_DMA2D_LWR (STM32_DMA2D_BASE+STM32_DMA2D_LWR_OFFSET) +#define STM32_DMA2D_CR (STM32_DMA2D_BASE + STM32_DMA2D_CR_OFFSET) +#define STM32_DMA2D_ISR (STM32_DMA2D_BASE + STM32_DMA2D_ISR_OFFSET) +#define STM32_DMA2D_IFCR (STM32_DMA2D_BASE + STM32_DMA2D_IFCR_OFFSET) +#define STM32_DMA2D_FGMAR (STM32_DMA2D_BASE + STM32_DMA2D_FGMAR_OFFSET) +#define STM32_DMA2D_FGOR (STM32_DMA2D_BASE + STM32_DMA2D_FGOR_OFFSET) +#define STM32_DMA2D_BGMAR (STM32_DMA2D_BASE + STM32_DMA2D_BGMAR_OFFSET) +#define STM32_DMA2D_BGOR (STM32_DMA2D_BASE + STM32_DMA2D_BGOR_OFFSET) +#define STM32_DMA2D_FGPFCCR (STM32_DMA2D_BASE + STM32_DMA2D_FGPFCCR_OFFSET) +#define STM32_DMA2D_FGCOLR (STM32_DMA2D_BASE + STM32_DMA2D_FGCOLR_OFFSET) +#define STM32_DMA2D_BGPFCCR (STM32_DMA2D_BASE + STM32_DMA2D_BGPFCCR_OFFSET) +#define STM32_DMA2D_BGCOLR (STM32_DMA2D_BASE + STM32_DMA2D_BGCOLR_OFFSET) +#define STM32_DMA2D_FGCMAR (STM32_DMA2D_BASE + STM32_DMA2D_FGCMAR_OFFSET) +#define STM32_DMA2D_BGCMAR (STM32_DMA2D_BASE + STM32_DMA2D_BGCMAR_OFFSET) +#define STM32_DMA2D_OPFCCR (STM32_DMA2D_BASE + STM32_DMA2D_OPFCCR_OFFSET) +#define STM32_DMA2D_OCOLR (STM32_DMA2D_BASE + STM32_DMA2D_OCOLR_OFFSET) +#define STM32_DMA2D_OMAR (STM32_DMA2D_BASE + STM32_DMA2D_OMAR_OFFSET) +#define STM32_DMA2D_OOR (STM32_DMA2D_BASE + STM32_DMA2D_OOR_OFFSET) +#define STM32_DMA2D_NLR (STM32_DMA2D_BASE + STM32_DMA2D_NLR_OFFSET) +#define STM32_DMA2D_LWR (STM32_DMA2D_BASE + STM32_DMA2D_LWR_OFFSET) /* DMA2D Register Bit Definitions ********************************************/ @@ -156,6 +156,12 @@ #define DMA2D_xGPFCCR_ALPHA_MASK (0xFF << DMA2D_xGPFCCR_ALPHA_SHIFT) #define DMA2D_xGPFCCR_ALPHA(n) ((uint32_t)(n) << DMA2D_xGPFCCR_ALPHA_SHIFT) +/* DMA2D PFC alpha mode */ + +#define STM32_DMA2D_PFCCR_AM_NONE 0 +#define STM32_DMA2D_PFCCR_AM_CONST 1 +#define STM32_DMA2D_PFCCR_AM_PIXEL 2 + /* DMA2D Foreground/Background Color Register */ #define DMA2D_xGCOLR_BLUE_SHIFT (0) /* Bits 0-7 Blue Value */ @@ -178,6 +184,20 @@ #define DMA2D_OPFCCR_CM_MASK (7 << DMA2D_OPFCCR_CM_SHIFT) #define DMA2D_OPFCCR_CM(n) ((uint32_t)(n) << DMA2D_OPFCCR_CM_SHIFT) +/* DMA2D PFC Pixel Format */ + +#define DMA2D_PF_ARGB8888 0 +#define DMA2D_PF_RGB888 1 +#define DMA2D_PF_RGB565 2 +#define DMA2D_PF_ARGB1555 3 +#define DMA2D_PF_ARGB14444 4 +#define DMA2D_PF_L8 5 +#define DMA2D_PF_AL44 6 +#define DMA2D_PF_AL88 7 +#define DMA2D_PF_L4 8 +#define DMA2D_PF_A8 9 +#define DMA2D_PF_A4 10 + /* DMA2D Output Color Register */ #define DMA2D_OCOLR_BLUE_SHIFT (0) /* Bits 0-7 Blue Value */ @@ -227,4 +247,4 @@ * Public Types ****************************************************************************/ -#endif /* __ARCH_ARM_SRC_STM32_CHIP_STM32_DMA2D_H */ +#endif /* __ARCH_ARM_SRC_STM32F7_CHIP_STM32_DMA2D_H */ diff --git a/arch/arm/src/stm32f7/chip/stm32_ltdc.h b/arch/arm/src/stm32f7/chip/stm32_ltdc.h index ca7e1cd715a..1bac6074874 100644 --- a/arch/arm/src/stm32f7/chip/stm32_ltdc.h +++ b/arch/arm/src/stm32f7/chip/stm32_ltdc.h @@ -1,5 +1,5 @@ /************************************************************************************ - * arch/arm/src/stm32/chip/stm32_ltdc.h + * arch/arm/src/stm32f7/chip/stm32_ltdc.h * * Copyright (C) 2013 Ken Pettit. All rights reserved. * Author: Ken Pettit diff --git a/arch/arm/src/stm32f7/stm32_dma2d.c b/arch/arm/src/stm32f7/stm32_dma2d.c index d4c8ae7e09c..54130c542ff 100644 --- a/arch/arm/src/stm32f7/stm32_dma2d.c +++ b/arch/arm/src/stm32f7/stm32_dma2d.c @@ -1,7 +1,7 @@ /**************************************************************************** - * arch/arm/src/stm32/stm32_dma2d.c + * arch/arm/src/stm32f7/stm32_dma2d.c * - * Copyright (C) 2014-2015 Marco Krahl. All rights reserved. + * Copyright (C) 2014-2015, 2018 Marco Krahl. All rights reserved. * Author: Marco Krahl * * References: @@ -68,91 +68,50 @@ * Pre-processor Definitions ****************************************************************************/ -/* output, foreground and background layer */ +/* DMA2D supported operation layer (output, foreground, background) */ -#define DMA2D_NLAYERS 3 - -/* DMA2D PFC value definitions */ - -#define DMA2D_PF_ARGB8888 0 -#define DMA2D_PF_RGB888 1 -#define DMA2D_PF_RGB565 2 -#define DMA2D_PF_ARGB1555 3 -#define DMA2D_PF_ARGB14444 4 -#define DMA2D_PF_L8 5 -#define DMA2D_PF_AL44 6 -#define DMA2D_PF_AL88 7 -#define DMA2D_PF_L4 8 -#define DMA2D_PF_A8 9 -#define DMA2D_PF_A4 10 +#define DMA2D_NLAYERS 3 /* DMA2D blender control */ -#define STM32_DMA2D_CR_MODE_BLIT DMA2D_CR_MODE(0) -#define STM32_DMA2D_CR_MODE_BLITPFC DMA2D_CR_MODE(1) -#define STM32_DMA2D_CR_MODE_BLEND DMA2D_CR_MODE(2) -#define STM32_DMA2D_CR_MODE_COLOR DMA2D_CR_MODE(3) -#define STM32_DMA2D_CR_MODE_CLEAR STM32_DMA2D_CR_MODE_COLOR - -/* DMA2D PFC alpha mode */ - -#define STM32_DMA2D_PFCCR_AM_NONE 0 -#define STM32_DMA2D_PFCCR_AM_CONST 1 -#define STM32_DMA2D_PFCCR_AM_PIXEL 10 +#define STM32F7_DMA2D_CR_MODE_BLIT DMA2D_CR_MODE(0) +#define STM32F7_DMA2D_CR_MODE_BLITPFC DMA2D_CR_MODE(1) +#define STM32F7_DMA2D_CR_MODE_BLEND DMA2D_CR_MODE(2) +#define STM32F7_DMA2D_CR_MODE_COLOR DMA2D_CR_MODE(3) +#define STM32F7_DMA2D_CR_MODE_CLEAR STM32_DMA2D_CR_MODE_BLITPFC | \ + STM32_DMA2D_CR_MODE_BLEND | \ + STM32_DMA2D_CR_MODE_COLOR /* Only 8 bit per pixel overal supported */ -#define DMA2D_PF_BYPP(n) ((n) / 8) +#define DMA2D_PF_BYPP(n) ((n) / 8) -#define DMA2D_CLUT_SIZE STM32_LTDC_NCLUT - 1 +/* CC clut size */ + +#define DMA2D_CLUT_SIZE STM32F7_DMA2D_NCLUT - 1 /* Layer argb cmap conversion */ -#define DMA2D_CLUT_ALPHA(n) ((uint32_t)(n) << 24) -#define DMA2D_CLUT_RED(n) ((uint32_t)(n) << 16) -#define DMA2D_CLUT_GREEN(n) ((uint32_t)(n) << 8) -#define DMA2D_CLUT_BLUE(n) ((uint32_t)(n) << 0) +#define DMA2D_CLUT_ALPHA(n) ((uint32_t)(n) << 24) +#define DMA2D_CLUT_RED(n) ((uint32_t)(n) << 16) +#define DMA2D_CLUT_GREEN(n) ((uint32_t)(n) << 8) +#define DMA2D_CLUT_BLUE(n) ((uint32_t)(n) << 0) -#define DMA2D_CMAP_ALPHA(n) ((uint32_t)(n) >> 24) -#define DMA2D_CMAP_RED(n) ((uint32_t)(n) >> 16) -#define DMA2D_CMAP_GREEN(n) ((uint32_t)(n) >> 8) -#define DMA2D_CMAP_BLUE(n) ((uint32_t)(n) >> 0) - -/* Define shadow layer for ltdc interface */ - -#ifdef CONFIG_STM32F7_LTDC_INTERFACE -# ifdef CONFIG_STM32F7_LTDC_L2 -# define DMA2D_SHADOW_LAYER 2 -# define DMA2D_SHADOW_LAYER_L1 0 -# define DMA2D_SHADOW_LAYER_L2 1 -# else -# define DMA2D_SHADOW_LAYER 1 -# define DMA2D_SHADOW_LAYER_L1 0 -# endif -# define DMA2D_LAYER_NSIZE CONFIG_STM32F7_DMA2D_NLAYERS + DMA2D_SHADOW_LAYER -#else -# define DMA2D_LAYER_NSIZE CONFIG_STM32F7_DMA2D_NLAYERS -# define DMA2D_SHADOW_LAYER 0 -#endif +#define DMA2D_CMAP_ALPHA(n) ((uint32_t)(n) >> 24) +#define DMA2D_CMAP_RED(n) ((uint32_t)(n) >> 16) +#define DMA2D_CMAP_GREEN(n) ((uint32_t)(n) >> 8) +#define DMA2D_CMAP_BLUE(n) ((uint32_t)(n) >> 0) /* Debug option */ #ifdef CONFIG_STM32F7_DMA2D_REGDEBUG -# define regerr lcderr -# define reginfo lcdinfo +# define regerr lcderr +# define reginfo lcdinfo #else # define regerr(x...) # define reginfo(x...) #endif -/* check clut support */ - -#ifdef CONFIG_STM32F7_DMA2D_L8 -# ifndef CONFIG_FB_CMAP -# error "Enable cmap to support the configured layer formats!" -# endif -#endif - /**************************************************************************** * Private Types ****************************************************************************/ @@ -161,58 +120,22 @@ struct stm32_dma2d_s { - struct dma2d_layer_s dma2d; /* public dma2d interface */ + struct dma2d_layer_s dma2d; /* Public dma2d interface */ - /* Fixed settings */ - - int lid; /* Layer identifier */ - struct fb_videoinfo_s vinfo; /* Layer videoinfo */ - struct fb_planeinfo_s pinfo; /* Layer planeinfo */ - - /* Blending */ - - uint32_t blendmode; /* the interface blendmode */ - uint8_t alpha; /* the alpha value */ - - /* Coloring */ - -#ifdef CONFIG_STM32F7_DMA2D_L8 - uint32_t *clut; /* Color lookup table */ +#ifdef CONFIG_FB_CMAP + uint32_t *clut; /* Color lookup table */ #endif - /* Operation */ - uint8_t fmt; /* the controller pixel format */ - sem_t *lock; /* Ensure mutually exclusive access */ + sem_t *lock; /* Ensure mutually exclusive access */ }; -#ifdef CONFIG_STM32F7_LTDC_INTERFACE - -/* This structures provides the DMA2D layer for each LTDC layer */ - -struct stm32_ltdc_dma2d_s -{ - struct stm32_dma2d_s dma2ddev; -#ifdef CONFIG_STM32F7_DMA2D_L8 - FAR struct ltdc_layer_s *ltdc; -#endif -}; - -struct stm32_ltdc_layer_s -{ - /* Layer state */ - - struct stm32_ltdc_dma2d_s layer[DMA2D_SHADOW_LAYER]; -}; -#endif - /* Interrupt handling */ struct stm32_interrupt_s { - bool wait; /* Informs that the task is waiting for the irq */ - bool handled; /* Informs that an irq was handled */ - int irq; /* irq number */ - sem_t *sem; /* Semaphore for waiting for irq */ + int irq; /* irq number */ + int error; /* Interrupt error */ + sem_t *sem; /* Semaphore for waiting for irq */ }; /* This enumeration foreground and background layer supported by the dma2d @@ -262,7 +185,7 @@ static const uintptr_t stm32_color_layer_t[DMA2D_NLAYERS] = STM32_DMA2D_OCOLR }; -#if defined(CONFIG_STM32F7_DMA2D_L8) +#ifdef CONFIG_FB_CMAP /* DMA2D clut memory address register */ static const uintptr_t stm32_cmar_layer_t[DMA2D_NLAYERS - 1] = @@ -278,95 +201,69 @@ static const uintptr_t stm32_cmar_layer_t[DMA2D_NLAYERS - 1] = /* Private functions */ -static int stm32_dma2d_pixelformat(uint8_t fmt, uint8_t *fmtmap); -static int stm32_dma2d_bpp(uint8_t fmt, uint8_t *bpp); static void stm32_dma2d_control(uint32_t setbits, uint32_t clrbits); static int stm32_dma2dirq(int irq, void *context, FAR void *arg); static int stm32_dma2d_waitforirq(void); static int stm32_dma2d_start(void); -#ifdef CONFIG_STM32F7_DMA2D_L8 +#ifdef CONFIG_FB_CMAP static int stm32_dma2d_loadclut(uintptr_t reg); #endif -static uint32_t stm32_dma2d_memaddress(FAR const struct stm32_dma2d_s *layer, - fb_coord_t xpos, fb_coord_t ypos); -static fb_coord_t stm32_dma2d_lineoffset(FAR const struct stm32_dma2d_s *layer, - FAR const struct ltdc_area_s *area); +static uint32_t stm32_dma2d_memaddress(FAR struct stm32_dma2d_overlay_s *oinfo, + uint32_t xpos, uint32_t ypos); +static uint32_t stm32_dma2d_lineoffset(FAR struct stm32_dma2d_overlay_s *oinfo, + FAR const struct fb_area_s *area); +static void stm32_dma2d_lfifo(FAR struct stm32_dma2d_overlay_s *oinfo, int lid, + uint32_t xpos, uint32_t ypos, + FAR const struct fb_area_s *area); +static void stm32_dma2d_lcolor(int lid, uint32_t argb); +static void stm32_dma2d_llnr(FAR const struct fb_area_s *area); +static int stm32_dma2d_loutpfc(uint8_t fmt); +static void stm32_dma2d_lpfc(int lid, uint32_t blendmode, uint8_t alpha, + uint8_t fmt); -static int stm32_dma2d_lfreelid(void); -static FAR struct stm32_dma2d_s * stm32_dma2d_lalloc(void); -static void stm32_dma2d_lfree(FAR struct stm32_dma2d_s *layer); -static void stm32_dma2d_llayerscleanup(void); -static bool stm32_dma2d_lvalidate(FAR const struct stm32_dma2d_s *layer); -static bool stm32_dma2d_lvalidatesize(FAR const struct stm32_dma2d_s *layer, - fb_coord_t xpos, fb_coord_t ypos, - FAR const struct ltdc_area_s *area); -static void stm32_dma2d_linit(FAR struct stm32_dma2d_s *layer, - int lid, uint8_t fmt); - -static void stm32_dma2d_lfifo(FAR const struct stm32_dma2d_s *layer, int lid, - fb_coord_t xpos, fb_coord_t ypos, - FAR const struct ltdc_area_s *area); -static void stm32_dma2d_lcolor(FAR const struct stm32_dma2d_s *layer, - int lid, uint32_t color); -static void stm32_dma2d_llnr(FAR struct stm32_dma2d_s *layer, - FAR const struct ltdc_area_s *area); -static int stm32_dma2d_loutpfc(FAR const struct stm32_dma2d_s *layer); -static void stm32_dma2d_lpfc(FAR const struct stm32_dma2d_s *layer, - int lid, uint32_t blendmode); /* Public functions */ -static int stm32_dma2dgetvideoinfo(FAR struct dma2d_layer_s *layer, - FAR struct fb_videoinfo_s *vinfo); -static int stm32_dma2dgetplaneinfo(FAR struct dma2d_layer_s *layer, int planeno, - FAR struct fb_planeinfo_s *pinfo); -static int stm32_dma2dgetlid(FAR struct dma2d_layer_s *layer, int *lid); -#ifdef CONFIG_STM32F7_DMA2D_L8 -static int stm32_dma2dsetclut(FAR struct dma2d_layer_s *layer, - const FAR struct fb_cmap_s *cmap); -static int stm32_dma2dgetclut(FAR struct dma2d_layer_s *layer, - FAR struct fb_cmap_s *cmap); +#ifdef CONFIG_FB_CMAP +static int stm32_dma2d_setclut(FAR const struct fb_cmap_s *cmap); #endif -static int stm32_dma2dsetalpha(FAR struct dma2d_layer_s *layer, uint8_t alpha); -static int stm32_dma2dgetalpha(FAR struct dma2d_layer_s *layer, uint8_t *alpha); -static int stm32_dma2dsetblendmode(FAR struct dma2d_layer_s *layer, - uint32_t mode); -static int stm32_dma2dgetblendmode(FAR struct dma2d_layer_s *layer, - uint32_t *mode); -static int stm32_dma2dblit(FAR struct dma2d_layer_s *dest, - fb_coord_t destxpos, fb_coord_t destypos, - FAR const struct dma2d_layer_s *src, - FAR const struct ltdc_area_s *srcarea); -static int stm32_dma2dblend(FAR struct dma2d_layer_s *dest, - fb_coord_t destxpos, fb_coord_t destypos, - FAR const struct dma2d_layer_s *fore, - fb_coord_t forexpos, fb_coord_t foreypos, - FAR const struct dma2d_layer_s *back, - FAR const struct ltdc_area_s *backarea); -static int stm32_dma2dfillarea(FAR struct dma2d_layer_s *layer, - FAR const struct ltdc_area_s *area, uint32_t color); +static int stm32_dma2d_fillcolor(FAR struct stm32_dma2d_overlay_s *oinfo, + FAR const struct fb_area_s *area, + uint32_t argb); +static int stm32_dma2d_blit(FAR struct stm32_dma2d_overlay_s *doverlay, + uint32_t destxpos, uint32_t destypos, + FAR struct stm32_dma2d_overlay_s *soverlay, + FAR const struct fb_area_s *sarea); +static int stm32_dma2d_blend(FAR struct stm32_dma2d_overlay_s *doverlay, + uint32_t destxpos, uint32_t destypos, + FAR struct stm32_dma2d_overlay_s *foverlay, + uint32_t forexpos, uint32_t foreypos, + FAR struct stm32_dma2d_overlay_s *boverlay, + FAR const struct fb_area_s *barea); /**************************************************************************** * Private Data ****************************************************************************/ -/* Remember the layer references for alloc/deallocation */ +/* The initialized state of the driver */ -static struct stm32_dma2d_s *g_layers[DMA2D_LAYER_NSIZE]; +static bool g_initialized; + +/* Allocate clut */ + +#ifdef CONFIG_FB_CMAP +static uint32_t g_clut[STM32_DMA2D_NCLUT * +# ifdef CONFIG_FB_TRANSPARENCY + 4 +# else + 3 +# endif + / 4 ]; +#endif /* CONFIG_FB_CMAP */ /* The DMA2D semaphore that enforces mutually exclusive access */ static sem_t g_lock; -#ifdef CONFIG_STM32F7_LTDC_INTERFACE -/* This structure provides the DMA2D layer for each LTDC layer */ - -static struct stm32_ltdc_layer_s g_ltdc_layer; -#endif - -/* The initalized state of the driver */ - -static bool g_initialized; - /* Semaphore for interrupt handling */ static sem_t g_semirq; @@ -375,12 +272,28 @@ static sem_t g_semirq; static struct stm32_interrupt_s g_interrupt = { - .wait = false, - .handled = true, .irq = STM32_IRQ_DMA2D, + .error = OK, .sem = &g_semirq }; +static struct stm32_dma2d_s g_dma2ddev = +{ + .dma2d = + { +#ifdef CONFIG_FB_CMAP + .setclut = stm32_dma2d_setclut, +#endif + .fillcolor = stm32_dma2d_fillcolor, + .blit = stm32_dma2d_blit, + .blend = stm32_dma2d_blend + }, +#ifdef CONFIG_FB_CMAP + .clut = g_clut, +#endif + .lock = &g_lock +}; + /**************************************************************************** * Public Data ****************************************************************************/ @@ -410,6 +323,8 @@ static void stm32_dma2d_control(uint32_t setbits, uint32_t clrbits) cr = getreg32(STM32_DMA2D_CR); cr &= ~clrbits; cr |= setbits; + + lcdinfo("cr=%08x\n", cr); putreg32(cr, STM32_DMA2D_CR); } @@ -423,6 +338,7 @@ static void stm32_dma2d_control(uint32_t setbits, uint32_t clrbits) static int stm32_dma2dirq(int irq, void *context, FAR void *arg) { + int ret; uint32_t regval = getreg32(STM32_DMA2D_ISR); FAR struct stm32_interrupt_s *priv = &g_interrupt; @@ -434,7 +350,9 @@ static int stm32_dma2dirq(int irq, void *context, FAR void *arg) /* Clear the interrupt status register */ + reginfo("DMA transfer complete\n"); putreg32(DMA2D_IFCR_CTCIF, STM32_DMA2D_IFCR); + priv->error = OK; } #ifdef CONFIG_STM32F7_DMA2D_L8 else if (regval & DMA2D_ISR_CTCIF) @@ -443,31 +361,65 @@ static int stm32_dma2dirq(int irq, void *context, FAR void *arg) /* Clear the interrupt status register */ + reginfo("CLUT transfer complete\n"); putreg32(DMA2D_IFCR_CCTCIF, STM32_DMA2D_IFCR); + priv->error = OK; } #endif + else if (regval & DMA2D_ISR_TWIF) + { + /* Watermark transfer complete interrupt */ + + /* Clear the interrupt status register */ + + reginfo("Watermark transfer complete\n"); + putreg32(DMA2D_IFCR_CTWIF, STM32_DMA2D_IFCR); + priv->error = OK; + } + else if (regval & DMA2D_ISR_TEIF) + { + /* Transfer error interrupt */ + + /* Clear the interrupt status register */ + + reginfo("ERROR: transfer\n"); + putreg32(DMA2D_IFCR_CTEIF, STM32_DMA2D_IFCR); + priv->error = -ECANCELED; + } + else if (regval & DMA2D_ISR_CAEIF) + { + /* CLUT access error interrupt */ + + /* Clear the interrupt status register */ + + reginfo("ERROR: clut access\n"); + putreg32(DMA2D_IFCR_CAECIF, STM32_DMA2D_IFCR); + priv->error = -ECANCELED; + } + else if (regval & DMA2D_ISR_CEIF) + { + /* Configuration error interrupt */ + + /* Clear the interrupt status register */ + + reginfo("ERROR: configuration\n"); + putreg32(DMA2D_IFCR_CCEIF, STM32_DMA2D_IFCR); + priv->error = -ECANCELED; + } else { /* Unknown irq, should not occur */ - return OK; + ASSERT("Unknown interrupt error\n"); } - /* Update the handled flag */ - - priv->handled = true; - /* Unlock the semaphore if locked */ - if (priv->wait) + ret = nxsem_post(priv->sem); + + if (ret < 0) { - - int ret = nxsem_post(priv->sem); - - if (ret < 0) - { - lcderr("ERROR: nxsem_post() failed\n"); - } + lcderr("ERROR: nxsem_post() failed\n"); } return OK; @@ -488,32 +440,20 @@ static int stm32_dma2dirq(int irq, void *context, FAR void *arg) static int stm32_dma2d_waitforirq(void) { + int ret; FAR struct stm32_interrupt_s *priv = &g_interrupt; - /* Only waits if last enabled interrupt is currently not handled */ + ret = nxsem_wait(priv->sem); - if (!priv->handled) + if (ret < 0) { - int ret; - - /* Inform the irq handler the task is able to wait for the irq */ - - priv->wait = true; - - ret = nxsem_wait(priv->sem); - - /* irq or an error occurs, reset the wait flag */ - - priv->wait = false; - - if (ret < 0) - { - lcderr("ERROR: nxsem_wait() failed\n"); - return ret; - } + lcderr("ERROR: nxsem_wait() failed\n"); + return ret; } - return OK; + ret = priv->error; + + return ret; } #ifdef CONFIG_STM32F7_DMA2D_L8 @@ -532,34 +472,25 @@ static int stm32_dma2d_waitforirq(void) * ****************************************************************************/ +#ifdef CONFIG_STM32F7_DMA2D_L8 static int stm32_dma2d_loadclut(uintptr_t pfcreg) { int ret; uint32_t regval; - irqstate_t flags; - flags = enter_critical_section(); + /* Start clut loading */ + + regval = getreg32(pfcreg); + regval |= DMA2D_xGPFCCR_START; + reginfo("set regval=%08x\n", regval); + putreg32(regval, pfcreg); + reginfo("configured regval=%08x\n", getreg32(pfcreg)); + + /* Wait until clut is finished */ ret = stm32_dma2d_waitforirq(); - if (ret == OK) - { - FAR struct stm32_interrupt_s *priv = &g_interrupt; - /* Reset the handled flag */ - - priv->handled = false; - - /* Start clut loading */ - - regval = getreg32(pfcreg); - regval |= DMA2D_xGPFCCR_START; - reginfo("set regval=%08x\n", regval); - putreg32(regval, pfcreg); - reginfo("configured regval=%08x\n", getreg32(pfcreg)); - } - - leave_critical_section(flags); - return OK; + return ret; } #endif @@ -579,29 +510,15 @@ static int stm32_dma2d_loadclut(uintptr_t pfcreg) static int stm32_dma2d_start(void) { int ret; - irqstate_t flags; - flags = enter_critical_section(); + /* Start dma transfer */ + + stm32_dma2d_control(DMA2D_CR_START, 0); + + /* wait until transfer is complete */ ret = stm32_dma2d_waitforirq(); - if (ret == OK) - { - FAR struct stm32_interrupt_s *priv = &g_interrupt; - /* Reset the handled flag */ - - priv->handled = false; - - /* Start clut loading */ - - stm32_dma2d_control(DMA2D_CR_START, 0); - - /* wait until transfer is complete */ - - ret = stm32_dma2d_waitforirq(); - } - - leave_critical_section(flags); return ret; } @@ -612,23 +529,25 @@ static int stm32_dma2d_start(void) * Helper to calculate the layer memory address * * Input Parameters: - * layer - Reference to the common layer state structure + * oinfo - Reference to overlay information + * xpos - x-Offset + * ypos - y-Offset * * Returned Value: * memory address * ****************************************************************************/ -static uint32_t stm32_dma2d_memaddress(FAR const struct stm32_dma2d_s *layer, - fb_coord_t xpos, fb_coord_t ypos) +static uint32_t stm32_dma2d_memaddress(FAR struct stm32_dma2d_overlay_s *oinfo, + uint32_t xpos, uint32_t ypos) { - FAR const struct fb_planeinfo_s *pinfo = &layer->pinfo; uint32_t offset; + FAR struct fb_overlayinfo_s *poverlay = oinfo->oinfo; - offset = xpos * DMA2D_PF_BYPP(layer->pinfo.bpp) + layer->pinfo.stride * ypos; + offset = xpos * DMA2D_PF_BYPP(poverlay->bpp) + poverlay->stride * ypos; - lcdinfo("%p\n", ((uint32_t) pinfo->fbmem) + offset); - return ((uint32_t) pinfo->fbmem) + offset; + lcdinfo("%p, offset=%d\n", ((uint32_t) poverlay->fbmem) + offset, offset); + return ((uint32_t) poverlay->fbmem) + offset; } /**************************************************************************** @@ -638,329 +557,24 @@ static uint32_t stm32_dma2d_memaddress(FAR const struct stm32_dma2d_s *layer, * Helper to calculate the layer line offset * * Input Parameters: - * layer - Reference to the common layer state structure + * oinfo - Reference to overlay information * * Returned Value: * line offset * ****************************************************************************/ -static fb_coord_t stm32_dma2d_lineoffset(FAR const struct stm32_dma2d_s *layer, - FAR const struct ltdc_area_s *area) +static uint32_t stm32_dma2d_lineoffset(FAR struct stm32_dma2d_overlay_s *oinfo, + FAR const struct fb_area_s *area) { + uint32_t loffset; + /* offset at the end of each line in the context to the area layer */ - lcdinfo("%d\n", layer->vinfo.xres - area->xres); - return layer->vinfo.xres - area->xres; -} + loffset = oinfo->xres - area->w; -/**************************************************************************** - * Name: stm32_dma2d_pixelformat - * - * Description: - * Helper to map to dma2d controller pixel format - * - * Input Parameters: - * layer - Reference to the common layer state structure - * fmt - Reference to the location to store the pixel format - * - * Returned Value: - * On success - OK - * On error - -EINVAL - * - ****************************************************************************/ - -static int stm32_dma2d_pixelformat(uint8_t fmt, uint8_t *fmtmap) -{ - lcdinfo("fmt=%d, fmtmap=%p\n", fmt, fmtmap); - - /* Map to the controller known format - * - * Not supported by NuttX: - * ARGB8888 - * ARGB1555 - * ARGB4444 - * AL44 - * AL88 - * L8 (non output layer only) - * L4 - * A8 - * A4 - */ - - switch (fmt) - { -#ifdef CONFIG_STM32F7_DMA2D_RGB565 - case FB_FMT_RGB16_565: - *fmtmap = DMA2D_PF_RGB565; - break; -#endif -#ifdef CONFIG_STM32F7_DMA2D_RGB888 - case FB_FMT_RGB24: - *fmtmap = DMA2D_PF_RGB888; - break; -#endif -#ifdef CONFIG_STM32F7_DMA2D_L8 - case FB_FMT_RGB8: - *fmtmap = DMA2D_PF_L8; - break; -#endif - default: - lcderr("ERROR: Returning EINVAL\n"); - return -EINVAL; - } - - return OK; -} - -/**************************************************************************** - * Name: stm32_dma2d_bpp - * - * Description: - * Helper to get the bits per pixel - * - * Input Parameters: - * layer - Reference to the common layer state structure - * bpp - Reference to the location to store the pixel format - * - * Returned Value: - * On success - OK - * On error - -EINVAL - * - ****************************************************************************/ - -static int stm32_dma2d_bpp(uint8_t fmt, uint8_t *bpp) -{ - lcdinfo("fmt=%d, bpp=%p\n", fmt, bpp); - - switch (fmt) - { -#ifdef CONFIG_STM32F7_DMA2D_RGB565 - case FB_FMT_RGB16_565: - *bpp = 16; - break; -#endif -#ifdef CONFIG_STM32F7_DMA2D_RGB888 - case FB_FMT_RGB24: - *bpp = 24; - break; -#endif -#ifdef CONFIG_STM32F7_DMA2D_L8 - case FB_FMT_RGB8: - *bpp = 8; - break; -#endif - default: - lcderr("ERROR: Returning EINVAL\n"); - return -EINVAL; - } - - return OK; -} - -/**************************************************************************** - * Name: stm32_dma2d_lfreelid - * - * Description: - * Get a free layer id - * - * Returned Value: - * The number of the free layer - * -1 if no free layer is available - * - ****************************************************************************/ - -static int stm32_dma2d_lfreelid(void) -{ - int n; - - for (n = DMA2D_SHADOW_LAYER; n < DMA2D_LAYER_NSIZE; n++) - { - if (g_layers[n] == NULL) - { - return n; - } - } - - return -1; -} - -/**************************************************************************** - * Name: stm32_dma2d_lalloc - * - * Description: - * Allocate a new layer structure - * - * Returned Value: - * A new allocated layer structure or NULL on error. - * - ****************************************************************************/ - -static FAR struct stm32_dma2d_s * stm32_dma2d_lalloc(void) -{ - FAR struct stm32_dma2d_s *layer; - -#ifdef HAVE_DTCM_HEAP - /* First try to allocate from the dtcm heap */ - - layer = dtcm_malloc(sizeof(struct stm32_dma2d_s)); - - if (!layer) - { - /* Use default allocator */ - - layer = kmm_malloc(sizeof(struct stm32_dma2d_s)); - } -#else - layer = kmm_malloc(sizeof(struct stm32_dma2d_s)); -#endif - - return layer; -} - -/**************************************************************************** - * Name: stm32_dma2d_lfree - * - * Description: - * Deallocate the dynamic allocated layer structure - * - * Input Parameters: - * A previous allocated layer structure - * - ****************************************************************************/ - -static void stm32_dma2d_lfree(FAR struct stm32_dma2d_s *layer) -{ - if (layer) - { -#ifdef HAVE_DTCM_HEAP - if ( (void*)(DTCM_START) <= layer && layer <= (void*)(DTCM_END) ) - { - dtcm_free(layer); - } - else - { - kmm_free(layer); - } -#else - kmm_free(layer); -#endif - } -} - -/**************************************************************************** - * Name: stm32_dma2d_llayerscleanup - * - * Description: - * Cleanup all allocated layers - * - ****************************************************************************/ - -static void stm32_dma2d_llayerscleanup(void) -{ - int n; - - /* Do not uninitialize the ltdc related dma2d layer */ - - for (n = DMA2D_SHADOW_LAYER; n < DMA2D_LAYER_NSIZE; n++) - { - FAR struct stm32_dma2d_s *priv = g_layers[n]; - if (priv) - { - kmm_free(priv->pinfo.fbmem); - stm32_dma2d_lfree(priv); - g_layers[n] = NULL; - } - } -} - -/**************************************************************************** - * Name: stm32_dma2d_lvalidate - * - * Description: - * Helper to validate if the layer is valid - * - * Returned Value: - * true if validates otherwise false - * - ****************************************************************************/ - -static inline bool stm32_dma2d_lvalidate(FAR const struct stm32_dma2d_s *layer) -{ - return layer && layer->lid < DMA2D_LAYER_NSIZE; -} - -/**************************************************************************** - * Name: stm32_dma2d_lvalidatesize - * - * Description: - * Helper to check if area is outside the whole layer. - * - * Input Parameters: - * layer - Reference to the layer control structure - * xpos - The x position inside the whole layer - * ypos - The y position inside the whole layer - * area - the area inside the whole layer - * - * Returned Value: - * true if area is inside the whole layer otherwise false - * - ****************************************************************************/ - -static bool stm32_dma2d_lvalidatesize(FAR const struct stm32_dma2d_s *layer, - fb_coord_t xpos, fb_coord_t ypos, - FAR const struct ltdc_area_s *area) -{ - return stm32_dma2d_lvalidate(layer) && - ((layer->vinfo.xres - xpos) * (layer->vinfo.yres - ypos) >= - area->xres * area->yres); -} - -/**************************************************************************** - * Name: stm32_dma2d_linit - * - * Description: - * Initialize the internal layer structure - * - * Input Parameters: - * - * - ****************************************************************************/ - -static void stm32_dma2d_linit(FAR struct stm32_dma2d_s *layer, - int lid, uint8_t fmt) -{ - FAR struct dma2d_layer_s *priv = &layer->dma2d; - - lcdinfo("layer=%p, lid=%d, fmt=%02x\n", layer, lid, fmt); - - /* initialize the layer interface */ - - priv->getvideoinfo = stm32_dma2dgetvideoinfo; - priv->getplaneinfo = stm32_dma2dgetplaneinfo; - priv->getlid = stm32_dma2dgetlid; -#ifdef CONFIG_STM32F7_DMA2D_L8 - priv->setclut = stm32_dma2dsetclut; - priv->getclut = stm32_dma2dgetclut; -#endif - priv->setalpha = stm32_dma2dsetalpha; - priv->getalpha = stm32_dma2dgetalpha; - priv->setblendmode = stm32_dma2dsetblendmode; - priv->getblendmode = stm32_dma2dgetblendmode; - priv->blit = stm32_dma2dblit; - priv->blend = stm32_dma2dblend; - priv->fillarea = stm32_dma2dfillarea; - - /* Initialize the layer structure */ - - layer->lid = lid; -#ifdef CONFIG_STM32F7_DMA2D_L8 - layer->clut = 0; -#endif - layer->blendmode = DMA2D_BLEND_NONE; - layer->alpha = 255; - layer->fmt = fmt; - layer->lock = &g_lock; + lcdinfo("%d\n", loffset); + return loffset; } /**************************************************************************** @@ -976,15 +590,15 @@ static void stm32_dma2d_linit(FAR struct stm32_dma2d_s *layer, * ****************************************************************************/ -static void stm32_dma2d_lfifo(FAR const struct stm32_dma2d_s *layer, int lid, - fb_coord_t xpos, fb_coord_t ypos, - FAR const struct ltdc_area_s *area) +static void stm32_dma2d_lfifo(FAR struct stm32_dma2d_overlay_s *oinfo, + int lid, uint32_t xpos, uint32_t ypos, + FAR const struct fb_area_s *area) { - lcdinfo("layer=%p, lid=%d, xpos=%d, ypos=%d, area=%p\n", - layer, lid, xpos, ypos, area); + lcdinfo("oinfo=%p, lid=%d, xpos=%d, ypos=%d, area=%p\n", + oinfo, lid, xpos, ypos, area); - putreg32(stm32_dma2d_memaddress(layer, xpos, ypos), stm32_mar_layer_t[lid]); - putreg32(stm32_dma2d_lineoffset(layer, area), stm32_or_layer_t[lid]); + putreg32(stm32_dma2d_memaddress(oinfo, xpos, ypos), stm32_mar_layer_t[lid]); + putreg32(stm32_dma2d_lineoffset(oinfo, area), stm32_or_layer_t[lid]); } /**************************************************************************** @@ -994,15 +608,15 @@ static void stm32_dma2d_lfifo(FAR const struct stm32_dma2d_s *layer, int lid, * Set the color for the layer * * Input Parameters: - * layer - Reference to the common layer state structure + * lid - Layer type (output, foreground, background) + * argb - argb8888 color * ****************************************************************************/ -static void stm32_dma2d_lcolor(FAR const struct stm32_dma2d_s *layer, - int lid, uint32_t color) +static void stm32_dma2d_lcolor(int lid, uint32_t argb) { - lcdinfo("layer=%p, lid=%d, color=%08x\n", layer, lid, color); - putreg32(color, stm32_color_layer_t[lid]); + lcdinfo("lid=%d, argb=%08x\n", lid, argb); + putreg32(argb, stm32_color_layer_t[lid]); } /**************************************************************************** @@ -1012,20 +626,18 @@ static void stm32_dma2d_lcolor(FAR const struct stm32_dma2d_s *layer, * Set the number of line register * * Input Parameters: - * layer - Reference to the common layer state structure - * area - Reference to the area to copy + * area - Reference to area information * ****************************************************************************/ -static void stm32_dma2d_llnr(FAR struct stm32_dma2d_s *layer, - FAR const struct ltdc_area_s *area) +static void stm32_dma2d_llnr(FAR const struct fb_area_s *area) { uint32_t nlrreg; - lcdinfo("pixel per line: %d, number of lines: %d\n", area->xres, area->yres); + lcdinfo("pixel per line: %d, number of lines: %d\n", area->w, area->h); nlrreg = getreg32(STM32_DMA2D_NLR); - nlrreg = (DMA2D_NLR_PL(area->xres) | DMA2D_NLR_NL(area->yres)); + nlrreg = (DMA2D_NLR_PL(area->w) | DMA2D_NLR_NL(area->h)); putreg32(nlrreg, STM32_DMA2D_NLR); } @@ -1036,28 +648,17 @@ static void stm32_dma2d_llnr(FAR struct stm32_dma2d_s *layer, * Set the output PFC control register * * Input Parameters: - * layer - Reference to the common layer state structure + * fmt - DMA2D pixel format * ****************************************************************************/ -static int stm32_dma2d_loutpfc(FAR const struct stm32_dma2d_s *layer) +static int stm32_dma2d_loutpfc(uint8_t fmt) { - lcdinfo("layer=%p\n", layer); + lcdinfo("pixel format: %d\n", fmt); - /* CLUT format isn't supported by the dma2d controller */ + /* Set the mapped pixel format of the destination layer */ - if (layer->fmt == DMA2D_PF_L8) - { - /* Destination layer doesn't support CLUT output */ - - lcderr("ERROR: Returning ENOSYS, " - "output to layer with CLUT format not supported.\n"); - return -ENOSYS; - } - - /* Set the mapped pixel format of source layer */ - - putreg32(DMA2D_OPFCCR_CM(layer->fmt), STM32_DMA2D_OPFCCR); + putreg32(DMA2D_OPFCCR_CM(fmt), STM32_DMA2D_OPFCCR); return OK; } @@ -1069,33 +670,38 @@ static int stm32_dma2d_loutpfc(FAR const struct stm32_dma2d_s *layer) * Configure foreground and background layer PFC control register * * Input Parameters: - * layer - Reference to the common layer state structure + * lid - Layer id (output, foreground, background) + * blendmode - Layer blendmode (dma2d register values) + * alpha - Transparency * ****************************************************************************/ -static void stm32_dma2d_lpfc(FAR const struct stm32_dma2d_s *layer, - int lid, uint32_t blendmode) +static void stm32_dma2d_lpfc(int lid, uint32_t blendmode, uint8_t alpha, + uint8_t fmt) { uint32_t pfccrreg; - lcdinfo("layer=%p, lid=%d, blendmode=%08x\n", layer, lid, blendmode); + lcdinfo("lid=%d, blendmode=%08x, alpha=%02x, fmt=%d\n", lid, blendmode, alpha, + fmt); /* Set color format */ - pfccrreg = DMA2D_xGPFCCR_CM(layer->fmt); + pfccrreg = DMA2D_xGPFCCR_CM(fmt); -#ifdef CONFIG_STM32F7_DMA2D_L8 - if (layer->fmt == DMA2D_PF_L8) +#ifdef CONFIG_FB_CMAP + if (fmt == DMA2D_PF_L8) { + FAR struct stm32_dma2d_s * layer = &g_dma2ddev; + /* Load CLUT automatically */ pfccrreg |= DMA2D_xGPFCCR_START; /* Set the CLUT color mode */ -#ifndef CONFIG_FB_TRANSPARENCY +# ifndef CONFIG_FB_TRANSPARENCY pfccrreg |= DMA2D_xGPFCCR_CCM; -#endif +# endif /* Set CLUT size */ @@ -1109,34 +715,19 @@ static void stm32_dma2d_lpfc(FAR const struct stm32_dma2d_s *layer, stm32_dma2d_loadclut(stm32_pfccr_layer_t[lid]); } -#endif +#endif /* CONFIG_FB_CMAP */ - if (blendmode & DMA2D_BLEND_NONE) - { - /* No blend operation */ + /* Set alpha blend mode */ - pfccrreg |= DMA2D_xGPFCCR_AM(STM32_DMA2D_PFCCR_AM_NONE); - } - else + pfccrreg |= DMA2D_xGPFCCR_AM(blendmode); + + if (blendmode == STM32_DMA2D_PFCCR_AM_CONST || + blendmode == STM32_DMA2D_PFCCR_AM_PIXEL) { /* Set alpha value */ - pfccrreg |= DMA2D_xGPFCCR_ALPHA(layer->alpha); + pfccrreg |= DMA2D_xGPFCCR_ALPHA(alpha); - /* Set alpha mode */ - - if (layer->blendmode & DMA2D_BLEND_ALPHA) - { - /* Blend with constant alpha */ - - pfccrreg |= DMA2D_xGPFCCR_AM(STM32_DMA2D_PFCCR_AM_CONST); - } - else if (layer->blendmode & DMA2D_BLEND_PIXELALPHA) - { - /* Blend with pixel alpha value */ - - pfccrreg |= DMA2D_xGPFCCR_AM(STM32_DMA2D_PFCCR_AM_PIXEL); - } } putreg32(pfccrreg, stm32_pfccr_layer_t[lid]); @@ -1145,125 +736,15 @@ static void stm32_dma2d_lpfc(FAR const struct stm32_dma2d_s *layer, /**************************************************************************** * Public Functions ****************************************************************************/ - + /**************************************************************************** - * Name: stm32_dma2dgetvideoinfo - * - * Description: - * Get video information about the layer - * - * Input Parameters: - * layer - Reference to the layer control structure - * vinfo - Reference to the video info structure - * - * Returned Value: - * On success - OK - * On error - -EINVAL - * - ****************************************************************************/ - -static int stm32_dma2dgetvideoinfo(FAR struct dma2d_layer_s *layer, - FAR struct fb_videoinfo_s *vinfo) -{ - FAR struct stm32_dma2d_s *priv = (FAR struct stm32_dma2d_s *)layer; - - lcdinfo("layer=%p, vinfo=%p\n", layer, vinfo); - - if (stm32_dma2d_lvalidate(priv) && vinfo) - { - nxsem_wait(priv->lock); - memcpy(vinfo, &priv->vinfo, sizeof(struct fb_videoinfo_s)); - nxsem_post(priv->lock); - - return OK; - } - - lcderr("ERROR: Returning EINVAL\n"); - return -ENOSYS; -} - -/**************************************************************************** - * Name: stm32_dma2dgetplaneinfo - * - * Description: - * Get plane information about the layer - * - * Input Parameters: - * layer - Reference to the layer control structure - * planeno - Number of the plane - * pinfo - Reference to the plane info structure - * - * Returned Value: - * On success - OK - * On error - -EINVAL - * - ****************************************************************************/ - -static int stm32_dma2dgetplaneinfo(FAR struct dma2d_layer_s *layer, int planeno, - FAR struct fb_planeinfo_s *pinfo) -{ - FAR struct stm32_dma2d_s *priv = (FAR struct stm32_dma2d_s *)layer; - - lcdinfo("layer=%p, planeno=%d, pinfo=%p\n", layer, planeno, pinfo); - - if (stm32_dma2d_lvalidate(priv) && pinfo && planeno == 0) - { - nxsem_wait(priv->lock); - memcpy(pinfo, &priv->pinfo, sizeof(struct fb_planeinfo_s)); - nxsem_post(priv->lock); - - return OK; - } - - lcderr("ERROR: Returning EINVAL\n"); - return -EINVAL; -} - -/**************************************************************************** - * Name: stm32_dma2dgetlid - * - * Description: - * Get a specific layer identifier. - * - * Input Parameters: - * layer - Reference to the layer structure - * lid - Reference to store the layer id - * - * Returned Value: - * On success - OK - * On error - -EINVAL - * - ****************************************************************************/ - -static int stm32_dma2dgetlid(FAR struct dma2d_layer_s *layer, int *lid) -{ - FAR struct stm32_dma2d_s *priv = (FAR struct stm32_dma2d_s *)layer; - - lcdinfo("layer=%p, lid=%p\n", layer, lid); - - if (stm32_dma2d_lvalidate(priv) && lid) - { - nxsem_wait(priv->lock); - *lid = priv->lid; - nxsem_post(priv->lock); - return OK; - } - - lcderr("ERROR: Returning EINVAL\n"); - return -EINVAL; -} - -#ifdef CONFIG_STM32F7_DMA2D_L8 -/**************************************************************************** - * Name: stm32_dma2dsetclut + * Name: stm32_dma2d_setclut * * Description: * Configure layer clut (color lookup table). - * Non clut is defined during initializing. * * Input Parameters: - * layer - Reference to the layer structure - * cmap - color lookup table with up the 256 entries + * cmap - Color lookup table with up the 256 entries * * Returned Value: * On success - OK @@ -1271,587 +752,65 @@ static int stm32_dma2dgetlid(FAR struct dma2d_layer_s *layer, int *lid) * ****************************************************************************/ -static int stm32_dma2dsetclut(FAR struct dma2d_layer_s *layer, - const FAR struct fb_cmap_s *cmap) +#ifdef CONFIG_FB_CMAP +static int stm32_dma2d_setclut(FAR const struct fb_cmap_s *cmap) { - int ret; - FAR struct stm32_dma2d_s *priv = (FAR struct stm32_dma2d_s *)layer; + int n; + FAR struct stm32_dma2d_s * priv = &g_dma2ddev; - lcdinfo("layer=%p, cmap=%p\n", layer, cmap); + lcdinfo("cmap=%p\n", cmap); - if (stm32_dma2d_lvalidate(priv) && cmap) + nxsem_wait(priv->lock); + + for (n = cmap->first; n < cmap->len - 1 && n < STM32_DMA2D_NCLUT; n++) { - nxsem_wait(priv->lock); + /* Update the layer clut entry, will be automatically loaded before + * blit operation becomes active + */ -#ifdef CONFIG_STM32F7_LTDC_INTERFACE - if (priv->lid < DMA2D_SHADOW_LAYER) - { - /* Update the shared color lookup table. - * - * Background: - * - * We share the same memory region of the clut table with the LTDC - * driver. (see stm32_dma2dinitltdc). This is important because any - * changes to the framebuffer and color lookup table by the ltdc - * related dma2d layer should also effects to the ltdc visibility, - * except operation settings, alpha and blendmode. - * - * But we can not only update the clut memory region. The LTDC driver - * also must update they own LTDC clut register to make the changes - * visible. Using the LTDC interface to update the clut table will - * also update the clut table of the related dma2d layer. - */ +# ifndef CONFIG_FB_TRANSPARENCY + uint8_t *clut = (uint8_t *)g_dma2ddev.clut; + uint16_t offset = 3 * n; - FAR struct ltdc_layer_s *ltdc = - g_ltdc_layer.layer[DMA2D_SHADOW_LAYER_L1].ltdc; + clut[offset] = cmap->blue[n]; + clut[offset + 1] = cmap->green[n]; + clut[offset + 2] = cmap->red[n]; - ret = ltdc->setclut(ltdc, cmap); + reginfo("n=%d, red=%02x, green=%02x, blue=%02x\n", n, clut[offset], + clut[offset + 1], clut[offset + 2]); +# else + uint32_t *clut = g_dma2ddev.clut; - nxsem_post(priv->lock); + clut[n] = (uint32_t)DMA2D_CLUT_ALPHA(cmap->transp[n]) | + (uint32_t)DMA2D_CLUT_RED(cmap->red[n]) | + (uint32_t)DMA2D_CLUT_GREEN(cmap->green[n]) | + (uint32_t)DMA2D_CLUT_BLUE(cmap->blue[n]); - return ret; - } -#endif - - if (priv->fmt != DMA2D_PF_L8) - { - lcderr("ERROR: CLUT is not supported for the pixel format: %d\n", - priv->vinfo.fmt); - ret = -EINVAL; - } - else if (cmap->first >= STM32_DMA2D_NCLUT) - { - lcderr("ERROR: only %d color table entries supported\n", - STM32_DMA2D_NCLUT); - ret = -EINVAL; - } - else - { - uint32_t *clut; - int n; - - clut = priv->clut; - - for (n = cmap->first; n < cmap->len && n < STM32_DMA2D_NCLUT; n++) - { - /* Update the layer clut entry */ - -#ifndef CONFIG_FB_TRANSPARENCY - uint8_t *clut888 = (uint8_t *)clut; - uint16_t offset = 3 * n; - - clut888[offset] = cmap->blue[n]; - clut888[offset + 1] = cmap->green[n]; - clut888[offset + 2] = cmap->red[n]; - - reginfo("n=%d, red=%02x, green=%02x, blue=%02x\n", n, - clut888[offset], clut888[offset + 1], - clut888[offset + 2]); -#else - clut[n] = (uint32_t)DMA2D_CLUT_RED(cmap->transp[n]) | - (uint32_t)DMA2D_CLUT_GREEN(cmap->red[n]) | - (uint32_t)DMA2D_CLUT_GREEN(cmap->green[n]) | - (uint32_t)DMA2D_CLUT_BLUE(cmap->blue[n]); - - reginfo("n=%d, alpha=%02x, red=%02x, green=%02x, blue=%02x\n", n, - DMA2D_CLUT_ALPHA(cmap->alpha[n]), - DMA2D_CLUT_RED(cmap->red[n]), - DMA2D_CLUT_GREEN(cmap->green[n]), - DMA2D_CLUT_BLUE(cmap->blue[n])); -#endif - } - - - ret = OK; - } - - nxsem_post(priv->lock); - return ret; + reginfo("n=%d, alpha=%02x, red=%02x, green=%02x, blue=%02x\n", n, + DMA2D_CLUT_ALPHA(cmap->transp[n]), + DMA2D_CLUT_RED(cmap->red[n]), + DMA2D_CLUT_GREEN(cmap->green[n]), + DMA2D_CLUT_BLUE(cmap->blue[n])); +# endif } - lcderr("ERROR: Returning EINVAL\n"); - return -EINVAL; + nxsem_post(priv->lock); + + return OK; } +#endif /* CONFIG_FB_CMAP */ /**************************************************************************** - * Name: stm32_dma2dgetclut + * Name: stm32_dma2d_fillcolor * * Description: - * Get configured layer clut (color lookup table). + * Fill the selected area of the whole overlay with a specific color. + * The caller must ensure that the area is within the entire overlay. * * Input Parameters: - * layer - Reference to the layer structure - * cmap - Reference to valid color lookup table accept up the 256 color - * entries - * - * Returned Value: - * On success - OK - * On error - -EINVAL - * - ****************************************************************************/ - -static int stm32_dma2dgetclut(FAR struct dma2d_layer_s *layer, - FAR struct fb_cmap_s *cmap) -{ - int ret; - FAR struct stm32_dma2d_s *priv = (FAR struct stm32_dma2d_s *)layer; - - lcdinfo("layer=%p, cmap=%p\n", layer, cmap); - - if (stm32_dma2d_lvalidate(priv) && cmap) - { - nxsem_wait(priv->lock); - - if (priv->fmt != DMA2D_PF_L8) - { - lcderr("ERROR: CLUT is not supported for the pixel format: %d\n", - priv->vinfo.fmt); - ret = -EINVAL; - } - else if (cmap->first >= STM32_DMA2D_NCLUT) - { - lcderr("ERROR: only %d color table entries supported\n", - STM32_DMA2D_NCLUT); - ret = -EINVAL; - } - else - { - /* Copy from the layer clut */ - - uint32_t *clut; - int n; - - clut = priv->clut; - - for (n = cmap->first; n < cmap->len && n < STM32_DMA2D_NCLUT; n++) - { -#ifndef CONFIG_FB_TRANSPARENCY - uint8_t *clut888 = (uint8_t *)clut; - uint16_t offset = 3 * n; - - cmap->blue[n] = clut888[offset]; - cmap->green[n] = clut888[offset + 1]; - cmap->red[n] = clut888[offset + 2]; - - reginfo("n=%d, red=%02x, green=%02x, blue=%02x\n", n, - clut888[offset], clut888[offset + 1], - clut888[offset + 2]); -#else - cmap->transp[n] = (uint8_t)DMA2D_CMAP_ALPHA(clut[n]); - cmap->red[n] = (uint8_t)DMA2D_CMAP_RED(clut[n]); - cmap->green[n] = (uint8_t)DMA2D_CMAP_GREEN(clut[n]); - cmap->blue[n] = (uint8_t)DMA2D_CMAP_BLUE(clut[n]); - - reginfo("n=%d, alpha=%02x, red=%02x, green=%02x, blue=%02x\n", n, - DMA2D_CMAP_ALPHA(clut[n]), DMA2D_CMAP_RED(clut[n]), - DMA2D_CMAP_GREEN(clut[n]), DMA2D_CMAP_BLUE(clut[n])); -#endif - } - - ret = OK; - } - - nxsem_post(priv->lock); - - return ret; - } - - lcderr("ERROR: Returning EINVAL\n"); - return -EINVAL; -} -#endif - -/**************************************************************************** - * Name: stm32_dma2dsetalpha - * - * Description: - * Configure layer alpha value factor into blend operation. - * During the layer blend operation the source alpha value is multiplied - * with this alpha value. If the source color format doesn't support alpha - * channel (e.g. non ARGB8888) this alpha value will be used as constant - * alpha value for blend operation. - * Default value during initializing: 0xff - * - * Input Parameters: - * layer - Reference to the layer structure - * alpha - Alpha value - * - * Returned Value: - * On success - OK - * On error - -EINVAL - * - ****************************************************************************/ - -static int stm32_dma2dsetalpha(FAR struct dma2d_layer_s *layer, uint8_t alpha) -{ - FAR struct stm32_dma2d_s *priv = (FAR struct stm32_dma2d_s *)layer; - - lcdinfo("layer=%p, alpha=%02x\n", layer, alpha); - - if (stm32_dma2d_lvalidate(priv)) - { - nxsem_wait(priv->lock); - priv->alpha = alpha; - nxsem_post(priv->lock); - - return OK; - } - - lcderr("ERROR: Returning EINVAL\n"); - return -EINVAL; -} - -/**************************************************************************** - * Name: stm32_dma2dgetalpha - * - * Description: - * Get configured layer alpha value factor for blend operation. - * - * Input Parameters: - * layer - Reference to the layer structure - * alpha - Reference to store the alpha value - * - * Returned Value: - * On success - OK - * On error - -EINVAL - * - ****************************************************************************/ - -static int stm32_dma2dgetalpha(FAR struct dma2d_layer_s *layer, uint8_t *alpha) -{ - FAR struct stm32_dma2d_s *priv = (FAR struct stm32_dma2d_s *)layer; - - lcdinfo("layer=%p, alpha=%p\n", layer, alpha); - - if (stm32_dma2d_lvalidate(priv)) - { - nxsem_wait(priv->lock); - *alpha = priv->alpha; - nxsem_post(priv->lock); - - return OK; - } - - lcderr("ERROR: Returning EINVAL\n"); - return -EINVAL; -} - -/**************************************************************************** - * Name: stm32_dma2dsetblendmode - * - * Description: - * Configure blend mode of the layer. - * Default mode during initializing: DMA2D_BLEND_NONE - * Blendmode is active after next update. - * - * Input Parameters: - * layer - Reference to the layer structure - * mode - Blend mode (see DMA2D_BLEND_*) - * - * Returned Value: - * On success - OK - * On error - -EINVAL - * - * Procedure information: - * DMA2D_BLEND_NONE: - * Informs the driver to disable all blend operation for the given layer. - * That means the layer is opaque. - * - * DMA2D_BLEND_ALPHA: - * Informs the driver to enable alpha blending for the given layer. - * - * DMA2D_BLEND_PIXELALPHA: - * Informs the driver to use the pixel alpha value of the layer instead - * the constant alpha value. This is only useful for ARGB8888 - * color format. - * - ****************************************************************************/ - -static int stm32_dma2dsetblendmode(FAR struct dma2d_layer_s *layer, - uint32_t mode) -{ - FAR struct stm32_dma2d_s *priv = (FAR struct stm32_dma2d_s *)layer; - - lcdinfo("layer=%p, mode=%08x\n", layer, mode); - - if (stm32_dma2d_lvalidate(priv)) - { - nxsem_wait(priv->lock); - priv->blendmode = mode; - nxsem_post(priv->lock); - - return OK; - } - - lcderr("ERROR: Returning EINVAL\n"); - return -EINVAL; -} - -/**************************************************************************** - * Name: stm32_getblendmode - * - * Description: - * Get configured blend mode of the layer. - * - * Input Parameters: - * layer - Reference to the layer structure - * mode - Reference to store the blend mode - * - * Returned Value: - * On success - OK - * On error - -EINVAL - * - ****************************************************************************/ - -static int stm32_dma2dgetblendmode(FAR struct dma2d_layer_s *layer, - uint32_t *mode) -{ - FAR struct stm32_dma2d_s *priv = (FAR struct stm32_dma2d_s *)layer; - - lcdinfo("layer=%p, mode=%p\n", layer, mode); - - if (stm32_dma2d_lvalidate(priv) && mode) - { - nxsem_wait(priv->lock); - *mode = priv->blendmode; - nxsem_post(priv->lock); - - return OK; - } - - lcderr("ERROR: Returning EINVAL\n"); - return -EINVAL; -} - -/**************************************************************************** - * Name: stm32_dma2dblit - * - * Description: - * Copy selected area from a source layer to selected position of the - * destination layer. - * - * Input Parameters: - * dest - Valid reference to the destination layer - * destxpos - Valid selected x position of the destination layer - * destypos - Valid selected y position of the destination layer - * src - Valid reference to the source layer - * srcarea - Valid reference to the selected area of the source layer - * - * Returned Value: - * OK - On success - * -EINVAL - If one of the parameter invalid or if the size of the selected - * source area outside the visible area of the destination layer. - * (The visible area usually represents the display size) - * -ECANCELED - Operation cancelled, something goes wrong. - * - ****************************************************************************/ - -static int stm32_dma2dblit(FAR struct dma2d_layer_s *dest, - fb_coord_t destxpos, fb_coord_t destypos, - FAR const struct dma2d_layer_s *src, - FAR const struct ltdc_area_s *srcarea) -{ - uint32_t mode; - int ret; - FAR struct stm32_dma2d_s * destlayer = (FAR struct stm32_dma2d_s *)dest; - FAR struct stm32_dma2d_s * srclayer = (FAR struct stm32_dma2d_s *)src; - - lcdinfo("dest=%p, destxpos=%d, destypos=%d, src=%p, srcarea=%p\n", - dest, destxpos, destypos, src, srcarea); - - if (stm32_dma2d_lvalidatesize(destlayer, destxpos, destypos, srcarea) && - stm32_dma2d_lvalidatesize(srclayer, srcarea->xpos, - srcarea->ypos, srcarea)) - { - nxsem_wait(destlayer->lock); - - /* Set output pfc */ - - ret = stm32_dma2d_loutpfc(destlayer); - - if (ret == OK) - { - /* Set foreground pfc */ - - stm32_dma2d_lpfc(srclayer, DMA2D_LAYER_LFORE, DMA2D_BLEND_NONE); - - /* Set foreground fifo */ - - stm32_dma2d_lfifo(srclayer, DMA2D_LAYER_LFORE, - srcarea->xpos, srcarea->ypos, srcarea); - - /* Set output fifo */ - - stm32_dma2d_lfifo(destlayer, DMA2D_LAYER_LOUT, - destxpos, destypos, srcarea); - - /* Set number of lines and pixel per line */ - - stm32_dma2d_llnr(destlayer, srcarea); - - /* Set dma2d mode for blit operation */ - - if (destlayer->fmt == srclayer->fmt) - { - /* Blit without pfc */ - - mode = STM32_DMA2D_CR_MODE_BLIT; - } - else - { - /* Blit with pfc */ - - mode = STM32_DMA2D_CR_MODE_BLITPFC; - } - - stm32_dma2d_control(mode, STM32_DMA2D_CR_MODE_CLEAR); - - /* Start DMA2D and wait until completed */ - - ret = stm32_dma2d_start(); - - if (ret != OK) - { - ret = -ECANCELED; - lcderr("ERROR: Returning ECANCELED\n"); - } - } - - nxsem_post(destlayer->lock); - } - else - { - ret = -EINVAL; - lcderr("ERROR: Returning EINVAL\n"); - } - - return ret; -} - -/**************************************************************************** - * Name: stm32_dma2dblend - * - * Description: - * Blends the selected area from a background layer with selected position - * of the foreground layer. Copies the result to the selected position of - * the destination layer. Note! The content of the foreground and background - * layer keeps unchanged as long destination layer is unequal to the - * foreground and background layer. - * - * Input Parameters: - * dest - Reference to the destination layer - * fore - Reference to the foreground layer - * forexpos - Selected x target position of the foreground layer - * foreypos - Selected y target position of the foreground layer - * back - Reference to the background layer - * backarea - Reference to the selected area of the background layer - * - * Returned Value: - * OK - On success - * -EINVAL - If one of the parameter invalid or if the size of the selected - * source area outside the visible area of the destination layer. - * (The visible area usually represents the display size) - * -ECANCELED - Operation cancelled, something goes wrong. - * - ****************************************************************************/ - -static int stm32_dma2dblend(FAR struct dma2d_layer_s *dest, - fb_coord_t destxpos, fb_coord_t destypos, - FAR const struct dma2d_layer_s *fore, - fb_coord_t forexpos, fb_coord_t foreypos, - FAR const struct dma2d_layer_s *back, - FAR const struct ltdc_area_s *backarea) -{ - int ret; - FAR struct stm32_dma2d_s * destlayer = (FAR struct stm32_dma2d_s *)dest; - FAR struct stm32_dma2d_s * forelayer = (FAR struct stm32_dma2d_s *)fore; - FAR struct stm32_dma2d_s * backlayer = (FAR struct stm32_dma2d_s *)back; - - lcdinfo("dest=%p, destxpos=%d, destypos=%d, " - "fore=%p, forexpos=%d, foreypos=%d, " - "back=%p, backarea=%p\n", - dest, destxpos, destypos, fore, forexpos, foreypos, back, backarea); - - if (stm32_dma2d_lvalidatesize(destlayer, destxpos, destypos, backarea) && - stm32_dma2d_lvalidatesize(forelayer, forexpos, foreypos, backarea) && - stm32_dma2d_lvalidatesize(backlayer, backarea->xpos, - backarea->ypos, backarea)) - { - nxsem_wait(destlayer->lock); - - /* Set output pfc */ - - ret = stm32_dma2d_loutpfc(destlayer); - - if (ret == OK) - { - /* Set background pfc */ - - stm32_dma2d_lpfc(backlayer, DMA2D_LAYER_LBACK, backlayer->blendmode); - - /* Set foreground pfc */ - - stm32_dma2d_lpfc(forelayer, DMA2D_LAYER_LFORE, forelayer->blendmode); - - /* Set background fifo */ - - stm32_dma2d_lfifo(backlayer, DMA2D_LAYER_LBACK, - backarea->xpos, backarea->ypos, backarea); - - /* Set foreground fifo */ - - stm32_dma2d_lfifo(forelayer, DMA2D_LAYER_LFORE, - forexpos, foreypos, backarea); - - /* Set output fifo */ - - stm32_dma2d_lfifo(destlayer, DMA2D_LAYER_LOUT, - destxpos, destypos, backarea); - - /* Set number of lines and pixel per line */ - - stm32_dma2d_llnr(destlayer, backarea); - - /* Set watermark */ - - /* Enable DMA2D blender */ - - stm32_dma2d_control(STM32_DMA2D_CR_MODE_BLEND, - STM32_DMA2D_CR_MODE_CLEAR); - - /* Start DMA2D and wait until completed */ - - ret = stm32_dma2d_start(); - - if (ret != OK) - { - ret = -ECANCELED; - lcderr("ERROR: Returning ECANCELED\n"); - } - } - - nxsem_post(destlayer->lock); - } - else - { - ret = -EINVAL; - lcderr("ERROR: Returning EINVAL\n"); - } - - return ret; -} - -/**************************************************************************** - * Name: stm32_dma2dfillarea - * - * Description: - * Fill the selected area of the whole layer with a specific color. - * - * Input Parameters: - * layer - Reference to the layer structure - * area - Reference to the valid area structure select the area - * color - Color to fill the selected area. Color must be formatted - * according to the layer pixel format. + * oinfo - Overlay to fill + * area - Reference to the valid area structure select the area + * argb - Color to fill the selected area. Color must be argb8888 formated. * * Returned Value: * OK - On success @@ -1861,265 +820,263 @@ static int stm32_dma2dblend(FAR struct dma2d_layer_s *dest, * ****************************************************************************/ -static int stm32_dma2dfillarea(FAR struct dma2d_layer_s *layer, - FAR const struct ltdc_area_s *area, - uint32_t color) +static int stm32_dma2d_fillcolor(FAR struct stm32_dma2d_overlay_s *oinfo, + FAR const struct fb_area_s *area, + uint32_t argb) { int ret; - FAR struct stm32_dma2d_s *priv = (FAR struct stm32_dma2d_s *)layer; + FAR struct stm32_dma2d_s * priv = &g_dma2ddev; + DEBUGASSERT(oinfo != NULL && oinfo->oinfo != NULL && area != NULL); - lcdinfo("layer=%p, area=%p, color=%08x\n", layer, area, color); + lcdinfo("oinfo=%p, argb=%08x\n", oinfo, argb); - if (stm32_dma2d_lvalidatesize(priv, area->xpos, area->ypos, area)) +#ifdef CONFIG_FB_CMAP + if (oinfo->fmt == DMA2D_PF_L8) { - nxsem_wait(priv->lock); + /* CLUT output not supported */ - /* Set output pfc */ - - ret = stm32_dma2d_loutpfc(priv); - - if (ret == OK) - { - /* Set output fifo */ - - stm32_dma2d_lfifo(priv, DMA2D_LAYER_LOUT, - area->xpos, area->ypos, area); - - /* Set the output color register */ - - stm32_dma2d_lcolor(priv, DMA2D_LAYER_LOUT, color); - - /* Set number of lines and pixel per line */ - - stm32_dma2d_llnr(priv, area); - - /* Set register to memory transfer */ - - stm32_dma2d_control(STM32_DMA2D_CR_MODE_COLOR, - STM32_DMA2D_CR_MODE_CLEAR); - - /* Start DMA2D and wait until completed */ - - ret = stm32_dma2d_start(); - - if (ret != OK) - { - ret = -ECANCELED; - lcderr("ERROR: Returning ECANCELED\n"); - } - } - - nxsem_post(priv->lock); - } - else - { - ret = -EINVAL; - lcderr("ERROR: Returning EINVAL\n"); + lcderr("ERROR: Returning ENOSYS, " + "output to layer with CLUT format not supported.\n"); + return -ENOSYS; } +#endif - return ret; -} + nxsem_wait(priv->lock); -/**************************************************************************** - * Name: up_dma2dgetlayer - * - * Description: - * Get a dma2d layer structure by the layer identifier - * - * Input Parameters: - * lid - Layer identifier - * - * Returned Value: - * Reference to the dma2d layer control structure on success or Null if no - * related exist. - * - ****************************************************************************/ + /* Set output pfc */ -FAR struct dma2d_layer_s *up_dma2dgetlayer(int lid) -{ - if (lid < DMA2D_LAYER_NSIZE) - { - FAR struct stm32_dma2d_s *priv; - nxsem_wait(&g_lock); - priv = g_layers[lid]; - nxsem_post(&g_lock); + stm32_dma2d_loutpfc(oinfo->fmt); - return &priv->dma2d; - } + /* Set output fifo */ - lcderr("ERROR: lid invalid: %d\n", lid); - return NULL; -} + stm32_dma2d_lfifo(oinfo, DMA2D_LAYER_LOUT, area->x, area->y, area); -/**************************************************************************** - * Name: up_dma2dcreatelayer - * - * Description: - * Create a new dma2d layer object to interact with the dma2d controller - * - * Input Parameters: - * width - Layer width - * height - Layer height - * fmt - Pixel format of the layer - * - * Returned Value: - * On success - A valid dma2d layer reference - * On error - NULL - * - ****************************************************************************/ + /* Set the output color register */ -FAR struct dma2d_layer_s *up_dma2dcreatelayer(fb_coord_t width, - fb_coord_t height, - uint8_t fmt) -{ - FAR struct stm32_dma2d_s *layer = NULL; - int ret; - int lid; - uint8_t fmtmap; - uint8_t bpp = 0; + stm32_dma2d_lcolor(DMA2D_LAYER_LOUT, argb); - lcdinfo("width=%d, height=%d, fmt=%02x \n", width, height, fmt); + /* Set number of lines and pixel per line */ - /* Validate if pixel format supported */ + stm32_dma2d_llnr(area); - ret = stm32_dma2d_pixelformat(fmt, &fmtmap); + /* Set register to memory transfer */ + + stm32_dma2d_control(STM32_DMA2D_CR_MODE_COLOR, STM32_DMA2D_CR_MODE_CLEAR); + + /* Start DMA2D and wait until completed */ + + ret = stm32_dma2d_start(); if (ret != OK) { - return NULL; - } - - ret = stm32_dma2d_bpp(fmt, &bpp); - - nxsem_wait(&g_lock); - - /* Get a free layer identifier */ - - lid = stm32_dma2d_lfreelid(); - - if (lid >= 0) - { - layer = stm32_dma2d_lalloc(); - - if (layer) - { - uint32_t fblen; - void *fbmem; - fb_coord_t stride; - - /* Stride calculation for the supported formats */ - - stride = width * bpp / 8; - - /* Calculate buffer size */ - - fblen = stride * height; - - /* Allocate 32-bit aligned memory for the layer buffer. As reported in - * mm_memalign 8-byte alignment is guaranteed by normal malloc calls. - * We have also ensure memory is allocated from the SRAM1/2/3 block. - */ - - fbmem = kmm_zalloc(fblen); /* STM32F7: Should use DTCM ? */ - - if (fbmem) - { - FAR struct fb_videoinfo_s *vinfo = &layer->vinfo; - FAR struct fb_planeinfo_s *pinfo = &layer->pinfo; - - /* Initialize dma2d structure */ - - stm32_dma2d_linit(layer, lid, fmtmap); - - /* Initialize the videoinfo structure */ - - vinfo->fmt = fmt; - vinfo->xres = width; - vinfo->yres = height; - vinfo->nplanes = 1; - - /* Initialize the planeinfo structure */ - - pinfo->fbmem = fbmem; - pinfo->fblen = fblen; - pinfo->stride = stride; - pinfo->display = 0; - pinfo->bpp = bpp; - - /* Bind the layer to the identifier */ - - g_layers[lid] = layer; - } - else - { - /* free the layer struture */ - - kmm_free(layer); - layer = NULL; - lcderr("ERROR: ENOMEM, Unable to allocate layer buffer\n"); - } - } - else - { - lcderr("ERROR: ENOMEM, unable to allocate layer structure\n"); - } - } - else - { - lcderr("ERROR: EINVAL, no free layer available\n"); - } - - nxsem_post(&g_lock); - return (FAR struct dma2d_layer_s *)layer; -} - -/**************************************************************************** - * Name: up_dma2dremovelayer - * - * Description: - * Remove and deallocate the dma2d layer - * - * Input Parameters: - * layer - Reference to the layer to remove - * - * Returned Value: - * On success - OK - * On error - -EINVAL - * - ****************************************************************************/ - -int up_dma2dremovelayer(FAR struct dma2d_layer_s *layer) -{ - int ret = -EINVAL; - FAR struct stm32_dma2d_s *priv = (FAR struct stm32_dma2d_s *)layer; - - /* Check if the layer is valid and unlike a ltdc related layer */ - - if (stm32_dma2d_lvalidate(priv) && priv->lid >= DMA2D_SHADOW_LAYER) - { - nxsem_wait(priv->lock); - - /* Check also if the layer id is valid to the layer reference */ - - if (priv == g_layers[priv->lid]) - { - int lid = priv->lid; - - kmm_free(priv->pinfo.fbmem); - stm32_dma2d_lfree(priv); - - g_layers[lid] = NULL; - ret = OK; - } - - nxsem_post(priv->lock); + ret = -ECANCELED; + lcderr("ERROR: Returning ECANCELED\n"); } + nxsem_post(priv->lock); return ret; } /**************************************************************************** - * Name: up_dma2dinitialize + * Name: stm32_dma2d_blit + * + * Description: + * Copy memory from a source overlay (defined by sarea) to destination + * overlay position (defined by destxpos and destypos). + * + * Input Parameters: + * doverlay - Valid reference to the destination overlay + * destxpos - Valid selected x position of the destination overlay + * destypos - Valid selected y position of the destination overlay + * soverlay - Valid reference to the source overlay + * sarea - Valid reference to the selected area of the source overlay + * + * Returned Value: + * OK - On success + * -EINVAL - If one of the parameter invalid or if the size of the selected + * source area outside the visible area of the destination layer. + * (The visible area usually represents the display size) + * -ECANCELED - Operation cancelled, something goes wrong. + * + ****************************************************************************/ + +static int stm32_dma2d_blit(FAR struct stm32_dma2d_overlay_s *doverlay, + uint32_t destxpos, uint32_t destypos, + FAR struct stm32_dma2d_overlay_s *soverlay, + FAR const struct fb_area_s *sarea) +{ + int ret; + uint32_t mode; + FAR struct stm32_dma2d_s * priv = &g_dma2ddev; + + lcdinfo("doverlay=%p, destxpos=%d, destypos=%d, soverlay=%p, sarea=%p\n", + doverlay, destxpos, destypos, soverlay, sarea); + + nxsem_wait(priv->lock); + + /* Set output pfc */ + + stm32_dma2d_loutpfc(doverlay->fmt); + + /* Set foreground pfc */ + + stm32_dma2d_lpfc(DMA2D_LAYER_LFORE, STM32_DMA2D_PFCCR_AM_NONE, 0, + soverlay->fmt); + + /* Set foreground fifo */ + + stm32_dma2d_lfifo(soverlay, DMA2D_LAYER_LFORE, sarea->x, sarea->y, sarea); + + /* Set output fifo */ + + stm32_dma2d_lfifo(doverlay, DMA2D_LAYER_LOUT, destxpos, destypos, sarea); + + /* Set number of lines and pixel per line */ + + stm32_dma2d_llnr(sarea); + + /* Set dma2d mode for blit operation */ + + if (doverlay->fmt == soverlay->fmt) + { + /* Blit without pfc */ + + mode = STM32_DMA2D_CR_MODE_BLIT; + } + else + { + /* Blit with pfc */ + + mode = STM32_DMA2D_CR_MODE_BLITPFC; + } + + stm32_dma2d_control(mode, STM32_DMA2D_CR_MODE_CLEAR); + + /* Start DMA2D and wait until completed */ + + ret = stm32_dma2d_start(); + + if (ret != OK) + { + ret = -ECANCELED; + lcderr("ERROR: Returning ECANCELED\n"); + } + + nxsem_post(priv->lock); + return ret; +} + +/**************************************************************************** + * Name: stm32_dma2d_blend + * + * Description: + * Blends the selected area from a background layer with selected position + * of the foreground layer. Copies the result to the selected position of + * the destination layer. Note! The content of the foreground and background + * layer keeps unchanged as long destination layer is unequal to the + * foreground and background layer. + * + * Input Parameters: + * doverlay - Destination overlay + * destxpos - x-Offset destination overlay + * destypos - y-Offset destination overlay + * foverlay - Foreground overlay + * forexpos - x-Offset foreground overlay + * foreypos - y-Offset foreground overlay + * boverlay - Background overlay + * barea - x-Offset, y-Offset, x-resolution and y-resolution of background + * overlay + * + * Returned Value: + * OK - On success + * -EINVAL - If one of the parameter invalid or if the size of the selected + * source area outside the visible area of the destination layer. + * (The visible area usually represents the display size) + * -ECANCELED - Operation cancelled, something goes wrong. + * + ****************************************************************************/ + +static int stm32_dma2d_blend(FAR struct stm32_dma2d_overlay_s *doverlay, + uint32_t destxpos, uint32_t destypos, + FAR struct stm32_dma2d_overlay_s *foverlay, + uint32_t forexpos, uint32_t foreypos, + FAR struct stm32_dma2d_overlay_s *boverlay, + FAR const struct fb_area_s *barea) +{ + int ret; + FAR struct stm32_dma2d_s * priv = &g_dma2ddev; + + lcdinfo("doverlay=%p, destxpos=%d, destypos=%d, " + "foverlay=%p, forexpos=%d, foreypos=%d, " + "boverlay=%p, barea=%p, barea.x=%d, barea.y=%d, barea.w=%d, " + "barea.h=%d\n", doverlay, destxpos, destypos, foverlay, forexpos, + foreypos, boverlay, barea, barea->x, barea->y, barea->w, barea->h); + +#ifdef CONFIG_FB_CMAP + if (doverlay->fmt == DMA2D_PF_L8) + { + /* CLUT output not supported */ + + lcderr("ERROR: Returning ENOSYS, " + "output to layer with CLUT format not supported.\n"); + return -ENOSYS; + } +#endif + + nxsem_wait(priv->lock); + + /* Set output pfc */ + + stm32_dma2d_loutpfc(doverlay->fmt); + + /* Set background pfc */ + + stm32_dma2d_lpfc(DMA2D_LAYER_LBACK, boverlay->transp_mode, + boverlay->oinfo->transp.transp, boverlay->fmt); + + /* Set foreground pfc */ + + stm32_dma2d_lpfc(DMA2D_LAYER_LFORE, foverlay->transp_mode, + foverlay->oinfo->transp.transp, foverlay->fmt); + + /* Set background fifo */ + + stm32_dma2d_lfifo(boverlay, DMA2D_LAYER_LBACK, barea->x, barea->y, barea); + + /* Set foreground fifo */ + + stm32_dma2d_lfifo(foverlay, DMA2D_LAYER_LFORE, forexpos, foreypos, barea); + + /* Set output fifo */ + + stm32_dma2d_lfifo(doverlay, DMA2D_LAYER_LOUT, destxpos, destypos, barea); + + /* Set number of lines and pixel per line */ + + stm32_dma2d_llnr(barea); + + /* Set watermark */ + + /* Enable DMA2D blender */ + + stm32_dma2d_control(STM32_DMA2D_CR_MODE_BLEND, STM32_DMA2D_CR_MODE_CLEAR); + + /* Start DMA2D and wait until completed */ + + ret = stm32_dma2d_start(); + + if (ret != OK) + { + ret = -ECANCELED; + lcderr("ERROR: Returning ECANCELED\n"); + } + + nxsem_post(priv->lock); + return ret; +} + +/**************************************************************************** + * Name: stm32_dma2dinitialize * * Description: * Initialize the dma2d controller @@ -2130,7 +1087,7 @@ int up_dma2dremovelayer(FAR struct dma2d_layer_s *layer) * ****************************************************************************/ -int up_dma2dinitialize(void) +int stm32_dma2dinitialize(void) { lcdinfo("Initialize DMA2D driver\n"); @@ -2138,10 +1095,10 @@ int up_dma2dinitialize(void) { /* Abort current dma2d data transfer */ - up_dma2duninitialize(); + stm32_dma2duninitialize(); /* Enable dma2d is done in rcc_enableahb1, see - * arch/arm/src/stm32/stm32f40xxx_rcc.c + * arch/arm/src/stm32f7/stm32f7xxxx_rcc.c */ /* Initialize the DMA2D semaphore that enforces mutually exclusive access @@ -2158,7 +1115,7 @@ int up_dma2dinitialize(void) nxsem_init(g_interrupt.sem, 0, 0); nxsem_setprotocol(g_interrupt.sem, SEM_PRIO_NONE); -#ifdef CONFIG_STM32F7_DMA2D_L8 +#ifdef CONFIG_FB_CMAP /* Enable dma2d transfer and clut loading interrupts only */ stm32_dma2d_control(DMA2D_CR_TCIE | DMA2D_CR_CTCIE, DMA2D_CR_TEIE | @@ -2170,6 +1127,9 @@ int up_dma2dinitialize(void) DMA2D_CR_CAEIE | DMA2D_CR_CTCIE | DMA2D_CR_CEIE); #endif + stm32_dma2d_control(DMA2D_CR_TCIE | DMA2D_CR_CTCIE | DMA2D_CR_TEIE | + DMA2D_CR_CAEIE | DMA2D_CR_CTCIE | DMA2D_CR_CEIE, 0); + /* Attach DMA2D interrupt vector */ (void)irq_attach(g_interrupt.irq, stm32_dma2dirq, NULL); @@ -2178,18 +1138,6 @@ int up_dma2dinitialize(void) up_enable_irq(g_interrupt.irq); - /* Initialize the dma2d layer for ltdc binding */ - -#ifdef DMA2D_SHADOW_LAYER_L1 - g_layers[DMA2D_SHADOW_LAYER_L1] = - &g_ltdc_layer.layer[DMA2D_SHADOW_LAYER_L1].dma2ddev; -#endif -#ifdef DMA2D_SHADOW_LAYER_L2 - g_layers[DMA2D_SHADOW_LAYER_L2] = - &g_ltdc_layer.layer[DMA2D_SHADOW_LAYER_L2].dma2ddev; -#endif - /* Set initialized state */ - g_initialized = true; } @@ -2197,24 +1145,20 @@ int up_dma2dinitialize(void) } /**************************************************************************** - * Name: up_dma2duninitialize + * Name: stm32_dma2duninitialize * * Description: * Uninitialize the dma2d controller * ****************************************************************************/ -void up_dma2duninitialize(void) +void stm32_dma2duninitialize(void) { /* Disable DMA2D interrupts */ up_disable_irq(g_interrupt.irq); irq_detach(g_interrupt.irq); - /* Cleanup all layers */ - - stm32_dma2d_llayerscleanup(); - /* Abort current dma2d transfer */ stm32_dma2d_control(DMA2D_CR_ABORT, 0); @@ -2224,21 +1168,11 @@ void up_dma2duninitialize(void) g_initialized = false; } -#ifdef CONFIG_STM32F7_LTDC_INTERFACE /**************************************************************************** - * Name: stm32_dma2dinitltdc + * Name: stm32_dma2ddev * * Description: - * Get a reference to the dma2d layer coupled with the ltdc layer. - * It not intends to use this by user space applications. - * It resolves the following requirements: - * 1. Share the color lookup table - * 2. Share the planeinfo information - * 3. Share the videoinfo information - * - * Input Parameters: - * layer - a valid reference to the low level ltdc layer structure - * clut - a pointer to a valid memory region to hold 256 clut colors + * Get a reference to the dma2d controller. * * Returned Value: * On success - A valid dma2d layer reference @@ -2246,44 +1180,7 @@ void up_dma2duninitialize(void) * ****************************************************************************/ -FAR struct dma2d_layer_s *stm32_dma2dinitltdc(FAR struct stm32_ltdc_s *layer) +FAR struct dma2d_layer_s *stm32_dma2ddev(void) { - int ret; - uint8_t fmt = 0; - FAR struct stm32_ltdc_dma2d_s *priv; - - lcdinfo("layer=%p\n", layer); - DEBUGASSERT(layer && layer->lid >= 0 && layer->lid < DMA2D_SHADOW_LAYER); - - ret = stm32_dma2d_pixelformat(layer->vinfo.fmt, &fmt); - - if (ret != OK) - { - lcderr("ERROR: Returning -EINVAL, unsupported pixel format: %d\n", - layer->vinfo.fmt); - return NULL; - } - - priv = &g_ltdc_layer.layer[layer->lid]; - - stm32_dma2d_linit(&priv->dma2ddev, layer->lid, fmt); - - memcpy(&priv->dma2ddev.vinfo, &layer->vinfo, sizeof(struct fb_videoinfo_s)); - memcpy(&priv->dma2ddev.pinfo, &layer->pinfo, sizeof(struct fb_planeinfo_s)); - -#ifdef CONFIG_STM32F7_DMA2D_L8 - /* Verifies that the ltdc layer has a clut. This ensures that DMA2D driver can - * support clut format but the LTDC driver does not and vice versa. - */ - - if (layer->vinfo.fmt == FB_FMT_RGB8) - { - priv->dma2ddev.clut = layer->clut; - priv->ltdc = stm32_ltdcgetlayer(layer->lid); - DEBUGASSERT(priv->ltdc != NULL); - } -#endif - - return &priv->dma2ddev.dma2d; + return &g_dma2ddev.dma2d; } -#endif /* CONFIG_STM32F7_LTDC_INTERFACE */ diff --git a/arch/arm/src/stm32f7/stm32_dma2d.h b/arch/arm/src/stm32f7/stm32_dma2d.h index d7110d35e7a..1c2db28c5d0 100644 --- a/arch/arm/src/stm32f7/stm32_dma2d.h +++ b/arch/arm/src/stm32f7/stm32_dma2d.h @@ -1,7 +1,7 @@ /**************************************************************************** - * arch/arm/src/stm32/stm32_dma2d.h + * arch/arm/src/stm32f7/stm32_dma2d.h * - * Copyright (C) 2014-2015 Marco Krahl. All rights reserved. + * Copyright (C) 2014-2015, 2018 Marco Krahl. All rights reserved. * Author: Marco Krahl * * Redistribution and use in source and binary forms, with or without @@ -44,374 +44,145 @@ #include #include "stm32_ltdc.h" -#ifdef CONFIG_STM32F7_DMA2D +#ifdef CONFIG_FB_OVERLAY /**************************************************************************** * Public Types ****************************************************************************/ -struct ltdc_area_s; /* see arch/arm/src/stm32f7/stm32_ltdc.h */ +/* This structure describes DMA2D overlay information */ -/* Blend mode definitions */ - -enum dma2d_blend_e +struct stm32_dma2d_overlay_s { - DMA2D_BLEND_NONE = 0, /* Disable all blend operation */ - DMA2D_BLEND_ALPHA = 0x1, /* Enable alpha blending */ - DMA2D_BLEND_PIXELALPHA = 0x2, /* Enable alpha blending from pixel color */ + uint8_t fmt; /* DMA2D pixel format */ + uint8_t transp_mode; /* DMA2D transparency mode */ + fb_coord_t xres; /* X-resolution overlay */ + fb_coord_t yres; /* Y-resolution overlay */ + FAR struct fb_overlayinfo_s *oinfo; /* Framebuffer overlay information */ }; -/* The layer is controlled through the following structure */ +/* DMA2D is controlled by the following interface */ struct dma2d_layer_s { - /* Name: getvideoinfo - * - * Description: - * Get video information about the layer - * - * Parameter: - * layer - Reference to the layer control structure - * vinfo - Reference to the video info structure - * - * Returned Value: - * On success - OK - * On error - -EINVAL - */ - - int (*getvideoinfo)(FAR struct dma2d_layer_s *layer, - FAR struct fb_videoinfo_s *vinfo); - - /* Name: getplaneinfo - * - * Description: - * Get plane information about the layer - * - * Parameter: - * layer - Reference to the layer control structure - * planeno - Number of the plane - * pinfo - Reference to the plane info structure - * - * Returned Value: - * On success - OK - * On error - -EINVAL - */ - - int (*getplaneinfo)(FAR struct dma2d_layer_s *layer, int planeno, - FAR struct fb_planeinfo_s *pinfo); - - /* Name: getlid - * - * Description: - * Get a specific layer identifier. - * - * Parameter: - * layer - Reference to the layer structure - * lid - Reference to store the layer id - * - * Returned Value: - * On success - OK - * On error - -EINVAL - */ - - int (*getlid)(FAR struct dma2d_layer_s *layer, int *lid); - -#ifdef CONFIG_STM32F7_DMA2D_L8 /* Name: setclut * * Description: - * Configure layer clut (color lookup table). - * Non clut is defined during initializing. + * Set the cmap table for both foreground and background layer. + * Up to 256 colors supported. * * Parameter: - * layer - Reference to the layer structure - * cmap - color lookup table with up the 256 entries + * cmap - Reference to the cmap table * * Returned Value: * On success - OK * On error - -EINVAL */ - int (*setclut)(FAR struct dma2d_layer_s *layer, - const FAR struct fb_cmap_s *cmap); - - /* Name: getclut - * - * Description: - * Get configured layer clut (color lookup table). - * - * Parameter: - * layer - Reference to the layer structure - * cmap - Reference to valid color lookup table accept up the 256 color - * entries - * - * Returned Value: - * On success - OK - * On error - -EINVAL - */ - - int (*getclut)(FAR struct dma2d_layer_s *layer, FAR struct fb_cmap_s *cmap); +#ifdef CONFIG_FB_CMAP + int (*setclut)(FAR const struct fb_cmap_s * cmap); #endif - /* Name: setalpha + /* Name: fillcolor * * Description: - * Configure layer alpha value factor into blend operation. - * During the layer blend operation the source alpha value is multiplied - * with this alpha value. If the source color format doesn't support alpha - * channel (e.g. non ARGB8888) this alpha value will be used as constant - * alpha value for blend operation. - * Default value during initializing: 0xff + * Fill a specific memory region with a color. + * The caller must ensure that the memory region (area) is within the entire + * overlay. * * Parameter: - * layer - Reference to the layer structure - * alpha - Alpha value + * oinfo - Reference to overlay information + * area - Reference to the area to fill + * argb - argb8888 color * * Returned Value: * On success - OK - * On error - -EINVAL + * On error - -EINVAL */ - int (*setalpha)(FAR struct dma2d_layer_s *layer, uint8_t alpha); - - /* Name: getalpha - * - * Description: - * Get configured layer alpha value factor for blend operation. - * - * Parameter: - * layer - Reference to the layer structure - * alpha - Reference to store the alpha value - * - * Returned Value: - * On success - OK - * On error - -EINVAL - */ - - int (*getalpha)(FAR struct dma2d_layer_s *layer, uint8_t *alpha); - - /* Name: setblendmode - * - * Description: - * Configure blend mode of the layer. - * Default mode during initializing: DMA2D_BLEND_NONE - * Blendmode is active after next update. - * - * Parameter: - * layer - Reference to the layer structure - * mode - Blend mode (see DMA2D_BLEND_*) - * - * Returned Value: - * On success - OK - * On error - -EINVAL - * - * Procedure information: - * DMA2D_BLEND_NONE: - * Informs the driver to disable all blend operation for the given layer. - * That means the layer is opaque. - * - * DMA2D_BLEND_ALPHA: - * Informs the driver to enable alpha blending for the given layer. - * - * DMA2D_BLEND_PIXELALPHA: - * Informs the driver to use the pixel alpha value of the layer instead - * the constant alpha value. This is only useful for ARGB8888 - * color format. - */ - - int (*setblendmode)(FAR struct dma2d_layer_s *layer, uint32_t mode); - - /* Name: getblendmode - * - * Description: - * Get configured blend mode of the layer. - * - * Parameter: - * layer - Reference to the layer structure - * mode - Reference to store the blend mode - * - * Returned Value: - * On success - OK - * On error - -EINVAL - */ - - int (*getblendmode)(FAR struct dma2d_layer_s *layer, uint32_t *mode); + int (*fillcolor)(FAR struct stm32_dma2d_overlay_s *oinfo, + FAR const struct fb_area_s *area, uint32_t argb); /* Name: blit * * Description: - * Copy selected area from a source layer to selected position of the - * destination layer. + * Copies memory from a source overlay (defined by sarea) to destination + * overlay position (defined by destxpos and destypos) without pixelformat + * conversion. The caller must ensure that the memory region (area) is + * within the entire overlay. * * Parameter: - * dest - Reference to the destination layer - * destxpos - Selected x target position of the destination layer - * destypos - Selected y target position of the destination layer - * src - Reference to the source layer - * srcarea - Reference to the selected area of the source layer + * doverlay - Reference destination overlay + * destxpos - x-Offset destination overlay + * destypos - y-Offset destination overlay + * soverlay - Reference source overlay + * sarea - Reference source area * * Returned Value: - * OK - On success - * -EINVAL - If one of the parameter invalid or if the size of the - * selected source area outside the visible area of the - * destination layer. (The visible area usually represents the - * display size) - * -ECANCELED - Operation cancelled, something goes wrong. + * On success - OK + * On error - -EINVAL */ - int (*blit)(FAR struct dma2d_layer_s *dest, - fb_coord_t destxpos, fb_coord_t destypos, - FAR const struct dma2d_layer_s *src, - FAR const struct ltdc_area_s *srcarea); + int (*blit)(FAR struct stm32_dma2d_overlay_s *doverlay, + uint32_t destxpos, uint32_t destypos, + FAR struct stm32_dma2d_overlay_s *soverlay, + FAR const struct fb_area_s *sarea); /* Name: blend * * Description: - * Blends the selected area from a background layer with selected position - * of the foreground layer. Copies the result to the selected position of - * the destination layer. Note! The content of the foreground and background - * layer keeps unchanged as long destination layer is unequal to the - * foreground and background layer. + * Blends two source memory areas to a destination memory area with + * pixelformat conversion if necessary. The caller must ensure that the + * memory region (area) is within the entire overlays. * * Parameter: - * dest - Reference to the destination layer - * fore - Reference to the foreground layer - * forexpos - Selected x target position of the foreground layer - * foreypos - Selected y target position of the foreground layer - * back - Reference to the background layer - * backarea - Reference to the selected area of the background layer + * doverlay - Destination overlay + * destxpos - x-Offset destination overlay + * destypos - y-Offset destination overlay + * foverlay - Foreground overlay + * forexpos - x-Offset foreground overlay + * foreypos - y-Offset foreground overlay + * boverlay - Background overlay + * barea - x-Offset, y-Offset, x-resolution and y-resolution of + * background overlay * * Returned Value: - * OK - On success - * -EINVAL - If one of the parameter invalid or if the size of the - * selected source area outside the visible area of the - * destination layer. (The visible area usually represents the - * display size) - * -ECANCELED - Operation cancelled, something goes wrong. + * On success - OK + * On error - -EINVAL or -ECANCELED */ - int (*blend)(FAR struct dma2d_layer_s *dest, - fb_coord_t destxpos, fb_coord_t destypos, - FAR const struct dma2d_layer_s *fore, - fb_coord_t forexpos, fb_coord_t foreypos, - FAR const struct dma2d_layer_s *back, - FAR const struct ltdc_area_s *backarea); - - /* Name: fillarea - * - * Description: - * Fill the selected area of the whole layer with a specific color. - * - * Parameter: - * layer - Reference to the layer structure - * area - Reference to the valid area structure select the area - * color - Color to fill the selected area. Color must be formatted - * according to the layer pixel format. - * - * Returned Value: - * OK - On success - * -EINVAL - If one of the parameter invalid or if the size of the - * selected area outside the visible area of the layer. - * -ECANCELED - Operation cancelled, something goes wrong. - */ - - int (*fillarea)(FAR struct dma2d_layer_s *layer, - FAR const struct ltdc_area_s *area, - uint32_t color); + int (*blend)(FAR struct stm32_dma2d_overlay_s *doverlay, + uint32_t destxpos, uint32_t destypos, + FAR struct stm32_dma2d_overlay_s *foverlay, + uint32_t forexpos, uint32_t foreypos, + FAR struct stm32_dma2d_overlay_s *boverlay, + FAR const struct fb_area_s *barea); }; /**************************************************************************** * Public Functions ****************************************************************************/ -struct stm32_ltdc_s; /* Forward declaration */ - /**************************************************************************** - * Name: stm32_dma2dinitltdc + * Name: stm32_dma2ddev * * Description: - * Get a reference to the dma2d layer coupled with the ltdc layer. - * It not intends to use this function by user space applications. - * It resolves the following requirements: - * 1. Share the color lookup table - * 2. Share the planeinfo information - * 3. Share the videoinfo information - * - * Input Parameters: - * layer - a valid reference to the low level ltdc layer structure + * Get a reference to the DMA2D controller. * * Returned Value: - * On success - A valid dma2d layer reference + * On success - A valid DMA2D controller reference * On error - NULL and errno is set to * -EINVAL if one of the parameter is invalid * ****************************************************************************/ -FAR struct dma2d_layer_s *stm32_dma2dinitltdc(FAR struct stm32_ltdc_s *layer); - -/**************************************************************************** - * Name: up_dma2dgetlayer - * - * Description: - * Get a dma2d layer structure by the layer identifier - * - * Input Parameters: - * lid - Layer identifier - * - * Returned Value: - * Reference to the dma2d layer control structure on success or Null if no - * related exist. - * - ****************************************************************************/ - -FAR struct dma2d_layer_s *up_dma2dgetlayer(int lid); - -/**************************************************************************** - * Name: up_dma2dcreatelayer - * - * Description: - * Create a new dma2d layer object to interact with the dma2d controller - * - * Input Parameters: - * width - Layer width - * height - Layer height - * fmt - Pixel format of the layer - * - * Returned Value: - * On success - A valid dma2d layer reference - * On error - NULL and errno is set to - * -EINVAL if one of the parameter is invalid - * -ENOMEM if no memory available or exceeds - * CONFIG_STM32F7_DMA2D_NLAYERS - * - ****************************************************************************/ - -FAR struct dma2d_layer_s *up_dma2dcreatelayer(fb_coord_t width, - fb_coord_t height, - uint8_t fmt); - -/**************************************************************************** - * Name: up_dma2dremovelayer - * - * Description: - * Remove and deallocate the dma2d layer - * - * Input Parameters: - * layer - Reference to the layer to remove - * - * Returned Value: - * On success - OK - * On error - -EINVAL - * - ****************************************************************************/ - -int up_dma2dremovelayer(FAR struct dma2d_layer_s *layer); +FAR struct dma2d_layer_s *stm32_dma2ddev(void); /**************************************************************************** * Name: up_dma2dinitialize * * Description: - * Initialize the dma2d controller + * Initialize the DMA2D controller * * Returned Value: * OK - On success @@ -419,17 +190,17 @@ int up_dma2dremovelayer(FAR struct dma2d_layer_s *layer); * ****************************************************************************/ -int up_dma2dinitialize(void); +int stm32_dma2dinitialize(void); /**************************************************************************** * Name: up_dma2duninitialize * * Description: - * Uninitialize the dma2d controller + * Uninitialize the DMA2D controller * ****************************************************************************/ -void up_dma2duninitialize(void); +void stm32_dma2duninitialize(void); -#endif /* CONFIG_STM32F7_DMA2D */ +#endif /* CONFIG_FB_OVERLAY */ #endif /* __ARCH_ARM_SRC_STM32F7_STM32_DMA2D_H */ diff --git a/arch/arm/src/stm32f7/stm32_ltdc.c b/arch/arm/src/stm32f7/stm32_ltdc.c index 19ff5f4ef50..a8be601e0c3 100644 --- a/arch/arm/src/stm32f7/stm32_ltdc.c +++ b/arch/arm/src/stm32f7/stm32_ltdc.c @@ -1,7 +1,7 @@ /**************************************************************************** - * arch/arm/src/stm32/stm32_ltdc.c + * arch/arm/src/stm32f7/stm32_ltdc.c * - * Copyright (C) 2013-2015 Ken Pettit. All rights reserved. + * Copyright (C) 2013-2015, 2018 Ken Pettit. All rights reserved. * Authors: Ken Pettit * Marco Krahl * @@ -58,9 +58,10 @@ #include "up_arch.h" #include "up_internal.h" #include "chip/stm32_ltdc.h" +#include "chip/stm32_dma2d.h" +#include "stm32_gpio.h" #include "stm32_ltdc.h" #include "stm32_dma2d.h" -#include "stm32_gpio.h" /**************************************************************************** * Pre-processor Definitions @@ -85,49 +86,57 @@ #define STM32_LTDC_LxWHPCR_WHSTPOS (BOARD_LTDC_HSYNC + BOARD_LTDC_HBP - 1) #define STM32_LTDC_LxWHPCR_WHSPPOS (BOARD_LTDC_HSYNC + BOARD_LTDC_HBP + \ - STM32_LTDC_WIDTH - 1) + STM32_LTDC_WIDTH - 1) /* LTDC_LxWVPCR register */ #define STM32_LTDC_LxWVPCR_WVSTPOS (BOARD_LTDC_VSYNC + BOARD_LTDC_VBP - 1) #define STM32_LTDC_LxWVPCR_WVSPPOS (BOARD_LTDC_VSYNC + BOARD_LTDC_VBP + \ - STM32_LTDC_HEIGHT - 1) + STM32_LTDC_HEIGHT - 1) /* LTDC_SSCR register */ -#define STM32_LTDC_SSCR_VSH LTDC_SSCR_VSH(BOARD_LTDC_VSYNC - 1) -#define STM32_LTDC_SSCR_HSW LTDC_SSCR_HSW(BOARD_LTDC_HSYNC - 1) +#define STM32_LTDC_SSCR_VSH LTDC_SSCR_VSH(BOARD_LTDC_VSYNC - 1) +#define STM32_LTDC_SSCR_HSW LTDC_SSCR_HSW(BOARD_LTDC_HSYNC - 1) /* LTDC_BPCR register */ -#define STM32_LTDC_BPCR_AVBP LTDC_BPCR_AVBP(STM32_LTDC_LxWVPCR_WVSTPOS) -#define STM32_LTDC_BPCR_AHBP LTDC_BPCR_AHBP(STM32_LTDC_LxWHPCR_WHSTPOS) +#define STM32_LTDC_BPCR_AVBP LTDC_BPCR_AVBP(STM32_LTDC_LxWVPCR_WVSTPOS) +#define STM32_LTDC_BPCR_AHBP LTDC_BPCR_AHBP(STM32_LTDC_LxWHPCR_WHSTPOS) /* LTDC_AWCR register */ -#define STM32_LTDC_AWCR_AAH LTDC_AWCR_AAH(STM32_LTDC_LxWVPCR_WVSPPOS) -#define STM32_LTDC_AWCR_AAW LTDC_AWCR_AAW(STM32_LTDC_LxWHPCR_WHSPPOS) +#define STM32_LTDC_AWCR_AAH LTDC_AWCR_AAH(STM32_LTDC_LxWVPCR_WVSPPOS) +#define STM32_LTDC_AWCR_AAW LTDC_AWCR_AAW(STM32_LTDC_LxWHPCR_WHSPPOS) /* LTDC_TWCR register */ -#define STM32_LTDC_TOTALHEIGHT (BOARD_LTDC_VSYNC + \ - BOARD_LTDC_VBP + \ - STM32_LTDC_HEIGHT + BOARD_LTDC_VFP - 1) -#define STM32_LTDC_TWCR_TOTALH LTDC_TWCR_TOTALH(STM32_LTDC_TOTALHEIGHT) -#define STM32_LTDC_TWCR_TOTALW LTDC_TWCR_TOTALW(BOARD_LTDC_HSYNC + \ - BOARD_LTDC_HBP + \ - STM32_LTDC_WIDTH + BOARD_LTDC_HFP - 1) +#define STM32_LTDC_TWCR_TOTALH LTDC_TWCR_TOTALH(BOARD_LTDC_VSYNC + \ + BOARD_LTDC_VBP + \ + STM32_LTDC_HEIGHT + BOARD_LTDC_VFP - 1) +#define STM32_LTDC_TWCR_TOTALW LTDC_TWCR_TOTALW(BOARD_LTDC_HSYNC + \ + BOARD_LTDC_HBP + \ + STM32_LTDC_WIDTH + BOARD_LTDC_HFP - 1) -/* Global GCR register: Synchronisation Polarity */ +/* Global GCR register */ -#define STM32_LTDC_GCR_PCPOL BOARD_LTDC_GCR_PCPOL -#define STM32_LTDC_GCR_DEPOL BOARD_LTDC_GCR_DEPOL -#define STM32_LTDC_GCR_VSPOL BOARD_LTDC_GCR_VSPOL -#define STM32_LTDC_GCR_HSPOL BOARD_LTDC_GCR_HSPOL +/* Synchronisation and Polarity */ + +#define STM32_LTDC_GCR_PCPOL BOARD_LTDC_GCR_PCPOL +#define STM32_LTDC_GCR_DEPOL BOARD_LTDC_GCR_DEPOL +#define STM32_LTDC_GCR_VSPOL BOARD_LTDC_GCR_VSPOL +#define STM32_LTDC_GCR_HSPOL BOARD_LTDC_GCR_HSPOL + +/* Dither */ + +#define STM32_LTDC_GCR_DEN BOARD_LTDC_GCR_DEN +#define STM32_LTDC_GCR_DBW LTDC_GCR_GBW(BOARD_LTDC_GCR_DBW) +#define STM32_LTDC_GCR_DGW LTDC_GCR_DGW(BOARD_LTDC_GCR_DGW) +#define STN32_LTDC_GCR_DRW LTDC_GCR_DBW(BOARD_LTDC_GCR_DRW) /* LIPCR register */ -#define STM32_LTDC_LIPCR_LIPOS LTDC_LIPCR_LIPOS(STM32_LTDC_TOTALHEIGHT) +#define STM32_LTDC_LIPCR_LIPOS LTDC_LIPCR_LIPOS(STM32_LTDC_TWCR_TOTALW) /* Configuration ************************************************************/ @@ -144,93 +153,75 @@ # define STM32_LTDC_L1_BPP 8 # define STM32_LTDC_L1_COLOR_FMT FB_FMT_RGB8 # define STM32_LTDC_L1PFCR_PF LTDC_LxPFCR_PF(LTDC_PF_L8) +# define STM32_LTDC_L1_DMA2D_PF DMA2D_PF_L8 # define STM32_LTDC_L1CMAP -#elif defined(CONFIG_STM32F7_LTDC_L1_AL44) -# define STM32_LTDC_L1_BPP 8 -# define STM32_LTDC_L1_COLOR_FMT ??? -# define STM32_LTDC_L1PFCR_PF LTDC_LxPFCR_PF(LTDC_PF_AL44) -#elif defined(CONFIG_STM32F7_LTDC_L1_AL88) -# define STM32_LTDC_L1_BPP 16 -# define STM32_LTDC_L1_COLOR_FMT ??? -# define STM32_LTDC_L1PFCR_PF LTDC_LxPFCR_PF(LTDC_PF_AL88) -#elif defined(CONFIG_STM32F7_LTDC_L1_ARGB4444) -# define STM32_LTDC_L1_BPP 16 -# define STM32_LTDC_L1_COLOR_FMT ??? -# define STM32_LTDC_L1PFCR_PF LTDC_LxPFCR_PF(LTDC_PF_ARGB4444) #elif defined(CONFIG_STM32F7_LTDC_L1_RGB565) # define STM32_LTDC_L1_BPP 16 # define STM32_LTDC_L1_COLOR_FMT FB_FMT_RGB16_565 # define STM32_LTDC_L1PFCR_PF LTDC_LxPFCR_PF(LTDC_PF_RGB565) -#elif defined(CONFIG_STM32F7_LTDC_L1_ARGB1555) -# define STM32_LTDC_L1_BPP 16 -# define STM32_LTDC_L1_COLOR_FMT ??? -# define STM32_LTDC_L1PFCR_PF LTDC_LxPFCR_PF(LTDC_PF_ARGB1555) +# define STM32_LTDC_L1_DMA2D_PF DMA2D_PF_RGB565 #elif defined(CONFIG_STM32F7_LTDC_L1_RGB888) # define STM32_LTDC_L1_BPP 24 # define STM32_LTDC_L1_COLOR_FMT FB_FMT_RGB24 # define STM32_LTDC_L1PFCR_PF LTDC_LxPFCR_PF(LTDC_PF_RGB888) +# define STM32_LTDC_L1_DMA2D_PF DMA2D_PF_RGB888 #elif defined(CONFIG_STM32F7_LTDC_L1_ARGB8888) # define STM32_LTDC_L1_BPP 32 -# define STM32_LTDC_L1_COLOR_FMT ??? +# define STM32_LTDC_L1_COLOR_FMT FB_FMT_RGB32 # define STM32_LTDC_L1PFCR_PF LTDC_LxPFCR_PF(LTDC_PF_ARGB8888) +# define STM32_LTDC_L1_DMA2D_PF DMA2D_PF_ARGB8888 +#else +# error "LTDC pixel format not supported" #endif /* Layer 2 format */ -#if defined(CONFIG_STM32F7_LTDC_L2_L8) -# define STM32_LTDC_L2_BPP 8 -# define STM32_LTDC_L2_COLOR_FMT FB_FMT_RGB8 -# define STM32_LTDC_L2PFCR_PF LTDC_LxPFCR_PF(LTDC_PF_L8) -# define STM32_LTDC_L2CMAP -#elif defined(CONFIG_STM32F7_LTDC_L2_AL44) -# define STM32_LTDC_L2_BPP 8 -# define STM32_LTDC_L2_COLOR_FMT ??? -# define STM32_LTDC_L2PFCR_PF LTDC_LxPFCR_PF(LTDC_PF_AL44) -#elif defined(CONFIG_STM32F7_LTDC_L2_AL88) -# define STM32_LTDC_L2_BPP 16 -# define STM32_LTDC_L2_COLOR_FMT ??? -# define STM32_LTDC_L2PFCR_PF LTDC_LxPFCR_PF(LTDC_PF_AL88) -#elif defined(CONFIG_STM32F7_LTDC_L2_ARGB4444) -# define STM32_LTDC_L2_BPP 16 -# define STM32_LTDC_L2_COLOR_FMT ??? -# define STM32_LTDC_L2PFCR_PF LTDC_LxPFCR_PF(LTDC_PF_ARGB4444) -#elif defined(CONFIG_STM32F7_LTDC_L2_RGB565) -# define STM32_LTDC_L2_BPP 16 -# define STM32_LTDC_L2_COLOR_FMT FB_FMT_RGB16_565 -# define STM32_LTDC_L2PFCR_PF LTDC_LxPFCR_PF(LTDC_PF_RGB565) -#elif defined(CONFIG_STM32F7_LTDC_L2_ARGB1555) -# define STM32_LTDC_L2_BPP 16 -# define STM32_LTDC_L2_COLOR_FMT ??? -# define STM32_LTDC_L2PFCR_PF LTDC_LxPFCR_PF(LTDC_PF_ARGB1555) -#elif defined(CONFIG_STM32F7_LTDC_L2_RGB888) -# define STM32_LTDC_L2_BPP 24 -# define STM32_LTDC_L2_COLOR_FMT FB_FMT_RGB24 -# define STM32_LTDC_L2PFCR_PF LTDC_LxPFCR_PF(LTDC_PF_RGB888) -#elif defined(CONFIG_STM32F7_LTDC_L2_ARGB8888) -# define STM32_LTDC_L2_BPP 32 -# define STM32_LTDC_L2_COLOR_FMT ??? -# define STM32_LTDC_L2PFCR_PF LTDC_LxPFCR_PF(LTDC_PF_ARGB8888) -#endif +#ifdef CONFIG_STM32F7_LTDC_L2 +# if defined(CONFIG_STM32F7_LTDC_L2_L8) +# define STM32_LTDC_L2_BPP 8 +# define STM32_LTDC_L2_COLOR_FMT FB_FMT_RGB8 +# define STM32_LTDC_L2PFCR_PF LTDC_LxPFCR_PF(LTDC_PF_L8) +# define STM32_LTDC_L2_DMA2D_PF DMA2D_PF_L8 +# define STM32_LTDC_L2CMAP +# elif defined(CONFIG_STM32F7_LTDC_L2_RGB565) +# define STM32_LTDC_L2_BPP 16 +# define STM32_LTDC_L2_COLOR_FMT FB_FMT_RGB16_565 +# define STM32_LTDC_L2PFCR_PF LTDC_LxPFCR_PF(LTDC_PF_RGB565) +# define STM32_LTDC_L2_DMA2D_PF DMA2D_PF_RGB565 +# elif defined(CONFIG_STM32F7_LTDC_L2_RGB888) +# define STM32_LTDC_L2_BPP 24 +# define STM32_LTDC_L2_COLOR_FMT FB_FMT_RGB24 +# define STM32_LTDC_L2PFCR_PF LTDC_LxPFCR_PF(LTDC_PF_RGB888) +# define STM32_LTDC_L2_DMA2D_PF DMA2D_PF_RGB888 +# elif defined(CONFIG_STM32F7_LTDC_L2_ARGB8888) +# define STM32_LTDC_L2_BPP 32 +# define STM32_LTDC_L2_COLOR_FMT FB_FMT_RGB32 +# define STM32_LTDC_L2PFCR_PF LTDC_LxPFCR_PF(LTDC_PF_ARGB8888) +# define STM32_LTDC_L2_DMA2D_PF DMA2D_PF_ARGB8888 +# else +# error "LTDC pixel format not supported" +# endif +#endif /* CONFIG_STM32F7_LTDC_L2 */ /* Framebuffer sizes in bytes */ #if STM32_LTDC_L1_BPP == 8 -# define STM32_L1_STRIDE (STM32_LTDC_WIDTH) +# define STM32_LTDC_L1_STRIDE (STM32_LTDC_WIDTH) #elif STM32_LTDC_L1_BPP == 16 -# define STM32_L1_STRIDE ((STM32_LTDC_WIDTH * 16 + 7) / 8) +# define STM32_LTDC_L1_STRIDE ((STM32_LTDC_WIDTH * 16 + 7) / 8) #elif STM32_LTDC_L1_BPP == 24 -# define STM32_L1_STRIDE ((STM32_LTDC_WIDTH * 24 + 7) / 8) +# define STM32_LTDC_L1_STRIDE ((STM32_LTDC_WIDTH * 24 + 7) / 8) #elif STM32_LTDC_L1_BPP == 32 -# define STM32_L1_STRIDE ((STM32_LTDC_WIDTH * 32 + 7) / 8) +# define STM32_LTDC_L1_STRIDE ((STM32_LTDC_WIDTH * 32 + 7) / 8) #else # error Undefined or unrecognized base resolution #endif /* LTDC only supports 8 bit per pixel overal */ -#define STM32_LTDC_Lx_BYPP(n) ((n) / 8) +#define STM32_LTDC_Lx_BYPP(n) ((n) / 8) -#define STM32_L1_FBSIZE (STM32_L1_STRIDE * STM32_LTDC_HEIGHT) +#define STM32_LTDC_L1_FBSIZE (STM32_LTDC_L1_STRIDE * STM32_LTDC_HEIGHT) #ifdef CONFIG_STM32F7_LTDC_L2 # ifndef CONFIG_STM32F7_LTDC_L2_WIDTH @@ -250,26 +241,28 @@ # endif # if STM32_LTDC_L2_BPP == 8 -# define STM32_L2_STRIDE (CONFIG_STM32F7_LTDC_L2_WIDTH) +# define STM32_LTDC_L2_STRIDE (CONFIG_STM32F7_LTDC_L2_WIDTH) # elif STM32_LTDC_L2_BPP == 16 -# define STM32_L2_STRIDE ((CONFIG_STM32F7_LTDC_L2_WIDTH * 16 + 7) / 8) +# define STM32_LTDC_L2_STRIDE ((CONFIG_STM32F7_LTDC_L2_WIDTH * 16 + 7) / 8) # elif STM32_LTDC_L2_BPP == 24 -# define STM32_L2_STRIDE ((CONFIG_STM32F7_LTDC_L2_WIDTH * 24 + 7) / 8) +# define STM32_LTDC_L2_STRIDE ((CONFIG_STM32F7_LTDC_L2_WIDTH * 24 + 7) / 8) # elif STM32_LTDC_L2_BPP == 32 -# define STM32_L2_STRIDE ((CONFIG_STM32F7_LTDC_L2_WIDTH * 32 + 7) / 8) +# define STM32_LTDC_L2_STRIDE ((CONFIG_STM32F7_LTDC_L2_WIDTH * 32 + 7) / 8) # else # error Undefined or unrecognized base resolution # endif -# define STM32_L2_FBSIZE (STM32_L2_STRIDE * CONFIG_STM32F7_LTDC_L2_HEIGHT) +# define STM32_LTDC_L2_FBSIZE (STM32_LTDC_L2_STRIDE * \ + CONFIG_STM32F7_LTDC_L2_HEIGHT) #else -# define STM32_L2_FBSIZE (0) +# define STM32_LTDC_L2_FBSIZE (0) #endif /* Total memory used for framebuffers */ -#define STM32_TOTAL_FBSIZE (STM32_L1_FBSIZE + STM32_L2_FBSIZE) +#define STM32_LTDC_TOTAL_FBSIZE (STM32_LTDC_L1_FBSIZE + \ + STM32_LTDC_L2_FBSIZE) /* Debug option */ @@ -288,10 +281,11 @@ * wild framebuffer writes. */ -#define STM32_LTDC_BUFFER_SIZE CONFIG_STM32F7_LTDC_FB_SIZE -#define STM32_LTDC_BUFFER_FREE (STM32_LTDC_BUFFER_SIZE - STM32_TOTAL_FBSIZE) -#define STM32_LTDC_BUFFER_START (CONFIG_STM32F7_LTDC_FB_BASE + \ - STM32_LTDC_BUFFER_FREE/2) +#define STM32_LTDC_BUFFER_SIZE CONFIG_STM32F7_LTDC_FB_SIZE +#define STM32_LTDC_BUFFER_FREE (STM32_LTDC_BUFFER_SIZE - \ + STM32_LTDC_TOTAL_FBSIZE) +#define STM32_LTDC_BUFFER_START (CONFIG_STM32F7_LTDC_FB_BASE + \ + STM32_LTDC_BUFFER_FREE/2) #if STM32_LTDC_BUFFER_FREE < 0 # error "STM32_LTDC_BUFFER_SIZE not large enough for frame buffers" @@ -299,17 +293,19 @@ /* Layer frame buffer */ -#define STM32_LTDC_BUFFER_L1 STM32_LTDC_BUFFER_START -#define STM32_LTDC_ENDBUF_L1 (STM32_LTDC_BUFFER_L1 + STM32_L1_FBSIZE) +#define STM32_LTDC_BUFFER_L1 STM32_LTDC_BUFFER_START +#define STM32_LTDC_ENDBUF_L1 (STM32_LTDC_BUFFER_L1 + \ + STM32_LTDC_L1_FBSIZE) #ifdef CONFIG_STM32F7_LTDC_L2 -# define STM32_LTDC_BUFFER_L2 STM32_LTDC_ENDBUF_L1 -# define STM32_LTDC_ENDBUF_L2 (STM32_LTDC_BUFFER_L2 + STM32_L2_FBSIZE) +# define STM32_LTDC_BUFFER_L2 STM32_LTDC_ENDBUF_L1 +# define STM32_LTDC_ENDBUF_L2 (STM32_LTDC_BUFFER_L2 + \ + STM32_LTDC_L2_FBSIZE) #else -# define STM32_LTDC_ENDBUF_L2 STM32_LTDC_ENDBUF_L1 +# define STM32_LTDC_ENDBUF_L2 STM32_LTDC_ENDBUF_L1 #endif -/* Layer helpers */ +/* LTDC layer */ #ifdef CONFIG_STM32F7_LTDC_L2 # define LTDC_NLAYERS 2 @@ -317,9 +313,56 @@ # define LTDC_NLAYERS 1 #endif -#define LAYER(i) g_ltdc.layer[i] -#define LAYER_L1 g_ltdc.layer[LTDC_LAYER_L1] -#define LAYER_L2 g_ltdc.layer[LTDC_LAYER_L2] +/* DMA2D layer */ + +#ifdef CONFIG_STM32F7_DMA2D +# define DMA2D_NLAYERS CONFIG_STM32F7_DMA2D_NLAYERS +# if DMA2D_NLAYERS < 1 +# error "DMA2D must at least support 1 overlay" +# endif + +#define STM32_DMA2D_WIDTH CONFIG_STM32F7_DMA2D_LAYER_PPLINE + +# if defined(CONFIG_STM32F7_DMA2D_L8) +# define STM32_DMA2D_STRIDE (STM32_DMA2D_WIDTH) +# define STM32_DMA2D_BPP 8 +# define STM32_DMA2D_COLOR_FMT DMA2D_PF_L8 +# elif defined(CONFIG_STM32F7_DMA2D_RGB565) +# define STM32_DMA2D_STRIDE ((STM32_DMA2D_WIDTH * 16 + 7) / 8) +# define STM32_DMA2D_BPP 16 +# define STM32_DMA2D_COLOR_FMT DMA2D_PF_RGB565 +# elif defined(CONFIG_STM32F7_DMA2D_RGB888) +# define STM32_DMA2D_STRIDE ((STM32_DMA2D_WIDTH * 24 + 7) / 8) +# define STM32_DMA2D_BPP 24 +# define STM32_DMA2D_COLOR_FMT DMA2D_PF_RGB888 +# elif defined(CONFIG_STM32F7_DMA2D_ARGB8888) +# define STM32_DMA2D_STRIDE ((STM32_DMA2D_WIDTH * 32 + 7) / 8) +# define STM32_DMA2D_BPP 32 +# define STM32_DMA2D_COLOR_FMT DMA2D_PF_ARGB8888 +# else +# error "DMA2D pixel format not supported" +# endif + + +# ifdef CONFIG_STM32F7_DMA2D_LAYER_SHARED +# define STM32_DMA2D_FBSIZE CONFIG_STM32F7_DMA2D_FB_SIZE +# define STM32_DMA2D_LAYER_SIZE 0 +# else +# define STM32_DMA2D_FBSIZE CONFIG_STM32F7_DMA2D_FB_SIZE / DMA2D_NLAYERS +# define STM32_DMA2D_LAYER_SIZE STM32_DMA2D_FBSIZE +# if STM32_DMA2D_FBSIZE * DMA2D_NLAYERS > CONFIG_STM32F7_DMA2D_FB_SIZE +# error "DMA2D framebuffer size to small for configured number of overlays" +# endif +# endif /* CONFIG_STM32F7_DMA2D_LAYER_SHARED */ + +# define STM32_DMA2D_HEIGHT STM32_DMA2D_FBSIZE / STM32_DMA2D_STRIDE + +# define STM32_DMA2D_BUFFER_START CONFIG_STM32F7_DMA2D_FB_BASE +#else +# define DMA2D_NLAYERS 0 +#endif /* CONFIG_STM32F7_DMA2D */ + +#define LTDC_NOVERLAYS LTDC_NLAYERS + DMA2D_NLAYERS /* Dithering */ @@ -347,6 +390,22 @@ # define STM32_LTDC_BACKCOLOR CONFIG_STM32F7_LTDC_BACKCOLOR #endif +/* Layer default color */ + +#ifdef CONFIG_STM32F7_LTDC_L1_COLOR +# define STM32_LTDC_L1_COLOR CONFIG_STM32F7_LTDC_L1_COLOR +#else +# define STM32_LTDC_L1_COLOR 0x000000 +#endif + +#ifdef CONFIG_STM32F7_LTDC_L2 +# ifdef CONFIG_STM32F7_LTDC_L2_COLOR +# define STM32_LTDC_L2_COLOR CONFIG_STM32F7_LTDC_L2_COLOR +# else +# define STM32_LTDC_L2_COLOR 0x000000 +# endif +#endif + /* Internal operation flags */ #define LTDC_LAYER_SETAREA (1 << 0) /* Change visible area */ @@ -379,13 +438,13 @@ # if defined(CONFIG_STM32F7_LTDC_L1_L8) || \ defined(CONFIG_STM32F7_LTDC_L2_L8) # if !defined(CONFIG_STM32F7_DMA2D_L8) -# error "DMA2D must support FB_FMT_RGB8 pixel format" +# error "DMA2D must support FB_FMT_RGB8 pixel format" # endif # endif # if defined(CONFIG_STM32F7_LTDC_L1_RGB565) || \ defined(CONFIG_STM32F7_LTDC_L2_RGB565) # if !defined(CONFIG_STM32F7_DMA2D_RGB565) -# error "DMA2D must support FB_FMT_RGB16_565 pixel format" +# error "DMA2D must support FB_FMT_RGB16_565 pixel format" # endif # endif # if defined(CONFIG_STM32F7_LTDC_L1_RGB888) || \ @@ -394,6 +453,12 @@ # error "DMA2D must support FB_FMT_RGB24 pixel format" # endif # endif +# if defined(CONFIG_STM32F7_LTDC_L1_ARGB8888) || \ + defined(CONFIG_STM32F7_LTDC_L2_ARGB8888) +# if !defined(CONFIG_STM32F7_DMA2D_ARGB8888) +# error "DMA2D must support FB_FMT_RGB32 pixel format" +# endif +# endif #endif /* Calculate the size of the layers clut table */ @@ -404,17 +469,17 @@ # endif # ifdef STM32_LTDC_L1CMAP # ifdef CONFIG_FB_TRANSPARENCY -# define STM32_LAYER_CLUT_SIZE STM32_LTDC_NCLUT * sizeof(uint32_t) +# define STM32_LAYER_CLUT_SIZE STM32_LTDC_NCLUT * sizeof(uint32_t) # else -# define STM32_LAYER_CLUT_SIZE STM32_LTDC_NCLUT * 3 * sizeof(uint8_t) +# define STM32_LAYER_CLUT_SIZE STM32_LTDC_NCLUT * 3 * sizeof(uint8_t) # endif # endif # ifdef STM32_LTDC_L2CMAP # undef STM32_LAYER_CLUT_SIZE # ifdef CONFIG_FB_TRANSPARENCY -# define STM32_LAYER_CLUT_SIZE STM32_LTDC_NCLUT * sizeof(uint32_t) * 2 +# define STM32_LAYER_CLUT_SIZE STM32_LTDC_NCLUT * sizeof(uint32_t) * 2 # else -# define STM32_LAYER_CLUT_SIZE STM32_LTDC_NCLUT * 3 * sizeof(uint8_t) * 2 +# define STM32_LAYER_CLUT_SIZE STM32_LTDC_NCLUT * 3 * sizeof(uint8_t) * 2 # endif # endif #endif @@ -452,6 +517,94 @@ #define LTDC_CMAP_GREEN(n) ((uint32_t)(n) >> 8) #define LTDC_CMAP_BLUE(n) ((uint32_t)(n) >> 0) +/* Hardware acceleration support */ + +/* Acceleration support for LTDC overlays */ + +#ifdef CONFIG_STM32F7_LTDC_L1_CHROMAKEYEN +# define STM32_LTDC_L1_CHROMAEN true +# define STM32_LTDC_L1_CHROMAKEY CONFIG_STM32F7_LTDC_L1_CHROMAKEY +# define LTDC_LTDC_ACCL_L1 FB_ACCL_TRANSP | FB_ACCL_CHROMA +#else +# define STM32_LTDC_L1_CHROMAEN false +# define STM32_LTDC_L1_CHROMAKEY 0 +# define LTDC_LTDC_ACCL_L1 FB_ACCL_TRANSP +#endif + +#ifdef CONFIG_STM32F7_LTDC_L2_CHROMAKEYEN +# define STM32_LTDC_L2_CHROMAEN true +# define STM32_LTDC_L2_CHROMAKEY CONFIG_STM32F7_LTDC_L2_CHROMAKEY +# define LTDC_LTDC_ACCL_L2 FB_ACCL_TRANSP | FB_ACCL_CHROMA +#else +# define STM32_LTDC_L2_CHROMAEN false +# define STM32_LTDC_L2_CHROMAKEY 0 +# define LTDC_LTDC_ACCL_L2 FB_ACCL_TRANSP +#endif + +#ifdef CONFIG_STM32F7_DMA2D +# ifdef CONFIG_FB_OVERLAY_BLIT +# ifdef CONFIG_FB_CMAP +# define LTDC_BLIT_ACCL FB_ACCL_BLIT +# else +# define LTDC_BLIT_ACCL FB_ACCL_BLIT | FB_ACCL_BLEND +# endif /* CONFIG_FB_CMAP */ +# else +# define LTDC_BLIT_ACCL 0 +# endif /* CONFIG_FB_OVERLAY_BLIT */ + +# ifdef CONFIG_FB_CMAP +# define LTDC_DMA2D_ACCL LTDC_BLIT_ACCL +# else +# define LTDC_DMA2D_ACCL FB_ACCL_COLOR | LTDC_BLIT_ACCL +# endif /* CONFIG_FB_CMAP */ +#else +# define LTDC_DMA2D_ACCL 0 +#endif /* CONFIG_STM32F7_DMA2D */ + +#define LTDC_L1_ACCL LTDC_LTDC_ACCL_L1 | LTDC_DMA2D_ACCL +#ifdef CONFIG_STM32F7_LTDC_L2 +# define LTDC_L2_ACCL LTDC_LTDC_ACCL_L2 | LTDC_DMA2D_ACCL +#endif + +/* Acceleration support for DMA2D overlays */ + +#ifdef CONFIG_FB_CMAP +# ifdef CONFIG_FB_OVERLAY_BLIT +# define DMA2D_ACCL FB_ACCL_BLIT | FB_ACCL_AREA +# else +# define DMA2D_ACCL FB_ACCL_AREA +# endif +#else +# ifdef CONFIG_FB_OVERLAY_BLIT +# define DMA2D_ACCL FB_ACCL_AREA | \ + FB_ACCL_TRANSP | \ + FB_ACCL_COLOR | \ + FB_ACCL_BLIT | \ + FB_ACCL_BLEND +# else +# define DMA2D_ACCL FB_ACCL_AREA | \ + FB_ACCL_TRANSP | \ + FB_ACCL_COLOR +# endif +#endif + +/* Helper */ + +#define MIN(x,y) ((x) < (y) ? (x) : (y)) + +/* Color normalization */ + +#if defined(CONFIG_STM32F7_LTDC_L1_RGB565) +# define RGB888_R(x) (((((x) >> 11) & 0x1f) * 527 + 23) >> 6) +# define RGB888_G(x) (((((x) >> 5) & 0x3f) * 259 + 33) >> 6) +# define RGB888_B(x) ((((x) & 0x1f) * 527 + 23) >> 6) +# define ARGB8888(x) ((RGB888_R(x) << 16) | \ + (RGB888_G(x) << 8) | \ + RGB888_B(x)) +#else +# define ARGB8888(x) (x) +#endif + /**************************************************************************** * Private Types ****************************************************************************/ @@ -466,65 +619,60 @@ enum stm32_layer_e /* LTDC General layer information */ -struct stm32_layer_s +struct stm32_ltdc_s { -#ifdef CONFIG_STM32F7_LTDC_INTERFACE - /* LTDC interface */ + int layerno; /* layer number */ - struct ltdc_layer_s ltdc; /* Layer control structure */ +#ifdef CONFIG_FB_OVERLAY + struct fb_overlayinfo_s oinfo; /* Overlay info */ #endif - struct stm32_ltdc_s state; /* Layer state structure */ - - /* Blending */ - - uint8_t opac; /* Opacity value for blending */ - uint8_t bf1; /* Blend factor 1 */ - uint8_t bf2; /* Blend factor 2 */ - - /* Operation */ - - uint8_t operation; /* Operation flags */ #ifdef CONFIG_STM32F7_DMA2D - FAR struct dma2d_layer_s *dma2d; /* dma2d interface */ + struct stm32_dma2d_overlay_s dma2dinfo; /* Overlay info for DMA2D */ #endif -}; -/* This structure provides the state of each LTDC layer */ - -struct stm32_state_s -{ - /* Layer state */ - - struct stm32_ltdc_s state[LTDC_NLAYERS]; + sem_t *lock; /* Layer exclusive access */ }; /* This structure provides the overall state of the LTDC layer */ struct stm32_ltdcdev_s { + /* Framebuffer interface */ + + struct fb_vtable_s vtable; + + /* Framebuffer video information */ + + struct fb_videoinfo_s vinfo; + + /* Framebuffer plane information */ + + struct fb_planeinfo_s pinfo; + + /* Cmap information */ + +#ifdef CONFIG_FB_CMAP + struct fb_cmap_s cmap; +#endif + /* Layer information */ - struct stm32_layer_s layer[LTDC_NLAYERS]; -}; + struct stm32_ltdc_s layer[LTDC_NOVERLAYS]; -/* Layer cmap table description */ +#ifdef CONFIG_STM32F7_DMA2D + /* Interface to the dma2d controller */ -#ifdef STM32_LAYER_CLUT_SIZE -enum stm32_clut_e -{ - LTDC_L1CLUT_OFFSET = 0, - LTDC_L2CLUT_OFFSET = STM32_LTDC_NCLUT * sizeof(uint32_t) -}; + FAR struct dma2d_layer_s *dma2d; #endif +}; /* Interrupt handling */ struct stm32_interrupt_s { - bool wait; /* Informs that the task is waiting for the irq */ - bool handled; /* Informs that an irq was handled */ int irq; /* irq number */ + int error; /* Interrupt error */ sem_t *sem; /* Semaphore for waiting for irq */ }; @@ -532,12 +680,10 @@ struct stm32_interrupt_s * Private Function Prototypes ****************************************************************************/ -/* Global register operation */ +/* Overal LTDC helper */ -static void stm32_lcd_enable(bool enable); -#if !defined(CONFIG_STM32F7_LTDC_USE_DSI) +static void stm32_ltdc_enable(bool enable); static void stm32_ltdc_gpioconfig(void); -#endif static void stm32_ltdc_periphconfig(void); static void stm32_ltdc_bgcolor(uint32_t rgb); static void stm32_ltdc_dither(bool enable, uint8_t red, @@ -546,112 +692,101 @@ static int stm32_ltdcirq(int irq, void *context, FAR void *arg); static int stm32_ltdc_waitforirq(void); static int stm32_ltdc_reload(uint8_t value, bool waitvblank); -/* Layer and layer register operation */ +/* Helper for layer register configuration */ -static inline void stm32_ltdc_lsetopac(FAR struct stm32_layer_s *layer); -static inline void stm32_ltdc_lunsetopac(FAR struct stm32_layer_s *layer); -static inline uint8_t stm32_ltdc_lgetopac(FAR struct stm32_layer_s *layer); -static inline bool stm32_ltdc_lvalidate(FAR const struct stm32_layer_s *layer); -#ifdef CONFIG_STM32F7_LTDC_INTERFACE -static int stm32_ltdc_lvalidatearea(FAR struct stm32_layer_s *layer, - fb_coord_t xpos, fb_coord_t ypos, - fb_coord_t xres, fb_coord_t yres, - fb_coord_t srcxpos, fb_coord_t srcypos); +static void stm32_ltdc_lpixelformat(FAR struct stm32_ltdc_s *layer); +static void stm32_ltdc_lframebuffer(FAR struct stm32_ltdc_s *layer); +static void stm32_ltdc_lenable(FAR struct stm32_ltdc_s *layer, bool enable); +static void stm32_ltdc_ldefaultcolor(FAR struct stm32_ltdc_s * layer, + uint32_t rgb); +static void stm32_ltdc_ltransp(FAR struct stm32_ltdc_s *layer, uint8_t transp, + uint32_t mode); +static void stm32_ltdc_lchromakey(FAR struct stm32_ltdc_s *layer, + uint32_t chromakey); +static void stm32_ltdc_lchromakeyenable(FAR struct stm32_ltdc_s *layer, + bool enable); +static void stm32_ltdc_linit(uint8_t lid); + +#ifdef CONFIG_STM32F7_DMA2D +static void stm32_ltdc_dma2dlinit(void); + +# ifdef CONFIG_FB_OVERLAY_BLIT +static bool stm32_ltdc_lvalidate(FAR const struct stm32_ltdc_s *layer, + FAR const struct fb_area_s *area); +# endif #endif -static void stm32_ltdc_lupdate(FAR struct stm32_layer_s *layer); -static void stm32_ltdc_lpixelformat(FAR struct stm32_layer_s *layer); -static inline void stm32_ltdc_lframebuffer(FAR struct stm32_layer_s *layer); -static void stm32_ltdc_larea(FAR struct stm32_layer_s *layer); -static void stm32_ltdc_lcolor(FAR struct stm32_layer_s *layer, uint32_t argb); -static void stm32_ltdc_lcolorkey(FAR struct stm32_layer_s *layer); -static void stm32_ltdc_lalpha(FAR struct stm32_layer_s *layer); -static void stm32_ltdc_lblendmode(FAR struct stm32_layer_s *layer, - uint8_t bf1, uint8_t bf2); - -#ifdef STM32_LAYER_CLUT_SIZE -static void stm32_ltdc_lclut(FAR struct stm32_layer_s *layer, - FAR const struct fb_cmap_s *cmap); -static void stm32_ltdc_lclutenable(FAR struct stm32_layer_s *layer, - bool enable); +#ifdef CONFIG_FB_CMAP +static void stm32_ltdc_lputclut(FAR struct stm32_ltdc_s * layer, + FAR const struct fb_cmap_s *cmap); +static void stm32_ltdc_lgetclut(FAR struct stm32_ltdc_s * layer, + FAR struct fb_cmap_s *cmap); +static void stm32_ltdc_lclutenable(FAR struct stm32_ltdc_s *layer, + bool enable); #endif -static void stm32_ltdc_linit(int lid); -static void stm32_ltdc_lenable(FAR struct stm32_layer_s *layer); -static void stm32_ltdc_lclear(FAR struct stm32_layer_s *layer, - nxgl_mxpixel_t color); -/* Generic frame buffer interface */ +static void stm32_ltdc_lclear(uint8_t overlayno); + +/* Framebuffer interface */ static int stm32_getvideoinfo(FAR struct fb_vtable_s *vtable, - struct fb_videoinfo_s *vinfo); + FAR struct fb_videoinfo_s *vinfo); static int stm32_getplaneinfo(FAR struct fb_vtable_s *vtable, - int planeno, struct fb_planeinfo_s *pinfo); + int planeno, + FAR struct fb_planeinfo_s *pinfo); /* The following is provided only if the video hardware supports RGB color * mapping */ -#ifdef STM32_LAYER_CLUT_SIZE -static int stm32_getcmap(struct fb_vtable_s *vtable, - struct fb_cmap_s *cmap); -static int stm32_putcmap(struct fb_vtable_s *vtable, - const struct fb_cmap_s *cmap); +#ifdef CONFIG_FB_CMAP +static int stm32_getcmap(FAR struct fb_vtable_s *vtable, + FAR struct fb_cmap_s *cmap); +static int stm32_putcmap(FAR struct fb_vtable_s *vtable, + FAR const struct fb_cmap_s *cmap); #endif -/* ltdc interface */ +/* The following is provided only if the video hardware signals vertical + * synchronisation + */ -#ifdef STM32_LAYER_CLUT_SIZE -static int stm32_setclut(struct ltdc_layer_s *layer, - const struct fb_cmap_s *cmap); -static int stm32_getclut(struct ltdc_layer_s *layer, - struct fb_cmap_s *cmap); +#ifdef CONFIG_FB_SYNC +static int stm32_waitforvsync(FAR struct fb_vtable_s *vtable); #endif -static int stm32_lgetvideoinfo(struct ltdc_layer_s *layer, - struct fb_videoinfo_s *vinfo); -static int stm32_lgetplaneinfo(struct ltdc_layer_s *layer, int planeno, - struct fb_planeinfo_s *pinfo); -#ifdef CONFIG_STM32F7_LTDC_INTERFACE -static int stm32_getlid(FAR struct ltdc_layer_s *layer, - int *lid, uint32_t flag); -static int stm32_setcolor(FAR struct ltdc_layer_s *layer, uint32_t argb); -static int stm32_getcolor(FAR struct ltdc_layer_s *layer, uint32_t *argb); -static int stm32_setcolorkey(FAR struct ltdc_layer_s *layer, uint32_t argb); -static int stm32_getcolorkey(FAR struct ltdc_layer_s *layer, uint32_t *argb); -static int stm32_setalpha(FAR struct ltdc_layer_s *layer, uint8_t alpha); -static int stm32_getalpha(FAR struct ltdc_layer_s *layer, uint8_t *alpha); -static int stm32_setblendmode(FAR struct ltdc_layer_s *layer, uint32_t mode); -static int stm32_getblendmode(FAR struct ltdc_layer_s *layer, uint32_t *mode); -static int stm32_setarea(FAR struct ltdc_layer_s *layer, - FAR const struct ltdc_area_s *area, - fb_coord_t srcxpos, fb_coord_t srcypos); -static int stm32_getarea(FAR struct ltdc_layer_s *layer, - FAR struct ltdc_area_s *area, - fb_coord_t *srcxpos, fb_coord_t *srcypos); -static int stm32_update(FAR struct ltdc_layer_s *layer, uint32_t mode); +/* The following is provided only if the video hardware supports overlays */ -#ifdef CONFIG_STM32F7_DMA2D -static int stm32_blit(FAR struct ltdc_layer_s *dest, - fb_coord_t destxpos, fb_coord_t destypos, - FAR const struct dma2d_layer_s *src, - FAR const struct ltdc_area_s *srcarea); -static int stm32_blend(FAR struct ltdc_layer_s *dest, - fb_coord_t destxpos, fb_coord_t destypos, - FAR const struct dma2d_layer_s *fore, - fb_coord_t forexpos, fb_coord_t foreypos, - FAR const struct dma2d_layer_s *back, - FAR const struct ltdc_area_s *backarea); -static int stm32_fillarea(FAR struct ltdc_layer_s *layer, - FAR const struct ltdc_area_s *area, - uint32_t color); -#endif -#endif /* CONFIG_STM32F7_LTDC_INTERFACE */ +#ifdef CONFIG_FB_OVERLAY +static int stm32_getoverlayinfo(FAR struct fb_vtable_s *vtable, + int overlayno, + FAR struct fb_overlayinfo_s *oinfo); +static int stm32_settransp(FAR struct fb_vtable_s *vtable, + FAR const struct fb_overlayinfo_s *oinfo); +static int stm32_setchromakey(FAR struct fb_vtable_s *vtable, + FAR const struct fb_overlayinfo_s *oinfo); +static int stm32_setcolor(FAR struct fb_vtable_s *vtable, + FAR const struct fb_overlayinfo_s *oinfo); +static int stm32_setblank(FAR struct fb_vtable_s *vtable, + FAR const struct fb_overlayinfo_s *oinfo); +static int stm32_setarea(FAR struct fb_vtable_s *vtable, + FAR const struct fb_overlayinfo_s *oinfo); + +/* The following is provided only if the video hardware supports blit and blend + * operation + */ + +# ifdef CONFIG_FB_OVERLAY_BLIT +static int stm32_blit(FAR struct fb_vtable_s *vtable, + FAR const struct fb_overlayblit_s *blit); +static int stm32_blend(FAR struct fb_vtable_s *vtable, + FAR const struct fb_overlayblend_s *blend); +# endif /* CONFIG_FB_OVERLAY_BLIT */ +#endif /* CONFIG_FB_OVERLAY */ /**************************************************************************** * Private Data ****************************************************************************/ -#if !defined(CONFIG_STM32F7_LTDC_USE_DSI) /* PIO pin configurations */ static const uint32_t g_ltdcpins[] = @@ -661,32 +796,29 @@ static const uint32_t g_ltdcpins[] = GPIO_LTDC_B4, GPIO_LTDC_B5, GPIO_LTDC_B6, GPIO_LTDC_B7, #if BOARD_LTDC_OUTPUT_BPP > 12 GPIO_LTDC_R3, GPIO_LTDC_G2, GPIO_LTDC_G3, GPIO_LTDC_B3, -# if BOARD_LTDC_OUTPUT_BPP > 16 +# if BOARD_LTDC_OUTPUT_BPP > 16 GPIO_LTDC_R2, GPIO_LTDC_B2, -# if BOARD_LTDC_OUTPUT_BPP > 18 +# if BOARD_LTDC_OUTPUT_BPP > 18 GPIO_LTDC_R0, GPIO_LTDC_R1, GPIO_LTDC_G0, GPIO_LTDC_G1, GPIO_LTDC_B0, GPIO_LTDC_B1, +# endif # endif -# endif #endif GPIO_LTDC_VSYNC, GPIO_LTDC_HSYNC, GPIO_LTDC_DE, GPIO_LTDC_CLK }; #define STM32_LTDC_NPINCONFIGS (sizeof(g_ltdcpins) / sizeof(uint32_t)) -#endif /* !CONFIG_STM32F7_LTDC_USE_DSI */ -/* This structure provides the base layer interface */ +#ifdef CONFIG_FB_CMAP +/* The layers clut table entries */ -static const struct fb_vtable_s g_vtable = -{ - .getvideoinfo = stm32_getvideoinfo, - .getplaneinfo = stm32_getplaneinfo -#ifdef STM32_LAYER_CLUT_SIZE - , - .getcmap = stm32_getcmap, - .putcmap = stm32_putcmap -#endif -}; +static uint8_t g_redclut[STM32_LTDC_NCLUT]; +static uint8_t g_greenclut[STM32_LTDC_NCLUT]; +static uint8_t g_blueclut[STM32_LTDC_NCLUT]; +# ifdef CONFIG_FB_TRANSPARENCY +static uint8_t g_transpclut[STM32_LTDC_NCLUT]; +# endif +#endif /* CONFIG_FB_CMAP */ /* The LTDC semaphore that enforces mutually exclusive access */ @@ -700,82 +832,281 @@ static sem_t g_semirq; static struct stm32_interrupt_s g_interrupt = { - .wait = false, - .handled = true, .irq = STM32_IRQ_LTDCINT, + .error = OK, .sem = &g_semirq }; -/* The layer active state */ +/* This structure provides the internal interface */ -static uint8_t g_lactive; - -#ifdef STM32_LAYER_CLUT_SIZE -/* The layers clut table entries */ - -static uint32_t g_clut[STM32_LAYER_CLUT_SIZE]; +static struct stm32_ltdcdev_s g_vtable = +{ + .vtable = + { + .getvideoinfo = stm32_getvideoinfo, + .getplaneinfo = stm32_getplaneinfo +#ifdef CONFIG_FB_SYNC + , + .waitforvsync = stm32_waitforvsync #endif -/* The initialized state of the overall LTDC layers */ +#ifdef CONFIG_FB_CMAP + , + .getcmap = stm32_getcmap, + .putcmap = stm32_putcmap +#endif -static struct stm32_ltdcdev_s g_ltdc = -{ +#ifdef CONFIG_FB_OVERLAY + , + .getoverlayinfo = stm32_getoverlayinfo, + .settransp = stm32_settransp, + .setchromakey = stm32_setchromakey, + .setcolor = stm32_setcolor, + .setblank = stm32_setblank, + .setarea = stm32_setarea +# ifdef CONFIG_FB_OVERLAY_BLIT + , + .blit = stm32_blit, + .blend = stm32_blend +# endif +#endif /* CONFIG_FB_OVERLAY */ + }, +#ifdef CONFIG_STM32F7_LTDC_L2 + .pinfo = + { + .fbmem = (uint8_t *)STM32_LTDC_BUFFER_L2, + .fblen = STM32_LTDC_L2_FBSIZE, + .stride = STM32_LTDC_L2_STRIDE, + .display = 0, + .bpp = STM32_LTDC_L2_BPP + }, + .vinfo = + { + .fmt = STM32_LTDC_L2_COLOR_FMT, + .xres = STM32_LTDC_WIDTH, + .yres = STM32_LTDC_HEIGHT, + .nplanes = 1, +# ifdef CONFIG_FB_OVERLAY + .noverlays = LTDC_NOVERLAYS +# endif + } +#else + .pinfo = + { + .fbmem = (uint8_t *)STM32_LTDC_BUFFER_L1, + .fblen = STM32_LTDC_L1_FBSIZE, + .stride = STM32_LTDC_L1_STRIDE, + .display = 0, + .bpp = STM32_LTDC_L1_BPP + }, + .vinfo = + { + .fmt = STM32_LTDC_L1_COLOR_FMT, + .xres = STM32_LTDC_WIDTH, + .yres = STM32_LTDC_HEIGHT, + .nplanes = 1, +# ifdef CONFIG_FB_OVERLAY + .noverlays = LTDC_NOVERLAYS +# endif + } +#endif /* CONFIG_STM32F7_LTDC_L2 */ + , +#ifdef CONFIG_FB_CMAP + .cmap = + { + .first = 0, + .len = STM32_LTDC_NCLUT, + .red = g_redclut, + .green = g_greenclut, + .blue = g_blueclut, +# ifdef CONFIG_FB_TRANSPARENCY + .transp = g_transpclut +# endif + } + , +#endif .layer[LTDC_LAYER_L1] = { - .state = + .layerno = LTDC_LAYER_L1, +#ifdef CONFIG_FB_OVERLAY + .oinfo = { - .lid = LTDC_LAYER_L1, - .pinfo = + .fbmem = (uint8_t *)STM32_LTDC_BUFFER_L1, + .fblen = STM32_LTDC_L1_FBSIZE, + .stride = STM32_LTDC_L1_STRIDE, + .overlay = LTDC_LAYER_L1, + .bpp = STM32_LTDC_L1_BPP, + .blank = 0, + .chromakey = 0, + .color = 0, + .transp = { - .fbmem = (uint8_t *)STM32_LTDC_BUFFER_L1, - .fblen = STM32_L1_FBSIZE, - .stride = STM32_L1_STRIDE, - .display = 0, - .bpp = STM32_LTDC_L1_BPP + .transp = 0xff, + .transp_mode = FB_CONST_ALPHA }, - .vinfo = + .sarea = { - .fmt = STM32_LTDC_L1_COLOR_FMT, - .xres = STM32_LTDC_WIDTH, - .yres = STM32_LTDC_HEIGHT, - .nplanes = 1 - } -#ifdef STM32_LTDC_L1CMAP - , .clut = &g_clut[LTDC_L1CLUT_OFFSET] + .x = 0, + .y = 0, + .w = STM32_LTDC_WIDTH, + .h = STM32_LTDC_HEIGHT + }, + .accl = LTDC_L1_ACCL + }, #endif - } + +#ifdef CONFIG_STM32F7_DMA2D + .dma2dinfo = + { + .fmt = STM32_LTDC_L1_DMA2D_PF, + .transp_mode = STM32_DMA2D_PFCCR_AM_NONE, + .xres = STM32_LTDC_WIDTH, + .yres = STM32_LTDC_HEIGHT, + .oinfo = &g_vtable.layer[LTDC_LAYER_L1].oinfo + }, +#endif + .lock = &g_lock } #ifdef CONFIG_STM32F7_LTDC_L2 , .layer[LTDC_LAYER_L2] = { - .state = + .layerno = LTDC_LAYER_L2, +#ifdef CONFIG_FB_OVERLAY + .oinfo = { - .lid = LTDC_LAYER_L2, - .pinfo = + .overlay = LTDC_LAYER_L2, + .fbmem = (uint8_t *)STM32_LTDC_BUFFER_L2, + .fblen = STM32_LTDC_L2_FBSIZE, + .stride = STM32_LTDC_L2_STRIDE, + .bpp = STM32_LTDC_L2_BPP, + .blank = 0, + .chromakey = 0, + .color = 0, + .transp = { - .fbmem = (uint8_t *)STM32_LTDC_BUFFER_L2, - .fblen = STM32_L2_FBSIZE, - .stride = STM32_L2_STRIDE, - .display = 1, - .bpp = STM32_LTDC_L2_BPP + .transp = 0xff, + .transp_mode = FB_CONST_ALPHA }, - .vinfo = + .sarea = { - .fmt = STM32_LTDC_L2_COLOR_FMT, - .xres = STM32_LTDC_WIDTH, - .yres = STM32_LTDC_HEIGHT, - .nplanes = 1 - } -#ifdef STM32_LTDC_L2CMAP - , .clut = &g_clut[LTDC_L2CLUT_OFFSET] + .x = 0, + .y = 0, + .w = STM32_LTDC_WIDTH, + .h = STM32_LTDC_HEIGHT + }, + .accl = LTDC_L2_ACCL + }, #endif - } + +#ifdef CONFIG_STM32F7_DMA2D + .dma2dinfo = + { + .fmt = STM32_LTDC_L2_DMA2D_PF, + .transp_mode = STM32_DMA2D_PFCCR_AM_NONE, + .xres = STM32_LTDC_WIDTH, + .yres = STM32_LTDC_HEIGHT, + .oinfo = &g_vtable.layer[LTDC_LAYER_L2].oinfo + }, +#endif + .lock = &g_lock } #endif }; -/* Pixel format lookup table */ +/* Configuration lookup tables */ + +/* LTDC width */ + +static const uint32_t stm32_width_layer_t[LTDC_NLAYERS] = +{ + STM32_LTDC_WIDTH +#ifdef CONFIG_STM32F7_LTDC_L2 + , STM32_LTDC_WIDTH +#endif +}; + +/* LTDC height */ + +static const uint32_t stm32_height_layer_t[LTDC_NLAYERS] = +{ + STM32_LTDC_HEIGHT +#ifdef CONFIG_STM32F7_LTDC_L2 + , STM32_LTDC_HEIGHT +#endif +}; + +/* LTDC stride */ + +static const uint32_t stm32_stride_layer_t[LTDC_NLAYERS] = +{ + STM32_LTDC_L1_STRIDE +#ifdef CONFIG_STM32F7_LTDC_L2 + , STM32_LTDC_L2_STRIDE +#endif +}; + +/* LTDC bpp */ + +static const uint32_t stm32_bpp_layer_t[LTDC_NLAYERS] = +{ + STM32_LTDC_L1_BPP +#ifdef CONFIG_STM32F7_LTDC_L2 + , STM32_LTDC_L2_BPP +#endif +}; + +/* LTDC framebuffer len */ + +static const uint32_t stm32_fblen_layer_t[LTDC_NLAYERS] = +{ + STM32_LTDC_L1_FBSIZE +#ifdef CONFIG_STM32F7_LTDC_L2 + , STM32_LTDC_L2_FBSIZE +#endif +}; + +/* LTDC framebuffer */ + +static const uint32_t stm32_fbmem_layer_t[LTDC_NLAYERS] = +{ + STM32_LTDC_BUFFER_L1 +#ifdef CONFIG_STM32F7_LTDC_L2 + , STM32_LTDC_BUFFER_L2 +#endif +}; + +/* LTDC default color lookup table */ + +static const uint32_t stm32_defaultcolor_layer_t[LTDC_NLAYERS] = +{ + STM32_LTDC_L1_COLOR +#ifdef CONFIG_STM32F7_LTDC_L2 + , STM32_LTDC_L2_COLOR +#endif +}; + +/* LTDC default chromakey */ + +static const uint32_t stm32_chromakey_layer_t[LTDC_NLAYERS] = +{ + STM32_LTDC_L1_CHROMAKEY +#ifdef CONFIG_STM32F7_LTDC_L2 + , STM32_LTDC_L2_CHROMAKEY +#endif +}; + +/* LTDC chromakey enabled state */ + +static const bool stm32_chromakeyen_layer_t[LTDC_NLAYERS] = +{ + STM32_LTDC_L1_CHROMAEN +#ifdef CONFIG_STM32F7_LTDC_L2 + , STM32_LTDC_L2_CHROMAEN +#endif +}; + +/* LTDC pixel format lookup table */ static const uint32_t stm32_fmt_layer_t[LTDC_NLAYERS] = { @@ -899,15 +1230,15 @@ static const uintptr_t stm32_cfblnr_layer_t[LTDC_NLAYERS] = /* LTDC_LxCLUTWR */ -#ifdef STM32_LAYER_CLUT_SIZE +#ifdef CONFIG_FB_CMAP static const uintptr_t stm32_clutwr_layer_t[LTDC_NLAYERS] = { STM32_LTDC_L1CLUTWR -# ifdef CONFIG_STM32F7_LTDC_L2 +# ifdef CONFIG_STM32F7_LTDC_L2 , STM32_LTDC_L2CLUTWR -# endif +# endif }; -#endif +#endif /* CONFIG_FB_CMAP */ /* The initialized state of the driver */ @@ -925,7 +1256,6 @@ static bool g_initialized; * ****************************************************************************/ -#if !defined(CONFIG_STM32F7_LTDC_USE_DSI) static void stm32_ltdc_gpioconfig(void) { int i; @@ -940,7 +1270,6 @@ static void stm32_ltdc_gpioconfig(void) stm32_configgpio(g_ltdcpins[i]); } } -#endif /**************************************************************************** * Name: stm32_ltdc_periphconfig @@ -955,28 +1284,21 @@ static void stm32_ltdc_periphconfig(void) { uint32_t regval; -#if defined(CONFIG_STM32F7_LTDC_USE_DSI) - /* work in progress; maybe move to lcdinfo when everything is OK. */ - - lcdwarn("LTDC: Expecting preconfigured DSI; not configuring pins for LCD interface\n"); -#else /* Configure GPIO's */ stm32_ltdc_gpioconfig(); -#endif - /* APB2 LTDC clock is expected to be externally preconfigured */ + /* Configure APB2 LTDC clock external */ reginfo("configured RCC_APB2ENR=%08x\n", getreg32(STM32_RCC_APB2ENR)); - /* SAI PLL is expected to be externally preconfigured to provide the LCD_CLK */ + /* Configure the SAI PLL external to provide the LCD_CLK */ reginfo("configured RCC_PLLSAI=%08x\n", getreg32(STM32_RCC_PLLSAICFGR)); - /* Dedicated clocks are expected to be externally preconfigured */ + /* Configure dedicated clock external */ - reginfo("configured RCC_DCKCFGR1=%08x\n", getreg32(STM32_RCC_DCKCFGR1)); - reginfo("configured RCC_DCKCFGR2=%08x\n", getreg32(STM32_RCC_DCKCFGR2)); + reginfo("configured RCC_DCKCFGR=%08x\n", getreg32(STM32_RCC_DCKCFGR)); /* Configure LTDC_SSCR */ @@ -1006,17 +1328,47 @@ static void stm32_ltdc_periphconfig(void) putreg32(regval, STM32_LTDC_TWCR); reginfo("configured LTDC_TWCR=%08x\n", getreg32(STM32_LTDC_TWCR)); - /* Configure signal polarities */ + /* Configure LTDC_GCR */ regval = getreg32(STM32_LTDC_GCR); - regval &= ~(LTDC_GCR_PCPOL | LTDC_GCR_DEPOL | LTDC_GCR_VSPOL | LTDC_GCR_HSPOL); + regval &= ~(LTDC_GCR_PCPOL | LTDC_GCR_DEPOL | LTDC_GCR_VSPOL | + LTDC_GCR_HSPOL); regval |= (STM32_LTDC_GCR_PCPOL | STM32_LTDC_GCR_DEPOL | STM32_LTDC_GCR_VSPOL | STM32_LTDC_GCR_HSPOL); + reginfo("set LTDC_GCR=%08x\n", regval); putreg32(regval, STM32_LTDC_GCR); reginfo("configured LTDC_GCR=%08x\n", getreg32(STM32_LTDC_GCR)); } +/**************************************************************************** + * Name: stm32_ltdc_ldefaultcolor + * + * Description: + * Configures layer default color. + * + * Input Parameters: + * layer - Reference to the layer control structure + * rgb - RGB888 background color + * + ****************************************************************************/ + +static void stm32_ltdc_ldefaultcolor(FAR struct stm32_ltdc_s * layer, + uint32_t rgb) +{ + DEBUGASSERT(layer->layerno < LTDC_NLAYERS); + reginfo("set LTDC_L%dDCCR=%08x\n", layer->layerno + 1, rgb); + + putreg32(rgb, stm32_dccr_layer_t[layer->layerno]); + + /* Reload shadow register */ + + stm32_ltdc_reload(LTDC_SRCR_IMR, false); + + reginfo("configured LTDC_L%dDCCR=%08x\n", layer->layerno + 1, + getreg32(STM32_LTDC_BCCR)); +} + /**************************************************************************** * Name: stm32_ltdc_bgcolor * @@ -1049,12 +1401,10 @@ static void stm32_ltdc_bgcolor(uint32_t rgb) * ****************************************************************************/ -static void stm32_ltdc_dither(bool enable, - uint8_t red, - uint8_t green, - uint8_t blue) +static void stm32_ltdc_dither(bool enable, uint8_t red, + uint8_t green, uint8_t blue) { - uint32_t regval; + uint32_t regval; regval = getreg32(STM32_LTDC_GCR); @@ -1126,8 +1476,8 @@ static void stm32_ltdc_irqctrl(uint32_t setirqs, uint32_t clrirqs) static int stm32_ltdcirq(int irq, void *context, FAR void *arg) { + int ret; FAR struct stm32_interrupt_s *priv = &g_interrupt; - uint32_t regval = getreg32(STM32_LTDC_ISR); reginfo("irq = %d, regval = %08x\n", irq, regval); @@ -1138,23 +1488,52 @@ static int stm32_ltdcirq(int irq, void *context, FAR void *arg) /* Clear the interrupt status register */ + reginfo("Register reloaded\n"); putreg32(LTDC_ICR_CRRIF, STM32_LTDC_ICR); + priv->error = OK; + } + else if (regval & LTDC_IER_LIE) + { + /* Line interrupt */ - /* Update the handled flag */ + /* Clear the interrupt status register */ - priv->handled = true; + reginfo("Line interrupt\n"); + putreg32(LTDC_ICR_CLIF, STM32_LTDC_ICR); + priv->error = OK; + } + else if (regval & LTDC_IER_TERRIE) + { + /* Transfer error interrupt */ - /* Unlock the semaphore if locked */ + /* Clear the interrupt status register */ - if (priv->wait) - { - int ret = nxsem_post(priv->sem); + reginfo("Error transfer\n"); + putreg32(LTDC_ICR_CTERRIF, STM32_LTDC_ICR); + priv->error = -ECANCELED; + } + else if (regval & LTDC_IER_FUIE) + { + /* Fifo underrun error interrupt */ - if (ret < 0) - { - lcderr("ERROR: nxsem_post() failed\n"); - } - } + /* Clear the interrupt status register */ + + reginfo("Error fifo underrun\n"); + putreg32(LTDC_ICR_CFUIF, STM32_LTDC_ICR); + priv->error = -ECANCELED; + } + else + { + ASSERT("Unknown interrupt"); + } + + /* Unlock the semaphore if locked */ + + ret = nxsem_post(priv->sem); + + if (ret < 0) + { + lcderr("ERROR: nxsem_post() failed\n"); } return OK; @@ -1178,31 +1557,15 @@ static int stm32_ltdc_waitforirq(void) int ret = OK; FAR struct stm32_interrupt_s *priv = &g_interrupt; - irqstate_t flags; + ret = nxsem_wait(priv->sem); - flags = enter_critical_section(); - - /* Only waits if last enabled interrupt is currently not handled */ - - if (!priv->handled) + if (ret < 0) { - /* Inform the irq handler the task is able to wait for the irq */ - - priv->wait = true; - - ret = nxsem_wait(priv->sem); - - /* irq or an error occurs, reset the wait flag */ - - priv->wait = false; - - if (ret < 0) - { - lcderr("ERROR: nxsem_wait() failed\n"); - } + lcderr("ERROR: nxsem_wait() failed\n"); } - leave_critical_section(flags); + ret = priv->error; + return ret; } @@ -1223,28 +1586,6 @@ static int stm32_ltdc_waitforirq(void) static int stm32_ltdc_reload(uint8_t value, bool waitvblank) { int ret = OK; - FAR struct stm32_interrupt_s *priv = &g_interrupt; - - if (value == LTDC_SRCR_VBR) - { - irqstate_t flags; - - /* Prepare shadow register reload for later detection by the task. - * At this point the last register reload must be completed. This is done - * in stm32_update before the next operation is triggered and manipulates - * the shadow register. This handling is only neccessary in the case of - * the application causes shadow register reload. - */ - - flags = enter_critical_section(); - - ASSERT(priv->handled == true); - - /* Reset the handled flag */ - - priv->handled = false; - leave_critical_section(flags); - } /* Reloads the shadow register. * Note! This will not trigger an register reload interrupt if @@ -1255,29 +1596,31 @@ static int stm32_ltdc_reload(uint8_t value, bool waitvblank) putreg32(value, STM32_LTDC_SRCR); reginfo("configured LTDC_SRCR=%08x\n", getreg32(STM32_LTDC_SRCR)); - if (waitvblank & (value == LTDC_SRCR_VBR)) + if (value == LTDC_SRCR_VBR && waitvblank) { /* Wait upon vertical blanking period */ ret = stm32_ltdc_waitforirq(); } + else + { + /* Wait until register reload hase been done */ - /* Otherwise check if reload is completed before the next operation */ + while (getreg32(STM32_LTDC_SRCR) & value); + } return ret; } /**************************************************************************** - * Name: stm32_global_configure + * Name: stm32_ltdc_irqconfig * * Description: - * Configure background color * Configure interrupts - * Configure dithering * ****************************************************************************/ -static void stm32_global_configure(void) +static void stm32_ltdc_irqconfig(void) { /* Initialize the LTDC semaphore that enforces mutually exclusive access */ @@ -1299,28 +1642,29 @@ static void stm32_global_configure(void) up_enable_irq(g_interrupt.irq); - /* Enable register reload interrupt only */ + /* Enable interrupts expect line interrupt */ - stm32_ltdc_irqctrl(LTDC_IER_RRIE, LTDC_IER_TERRIE | LTDC_IER_FUIE | LTDC_IER_LIE); + stm32_ltdc_irqctrl(LTDC_IER_RRIE | + LTDC_IER_TERRIE | + LTDC_IER_FUIE, + LTDC_IER_LIE); /* Configure line interrupt */ stm32_ltdc_linepos(); +} - /* Set the default active layer */ - -#ifndef CONFIG_STM32F7_LTDC_L2 - g_lactive = LTDC_LAYER_L1; -#else - g_lactive = LTDC_LAYER_L2; -#endif - -#ifdef STM32_LAYER_CLUT_SIZE - /* cleanup clut */ - - memset(g_clut, 0, sizeof(g_clut)); -#endif +/**************************************************************************** + * Name: stm32_ltdc_globalconfig + * + * Description: + * Configure background color + * Configure dithering + * + ****************************************************************************/ +static void stm32_ltdc_globalconfig(void) +{ /* Configure dither */ stm32_ltdc_dither( @@ -1333,13 +1677,13 @@ static void stm32_global_configure(void) STM32_LTDC_DITHER_GREEN, STM32_LTDC_DITHER_BLUE); - /* Configure background color of the controller */ + /* Configure background color */ stm32_ltdc_bgcolor(STM32_LTDC_BACKCOLOR); } /**************************************************************************** - * Name: stm32_lcd_enable + * Name: stm32_ltdc_enable * * Description: * Disable the LCD peripheral @@ -1349,7 +1693,7 @@ static void stm32_global_configure(void) * ****************************************************************************/ -static void stm32_lcd_enable(bool enable) +static void stm32_ltdc_enable(bool enable) { uint32_t regval; @@ -1371,9 +1715,287 @@ static void stm32_lcd_enable(bool enable) } /**************************************************************************** - * Configure layer register + * Name: stm32_ltdc_lpixelformat + * + * Description: + * Set the layer pixel format. + * Note! This changes have no effect until the shadow register reload has + * been done. + * + * Input Parameters: + * Reference to the layer control structure + * ****************************************************************************/ +static void stm32_ltdc_lpixelformat(FAR struct stm32_ltdc_s *layer) +{ + uint8_t overlay = layer->layerno; + DEBUGASSERT(layer->layerno < LTDC_NLAYERS); + + /* Configure PFCR register */ + + reginfo("set LTDC_L%dPFCR=%08x\n", overlay + 1, stm32_fmt_layer_t[overlay]); + putreg32(stm32_fmt_layer_t[overlay], stm32_pfcr_layer_t[overlay]); + + /* Reload shadow register */ + + stm32_ltdc_reload(LTDC_SRCR_IMR, false); +} + +/**************************************************************************** + * Name: stm32_ltdc_lframebuffer + * + * Description: + * Configure layer framebuffer of the entire window. + * Note! This changes have no effect until the shadow register reload has + * been done. + * + * Input Parameters: + * Reference to the layer control structure + * + ****************************************************************************/ + +static void stm32_ltdc_lframebuffer(FAR struct stm32_ltdc_s *layer) +{ + uint32_t cfblr; + uint32_t rxpos; + uint32_t rypos; + uint32_t whpcr; + uint32_t wvpcr; + uint8_t layerno = layer->layerno; + + DEBUGASSERT(layer->layerno < LTDC_NLAYERS); + reginfo("xpos = %d, ypos = %d, xres = %d, yres = %d\n", 0, 0, + stm32_width_layer_t[layerno], stm32_height_layer_t[layerno]); + + /* Calculate register position */ + + rxpos = STM32_LTDC_LxWHPCR_WHSTPOS + 1; + rypos = STM32_LTDC_LxWVPCR_WVSTPOS + 1; + + /* Accumulate horizontal position */ + + whpcr = LTDC_LxWHPCR_WHSTPOS(rxpos); + whpcr |= LTDC_LxWHPCR_WHSPPOS(rxpos + stm32_width_layer_t[layerno] - 1); + + /* Accumulate vertical position */ + + wvpcr = LTDC_LxWVPCR_WVSTPOS(rypos); + wvpcr |= LTDC_LxWVPCR_WVSPPOS(rypos + stm32_height_layer_t[layerno] - 1); + + /* Configure LxWHPCR / LxWVPCR register */ + + reginfo("set LTDC_L%dWHPCR=%08x\n", layerno + 1, whpcr); + putreg32(whpcr, stm32_whpcr_layer_t[layerno]); + reginfo("set LTDC_L%dWVPCR=%08x\n", layerno + 1, wvpcr); + putreg32(wvpcr, stm32_wvpcr_layer_t[layerno]); + + /* Configure LxCFBAR register */ + + reginfo("set LTDC_L%dCFBAR=%08x\n", layerno + 1, + stm32_fbmem_layer_t[layerno]); + putreg32(stm32_fbmem_layer_t[layerno], stm32_cfbar_layer_t[layerno]); + + /* Configure LxCFBLR register */ + + /* Calculate line length */ + + cfblr = LTDC_LxCFBLR_CFBP(stm32_stride_layer_t[layerno]) | + LTDC_LxCFBLR_CFBLL(stm32_width_layer_t[layerno] * + STM32_LTDC_Lx_BYPP(stm32_bpp_layer_t[layerno]) + 3); + + reginfo("set LTDC_L%dCFBLR=%08x\n", layerno + 1, cfblr); + putreg32(cfblr, stm32_cfblr_layer_t[layerno]); + + /* Configure LxCFBLNR register */ + + reginfo("set LTDC_L%dCFBLNR=%08x\n", layerno + 1, stm32_height_layer_t[layerno]); + putreg32(stm32_height_layer_t[layerno], stm32_cfblnr_layer_t[layerno]); + + /* Reload shadow register */ + + stm32_ltdc_reload(LTDC_SRCR_IMR, false); +} + +/**************************************************************************** + * Name: stm32_ltdc_lenable + * + * Description: + * Enable or disable layer. + * Note! This changes have no effect until the shadow register reload has + * been done. + * + * Input Parameters: + * layer - Reference to the layer control structure + * enable - Enable or disable layer + * + ****************************************************************************/ + +static void stm32_ltdc_lenable(FAR struct stm32_ltdc_s *layer, bool enable) +{ + uint32_t regval; + DEBUGASSERT(layer->layerno < LTDC_NLAYERS); + + regval = getreg32(stm32_cr_layer_t[layer->layerno]); + + if (enable == true) + { + regval |= LTDC_LxCR_LEN; + } + else + { + regval &= ~LTDC_LxCR_LEN; + } + + /* Enable/Disable layer */ + + reginfo("set LTDC_L%dCR=%08x\n", layer->layerno + 1, regval); + putreg32(regval, stm32_cr_layer_t[layer->layerno]); + + /* Reload shadow register */ + + stm32_ltdc_reload(LTDC_SRCR_IMR, false); +} + +/**************************************************************************** + * Name: stm32_ltdc_ltransp + * + * Description: + * Change layer transparency. + * Note! This changes have no effect until the shadow register reload has + * been done. + * + * Input Parameters: + * layer - Reference to the layer control structure + * transp - Transparency + * mode - Transparency mode + * + ****************************************************************************/ + +static void stm32_ltdc_ltransp(FAR struct stm32_ltdc_s *layer, uint8_t transp, + uint32_t mode) +{ + uint32_t bf1; + uint32_t bf2; + + DEBUGASSERT(layer->layerno < LTDC_NLAYERS); + +#ifdef CONFIG_FB_OVERLAY + if (mode == FB_CONST_ALPHA) + { + bf1 = LTDC_BF1_CONST_ALPHA; + bf2 = LTDC_BF2_CONST_ALPHA; + } + else + { + bf1 = LTDC_BF1_PIXEL_ALPHA; + bf2 = LTDC_BF2_PIXEL_ALPHA; + } +#else + bf1 = LTDC_BF1_CONST_ALPHA; + bf2 = LTDC_BF2_CONST_ALPHA; +#endif + + reginfo("set LTDC_L%dBFCR=%08x\n", layer->layerno + 1, + (LTDC_LxBFCR_BF1(bf1) | LTDC_LxBFCR_BF2(bf2))); + + /* Set blendmode */ + + putreg32((LTDC_LxBFCR_BF1(bf1) | LTDC_LxBFCR_BF2(bf2)), + stm32_bfcr_layer_t[layer->layerno]); + + /* Set alpha */ + + reginfo("set LTDC_L%dCACR=%02x\n", layer->layerno + 1, transp); + putreg32(transp, stm32_cacr_layer_t[layer->layerno]); + + /* Reload shadow register */ + + stm32_ltdc_reload(LTDC_SRCR_IMR, false); +} + +/**************************************************************************** + * Name: stm32_ltdc_lchromakey + * + * Description: + * Change layer chromakey. + * Note! This changes have no effect until the shadow register reload has + * been done. + * + * Input Parameters: + * layer - Reference to the layer control structure + * chroma - chromakey + * + ****************************************************************************/ + +static void stm32_ltdc_lchromakey(FAR struct stm32_ltdc_s *layer, + uint32_t chroma) +{ + uint32_t rgb; + DEBUGASSERT(layer->layerno < LTDC_NLAYERS); + + reginfo("%08x\n", getreg32(stm32_cr_layer_t[layer->layerno])); + + /* Set chromakey */ + +#ifdef CONFIG_FB_CMAP + uint8_t r = g_vtable.cmap.red[chroma]; + uint8_t g = g_vtable.cmap.green[chroma]; + uint8_t b = g_vtable.cmap.blue[chroma]; + rgb = ((r << 16)|(g << 8)|b); +#else + rgb = ARGB8888(chroma); +#endif + + reginfo("set LTDC_L%dCKCR=%08x\n", layer->layerno + 1, rgb); + putreg32(rgb, stm32_ckcr_layer_t[layer->layerno]); + + /* Reload shadow register */ + + stm32_ltdc_reload(LTDC_SRCR_IMR, false); +} + +/**************************************************************************** + * Name: stm32_ltdc_lchromakeyenable + * + * Description: + * Enable or disable layer chromakey support. + * Note! This changes have no effect until the shadow register reload has + * been done. + * + * Input Parameters: + * layer - Reference to the layer control structure + * enable - Enable or disable chromakey + * + ****************************************************************************/ + +static void stm32_ltdc_lchromakeyenable(FAR struct stm32_ltdc_s *layer, + bool enable) +{ + uint32_t regval; + DEBUGASSERT(layer->layerno < LTDC_NLAYERS); + + regval = getreg32(stm32_cr_layer_t[layer->layerno]); + + /* Enable/Disble colorkey */ + + if (enable == true) + { + regval |= LTDC_LxCR_COLKEN; + } + else + { + regval &= ~LTDC_LxCR_COLKEN; + } + + reginfo("set LTDC_L%dCR=%08x\n", layer->layerno + 1, regval); + putreg32(regval, stm32_cr_layer_t[layer->layerno]); + + /* Reload shadow register */ + + stm32_ltdc_reload(LTDC_SRCR_IMR, false); +} + /**************************************************************************** * Name: stm32_ltdc_lclutenable * @@ -1386,13 +2008,13 @@ static void stm32_lcd_enable(bool enable) * ****************************************************************************/ -#ifdef STM32_LAYER_CLUT_SIZE -static void stm32_ltdc_lclutenable(FAR struct stm32_layer_s *layer, bool enable) +#ifdef CONFIG_FB_CMAP +static void stm32_ltdc_lclutenable(FAR struct stm32_ltdc_s *layer, bool enable) { uint32_t regval; - regval = getreg32(stm32_cr_layer_t[layer->state.lid]); - reginfo("get LTDC_L%dCR=%08x\n", layer->state.lid + 1, regval); + regval = getreg32(stm32_cr_layer_t[layer->oinfo.overlay]); + reginfo("get LTDC_L%dCR=%08x\n", layer->oinfo.overlay + 1, regval); /* Disable the clut support during update the color table */ @@ -1405,512 +2027,60 @@ static void stm32_ltdc_lclutenable(FAR struct stm32_layer_s *layer, bool enable) regval &= ~LTDC_LxCR_CLUTEN; } - reginfo("set LTDC_L%dCR=%08x\n", layer->state.lid + 1, regval); - putreg32(regval, stm32_cr_layer_t[layer->state.lid]); -} -#endif + reginfo("set LTDC_L%dCR=%08x\n", layer->oinfo.overlay, regval); + putreg32(regval, stm32_cr_layer_t[layer->oinfo.overlay]); -/**************************************************************************** - * Name: stm32_ltdc_lsetopac - * - * Description: - * Helper to set the layer to opac - * - * Input Parameters: - * layer - Reference to the layer control structure - * - ****************************************************************************/ + /* Reload shadow register */ -static inline void stm32_ltdc_lsetopac(FAR struct stm32_layer_s *layer) -{ - layer->opac = 0xff; + stm32_ltdc_reload(LTDC_SRCR_IMR, false); } /**************************************************************************** - * Name: stm32_ltdc_lunsetopac - * - * Description: - * Helper to set the layer opacity to the alpha value - * - * Input Parameters: - * layer - Reference to the layer control structure - * - ****************************************************************************/ - -static inline void stm32_ltdc_lunsetopac(FAR struct stm32_layer_s *layer) -{ - layer->opac = 0; -} - -/**************************************************************************** - * Name: stm32_ltdc_lgetopac - * - * Description: - * Helper to get the configured layer opacity - * - * Input Parameters: - * layer - Reference to the layer control structure - * - ****************************************************************************/ - -static inline uint8_t stm32_ltdc_lgetopac(FAR struct stm32_layer_s *layer) -{ - return layer->opac | layer->state.alpha; -} - -/**************************************************************************** - * Name: stm32_ltdc_lvalidate - * - * Description: - * Helper to check if the layer is an valid ltdc layer - * - * Input Parameters: - * layer - Reference to the layer control structure - * - * Returned Value: - * true - layer valid - * false - layer invalid - * - ****************************************************************************/ - -static inline bool stm32_ltdc_lvalidate(FAR const struct stm32_layer_s *layer) -{ -#ifdef CONFIG_STM32F7_LTDC_L2 - return layer == &LAYER_L1 || layer == &LAYER_L2; -#else - return layer == &LAYER_L1; -#endif -} - -/**************************************************************************** - * Name: stm32_ltdc_lvalidatearea - * - * Description: - * Check if layer coordinates out of valid area. - * - * Input Parameters: - * layer - Reference to the layer control structure - * xpos - top left x position of the active area - * ypos - top left y position of the active area - * xres - width of the active area - * yres - height of teh active area - * srcxpos - Top left x position from where data visible in the active area - * srcypos - Top left y position from where data visible in the active area - * - * Returned Value: - * On success - OK - * On error - -EINVAL - * - ****************************************************************************/ - -#ifdef CONFIG_STM32F7_LTDC_INTERFACE -static int stm32_ltdc_lvalidatearea(FAR struct stm32_layer_s *layer, - fb_coord_t xpos, fb_coord_t ypos, - fb_coord_t xres, fb_coord_t yres, - fb_coord_t srcxpos, fb_coord_t srcypos) -{ - FAR const struct fb_videoinfo_s *vinfo = &layer->state.vinfo; - - if ((xpos > vinfo->xres - 1) || - (ypos > vinfo->yres -1) || - (xres > vinfo->xres - xpos) || - (yres > vinfo->yres - ypos) || - (srcxpos > xpos + xres - 1) || - (srcypos > ypos + yres - 1)) - - { - lcderr("ERROR: layer coordinates out of valid area: xpos = %d > %d, \ - ypos = %d > %d, width = %d > %d, height = %d > %d, \ - srcxpos = %d > %d, srcypos = %d > %d", - xpos, vinfo->xres - 1, - ypos, vinfo->yres - 1, - xres, vinfo->xres - xpos, - yres, vinfo->yres - ypos, - srcxpos, xpos + xres - 1, - srcypos, ypos + yres - 1); - - lcderr(" Returning EINVAL\n"); - return -EINVAL; - } - - return OK; -} -#endif - -/**************************************************************************** - * Name: stm32_ltdc_lupdate - * - * Description: - * Updates shadow register content depending on the layer operation flag. - * This made changes for the given layer visible after the next shadow - * register reload. - * - * Input Parameters: - * layer - Reference to the layer control structure - * - ****************************************************************************/ - -static void stm32_ltdc_lupdate(FAR struct stm32_layer_s *layer) -{ - if (layer->operation & LTDC_LAYER_SETAREA) - { - /* Updates the layer horizontal and vertical position register */ - - stm32_ltdc_larea(layer); - } - - if (layer->operation & LTDC_LAYER_SETALPHAVALUE) - { - /* Updates the constant alpha register */ - - stm32_ltdc_lalpha(layer); - } - - if (layer->operation & LTDC_LAYER_SETBLENDMODE) - { - /* Update blendfactor 1 and 2 register */ - - stm32_ltdc_lblendmode(layer, layer->bf1, layer->bf2); - } - - if (layer->operation & LTDC_LAYER_SETCOLORKEY) - { - /* Update layer colorkey register */ - - stm32_ltdc_lcolorkey(layer); - } - - if (layer->operation & LTDC_LAYER_SETCOLOR) - { - /* Update layer color register */ - - stm32_ltdc_lcolor(layer, layer->state.color); - } - - if (layer->operation & LTDC_LAYER_SETENABLE) - { - /* Enable the layer */ - - stm32_ltdc_lenable(layer); - } -} - -/**************************************************************************** - * Name: stm32_ltdc_larea - * - * Description: - * Change the active area of the layer - * - * Input Parameters: - * layer - Reference to the layer control structure - * - ****************************************************************************/ - -static void stm32_ltdc_larea(struct stm32_layer_s *layer) -{ - uint32_t lxpos; - uint32_t lypos; - uint32_t whpcr; - uint32_t wvpcr; - FAR struct stm32_ltdc_s *priv = &layer->state; - FAR struct ltdc_area_s *area = &priv->area; - - reginfo("xpos = %d, ypos = %d, xres = %d, yres = %d\n", - area->xpos, area->ypos, area->xres, area->yres); - - lxpos = area->xpos + (STM32_LTDC_LxWHPCR_WHSTPOS + 1); - lypos = area->ypos + (STM32_LTDC_LxWVPCR_WVSTPOS + 1); - - /* Accumulate horizontal position */ - - whpcr = LTDC_LxWHPCR_WHSTPOS(lxpos); - whpcr |= LTDC_LxWHPCR_WHSPPOS(lxpos + area->xres - 1); - - /* Accumulate vertical position */ - - wvpcr = LTDC_LxWVPCR_WVSTPOS(lypos); - wvpcr |= LTDC_LxWVPCR_WVSPPOS(lypos + area->yres - 1); - - /* Configure LxWHPCR / LxWVPCR register */ - - reginfo("set LTDC_L%dWHPCR=%08x\n", priv->lid + 1, whpcr); - putreg32(whpcr, stm32_whpcr_layer_t[priv->lid]); - reginfo("set LTDC_L%dWVPCR=%08x\n", priv->lid + 1, wvpcr); - putreg32(wvpcr, stm32_wvpcr_layer_t[priv->lid]); - - /* Configure framebuffer */ - - stm32_ltdc_lframebuffer(layer); - - /* Clear area operation flag */ - - layer->operation &= ~LTDC_LAYER_SETAREA; -} - -/**************************************************************************** - * Name: stm32_ltdc_lpixelformat - * - * Description: - * Set the layer pixel format. - * Note! This changes have no effect until the shadow register reload has - * been done. - * - * Input Parameters: - * Reference to the layer control structure - * - ****************************************************************************/ - -static void stm32_ltdc_lpixelformat(FAR struct stm32_layer_s *layer) -{ - /* Configure PFCR register */ - - reginfo("set LTDC_L%dPFCR=%08x\n", layer->state.lid + 1, - stm32_fmt_layer_t[layer->state.lid]); - putreg32(stm32_fmt_layer_t[layer->state.lid], - stm32_pfcr_layer_t[layer->state.lid]); -} - -/**************************************************************************** - * Name: stm32_ltdc_framebuffer - * - * Description: - * Change layer framebuffer offset. - * Note! This changes have no effect until the shadow register reload has - * been done. - * - * Input Parameters: - * Reference to the layer control structure - * - ****************************************************************************/ - -static inline void stm32_ltdc_lframebuffer(FAR struct stm32_layer_s *layer) -{ - uint32_t offset; - uint32_t cfblr; - FAR struct stm32_ltdc_s *priv = &layer->state; - FAR struct ltdc_area_s *area = &priv->area; - FAR const struct fb_planeinfo_s *pinfo = &priv->pinfo; - - /* Configure LxCFBAR register */ - - /* Calculate offset position in the framebuffer */ - - offset = priv->xpos * STM32_LTDC_Lx_BYPP(pinfo->bpp) + - pinfo->stride * priv->ypos; - - reginfo("set LTDC_L%dCFBAR=%08x\n", priv->lid + 1, pinfo->fbmem + offset); - putreg32((uint32_t)pinfo->fbmem + offset, stm32_cfbar_layer_t[priv->lid]); - - /* Configure LxCFBLR register */ - - /* Calculate line length */ - - cfblr = LTDC_LxCFBLR_CFBP(pinfo->stride) | - LTDC_LxCFBLR_CFBLL(area->xres * STM32_LTDC_Lx_BYPP(pinfo->bpp) + 3); - - reginfo("set LTDC_L%dCFBLR=%08x\n", priv->lid + 1, cfblr); - putreg32(cfblr, stm32_cfblr_layer_t[priv->lid]); - - /* Configure LxCFBLNR register */ - - reginfo("set LTDC_L%dCFBLNR=%08x\n", priv->lid + 1, area->yres); - putreg32(area->yres, stm32_cfblnr_layer_t[priv->lid]); -} - -/**************************************************************************** - * Name: stm32_ltdc_lalpha - * - * Description: - * Change the layer alpha value and clear the alpha operation flag. - * Note! This changes have no effect until the shadow register reload has - * been done. - * - * Input Parameters: - * layer - Reference to the layer control structure - * - ****************************************************************************/ - -static void stm32_ltdc_lalpha(FAR struct stm32_layer_s *layer) -{ - uint8_t opac = stm32_ltdc_lgetopac(layer); - reginfo("set LTDC_L%dCACR=%02x\n", layer->state.lid + 1, opac); - putreg32(opac, stm32_cacr_layer_t[layer->state.lid]); - - /* Clear the constant alpha operation flag */ - - layer->operation &= ~LTDC_LAYER_SETALPHAVALUE; -} - -/**************************************************************************** - * Name: stm32_ltdc_blendfactor - * - * Description: - * Change layer blend factors used for blend operation and clear the - * blendmode operation flag. - * Note! This changes have no effect until the shadow register reload has - * been done. - * - * Input Parameters: - * layer - Reference to the laxer control structure - * bf1 - Value of blend factor 1 - * bf2 - Value of blend factor 2 - * - ****************************************************************************/ - -static void stm32_ltdc_lblendmode(FAR struct stm32_layer_s *layer, - uint8_t bf1, uint8_t bf2) -{ - reginfo("set LTDC_L%dBFCR=%08x\n", layer->state.lid + 1, - (LTDC_LxBFCR_BF1(bf1) | LTDC_LxBFCR_BF2(bf2))); - putreg32((LTDC_LxBFCR_BF1(bf1) | LTDC_LxBFCR_BF2(bf2)), - stm32_bfcr_layer_t[layer->state.lid]); - - /* Clear the blendmode operation flag */ - - layer->operation &= ~LTDC_LAYER_SETBLENDMODE; -} - -/**************************************************************************** - * Name: stm32_ltdc_lcolor - * - * Description: - * Change layer default color and clear the color operation flag. - * Note! This changes have no effect until the shadow register reload has - * been done. - * - * Input Parameters: - * layer - Reference to the layer control structure - * - ****************************************************************************/ - -static void stm32_ltdc_lcolor(FAR struct stm32_layer_s *layer, uint32_t argb) -{ - reginfo("set LTDC_L%dDCCR=%08x\n", layer->state.lid + 1, argb); - putreg32(argb, stm32_dccr_layer_t[layer->state.lid]); - - /* Clear the color operation flag */ - - layer->operation &= ~LTDC_LAYER_SETCOLOR; -} - -/**************************************************************************** - * Name: stm32_ltdc_lcolorkey - * - * Description: - * Change layer colorkey and clear the colorkey operation flag. - * Note! This changes have no effect until the shadow register reload has - * been done. - * - * Input Parameters: - * layer - Reference to the layer control structure - * - ****************************************************************************/ - -static void stm32_ltdc_lcolorkey(FAR struct stm32_layer_s *layer) -{ - uint32_t regval; - - regval = getreg32(stm32_cr_layer_t[layer->state.lid]); - - if (layer->operation & LTDC_LAYER_ENABLECOLORKEY) - { - /* Set colorkey */ - - reginfo("set LTDC_L%dCKCR=%08x\n", - layer->state.lid + 1, layer->state.colorkey); - putreg32(layer->state.colorkey, stm32_ckcr_layer_t[layer->state.lid]); - - /* Enable colorkey */ - - regval |= LTDC_LxCR_COLKEN; - } - else - { - /* Disable colorkey */ - - regval &= ~LTDC_LxCR_COLKEN; - } - - reginfo("set LTDC_L%dCR=%08x\n", layer->state.lid + 1, regval); - putreg32(regval, stm32_cr_layer_t[layer->state.lid]); - - /* Clear the colorkey operation flag */ - - layer->operation &= ~LTDC_LAYER_SETCOLORKEY; -} - -/**************************************************************************** - * Name: stm32_ltdc_lclut + * Name: stm32_ltdc_lputclut * * Description: * Update the clut layer register during blank period. - * Note! The clut register are no shadow register. + * Note! The clut register is no shadow register. * * Input Parameters: * layer - Reference to the layer control structure + * cmap - Color map * ****************************************************************************/ -#ifdef STM32_LAYER_CLUT_SIZE -static void stm32_ltdc_lclut(FAR struct stm32_layer_s *layer, - FAR const struct fb_cmap_s *cmap) +static void stm32_ltdc_lputclut(FAR struct stm32_ltdc_s *layer, + FAR const struct fb_cmap_s *cmap) { int n; - uint32_t regval; - uint32_t *clut; irqstate_t flags; /* Disable clut during register update */ stm32_ltdc_lclutenable(layer, false); - /* Set the clut memory address */ - - clut = layer->state.clut; - - /* Reload shadow control register. - * This never changed any layer setting as long the layer register not up to - * date. This is what stm32_update does. + /* Update the clut registers. Ensure operation is atomic or in interrupt + * protected context. */ - stm32_ltdc_reload(LTDC_SRCR_IMR, false); - flags = enter_critical_section(); - /* Update the clut registers */ - for (n = cmap->first; n < cmap->len && n < STM32_LTDC_NCLUT; n++) { - /* Update the layer clut entry */ -#ifndef CONFIG_FB_TRANSPARENCY - uint8_t *clut888 = (uint8_t *)clut; - uint16_t offset = 3 * n; + uint32_t regval; - clut888[offset] = cmap->blue[n]; - clut888[offset + 1] = cmap->green[n]; - clut888[offset + 2] = cmap->red[n]; + regval = (uint32_t)LTDC_CLUT_ADD(n) | + (uint32_t)LTDC_CLUT_RED(cmap->red[n]) | + (uint32_t)LTDC_CLUT_GREEN(cmap->green[n]) | + (uint32_t)LTDC_CLUT_BLUE(cmap->blue[n]); - regval = (uint32_t)LTDC_CLUT_BLUE(clut888[offset]) | - (uint32_t)LTDC_CLUT_GREEN(clut888[offset + 1]) | - (uint32_t)LTDC_CLUT_RED(clut888[offset + 2]) | - (uint32_t)LTDC_CLUT_ADD(n); -#else - clut[n] = (uint32_t)LTDC_CLUT_ALPHA(cmap->transp[n]) | - (uint32_t)LTDC_CLUT_RED(cmap->red[n]) | - (uint32_t)LTDC_CLUT_GREEN(cmap->green[n]) | - (uint32_t)LTDC_CLUT_BLUE(cmap->blue[n]); - regval = (uint32_t)LTDC_CLUT_ADD(n) | (clut[n] & LTDC_CLUT_RGB888_MASK); -#endif - - - reginfo("set LTDC_L%dCLUTWR = %08x, cmap->first = %d, cmap->len = %d\n", - layer->state.lid + 1, regval, cmap->first, cmap->len); - putreg32(regval, stm32_clutwr_layer_t[layer->state.lid]); + reginfo("set LTDC_L%dCLUTWR = %08x, first = %d, len = %d\n", + layer->oinfo.overlay + 1, regval, cmap->first, cmap->len); + putreg32(regval, stm32_clutwr_layer_t[layer->oinfo.overlay]); } leave_critical_section(flags); - /* Enable clut */ + /* Enable clut after register update */ stm32_ltdc_lclutenable(layer, true); @@ -1918,45 +2088,47 @@ static void stm32_ltdc_lclut(FAR struct stm32_layer_s *layer, stm32_ltdc_reload(LTDC_SRCR_IMR, false); } -#endif /**************************************************************************** - * Name: stm32_ltdc_lenable + * Name: stm32_ltdc_lgetclut * * Description: - * Disable or enable specific layer. - * Note! This changes have no effect until the shadow register reload has - * been done. + * Copy the layers color lookup table. * * Input Parameters: - * layer - Reference to the layer control structure + * layer - Reference to the layer control structure + * cmap - Color map * ****************************************************************************/ -static void stm32_ltdc_lenable(FAR struct stm32_layer_s *layer) +static void stm32_ltdc_lgetclut(FAR struct stm32_ltdc_s * layer, + FAR struct fb_cmap_s * cmap) { - uint32_t regval; + int n; + FAR struct fb_cmap_s *priv_cmap = &g_vtable.cmap; - /* Enable or disable layer */ + /* Copy from internal cmap */ - regval = getreg32(stm32_cr_layer_t[layer->state.lid]); - - if (layer->operation & LTDC_LAYER_ENABLE) + for (n = cmap->first; n < cmap->len && n < STM32_LTDC_NCLUT; n++) { - regval |= LTDC_LxCR_LEN; + +# ifdef CONFIG_FB_TRANSPARENCY + cmap->transp[n] = priv_cmap->transp[n]; +# endif + cmap->red[n] = priv_cmap->red[n]; + cmap->green[n] = priv_cmap->green[n]; + cmap->blue[n] = priv_cmap->blue[n]; + + reginfo("color = %d, transp=%02x, red=%02x, green=%02x, blue=%02x\n", n, +# ifdef CONFIG_FB_TRANSPARENCY + cmap->transp[n], +# endif + cmap->red[n], + cmap->green[n], + cmap->blue[n]); } - else - { - regval &= ~LTDC_LxCR_LEN; - } - - reginfo("set LTDC_L%dCR=%08x\n", layer->state.lid + 1, regval); - putreg32(regval, stm32_cr_layer_t[layer->state.lid]); - - /* Clear the enable operation flag */ - - layer->operation &= ~LTDC_LAYER_SETENABLE; } +#endif /* CONFIG_FB_CMAP */ /**************************************************************************** * Name: stm32_ltdc_lclear @@ -1965,100 +2137,42 @@ static void stm32_ltdc_lenable(FAR struct stm32_layer_s *layer) * Clear the whole layer * * Input Parameters: - * layer - Reference to the layer control structure - * color - The color to clear - * - * Returned Value: - * OK - On success - * -EINVAL - If one of the parameter invalid + * overlayno - Number overlay * ****************************************************************************/ -static void stm32_ltdc_lclear(FAR struct stm32_layer_s *layer, - nxgl_mxpixel_t color) +static void stm32_ltdc_lclear(uint8_t overlayno) { - FAR struct stm32_ltdc_s *priv = &layer->state; - -#if STM32_LTDC_L1_BPP == 8 || STM32_LTDC_L2_BPP == 8 - if (priv->pinfo.bpp == 8) - { - uint8_t *dest = (uint8_t *)priv->pinfo.fbmem; - int i; - - lcdinfo("Clearing display: BPP=%d color=%04x framebuffer=%08x size=%d\n", - priv->pinfo.bpp, color, dest, priv->pinfo.fblen); - - for (i = 0; i < priv->pinfo.fblen; i += sizeof(uint8_t)) - { - *dest++ = (uint8_t)color; - } - - return; - } -#endif - -#if STM32_LTDC_L1_BPP == 16 || STM32_LTDC_L2_BPP == 16 - if (priv->pinfo.bpp == 16) - { - uint16_t *dest = (uint16_t *)priv->pinfo.fbmem; - int i; - - lcdinfo("Clearing display: BPP=%d color=%04x framebuffer=%08x size=%d\n", - priv->pinfo.bpp, color, dest, priv->pinfo.fblen); - - for (i = 0; i < priv->pinfo.fblen; i += sizeof(uint16_t)) - { - *dest++ = (uint16_t)color; - } - - return; - } -#endif - -#if STM32_LTDC_L1_BPP == 24 || STM32_LTDC_L2_BPP == 24 - if (priv->pinfo.bpp == 24) - { - uint8_t *dest = (uint8_t *)priv->pinfo.fbmem; - uint8_t r; - uint8_t g; - uint8_t b; - int i; - - lcdinfo("Clearing display: BPP=%d color=%04x framebuffer=%08x size=%d\n", - priv->pinfo.bpp, color, dest, priv->pinfo.fblen); - - r = (uint8_t) color; - g = (uint8_t) (color >> 8); - b = (uint8_t) (color >> 16); - - for (i = 0; i < priv->pinfo.fblen; i += 3*sizeof(uint8_t)) - { - *dest++ = r; - *dest++ = g; - *dest++ = b; - } - - return; - } -#endif - -#if STM32_LTDC_L1_BPP == 32 || STM32_LTDC_L2_BPP == 32 - if (priv->pinfo.bpp == 32) - { - uint32_t *dest = (uint32_t *)priv->pinfo.fbmem; - int i; - - lcdinfo("Clearing display: BPP=%d color=%04x framebuffer=%08x size=%d\n", - priv->pinfo.bpp, color, dest, priv->pinfo.fblen); - - for (i = 0; i < priv->pinfo.fblen; i += sizeof(uint32_t)) - { - *dest++ = (uint32_t)color; - } - } -#endif + memset((uint8_t*)stm32_fbmem_layer_t[overlayno], 0, + stm32_fblen_layer_t[overlayno]); } +/**************************************************************************** + * Name: stm32_ltdc_lvalidate + * + * Description: + * Validates if the given area is within the overlay framebuffer memory + * region + * + * Input Parameters: + * layer - Reference to the layer control structure + * area - Reference to the overlay area + * + ****************************************************************************/ + +#if defined(CONFIG_STM32F7_DMA2D) && defined(CONFIG_FB_OVERLAY_BLIT) +static bool stm32_ltdc_lvalidate(FAR const struct stm32_ltdc_s *layer, + FAR const struct fb_area_s *area) +{ + uint32_t offset; + + offset = (area->y + area->h - 1) * layer->oinfo.stride + (area->x + area->w) * + layer->oinfo.bpp / 8; + + return (offset <= layer->oinfo.fblen && area->w > 0 && area->h > 0); +} +#endif /* defined(CONFIG_STM32F7_DMA2D) && defined(CONFIG_FB_OVERLAY_BLIT) */ + /**************************************************************************** * Name: stm32_ltdc_linit * @@ -2066,107 +2180,134 @@ static void stm32_ltdc_lclear(FAR struct stm32_layer_s *layer, * Initialize layer to their default states. * * Initialize: - * - Reset layer - * - layer fram - * - Reset layerebuffers - * - layer position + * - layer framebuffer * - layer pixelformat + * - layer defaultcolor + * - layer chromakey + * - layer transparency + * - layer clut + * + * Input Parameters: + * layer - Reference to the layer control structure + * + ****************************************************************************/ + +static void stm32_ltdc_linit(uint8_t overlay) +{ + DEBUGASSERT(overlay < LTDC_NLAYERS); + + FAR struct stm32_ltdcdev_s *dev = &g_vtable; + FAR struct stm32_ltdc_s *layer = &dev->layer[overlay]; + + /* Disable layer */ + + stm32_ltdc_lenable(layer, false); + + /* Clear the layer framebuffer */ + + stm32_ltdc_lclear(overlay); + + /* Set layers framebuffer */ + + stm32_ltdc_lframebuffer(layer); + + /* Set layers pixel input format */ + + stm32_ltdc_lpixelformat(layer); + + /* Configure layer default color */ + + stm32_ltdc_ldefaultcolor(layer, stm32_defaultcolor_layer_t[overlay]); + + /* Layers default transparency */ + + stm32_ltdc_ltransp(layer, 0xff, 0); + + /* Layers chromakey */ + + stm32_ltdc_lchromakey(layer, stm32_chromakey_layer_t[overlay]); + + /* Enable chromakey */ + + stm32_ltdc_lchromakeyenable(layer, stm32_chromakeyen_layer_t[overlay]); + +#ifdef CONFIG_FB_CMAP + /* Disable clut by default */ + + if (dev->vinfo.fmt == FB_FMT_RGB8) + { + /* Initialize LTDC clut register */ + + stm32_ltdc_lputclut(layer, &g_vtable.cmap); + + /* Configure the clut register */ + + stm32_ltdc_lclutenable(layer, true); + } +#endif + + /* Finally enable the layer */ + + stm32_ltdc_lenable(layer, true); +} + +/**************************************************************************** + * Name: stm32_ltdc_dma2dlinit + * + * Description: + * Initialize dma2d layer to their default states. + * + * Initialize: + * - layer framebuffer + * - layer pixelformat + * - layer size * - layer color - * - layer colorkey - * - layer alpha - * - layer blendmode - * - layer dma2d interface binding + * - layer chromakey + * - layer transparency + * - layer clut * * Input Parameters: * layer - Reference to the layer control structure * ****************************************************************************/ -static void stm32_ltdc_linit(int lid) -{ - /* Reset layer to their default state */ - - FAR struct stm32_layer_s *layer = &LAYER(lid); - FAR struct stm32_ltdc_s *state = &layer->state; -#ifdef CONFIG_STM32F7_LTDC_INTERFACE - FAR struct ltdc_layer_s *ltdc = &layer->ltdc; - - /* Initialize the ltdc interface */ - - ltdc->getlid = stm32_getlid; - ltdc->getvideoinfo = stm32_lgetvideoinfo; - ltdc->getplaneinfo = stm32_lgetplaneinfo; -# ifdef STM32_LAYER_CLUT_SIZE - ltdc->setclut = stm32_setclut; - ltdc->getclut = stm32_getclut; -#endif - ltdc->setcolor = stm32_setcolor; - ltdc->getcolor = stm32_getcolor; - ltdc->setcolorkey = stm32_setcolorkey; - ltdc->getcolorkey = stm32_getcolorkey; - ltdc->setalpha = stm32_setalpha; - ltdc->getalpha = stm32_getalpha; - ltdc->setblendmode = stm32_setblendmode; - ltdc->getblendmode = stm32_getblendmode; - ltdc->setarea = stm32_setarea; - ltdc->getarea = stm32_getarea; - ltdc->update = stm32_update; #ifdef CONFIG_STM32F7_DMA2D - ltdc->blit = stm32_blit; - ltdc->blend = stm32_blend; - ltdc->fillarea = stm32_fillarea; -#endif -#endif +static void stm32_ltdc_dma2dlinit(void) +{ + int n; + FAR struct stm32_ltdcdev_s *dev = &g_vtable; - /* Initialize the layer state */ - - state->area.xpos = 0; - state->area.ypos = 0; - state->area.xres = STM32_LTDC_WIDTH; - state->area.yres = STM32_LTDC_HEIGHT; - state->xpos = 0; - state->ypos = 0; - state->color = 0; - state->colorkey = 0; - state->alpha = 0xff; - state->blendmode = LTDC_BLEND_NONE; - state->lock = &g_lock; - - /* Initialize driver internals */ - - layer->opac = 0xff; - layer->bf1 = LTDC_BF1_CONST_ALPHA; - layer->bf2 = LTDC_BF2_CONST_ALPHA; - layer->operation = LTDC_LAYER_INIT; - - /* Clear the layer framebuffer */ - - stm32_ltdc_lclear(layer, 0); - - /* Set Pixel input format */ - - stm32_ltdc_lpixelformat(layer); - - /* Set position, color, colorkey, blendmode, alpha */ - - stm32_ltdc_lupdate(layer); - -#ifdef STM32_LAYER_CLUT_SIZE - /* Disable clut by default */ - - if (layer->state.vinfo.fmt == FB_FMT_RGB8) + for (n = 0; n < DMA2D_NLAYERS; n++) { - stm32_ltdc_lclutenable(layer, false); + uint32_t overlay = n + LTDC_NLAYERS; + FAR struct stm32_ltdc_s *layer = &dev->layer[overlay]; + uint8_t * fbmem = (uint8_t *)STM32_DMA2D_BUFFER_START; + + layer->layerno = overlay; + layer->oinfo.fbmem = fbmem + STM32_DMA2D_LAYER_SIZE * n; + layer->oinfo.fblen = STM32_DMA2D_FBSIZE; + layer->oinfo.stride = STM32_DMA2D_STRIDE; + layer->oinfo.overlay = overlay; + layer->oinfo.bpp = STM32_DMA2D_BPP; + layer->oinfo.blank = 0; + layer->oinfo.chromakey = 0; + layer->oinfo.color = 0; + layer->oinfo.transp.transp = 0xff; + layer->oinfo.transp.transp_mode = 0; + layer->oinfo.sarea.x = 0; + layer->oinfo.sarea.y = 0; + layer->oinfo.sarea.w = STM32_DMA2D_WIDTH; + layer->oinfo.sarea.h = STM32_DMA2D_HEIGHT; + layer->oinfo.accl = DMA2D_ACCL; + layer->lock = &g_lock; + layer->dma2dinfo.fmt = STM32_DMA2D_COLOR_FMT; + layer->dma2dinfo.transp_mode = STM32_DMA2D_PFCCR_AM_NONE; + layer->dma2dinfo.xres = layer->oinfo.sarea.w; + layer->dma2dinfo.yres = layer->oinfo.sarea.h; + layer->dma2dinfo.oinfo = &layer->oinfo; } -#endif - -#if defined(CONFIG_STM32F7_DMA2D) && defined(CONFIG_STM32F7_LTDC_INTERFACE) - /* Bind the dma2d interface */ - - layer->dma2d = stm32_dma2dinitltdc(state); - DEBUGASSERT(layer->dma2d); -#endif } +#endif /* CONFIG_STM32F7_DMA2D */ /**************************************************************************** * Public Functions @@ -2176,6 +2317,7 @@ static void stm32_ltdc_linit(int lid) * Name: stm32_getvideoinfo * * Description: + * Entrypoint ioctl FBIOGET_VIDEOINFO * Get the videoinfo for the framebuffer * * Input Parameters: @@ -2191,26 +2333,20 @@ static void stm32_ltdc_linit(int lid) static int stm32_getvideoinfo(struct fb_vtable_s *vtable, struct fb_videoinfo_s *vinfo) { - lcdinfo("vtable=%p vinfo=%p\n", vtable, vinfo); - if (vtable) - { - FAR struct ltdc_layer_s *ltdc; -#ifdef CONFIG_STM32F7_LTDC_L2 - ltdc = (FAR struct ltdc_layer_s *)&LAYER_L2; -#else - ltdc = (FAR struct ltdc_layer_s *)&LAYER_L1; -#endif - return stm32_lgetvideoinfo(ltdc, vinfo); - } + FAR struct stm32_ltdcdev_s *priv = (FAR struct stm32_ltdcdev_s *)vtable; - lcderr("ERROR: Returning EINVAL\n"); - return -EINVAL; + lcdinfo("vtable=%p vinfo=%p\n", vtable, vinfo); + DEBUGASSERT(vtable != NULL && priv == &g_vtable && vinfo != NULL); + + memcpy(vinfo, &priv->vinfo, sizeof(struct fb_videoinfo_s)); + return OK; } /**************************************************************************** * Name: stm32_getplaneinfo * * Description: + * Entrypoint ioctl FBIOGET_PLANEINFO * Get the planeinfo for the framebuffer * * Input Parameters: @@ -2226,16 +2362,15 @@ static int stm32_getvideoinfo(struct fb_vtable_s *vtable, static int stm32_getplaneinfo(struct fb_vtable_s *vtable, int planeno, struct fb_planeinfo_s *pinfo) { + FAR struct stm32_ltdcdev_s *priv = (FAR struct stm32_ltdcdev_s *)vtable; + + DEBUGASSERT(vtable != NULL && priv == &g_vtable); lcdinfo("vtable=%p planeno=%d pinfo=%p\n", vtable, planeno, pinfo); - if (vtable) + + if (planeno == 0) { - FAR struct ltdc_layer_s *ltdc; -#ifdef CONFIG_STM32F7_LTDC_L2 - ltdc = (FAR struct ltdc_layer_s *)&LAYER_L2; -#else - ltdc = (FAR struct ltdc_layer_s *)&LAYER_L1; -#endif - return stm32_lgetplaneinfo(ltdc, planeno, pinfo); + memcpy(pinfo, &priv->pinfo, sizeof(struct fb_planeinfo_s)); + return OK; } lcderr("ERROR: Returning EINVAL\n"); @@ -2246,6 +2381,7 @@ static int stm32_getplaneinfo(struct fb_vtable_s *vtable, int planeno, * Name: stm32_getcmap * * Description: + * Entrypoint ioctl FBIOGET_CMAP * Get a range of CLUT values for the LCD * * Input Parameters: @@ -2258,21 +2394,56 @@ static int stm32_getplaneinfo(struct fb_vtable_s *vtable, int planeno, * ****************************************************************************/ -#ifdef STM32_LAYER_CLUT_SIZE +#ifdef CONFIG_FB_CMAP static int stm32_getcmap(struct fb_vtable_s *vtable, struct fb_cmap_s *cmap) { -#ifdef CONFIG_STM32F7_LTDC_L2 - return stm32_getclut((FAR struct ltdc_layer_s *)&LAYER_L2, cmap); -#else - return stm32_getclut((FAR struct ltdc_layer_s *)&LAYER_L1, cmap); -#endif + int ret; + FAR struct stm32_ltdcdev_s *priv = (FAR struct stm32_ltdcdev_s *)vtable; + + DEBUGASSERT(vtable != NULL && priv == &g_vtable && cmap != NULL); + lcdinfo("vtable=%p cmap=%p\n", vtable, cmap); + + if (priv->vinfo.fmt != FB_FMT_RGB8) + { + lcderr("ERROR: CLUT is not supported for the pixel format: %d\n", + priv->vinfo.fmt); + ret = -EINVAL; + } + else if (cmap->first >= STM32_LTDC_NCLUT) + { + lcderr("ERROR: only %d color table entries supported\n", + STM32_LTDC_NCLUT); + ret = -EINVAL; + } + else + { + /* Currently, there is no api to set color map for each overlay + * separately. LTDC layers can have different color maps. Get the cmap + * from the main overlay. + */ + + FAR struct stm32_ltdc_s * layer; +# ifdef CONFIG_STM32F7_LTDC_L2 + layer = &priv->layer[LTDC_LAYER_L2]; +# else + layer = &priv->layer[LTDC_LAYER_L1]; +# endif + nxsem_wait(layer->lock); + stm32_ltdc_lgetclut(layer, cmap); + nxsem_post(layer->lock); + + ret = OK; + } + + return ret; } /**************************************************************************** * Name: stm32_putcmap * * Description: + * Entrypoint ioctl FBIOPUT_CMAP * Set a range of the CLUT values for the LCD * * Input Parameters: @@ -2288,347 +2459,115 @@ static int stm32_getcmap(struct fb_vtable_s *vtable, static int stm32_putcmap(struct fb_vtable_s *vtable, const struct fb_cmap_s *cmap) { -#ifdef CONFIG_STM32F7_LTDC_L2 - return stm32_setclut((FAR struct ltdc_layer_s *)&LAYER_L2, cmap); -#else - return stm32_setclut((FAR struct ltdc_layer_s *)&LAYER_L1, cmap); -#endif -} -#endif /* STM32_LAYER_CLUT_SIZE */ - -/**************************************************************************** - * Name: stm32_lgetvideoinfo - * - * Description: - * Get video information about the layer - * - * Input Parameters: - * layer - Reference to the layer control structure - * vinfo - Reference to the video info structure - * - * Returned Value: - * On success - OK - * On error - -EINVAL - * - ****************************************************************************/ - -static int stm32_lgetvideoinfo(struct ltdc_layer_s *layer, - struct fb_videoinfo_s *vinfo) -{ - lcdinfo("layer=%p vinfo=%p\n", layer, vinfo); - FAR struct stm32_layer_s *priv = (FAR struct stm32_layer_s *)layer; - - if (stm32_ltdc_lvalidate(priv)) - { - memcpy(vinfo, &priv->state.vinfo, sizeof(struct fb_videoinfo_s)); - - return OK; - } - - lcderr("ERROR: Returning EINVAL\n"); - return -EINVAL; -} - -/**************************************************************************** - * Name: stm32_lgetplaneinfo - * - * Description: - * Get plane information about the layer - * - * Input Parameters: - * layer - Reference to the layer control structure - * planeno - Number of the plane - * pinfo - Reference to the plane info structure - * - * Returned Value: - * On success - OK - * On error - -EINVAL - * - ****************************************************************************/ - -static int stm32_lgetplaneinfo(struct ltdc_layer_s *layer, int planeno, - struct fb_planeinfo_s *pinfo) -{ - FAR struct stm32_layer_s *priv = (FAR struct stm32_layer_s *)layer; - - lcdinfo("layer=%p planeno=%d pinfo=%p\n", layer, planeno, pinfo); - if (stm32_ltdc_lvalidate(priv) && planeno == 0) - { - memcpy(pinfo, &priv->state.pinfo, sizeof(struct fb_planeinfo_s)); - return OK; - } - - lcderr("ERROR: Returning EINVAL\n"); - return -EINVAL; -} - -/**************************************************************************** - * Name: stm32_setclut - * - * Description: - * Configure layer clut (color lookup table). - * Non clut is defined during initializing. - * Clut is active during next vertical blank period. Do not need an update. - * - * Input Parameters: - * layer - Reference to the layer structure - * cmap - color lookup table with up the 256 entries - * - * Returned Value: - * On success - OK - * On error - -EINVAL - * - ****************************************************************************/ - -#ifdef STM32_LAYER_CLUT_SIZE -static int stm32_setclut(struct ltdc_layer_s *layer, - const struct fb_cmap_s *cmap) -{ - FAR struct stm32_layer_s *priv = (FAR struct stm32_layer_s *)layer; int ret; + FAR struct stm32_ltdcdev_s *priv = (FAR struct stm32_ltdcdev_s *)vtable; - lcdinfo("layer=%p cmap=%p\n", layer, cmap); + DEBUGASSERT(vtable != NULL && priv == &g_vtable && cmap != NULL); + lcdinfo("vtable=%p cmap=%p\n", vtable, cmap); - if (stm32_ltdc_lvalidate(priv) && cmap) + if (priv->vinfo.fmt != FB_FMT_RGB8) { - nxsem_wait(priv->state.lock); - - if (priv->state.vinfo.fmt != FB_FMT_RGB8) - { - lcderr("ERROR: CLUT is not supported for the pixel format: %d\n", - priv->state.vinfo.fmt); - ret = -EINVAL; - } - else if (cmap->first >= STM32_LTDC_NCLUT) - { - lcderr("ERROR: only %d color table entries supported\n", - STM32_LTDC_NCLUT); - ret = -EINVAL; - } - else - { - /* Update layer clut and clut register */ - - stm32_ltdc_lclut(priv, cmap); - - ret = OK; - } - - nxsem_post(priv->state.lock); - - return ret; + lcderr("ERROR: CLUT is not supported for the pixel format: %d\n", + priv->vinfo.fmt); + ret = -EINVAL; } - - lcderr("ERROR: Returning EINVAL\n"); - return -EINVAL; -} - -/**************************************************************************** - * Name: stm32_getclut - * - * Description: - * Get configured layer clut (color lookup table). - * - * Input Parameters: - * layer - Reference to the layer structure - * cmap - Reference to valid color lookup table accept up the 256 color - * entries - * - * Returned Value: - * On success - OK - * On error - -EINVAL - * - ****************************************************************************/ - -static int stm32_getclut(struct ltdc_layer_s *layer, - struct fb_cmap_s *cmap) -{ - FAR struct stm32_layer_s *priv = (FAR struct stm32_layer_s *)layer; - int ret; - - lcdinfo("layer=%p cmap=%p\n", layer, cmap); - - if (priv == &LAYER_L1 || priv == &LAYER_L2) + else if (cmap->first >= STM32_LTDC_NCLUT) { - nxsem_wait(priv->state.lock); -#ifdef CONFIG_STM32F7_DMA2D - /* Note! We share the same color lookup table with the dma2d driver and - * the getclut implementation works in the same way. - * To prevent redundant code we simply call the getclut function of the - * dma2d interface. + lcderr("ERROR: only %d color table entries supported\n", + STM32_LTDC_NCLUT); + ret = -EINVAL; + } + else + { + /* Currently, there is no api to set color map for each overlay + * separately. LTDC layers can have different color maps, but is shared + * for now. */ - ret = priv->dma2d->getclut(priv->dma2d, cmap); -#else - if (priv->state.vinfo.fmt != FB_FMT_RGB8) + int n; + FAR struct fb_cmap_s *priv_cmap = &g_vtable.cmap; + + /* First copy to internal cmap */ + + for (n = cmap->first; n < cmap->len && n < STM32_LTDC_NCLUT; n++) { - lcderr("ERROR: CLUT is not supported for the pixel format: %d\n", - priv->state.vinfo.fmt); - ret = -EINVAL; + priv_cmap->red[n] = cmap->red[n]; + priv_cmap->green[n] = cmap->green[n]; + priv_cmap->blue[n] = cmap->blue[n]; +# ifdef CONFIG_FB_TRANSPARENCY + /* Not supported by LTDC */ + + priv_cmap->transp[n] = cmap->transp[n]; +# endif } - else if (cmap->first >= STM32_LTDC_NCLUT) + + priv_cmap->first = cmap->first; + priv_cmap->len = cmap->len; + + /* Update the layer clut register */ + + nxsem_wait(&g_lock); + + for (n = 0; n < LTDC_NLAYERS; n++) { - lcderr("ERROR: only %d color table entries supported\n", - STM32_LTDC_NCLUT); - ret = -EINVAL; + FAR struct stm32_ltdc_s * layer = &priv->layer[n]; + stm32_ltdc_lputclut(layer, priv_cmap); } - else - { - /* Copy from the layer clut */ +# ifdef CONFIG_STM32F7_DMA2D + /* Update dma2d cmap */ - uint32_t *clut; - int n; + priv->dma2d->setclut(cmap); +# endif + nxsem_post(&g_lock); - clut = priv->state.clut; - - for (n = cmap->first; n < cmap->len && n < STM32_LTDC_NCLUT; n++) - { -# ifndef CONFIG_FB_TRANSPARENCY - uint8_t *clut888 = (uint8_t *)clut; - uint16_t offset = 3 * n; - - cmap->blue[n] = clut888[offset]; - cmap->green[n] = clut888[offset + 1]; - cmap->red[n] = clut888[offset + 2]; - - reginfo("n=%d, red=%02x, green=%02x, blue=%02x\n", n, - clut888[offset], clut888[offset + 1], - clut888[offset + 2]); -# else - cmap->transp[n] = (uint8_t)LTDC_CMAP_ALPHA(clut[n]); - cmap->red[n] = (uint8_t)LTDC_CMAP_RED(clut[n]); - cmap->green[n] = (uint8_t)LTDC_CMAP_GREEN(clut[n]); - cmap->blue[n] = (uint8_t)LTDC_CMAP_BLUE(clut[n]); - - reginfo("n=%d, alpha=%02x, red=%02x, green=%02x, blue=%02x\n", n, - DMA2D_CMAP_ALPHA(clut[n]), DMA2D_CMAP_RED(clut[n]), - DMA2D_CMAP_GREEN(clut[n]), DMA2D_CMAP_BLUE(clut[n])); -# endif - } - - ret = OK; - } -#endif - nxsem_post(priv->state.lock); - - return ret; + ret = OK; } - lcderr("ERROR: Returning EINVAL\n"); - return -EINVAL; + return ret; } -#endif /* STM32_LAYER_CLUT_SIZE */ +#endif /* CONFIG_FB_CMAP */ -#ifdef CONFIG_STM32F7_LTDC_INTERFACE -/**************************************************************************** - * Name: getlid - * +/*************************************************************************** + * Name: stm32_ioctl_waitforvsync * Description: - * Get a specific layer identifier. - * - * Input Parameters: - * layer - Reference to the layer structure - * lid - Reference to store the layer id - * flag - Operation flag describe the layer identifier - * e.g. get the current active or inactive layer. - * See LTDC_LAYER_* for possible values - * - * Returned Value: - * OK - On success - * Null if invalid flag - * - ****************************************************************************/ + * Entrypoint ioctl FBIO_WAITFORSYNC + ***************************************************************************/ -static int stm32_getlid(FAR struct ltdc_layer_s *layer, int *lid, - uint32_t flag) +#ifdef CONFIG_FB_SYNC +static int stm32_waitforvsync(FAR struct fb_vtable_s *vtable) { - FAR struct stm32_layer_s *priv = (FAR struct stm32_layer_s *)layer; + int ret; - lcdinfo("flag = %08x\n", flag); + DEBUGASSERT(vtable != NULL && vtable == &g_vtable.vtable); - if (stm32_ltdc_lvalidate(priv)) - { - int ret = OK; + /* Wait upon vertical synchronization. */ - nxsem_wait(priv->state.lock); + ret = stm32_ltdc_reload(LTDC_SRCR_VBR, true); - switch (flag) - { - case LTDC_LAYER_OWN: - *lid = priv->state.lid; - break; -#ifdef CONFIG_STM32F7_LTDC_L2 - case LTDC_LAYER_ACTIVE: - *lid = g_lactive; - break; - case LTDC_LAYER_INACTIVE: - *lid = !g_lactive; - break; - case LTDC_LAYER_TOP: - *lid = LTDC_LAYER_L2; - break; - case LTDC_LAYER_BOTTOM: - *lid = LTDC_LAYER_L1; - break; -#else - case LTDC_LAYER_ACTIVE: - case LTDC_LAYER_INACTIVE: - case LTDC_LAYER_TOP: - case LTDC_LAYER_BOTTOM: - *lid = LTDC_LAYER_L1; - break; -#endif -#ifdef CONFIG_STM32F7_DMA2D - case LTDC_LAYER_DMA2D: - ret = priv->dma2d->getlid(priv->dma2d, lid); - break; -#endif - default: - ret = EINVAL; - lcderr("ERROR: Returning EINVAL\n"); - break; - } - - nxsem_post(priv->state.lock); - - return ret; - } - - lcderr("ERROR: Returning EINVAL\n"); - return -EINVAL; + return ret; } +#endif /* CONFIG_FB_SYNC */ -/**************************************************************************** - * Name: stm32_setcolor - * +/*************************************************************************** + * Name: stm32_getoverlayinfo * Description: - * Configure layer default color value for the non active layer area. - * Default value during initializing: 0x00000000 - * Color is active after next update. - * - * Input Parameters: - * layer - Reference to the layer structure - * argb - ARGB8888 color value - * - * Returned Value: - * On success - OK - * On error - -EINVAL - * - ****************************************************************************/ + * Entrypoint ioctl FBIOGET_OVERLAYINFO + ***************************************************************************/ -static int stm32_setcolor(FAR struct ltdc_layer_s *layer, uint32_t argb) +#ifdef CONFIG_FB_OVERLAY +static int stm32_getoverlayinfo(FAR struct fb_vtable_s *vtable, + int overlayno, + FAR struct fb_overlayinfo_s *oinfo) { - FAR struct stm32_layer_s *priv = (FAR struct stm32_layer_s *)layer; + FAR struct stm32_ltdcdev_s *priv = (FAR struct stm32_ltdcdev_s*)vtable; - lcdinfo("layer = %p, argb = %08x\n", layer, argb); + lcdinfo("vtable=%p overlay=%d oinfo=%p\n", vtable, overlayno, oinfo); + DEBUGASSERT(vtable != NULL && priv == &g_vtable); - if (stm32_ltdc_lvalidate(priv)) + if (overlayno < LTDC_NOVERLAYS) { - nxsem_wait(priv->state.lock); - priv->state.color = argb; - priv->operation |= LTDC_LAYER_SETCOLOR; - nxsem_post(priv->state.lock); - + FAR struct stm32_ltdc_s * layer = &priv->layer[overlayno]; + memcpy(oinfo, &layer->oinfo, sizeof(struct fb_overlayinfo_s)); return OK; } @@ -2636,34 +2575,55 @@ static int stm32_setcolor(FAR struct ltdc_layer_s *layer, uint32_t argb) return -EINVAL; } -/**************************************************************************** - * Name: stm32_getcolor - * +/*************************************************************************** + * Name: stm32_settransp * Description: - * Get configured layer color for the non active layer area. - * - * Input Parameters: - * layer - Reference to the layer structure - * argb - Reference to store the ARGB8888 color value - * - * Returned Value: - * On success - OK - * On error - -EINVAL - * -*******************************************************************************/ + * Entrypoint ioctl FBIOSET_TRANSP + ***************************************************************************/ -static int stm32_getcolor(FAR struct ltdc_layer_s *layer, uint32_t *argb) +static int stm32_settransp(FAR struct fb_vtable_s *vtable, + FAR const struct fb_overlayinfo_s *oinfo) { - FAR struct stm32_layer_s *priv = (FAR struct stm32_layer_s *)layer; + FAR struct stm32_ltdcdev_s *priv = (FAR struct stm32_ltdcdev_s*)vtable; - lcdinfo("layer = %p, argb = %p\n", layer, argb); + DEBUGASSERT(vtable != NULL && priv == &g_vtable); + lcdinfo("vtable=%p, overlay=%d, transp=%02x, transp_mode=%02x\n", vtable, + oinfo->overlay, oinfo->transp.transp, oinfo->transp.transp_mode); - if (stm32_ltdc_lvalidate(priv)) + if (oinfo->transp.transp_mode > 1) { - nxsem_wait(priv->state.lock); - *argb = priv->state.color; - nxsem_post(priv->state.lock); + lcderr("ERROR: Returning ENOSYS, transparency mode not supported\n"); + return -ENOSYS; + } + if (oinfo->overlay < LTDC_NOVERLAYS) + { + FAR struct stm32_ltdc_s * layer = &priv->layer[oinfo->overlay]; + + nxsem_wait(layer->lock); + layer->oinfo.transp.transp = oinfo->transp.transp; + layer->oinfo.transp.transp_mode = oinfo->transp.transp_mode; + +# ifdef CONFIG_STM32F7_DMA2D + if (layer->oinfo.transp.transp_mode == 0) + { + layer->dma2dinfo.transp_mode = STM32_DMA2D_PFCCR_AM_CONST; + } + else if (layer->oinfo.transp.transp_mode == 1) + { + layer->dma2dinfo.transp_mode = STM32_DMA2D_PFCCR_AM_PIXEL; + } + + if (oinfo->overlay < LTDC_NLAYERS) +# endif + { + /* Set LTDC blendmode and alpha value */ + + stm32_ltdc_ltransp(layer, layer->oinfo.transp.transp, + layer->oinfo.transp.transp_mode); + } + + nxsem_post(layer->lock); return OK; } @@ -2671,766 +2631,323 @@ static int stm32_getcolor(FAR struct ltdc_layer_s *layer, uint32_t *argb) return -EINVAL; } -/**************************************************************************** - * Name: stm32_setcolorkey - * +/*************************************************************************** + * Name: stm32_setchromakey * Description: - * Configure layer default color key (chromakey) value for transparency. - * Layer default value during initializing: 0x00000000 - * Colorkey is active after next update. - * - * Input Parameters: - * layer - Reference to the layer structure - * rgb - RGB888 color value - * - * Returned Value: - * On success - OK - * On error - -EINVAL - * - ****************************************************************************/ + * Entrypoint ioctl FBIOSET_CHROMAKEY + ***************************************************************************/ -static int stm32_setcolorkey(FAR struct ltdc_layer_s *layer, uint32_t rgb) +static int stm32_setchromakey(FAR struct fb_vtable_s *vtable, + FAR const struct fb_overlayinfo_s *oinfo) { - FAR struct stm32_layer_s *priv = (FAR struct stm32_layer_s *)layer; + FAR struct stm32_ltdcdev_s *priv = (FAR struct stm32_ltdcdev_s *)vtable; - lcdinfo("layer = %p, argb = %08x\n", layer, rgb); + DEBUGASSERT(vtable != NULL && priv == &g_vtable && oinfo != NULL); + lcdinfo("vtable=%p, overlay=%d, chromakey=%08x\n", vtable, + oinfo->overlay, oinfo->chromakey); - if (stm32_ltdc_lvalidate(priv)) - { - nxsem_wait(priv->state.lock); - priv->state.colorkey = rgb; - priv->operation |= LTDC_LAYER_SETCOLORKEY; - nxsem_post(priv->state.lock); - - return OK; - } - - lcderr("ERROR: Returning EINVAL\n"); - return -EINVAL; -} - -/**************************************************************************** - * Name: stm32_getcolorkey - * - * Description: - * Get the configured layer color key (chromakey) for transparency. - * - * Input Parameters: - * layer - Reference to the layer structure - * rgb - Reference to store the RGB888 color key - * - * Returned Value: - * On success - OK - * On error - -EINVAL - * - ****************************************************************************/ - -static int stm32_getcolorkey(FAR struct ltdc_layer_s *layer, uint32_t *rgb) -{ - FAR struct stm32_layer_s *priv = (FAR struct stm32_layer_s *)layer; - - lcdinfo("layer = %p, argb = %p\n", layer, rgb); - - if (stm32_ltdc_lvalidate(priv)) - { - nxsem_wait(priv->state.lock); - *rgb = priv->state.colorkey; - nxsem_post(priv->state.lock); - - return OK; - } - - lcderr("ERROR: Returning EINVAL\n"); - return -EINVAL; -} - -/**************************************************************************** - * Name: setalpha - * - * Description: - * Configure layer alpha value factor into blend operation. - * During the layer blend operation the source alpha value is multiplied - * with this alpha value. If the source color format doesn't support alpha - * channel (e.g. non ARGB8888) this alpha value will be used as constant - * alpha value for blend operation. - * Default alpha value during initializing: 0xff - * Alpha is active after next update. - * - * Input Parameters: - * layer - Reference to the layer structure - * alpha - Alpha value - * - * Returned Value: - * On success - OK - * On error - -EINVAL - * - ****************************************************************************/ - -static int stm32_setalpha(FAR struct ltdc_layer_s *layer, uint8_t alpha) -{ - FAR struct stm32_layer_s *priv = (FAR struct stm32_layer_s *)layer; - - lcdinfo("layer = %p, alpha = %02x\n", layer, alpha); - - if (stm32_ltdc_lvalidate(priv)) - { - nxsem_wait(priv->state.lock); - priv->state.alpha = alpha; - priv->operation |= LTDC_LAYER_SETALPHAVALUE; - nxsem_post(priv->state.lock); - - return OK; - } - - lcderr("ERROR: Returning EINVAL\n"); - return -EINVAL; -} - -/**************************************************************************** - * Name: stm32_getalpha - * - * Description: - * Get configured layer alpha value factor for blend operation. - * - * Input Parameters: - * layer - Reference to the layer structure - * alpha - Reference to store the alpha value - * - * Returned Value: - * On success - OK - * On error - -EINVAL - * - ****************************************************************************/ - -static int stm32_getalpha(FAR struct ltdc_layer_s *layer, uint8_t *alpha) -{ - FAR struct stm32_layer_s *priv = (FAR struct stm32_layer_s *)layer; - - lcdinfo("layer = %p, alpha = %p\n", layer, alpha); - - if (stm32_ltdc_lvalidate(priv)) - { - nxsem_wait(priv->state.lock); - *alpha = priv->state.alpha; - nxsem_post(priv->state.lock); - - return OK; - } - - lcderr("ERROR: Returning EINVAL\n"); - return -EINVAL; -} - -/**************************************************************************** - * Name: setblendmode - * - * Description: - * Configure blend mode of the layer. - * Default mode during initializing: LTDC_BLEND_NONE - * Blendmode is active after next update. - * - * Input Parameters: - * layer - Reference to the layer structure - * mode - Blend mode (see LTDC_BLEND_*) - * - * Returned Value: - * On success - OK - * On error - -EINVAL - * - * Procedure information: - * LTDC_BLEND_NONE: - * Informs the driver to disable all blend operation for the given layer. - * That means the layer is opaque. Note this has no effect on the - * colorkey settings. - * - * LTDC_BLEND_ALPHA: - * Informs the driver to enable alpha blending for the given layer. - * - * LTDC_BLEND_COLORKEY: - * Informs the driver to enable colorkeying for the given layer. - * - * LTDC_BLEND_SRCPIXELALPHA: - * Informs the driver to use the pixel alpha value of the layer instead - * the constant alpha value. This is only useful for ARGB8888 - * color format. - * - * LTDC_BLEND_DESTPIXELALPHA: - * Informs the driver to use the pixel alpha value of the subjacent layer - * instead the constant alpha value. This is only useful for ARGB8888 - * color format. - * - ****************************************************************************/ - -static int stm32_setblendmode(FAR struct ltdc_layer_s *layer, uint32_t mode) -{ - FAR struct stm32_layer_s *priv = (FAR struct stm32_layer_s *)layer; - uint32_t blendmode = mode; - - lcdinfo("layer = %p, mode = %08x\n", layer, mode); - - if (stm32_ltdc_lvalidate(priv)) - { - int ret = OK; - - nxsem_wait(priv->state.lock); - - /* Disable colorkeying by default */ - - priv->operation &= ~LTDC_LAYER_ENABLECOLORKEY; - - if (blendmode & (LTDC_BLEND_ALPHA | LTDC_BLEND_PIXELALPHA | - LTDC_BLEND_ALPHAINV | LTDC_BLEND_PIXELALPHAINV)) - { - /* Enable any alpha blending */ - - stm32_ltdc_lunsetopac(priv); - } - else - { - /* Disable any alpha blending */ - - stm32_ltdc_lsetopac(priv); - } - - if (blendmode & LTDC_BLEND_ALPHA || blendmode == LTDC_BLEND_NONE) - { - /* alpha blending introduce LTDC_BLEND_ALPHAINV */ - - priv->bf1 = LTDC_BF1_CONST_ALPHA; - priv->bf2 = LTDC_BF2_CONST_ALPHA; - blendmode &= ~LTDC_BLEND_ALPHA; - } - - if (blendmode & LTDC_BLEND_PIXELALPHA) - { - /* pixel alpha blending introduce LTDC_BLEND_PIXELALPHAINV */ - - priv->bf1 = LTDC_BF1_PIXEL_ALPHA; - priv->bf2 = LTDC_BF2_PIXEL_ALPHA; - blendmode &= ~LTDC_BLEND_PIXELALPHA; - } - - if (blendmode & LTDC_BLEND_ALPHAINV) - { - /* alpha blending of source input */ - - priv->bf2 = LTDC_BF2_CONST_ALPHA; - blendmode &= ~LTDC_BLEND_ALPHAINV; - } - - if (blendmode & LTDC_BLEND_PIXELALPHAINV) - { - /* pixel alpha blending of source input */ - - priv->bf2 = LTDC_BF2_PIXEL_ALPHA; - blendmode &= ~LTDC_BLEND_PIXELALPHAINV; - } - - if (mode & LTDC_BLEND_COLORKEY) - { - /* Enable colorkeying */ - - priv->operation |= LTDC_LAYER_ENABLECOLORKEY; - blendmode &= ~LTDC_BLEND_COLORKEY; - } - if (blendmode) - { - lcderr("ERROR: Unknown blendmode %02x\n", blendmode); - ret = -EINVAL; - } - - if (ret == OK) - { - priv->state.blendmode = mode; - priv->operation |= (LTDC_LAYER_SETBLENDMODE | - LTDC_LAYER_SETALPHAVALUE | - LTDC_LAYER_SETCOLORKEY); - } - - nxsem_post(priv->state.lock); - return ret; - } - - lcderr("ERROR: Returning EINVAL\n"); - return -EINVAL; -} - -/**************************************************************************** - * Name: stm32_getblendmode - * - * Description: - * Get configured blend mode of the layer. - * - * Input Parameters: - * layer - Reference to the layer structure - * mode - Reference to store the blend mode - * - * Returned Value: - * On success - OK - * On error - -EINVAL - ****************************************************************************/ - -static int stm32_getblendmode(FAR struct ltdc_layer_s *layer, uint32_t *mode) -{ - FAR struct stm32_layer_s *priv = (FAR struct stm32_layer_s *)layer; - - lcdinfo("layer = %p, mode = %p\n", layer, mode); - - if (stm32_ltdc_lvalidate(priv)) - { - nxsem_wait(priv->state.lock); - *mode = priv->state.blendmode; - nxsem_post(priv->state.lock); - - return OK; - } - - lcderr("ERROR: Returning EINVAL\n"); - return -EINVAL; -} - -/**************************************************************************** - * Name: stm32_setarea - * - * Description: - * Configure visible layer area and the reference position of the first - * pixel of the whole layer which is the first visible top left pixel in - * the active area. - * Area is active after next update. - * - * Input Parameters: - * layer - Reference to the layer control structure - * area - Reference to the valid area structure for the new active area - * srcxpos - x position of the visible pixel of the whole layer - * srcypos - y position of the visible pixel of the whole layer - * - * Returned Value: - * On success - OK - * On error - -EINVAL - * - * Procedure Information: - * If the srcxpos and srcypos unequal the xpos and ypos of the area - * structure this acts like moving the visible area to another position on - * the screen during the next update operation. - * - ****************************************************************************/ - -static int stm32_setarea(FAR struct ltdc_layer_s *layer, - FAR const struct ltdc_area_s *area, - fb_coord_t srcxpos, - fb_coord_t srcypos) -{ - FAR struct stm32_layer_s *priv = (FAR struct stm32_layer_s *)layer; - - lcdinfo("layer = %p, area = %p, srcxpos = %d, srcypos = %d\n", - layer, area, srcxpos, srcypos); - - if (stm32_ltdc_lvalidate(priv)) + if (oinfo->overlay < LTDC_NLAYERS) { int ret; + FAR struct stm32_ltdc_s * layer = &priv->layer[oinfo->overlay]; - nxsem_wait(priv->state.lock); - - ret = stm32_ltdc_lvalidatearea(priv, area->xpos, area->ypos, area->xres, - area->yres, srcxpos, srcypos); - - if (ret == OK) +# ifndef CONFIG_STM32F7_LTDC_L1_CHROMAKEY + if (oinfo->overlay == LTDC_LAYER_L1) { - priv->state.xpos = srcxpos; - priv->state.ypos = srcypos; - priv->state.area.xpos = area->xpos; - priv->state.area.ypos = area->ypos; - priv->state.area.xres = area->xres; - priv->state.area.yres = area->yres; - priv->operation |= LTDC_LAYER_SETAREA; + return -ENOSYS; + } +# endif +# ifndef CONFIG_STM32F7_LTDC_L2_CHROMAKEY + if (oinfo->overlay == LTDC_LAYER_L2) + { + return -ENOSYS; + } +# endif + + nxsem_wait(layer->lock); +# ifdef CONFIG_FB_CMAP + if (oinfo->chromakey >= g_vtable.cmap.len) + { + lcderr("ERROR: Clut index %d is out of range\n", oinfo->chromakey); + ret = -EINVAL; + } + else +# endif + { + layer->oinfo.chromakey = oinfo->chromakey; + + /* Set chromakey */ + + stm32_ltdc_lchromakey(layer, layer->oinfo.chromakey); + ret = OK; } - nxsem_post(priv->state.lock); - + nxsem_post(layer->lock); return ret; } - - lcderr("ERROR: Returning EINVAL\n"); - return -EINVAL; -} - -/**************************************************************************** - * Name: stm32_getarea - * - * Description: - * Get configured visible layer area. - * - * Input Parameters: - * layer - Reference to the layer control structure - * area - Reference to the area structure to store the active area - * srcxpos - Reference to store the referenced x position of the whole layer - * srcypos - Reference to store the reterenced y position of the whole layer - * - * Returned Value: - * On success - OK - * On error - -EINVAL - * - ****************************************************************************/ - -static int stm32_getarea(FAR struct ltdc_layer_s *layer, - FAR struct ltdc_area_s *area, - fb_coord_t *srcxpos, fb_coord_t *srcypos) -{ - FAR struct stm32_layer_s *priv = (FAR struct stm32_layer_s *)layer; - - lcdinfo("layer = %p, area = %p, srcxpos = %p, srcypos = %p\n", - layer, area, srcxpos, srcypos); - - if (stm32_ltdc_lvalidate(priv)) +# ifdef CONFIG_STM32F7_DMA2D + else if (oinfo->overlay < LTDC_NOVERLAYS) { - nxsem_wait(priv->state.lock); - *srcxpos = priv->state.xpos; - *srcypos = priv->state.ypos; - memcpy(area, &priv->state.area, sizeof(struct ltdc_area_s)); - nxsem_post(priv->state.lock); + /* Chromakey not supported by DMA2D */ - return OK; + return -ENOSYS; } +# endif lcderr("ERROR: Returning EINVAL\n"); return -EINVAL; } -/**************************************************************************** - * Name: stm32_update - * +/*************************************************************************** + * Name: stm32_setcolor * Description: - * Update current layer settings and make changes visible. - * - * Input Parameters: - * layer - Reference to the layer structure - * mode - operation mode - * - * Returned Value: - * OK - On success - * -EINVAL - If one of the parameter invalid - * -ECANCELED - Operation cancelled, something goes wrong - * - * Procedure information: - * LTDC_UPDATE_SIM: - * Informs the driver to update both layers simultaneously. Otherwise update - * the given layer only. - * - * LTDC_UPDATE_FLIP: - * Informs the driver to perform a flip operation. - * This only effects the ltdc layer 1 and 2 and can be useful for double - * buffering. Each flip operation changed the active layer to the inactive - * and vice versa. In the context of the ltdc that means, the inactive layer - * is complete disabled. So the subjacent layer is the background layer - * (background color). To reactivate both layer and their current settings - * perform an update without LTDC_UPDATE_FLIP flag. - * - * LTDC_UPDATE_ACTIVATE: - * Informs the driver that the given layer should be the active layer when - * the operation is complete. - * - * LTDC_SYNC_VBLANK: - * Informs the driver to update the layer upon vertical blank. Otherwise - * immediately. - * - ****************************************************************************/ + * Entrypoint ioctl FBIOSET_COLOR + ***************************************************************************/ -static int stm32_update(FAR struct ltdc_layer_s *layer, uint32_t mode) +static int stm32_setcolor(FAR struct fb_vtable_s *vtable, + FAR const struct fb_overlayinfo_s *oinfo) { - FAR struct stm32_layer_s *priv = (FAR struct stm32_layer_s *)layer; -#ifdef CONFIG_STM32F7_LTDC_L2 - FAR struct stm32_layer_s *active = &LAYER(g_lactive); - FAR struct stm32_layer_s *inactive = &LAYER(!g_lactive); -#endif + DEBUGASSERT(vtable != NULL && vtable == &g_vtable.vtable && oinfo != NULL); + lcdinfo("vtable=%p, overlay=%d, color=%08x\n", vtable, oinfo->color); - lcdinfo("layer = %p, mode = %08x\n", layer, mode); - - if (stm32_ltdc_lvalidate(priv)) + if (oinfo->overlay < LTDC_NOVERLAYS) { - /* Reload immediately by default */ +# ifdef CONFIG_STM32F7_DMA2D - bool waitvblank = false; - uint8_t reload = LTDC_SRCR_IMR; - - nxsem_wait(priv->state.lock); - - if (mode & LTDC_SYNC_VBLANK) - { - reload = LTDC_SRCR_VBR; - } - - if (mode & LTDC_SYNC_WAIT) - { - waitvblank = true; - } - - /* Ensures that last register reload operation has been completed */ - - if (stm32_ltdc_waitforirq() != OK) - { - lcderr("ERROR: Returning ECANCELED\n"); - return -ECANCELED; - } - - /* Update the given layer */ - - stm32_ltdc_lupdate(priv); - -#ifdef CONFIG_STM32F7_LTDC_L2 - /* The following operation only useful if layer 2 is supported. - * Otherwise ignore it. + /* Set color within the active overlay is not supported by LTDC. So use + * DMA2D controller instead when configured. */ - if (mode & LTDC_UPDATE_SIM) - { - /* Also update the flip layer */ + int ret; + FAR struct stm32_ltdcdev_s *priv = (FAR struct stm32_ltdcdev_s*)vtable; + FAR struct stm32_ltdc_s * layer = &priv->layer[oinfo->overlay]; + FAR struct fb_overlayinfo_s * poverlay = layer->dma2dinfo.oinfo; - stm32_ltdc_lupdate(&LAYER(!priv->state.lid)); - } + DEBUGASSERT(&layer->oinfo == poverlay); - if (mode & LTDC_UPDATE_ACTIVATE) - { - /* Set the given layer to the next active layer */ + nxsem_wait(layer->lock); + poverlay->color = oinfo->color; + ret = priv->dma2d->fillcolor(&layer->dma2dinfo, &poverlay->sarea, + poverlay->color); + nxsem_post(layer->lock); - g_lactive = priv->state.lid; + return ret; +# else + /* Coloring not supported by LTDC */ - /* Also change the current active layer for flip operation */ + return -ENOSYS; +# endif + } - active = &LAYER(!g_lactive); - } + lcderr("ERROR: Returning EINVAL\n"); + return -EINVAL; +} - if (mode & LTDC_UPDATE_FLIP) - { - /* Reset if manipulated by ACTIVATE flag */ +/*************************************************************************** + * Name: stm32_setblank + * Description: + * Entrypoint ioctl FBIOSET_BLANK + ***************************************************************************/ - inactive = &LAYER(!active->state.lid); +static int stm32_setblank(FAR struct fb_vtable_s *vtable, + FAR const struct fb_overlayinfo_s *oinfo) +{ + FAR struct stm32_ltdcdev_s *priv = (FAR struct stm32_ltdcdev_s*)vtable; - /* Set blendfactor for current active layer to there reset value */ + DEBUGASSERT(vtable != NULL && priv == &g_vtable && oinfo != NULL); + lcdinfo("vtable=%p, overlay=%d, blank=%02x\n", vtable, oinfo->blank); - stm32_ltdc_lblendmode(active, STM32_LTDC_BF1_RESET, - STM32_LTDC_BF2_RESET); + if (oinfo->overlay < LTDC_NLAYERS) + { + FAR struct stm32_ltdc_s * layer = &priv->layer[oinfo->overlay]; - /* Set blendfactor for current inactive layer */ + nxsem_wait(layer->lock); + layer->oinfo.blank = oinfo->blank; - stm32_ltdc_lblendmode(inactive, inactive->bf1, inactive->bf2); + /* Enable or disable layer */ - /* Disable the active layer */ - - active->operation &= ~LTDC_LAYER_ENABLE; - - stm32_ltdc_lenable(active); - - /* Enable the inactive layer */ - - inactive->operation |= LTDC_LAYER_ENABLE; - - stm32_ltdc_lenable(inactive); - - /* Ensure that both layer active and the manipulated layer - * settings restored during the next update (non flip) operation - */ - - active->operation |= (LTDC_LAYER_SETBLENDMODE | - LTDC_LAYER_ENABLE | - LTDC_LAYER_SETCOLOR | - LTDC_LAYER_SETENABLE); - - /* Change layer activity */ - - g_lactive = inactive->state.lid; - } -#endif - - /* Make the changes visible */ - - stm32_ltdc_reload(reload, waitvblank); - - nxsem_post(priv->state.lock); + stm32_ltdc_lenable(layer, (layer->oinfo.blank == 0)); + nxsem_post(layer->lock); return OK; } +# ifdef CONFIG_STM32F7_DMA2D + else if (oinfo->overlay < LTDC_NOVERLAYS) + { + /* DMA2D overlays are non visible */ + + return OK; + } +# endif lcderr("ERROR: Returning EINVAL\n"); return -EINVAL; } -#ifdef CONFIG_STM32F7_DMA2D -/**************************************************************************** +/*************************************************************************** + * Name: stm32_setarea + * Description: + * Entrypoint ioctl FBIOSET_AREA + ***************************************************************************/ + +static int stm32_setarea(FAR struct fb_vtable_s *vtable, + FAR const struct fb_overlayinfo_s *oinfo) +{ + DEBUGASSERT(vtable != NULL && vtable == &g_vtable.vtable && oinfo != NULL); + lcdinfo("vtable=%p, overlay=%d, x=%d, y=%d, w=%d, h=%d\n", vtable, + oinfo->overlay, oinfo->sarea.x, oinfo->sarea.y, oinfo->sarea.w, + oinfo->sarea.h); + + if (oinfo->overlay < LTDC_NLAYERS) + { + /* LTDC area is defined by the overlay size (display resolution) only */ + + return -ENOSYS; + } +# ifdef CONFIG_STM32F7_DMA2D + if (oinfo->overlay < LTDC_NOVERLAYS) + { + FAR struct stm32_ltdcdev_s *priv = (FAR struct stm32_ltdcdev_s*)vtable; + FAR struct stm32_ltdc_s * layer = &priv->layer[oinfo->overlay]; + + nxsem_wait(layer->lock); + memcpy(&layer->oinfo.sarea, &oinfo->sarea, sizeof(struct fb_area_s)); + nxsem_post(layer->lock); + + return OK; + } +# endif + + lcderr("ERROR: Returning EINVAL\n"); + return -EINVAL; +} + +/*************************************************************************** * Name: stm32_blit - * * Description: - * Copy selected area from a source layer to selected position of the - * destination layer. - * - * Input Parameters: - * dest - Reference to the destination layer - * destxpos - Selected x position of the destination layer - * destypos - Selected y position of the destination layer - * src - Reference to the source layer - * srcarea - Reference to the selected area of the source layer - * - * Returned Value: - * OK - On success - * -EINVAL - If one of the parameter invalid or if the size of the selected - * source area outside the visible area of the destination layer. - * (The visible area usually represents the display size) - * - ****************************************************************************/ + * Entrypoint ioctl FBIOSET_BLIT + ***************************************************************************/ -static int stm32_blit(FAR struct ltdc_layer_s *dest, - fb_coord_t destxpos, fb_coord_t destypos, - FAR const struct dma2d_layer_s *src, - FAR const struct ltdc_area_s *srcarea) +# ifdef CONFIG_FB_OVERLAY_BLIT +static int stm32_blit(FAR struct fb_vtable_s *vtable, + FAR const struct fb_overlayblit_s *blit) { - FAR struct stm32_layer_s *priv = (FAR struct stm32_layer_s *)dest; + DEBUGASSERT(vtable != NULL && vtable == &g_vtable.vtable && blit != NULL); + lcdinfo("vtable = %p, blit = %p\n", vtable, blit); - lcdinfo("dest = %p, destxpos = %d, destypos = %d, src = %p, srcarea = %p\n", - dest, destxpos, destypos, src, srcarea); - - if (stm32_ltdc_lvalidate(priv)) + if (blit->dest.overlay < LTDC_NOVERLAYS && blit->src.overlay < LTDC_NOVERLAYS) { - int ret; +# ifdef CONFIG_STM32F7_DMA2D + int ret; + struct fb_area_s sarea; + FAR const struct fb_area_s *darea = &blit->dest.area; + FAR struct stm32_ltdcdev_s *priv = (FAR struct stm32_ltdcdev_s*)vtable; + FAR struct stm32_ltdc_s *dlayer = &priv->layer[blit->dest.overlay]; + FAR struct stm32_ltdc_s *slayer = &priv->layer[blit->src.overlay]; - nxsem_wait(priv->state.lock); - ret = priv->dma2d->blit(priv->dma2d, destxpos, destypos, src, srcarea); - nxsem_post(priv->state.lock); + DEBUGASSERT(&dlayer->oinfo == dlayer->dma2dinfo.oinfo && + &slayer->oinfo == slayer->dma2dinfo.oinfo); + + /* DMA2D doesn't support image scale, so set to the smallest area */ + + memcpy(&sarea, &blit->src.area, sizeof(struct fb_area_s)); + + /* Check if area is within the entire overlay */ + + if (!stm32_ltdc_lvalidate(dlayer, darea) || + !stm32_ltdc_lvalidate(slayer, &sarea)) + { + return -EINVAL; + } + + sarea.w = MIN(darea->w, sarea.w); + sarea.h = MIN(darea->h, sarea.h); + + nxsem_wait(dlayer->lock); + ret = priv->dma2d->blit(&dlayer->dma2dinfo, darea->x, darea->y, + &slayer->dma2dinfo, &sarea); + nxsem_post(dlayer->lock); return ret; +# else + /* LTDC doesn't support blit transfer */ + + return -ENOSYS; +# endif } lcderr("ERROR: Returning EINVAL\n"); return -EINVAL; } -/**************************************************************************** +/*************************************************************************** * Name: stm32_blend - * * Description: - * Blends the selected area from a foreground layer with selected position - * of the background layer. Copy the result to the destination layer. Note! - * The content of the foreground and background layer is not changed. - * - * Input Parameters: - * dest - Reference to the destination layer - * destxpos - Selected x position of the destination layer - * destypos - Selected y position of the destination layer - * fore - Reference to the foreground layer - * forexpos - Selected x position of the foreground layer - * foreypos - Selected y position of the foreground layer - * back - Reference to the background layer - * backarea - Reference to the selected area of the background layer - * - * Returned Value: - * OK - On success - * -EINVAL - If one of the parameter invalid or if the size of the selected - * source area outside the visible area of the destination layer. - * (The visible area usually represents the display size) - * - ****************************************************************************/ + * Entrypoint ioctl FBIOSET_BLEND + ***************************************************************************/ -static int stm32_blend(FAR struct ltdc_layer_s *dest, - fb_coord_t destxpos, fb_coord_t destypos, - FAR const struct dma2d_layer_s *fore, - fb_coord_t forexpos, fb_coord_t foreypos, - FAR const struct dma2d_layer_s *back, - FAR const struct ltdc_area_s *backarea) +static int stm32_blend(FAR struct fb_vtable_s *vtable, + FAR const struct fb_overlayblend_s *blend) { - FAR struct stm32_layer_s *priv = (FAR struct stm32_layer_s *)dest; + DEBUGASSERT(vtable != NULL && vtable == &g_vtable.vtable && blend != NULL); + lcdinfo("vtable = %p, blend = %p\n", vtable, blend); - lcdinfo("dest=%p, destxpos=%d, destypos=%d, " - "fore=%p, forexpos=%d foreypos=%d, " - "back=%p, backarea=%p\n", - dest, destxpos, destypos, fore, forexpos, foreypos, back, backarea); - - if (stm32_ltdc_lvalidate(priv)) + if (blend->dest.overlay < LTDC_NOVERLAYS && + blend->foreground.overlay < LTDC_NOVERLAYS && + blend->background.overlay < LTDC_NOVERLAYS) { - int ret; +# ifdef CONFIG_STM32F7_DMA2D + int ret; + struct fb_area_s barea; + FAR const struct fb_area_s *darea = &blend->dest.area; + FAR const struct fb_area_s *farea = &blend->foreground.area; + FAR struct stm32_ltdcdev_s *priv = (FAR struct stm32_ltdcdev_s*)vtable; + FAR struct stm32_ltdc_s *dlayer = &priv->layer[blend->dest.overlay]; + FAR struct stm32_ltdc_s *flayer = &priv->layer[blend->foreground.overlay]; + FAR struct stm32_ltdc_s *blayer = &priv->layer[blend->background.overlay]; - nxsem_wait(priv->state.lock); - ret = priv->dma2d->blend(priv->dma2d, destxpos, destypos, - fore, forexpos, foreypos, back, backarea); - nxsem_post(priv->state.lock); + DEBUGASSERT(&dlayer->oinfo == dlayer->dma2dinfo.oinfo && + &flayer->oinfo == flayer->dma2dinfo.oinfo && + &blayer->oinfo == blayer->dma2dinfo.oinfo); + + /* DMA2D doesn't support image scale, so set to the smallest area */ + + memcpy(&barea, &blend->background.area, sizeof(struct fb_area_s)); + + /* Check if area is within the entire overlay */ + + if (!stm32_ltdc_lvalidate(dlayer, darea) || + !stm32_ltdc_lvalidate(flayer, farea) || + !stm32_ltdc_lvalidate(blayer, &barea)) + { + lcderr("ERROR: Returning EINVAL\n"); + return -EINVAL; + } + + barea.w = MIN(darea->w, barea.w); + barea.h = MIN(darea->h, barea.h); + barea.w = MIN(farea->w, barea.w); + barea.h = MIN(farea->h, barea.h); + + nxsem_wait(dlayer->lock); + ret = priv->dma2d->blend(&dlayer->dma2dinfo, darea->x, darea->y, + &flayer->dma2dinfo, farea->x, farea->y, + &blayer->dma2dinfo, &barea); + nxsem_post(dlayer->lock); return ret; +# else + /* LTDC doesn't support blend transfer */ + + return -ENOSYS; +# endif } lcderr("ERROR: Returning EINVAL\n"); return -EINVAL; } - -/**************************************************************************** - * Name: fillarea - * - * Description: - * Fill the selected area of the whole layer with a specific color. - * - * Input Parameters: - * layer - Reference to the layer structure - * area - Reference to the valid area structure select the area - * color - Color to fill the selected area. Color must be formatted - * according to the layer pixel format. - * - * Returned Value: - * OK - On success - * -EINVAL - If one of the parameter invalid or if the size of the selected - * area outside the visible area of the layer. - * - ****************************************************************************/ - -static int stm32_fillarea(FAR struct ltdc_layer_s *layer, - FAR const struct ltdc_area_s *area, - uint32_t color) -{ - FAR struct stm32_layer_s *priv = (FAR struct stm32_layer_s *)layer; - - lcdinfo("layer = %p, area = %p, color = %08x\n", layer, area, color); - - if (stm32_ltdc_lvalidate(priv)) - { - int ret; - - nxsem_wait(priv->state.lock); - ret = priv->dma2d->fillarea(priv->dma2d, area, color); - nxsem_post(priv->state.lock); - - return ret; - } - - lcderr("ERROR: Returning EINVAL\n"); - return -EINVAL; -} -#endif - -/**************************************************************************** - * Name: stm32_ltdcgetlayer - * - * Description: - * This is a non-standard framebuffer interface. - * Get the specific layer object by the layer id to enable layer hardware - * support. - * - * Input Parameters: - * lid - Layer identifier - * - * Returned Value: - * Reference to the layer control structure on success or Null if lid - * is invalid. - * - ****************************************************************************/ - -FAR struct ltdc_layer_s *stm32_ltdcgetlayer(int lid) -{ - lcdinfo("lid: %d\n", lid); - - if (lid == LTDC_LAYER_L1 || lid == LTDC_LAYER_L2) - { - return (FAR struct ltdc_layer_s *) &LAYER(lid); - } - - lcderr("ERROR: lid invalid: %d\n", lid); - return NULL; -} -#endif /* CONFIG_STM32F7_LTDC_INTERFACE */ +# endif /* CONFIG_FB_OVERLAY_BLIT */ +#endif /* CONFIG_FB_OVERLAY */ /**************************************************************************** * Name: stm32_ltdcreset @@ -3442,8 +2959,9 @@ FAR struct ltdc_layer_s *stm32_ltdcgetlayer(int lid) void stm32_ltdcreset(void) { - *((uint32_t *)(STM32_RCC_APB2RSTR)) |= RCC_APB2RSTR_LTDCRST; - *((uint32_t *)(STM32_RCC_APB2RSTR)) &= ~RCC_APB2RSTR_LTDCRST; + uint32_t regval = getreg32(STM32_RCC_APB2RSTR); + putreg32(regval | RCC_APB2RSTR_LTDCRST, STM32_RCC_APB2RSTR); + putreg32(regval & ~RCC_APB2RSTR_LTDCRST, STM32_RCC_APB2RSTR); } /**************************************************************************** @@ -3459,20 +2977,18 @@ void stm32_ltdcreset(void) int stm32_ltdcinitialize(void) { -#ifdef CONFIG_STM32F7_DMA2D - int ret; -#endif + int ret = OK; lcdinfo("Initialize LTDC driver\n"); if (g_initialized == true) { - return OK; + return ret; } /* Disable the LCD */ - stm32_lcd_enable(false); + stm32_ltdc_enable(false); lcdinfo("Configuring the LCD controller\n"); @@ -3481,22 +2997,43 @@ int stm32_ltdcinitialize(void) lcdinfo("Configure lcd periphery\n"); stm32_ltdc_periphconfig(); + /* Configure interrupts */ + + lcdinfo("Configure interrupts\n"); + stm32_ltdc_irqconfig(); + /* Configure global ltdc register */ lcdinfo("Configure global register\n"); - stm32_global_configure(); + stm32_ltdc_globalconfig(); #ifdef CONFIG_STM32F7_DMA2D /* Initialize the dma2d controller */ - ret = up_dma2dinitialize(); + ret = stm32_dma2dinitialize(); if (ret != OK) { return ret; } + + /* Bind the dma2d interface */ + + g_vtable.dma2d = stm32_dma2ddev(); + DEBUGASSERT(g_vtable.dma2d != NULL); #endif +#ifdef CONFIG_FB_CMAP + /* Cleanup clut */ + + memset(&g_redclut, 0, STM32_LTDC_NCLUT); + memset(&g_blueclut, 0, STM32_LTDC_NCLUT); + memset(&g_greenclut, 0, STM32_LTDC_NCLUT); +# ifdef CONFIG_FB_TRANSPARENCY + memset(&g_transpclut, 0, STM32_LTDC_NCLUT); +# endif +#endif /* CONFIG_FB_CMAP */ + /* Initialize ltdc layer */ lcdinfo("Initialize ltdc layer\n"); @@ -3505,13 +3042,9 @@ int stm32_ltdcinitialize(void) stm32_ltdc_linit(LTDC_LAYER_L2); #endif - /* Display layer 1 and 2 */ - - stm32_ltdc_lenable(&LAYER_L1); -#ifdef CONFIG_STM32F7_LTDC_L2 - stm32_ltdc_lenable(&LAYER_L2); +#ifdef CONFIG_STM32F7_DMA2D + stm32_ltdc_dma2dlinit(); #endif - /* Enable the backlight */ #ifdef CONFIG_STM32F7_LCD_BACKLIGHT @@ -3526,12 +3059,12 @@ int stm32_ltdcinitialize(void) /* Turn the LCD on */ lcdinfo("Enabling the display\n"); - stm32_lcd_enable(true); + stm32_ltdc_enable(true); /* Set initialized state */ g_initialized = true; - return OK; + return ret; } /**************************************************************************** @@ -3555,7 +3088,7 @@ struct fb_vtable_s *stm32_ltdcgetvplane(int vplane) if (vplane == 0) { - return (struct fb_vtable_s *)&g_vtable; + return &g_vtable.vtable; } return NULL; @@ -3582,35 +3115,13 @@ void stm32_ltdcuninitialize(void) /* Disable the LCD controller */ - stm32_lcd_enable(false); + stm32_ltdc_enable(false); /* Set initialized state */ g_initialized = false; } -/**************************************************************************** - * Name: stm32_lcdclear - * - * Description: - * This is a non-standard LCD interface just for the STM32 LTDC. Clearing the - * display in the normal way by writing a sequences of runs that covers the - * entire display can be slow. Here the display is cleared by simply setting - * all video memory to the specified color. - * - * Input Parameters: - * color - The color the clear the whole framebuffer - * - ****************************************************************************/ - -void stm32_lcdclear(nxgl_mxpixel_t color) -{ -#ifdef CONFIG_STM32F7_LTDC_L2 - stm32_ltdc_lclear(&LAYER(LTDC_LAYER_L2), color); -#endif - stm32_ltdc_lclear(&LAYER(LTDC_LAYER_L1), color); -} - /**************************************************************************** * Name: stm32_lcd_backlight * diff --git a/arch/arm/src/stm32f7/stm32_ltdc.h b/arch/arm/src/stm32f7/stm32_ltdc.h index b0d8a8706ab..92733609e06 100644 --- a/arch/arm/src/stm32f7/stm32_ltdc.h +++ b/arch/arm/src/stm32f7/stm32_ltdc.h @@ -1,7 +1,7 @@ -/************************************************************************************ - * arch/arm/src/stm32/stm32_ltdc.h +/**************************************************************************** + * arch/arm/src/stm32f7/stm32_ltdc.h * - * Copyright (C) 2013-2014 Ken Pettit. All rights reserved. + * Copyright (C) 2013-2014, 2018 Ken Pettit. All rights reserved. * Authors: Ken Pettit * Marco Krahl * @@ -32,14 +32,14 @@ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * - ************************************************************************************/ + ****************************************************************************/ #ifndef __ARCH_ARM_SRC_STM32F7_STM32_LTDC_H #define __ARCH_ARM_SRC_STM32F7_STM32_LTDC_H -/************************************************************************************ +/**************************************************************************** * Included Files - ************************************************************************************/ + ****************************************************************************/ #include @@ -49,549 +49,9 @@ #include #include -#ifdef CONFIG_STM32F7_LTDC - -/************************************************************************************ - * Public Types - ************************************************************************************/ - -struct dma2d_layer_s; /* see arch/arm/src/stm32f7/stm32_dma2d.h */ - -/* Blend mode definitions */ - -enum ltdc_blend_e -{ - LTDC_BLEND_NONE = 0, /* Disable all blend operation */ - LTDC_BLEND_ALPHA = 0x1, /* Enable alpha blending */ - LTDC_BLEND_PIXELALPHA = 0x2, /* Enable alpha blending from pixel color */ - LTDC_BLEND_COLORKEY = 0x4, /* Enable colorkey */ - LTDC_BLEND_ALPHAINV = 0x8, /* Inverse alpha blending of source */ - LTDC_BLEND_PIXELALPHAINV = 0x10 /* Invers pixel alpha blending of source */ -}; - -/* layer control definitions */ - -enum ltdc_layer_e -{ - LTDC_LAYER_OWN = 0, /* The given layer */ - LTDC_LAYER_TOP = 0x1, /* The initialized top layer */ - LTDC_LAYER_BOTTOM = 0x2, /* the initialized bottom layer */ - LTDC_LAYER_ACTIVE = 0x4, /* The current visible flip layer */ - LTDC_LAYER_INACTIVE = 0x8 /* The current invisible flip layer */ -#ifdef CONFIG_STM32F7_DMA2D - ,LTDC_LAYER_DMA2D = 0x10 /* The dma2d interface layer id */ -#endif -}; - -/* Update operation flag */ - -enum ltdc_update_e -{ - LTDC_UPDATE_NONE = 0, /* Update given layer only */ - LTDC_UPDATE_SIM = 0x1, /* Update both layer simultaneous */ - LTDC_UPDATE_FLIP = 0x2, /* Perform flip operation */ - LTDC_UPDATE_ACTIVATE = 0x4 /* Set the given layer to the active layer */ -}; - -/* sync mode definitions */ - -enum ltdc_sync_e -{ - LTDC_SYNC_NONE = 0, /* Immediately */ - LTDC_SYNC_VBLANK = 0x100, /* Upon vertical sync */ - LTDC_SYNC_WAIT = 0x200 /* Waits upon vertical sync */ -}; - -/* Definition of the visible layer position and size */ - -struct ltdc_area_s -{ - fb_coord_t xpos; /* X position in pixel */ - fb_coord_t ypos; /* Y position in pixel */ - fb_coord_t xres; /* X resolution in pixel */ - fb_coord_t yres; /* Y resolution in pixel */ -}; - -/* The layer is controlled through the following structure */ - -struct ltdc_layer_s -{ - /* Name: getvideoinfo - * - * Description: - * Get video information about the layer - * - * Parameter: - * layer - Reference to the layer control structure - * vinfo - Reference to the video info structure - * - * Returned Value: - * On success - OK - * On error - -EINVAL - */ - - int (*getvideoinfo)(FAR struct ltdc_layer_s *layer, - FAR struct fb_videoinfo_s *vinfo); - - /* Name: getplaneinfo - * - * Description: - * Get plane information about the layer - * - * Parameter: - * layer - Reference to the layer control structure - * planeno - Number of the plane - * pinfo - Reference to the plane info structure - * - * Returned Value: - * On success - OK - * On error - -EINVAL - */ - - int (*getplaneinfo)(FAR struct ltdc_layer_s *layer, int planeno, - FAR struct fb_planeinfo_s *pinfo); - - /* Name: getlid - * - * Description: - * Get a specific layer identifier. - * - * Parameter: - * layer - Reference to the layer structure - * lid - Reference to store the layer id - * flag - Operation flag describe the layer identifier - * e.g. get the current active or inactive layer. - * See LTDC_LAYER_* for possible values - * - * Returned Value: - * On success - OK - * On error - -EINVAL - */ - - int (*getlid)(FAR struct ltdc_layer_s *layer, int *lid, uint32_t flag); - -#ifdef CONFIG_FB_CMAP - /* Name: setclut - * - * Description: - * Configure layer clut (color lookup table). - * Non clut is defined during initializing. - * Clut is active during next vertical blank period. Do not need an update. - * - * Parameter: - * layer - Reference to the layer structure - * cmap - color lookup table with up the 256 entries - * enable - Enable or disable clut support (if false cmap is ignored and can - * be NULL) - * - * Returned Value: - * On success - OK - * On error - -EINVAL - */ - - int (*setclut)(FAR struct ltdc_layer_s *layer, - const FAR struct fb_cmap_s *cmap); - - /* Name: getclut - * - * Description: - * Get configured layer clut (color lookup table). - * - * Parameter: - * layer - Reference to the layer structure - * cmap - Reference to valid color lookup table accept up the 256 color - * entries - * - * Returned Value: - * On success - OK - * On error - -EINVAL - */ - - int (*getclut)(FAR struct ltdc_layer_s *layer, FAR struct fb_cmap_s *cmap); -#endif - - /* Name: setcolor - * - * Description: - * Configure layer color for the non active layer area. - * Default value during initializing: 0x00000000 - * Color is active after next update. - * - * Parameter: - * layer - Reference to the layer structure - * argb - ARGB8888 color value - * - * Returned Value: - * On success - OK - * On error - -EINVAL - */ - - int (*setcolor)(FAR struct ltdc_layer_s *layer, uint32_t argb); - - /* Name: getcolor - * - * Description: - * Get configured layer color for the non active layer area. - * - * Parameter: - * layer - Reference to the layer structure - * argb - Reference to store the ARGB8888 color value - * - * Returned Value: - * On success - OK - * On error - -EINVAL - */ - - int (*getcolor)(FAR struct ltdc_layer_s *layer, uint32_t *argb); - - /* Name: setcolorkey - * - * Description: - * Configure the layer color key (chromakey) for transparence. - * Default value during initializing: 0x00000000 - * Colorkey is active after next update. - * - * Parameter: - * layer - Reference to the layer structure - * rgb - RGB888 color key - * - * Returned Value: - * On success - OK - * On error - -EINVAL - */ - - int (*setcolorkey)(FAR struct ltdc_layer_s *layer, uint32_t rgb); - - /* Name: getcolorkey - * - * Description: - * Get the configured layer color key (chromakey) for transparence. - * - * Parameter: - * layer - Reference to the layer structure - * rgb - Reference to store the RGB888 color key - * - * Returned Value: - * On success - OK - * On error - -EINVAL - */ - - int (*getcolorkey)(FAR struct ltdc_layer_s *layer, uint32_t *rgb); - - /* Name: setalpha - * - * Description: - * Configure layer alpha value factor into blend operation. - * During the layer blend operation the source alpha value is multiplied - * with this alpha value. If the source color format doesn't support alpha - * channel (e.g. non ARGB8888) this alpha value will be used as constant - * alpha value for blend operation. - * Default value during initializing: 0xff - * Alpha is active after next update. - * - * Parameter: - * layer - Reference to the layer structure - * alpha - Alpha value - * - * Returned Value: - * On success - OK - * On error - -EINVAL - */ - - int (*setalpha)(FAR struct ltdc_layer_s *layer, uint8_t alpha); - - /* Name: getalpha - * - * Description: - * Get configured layer alpha value factor for blend operation. - * - * Parameter: - * layer - Reference to the layer structure - * alpha - Reference to store the alpha value - * - * Returned Value: - * On success - OK - * On error - -EINVAL - */ - - int (*getalpha)(FAR struct ltdc_layer_s *layer, uint8_t *alpha); - - /* Name: setblendmode - * - * Description: - * Configure blend mode of the layer. - * Default mode during initializing: LTDC_BLEND_NONE - * Blendmode is active after next update. - * - * Parameter: - * layer - Reference to the layer structure - * mode - Blend mode (see LTDC_BLEND_*) - * - * Returned Value: - * On success - OK - * On error - -EINVAL - * - * Procedure information: - * LTDC_BLEND_NONE: - * Informs the driver to disable all blend operation for the given layer. - * That means the layer is opaque. Note this has no effect on the - * colorkey settings. - * - * LTDC_BLEND_ALPHA: - * Informs the driver to enable alpha blending for the given layer. - * - * LTDC_BLEND_COLORKEY: - * Informs the driver to enable colorkeying for the given layer. - * - * LTDC_BLEND_SRCPIXELALPHA: - * Informs the driver to use the pixel alpha value of the layer instead - * the constant alpha value. This is only useful for ARGB8888 - * color format. - * - * LTDC_BLEND_DESTPIXELALPHA: - * Informs the driver to use the pixel alpha value of the subjacent layer - * instead the constant alpha value. This is only useful for ARGB8888 - * color format. - */ - - int (*setblendmode)(FAR struct ltdc_layer_s *layer, uint32_t mode); - - /* Name: getblendmode - * - * Description: - * Get configured blend mode of the layer. - * - * Parameter: - * layer - Reference to the layer structure - * mode - Reference to store the blend mode - * - * Returned Value: - * On success - OK - * On error - -EINVAL - */ - - int (*getblendmode)(FAR struct ltdc_layer_s *layer, uint32_t *mode); - - /* Name: setarea - * - * Description: - * Configure visible layer area and the reference position of the first - * pixel of the whole layer which is the first visible top left pixel in - * the active area. - * Default value during initializing: - * xpos = 0 - * ypos = 0 - * xres = display x resolution - * yres = display y resolution - * - * Area is active after next update. - * - * Parameter: - * layer - Reference to the layer control structure - * area - Reference to the valid area structure for the new active area - * srcxpos - x position of the visible pixel of the whole layer - * srcypos - y position of the visible pixel of the whole layer - * - * Returned Value: - * On success - OK - * On error - -EINVAL - * - * Procedure Information: - * If the srcxpos and srcypos unequal the xpos and ypos of the coord - * structure this acts like moving the visible area to another position on - * the screen during the next update operation. - */ - - int (*setarea)(FAR struct ltdc_layer_s *layer, - FAR const struct ltdc_area_s *area, - fb_coord_t srcxpos, - fb_coord_t srcypos); - - /* Name: getarea - * - * Description: - * Get configured visible layer area. - * - * Parameter: - * layer - Reference to the layer control structure - * area - Reference to the area structure to store the active area - * srcxpos - Reference to store the referenced x position of the whole layer - * srcypos - Reference to store the reterenced y position of the whole layer - * - * Returned Value: - * On success - OK - * On error - -EINVAL - */ - - int (*getarea)(FAR struct ltdc_layer_s *layer, - FAR struct ltdc_area_s *area, - fb_coord_t *srcxpos, - fb_coord_t *srcypos); - - /* Name: update - * - * Description: - * Update current layer settings and make changes visible. - * - * Parameter: - * layer - Reference to the layer structure - * mode - operation mode (see LTDC_UPDATE_*) - * - * Returned Value: - * OK - On success - * -EINVAL - If one of the parameter invalid - * -ECANCELED - Operation cancelled, something goes wrong - * - * Procedure information: - * LTDC_UPDATE_SIM: - * Informs the driver to update both ltdc layers simultaneously. Otherwise - * update the given layer only. - * - * LTDC_UPDATE_FLIP: - * Informs the driver to perform a flip operation. - * This only effects the ltdc layer 1 and 2 and can be useful for double - * buffering. Each flip operation changed the active layer ot the inactive - * and vice versa. In the context of the ltdc that means, the inactive layer - * is complete disabled. So the subjacent layer is the background layer - * (background color). To reactivate both layer and their settings perform - * an update without LTDC_UPDATE_FLIP flag. - * - * LTDC_UPDATE_ACTIVATE: - * Informs the driver that the given layer should be the active layer when - * the operation is complete. - * - * LTDC_SYNC_VBLANK: - * Informs the driver to update the layer upon vertical blank. Otherwise - * immediately. - */ - - int (*update)(FAR struct ltdc_layer_s *layer, uint32_t mode); - -#ifdef CONFIG_STM32F7_DMA2D - /* Name: blit - * - * Description: - * Copy selected area from a source layer to selected position of the - * destination layer. - * - * Parameter: - * dest - Reference to the destination layer - * destxpos - Selected x position of the destination layer - * destypos - Selected y position of the destination layer - * src - Reference to the source layer - * srcarea - Reference to the selected area of the source layer - * - * Returned Value: - * OK - On success - * -EINVAL - If one of the parameter invalid or if the size of the selected - * source area outside the visible area of the destination layer. - * (The visible area usually represents the display size) - */ - - int (*blit)(FAR struct ltdc_layer_s *dest, - fb_coord_t destxpos, fb_coord_t destypos, - FAR const struct dma2d_layer_s *src, - FAR const struct ltdc_area_s *srcarea); - - /* Name: blend - * - * Description: - * Blends the selected area from a foreground layer with selected position - * of the background layer. Copy the result to the destination layer. Note! - * The content of the foreground and background layer is not changed. - * - * Parameter: - * dest - Reference to the destination layer - * destxpos - Selected x position of the destination layer - * destypos - Selected y position of the destination layer - * fore - Reference to the foreground layer - * forexpos - Selected x position of the foreground layer - * foreypos - Selected y position of the foreground layer - * back - Reference to the background layer - * backarea - Reference to the selected area of the background layer - * - * Returned Value: - * OK - On success - * -EINVAL - If one of the parameter invalid or if the size of the selected - * source area outside the visible area of the destination layer. - * (The visible area usually represents the display size) - */ - - int (*blend)(FAR struct ltdc_layer_s *dest, - fb_coord_t destxpos, fb_coord_t destypos, - FAR const struct dma2d_layer_s *fore, - fb_coord_t forexpos, fb_coord_t foreypos, - FAR const struct dma2d_layer_s *back, - FAR const struct ltdc_area_s *backarea); - - /* Name: fillarea - * - * Description: - * Fill the selected area of the whole layer with a specific color. - * - * Parameter: - * layer - Reference to the layer structure - * area - Reference to the valid area structure select the area - * color - Color to fill the selected area. Color must be formatted - * according to the layer pixel format. - * - * Returned Value: - * OK - On success - * -EINVAL - If one of the parameter invalid or if the size of the selected - * area outside the visible area of the layer. - */ - - int (*fillarea)(FAR struct ltdc_layer_s *layer, - FAR const struct ltdc_area_s *area, - uint32_t color); -#endif -}; - -/* Common layer state structure for the LTDC and DMA2D controller */ - -struct stm32_ltdc_s -{ - /* Fixed settings */ - - int lid; /* Layer identifier */ - struct fb_videoinfo_s vinfo; /* Layer videoinfo */ - struct fb_planeinfo_s pinfo; /* Layer planeinfo */ - - /* Positioning */ - - struct ltdc_area_s area; /* Active layer area */ - fb_coord_t xpos; /* Reference x position */ - fb_coord_t ypos; /* Reference y position */ - - /* Coloring */ - - uint32_t color; /* Layer color definition */ -#ifdef CONFIG_FB_CMAP - uint32_t *clut; /* 32-bit aligned clut color table */ -#endif - - /* Blending */ - - uint8_t alpha; /* Layer constant alpha value */ - uint32_t colorkey; /* Layer colorkey */ - uint32_t blendmode; /* Layer blend factor */ - - /* Operation */ - - sem_t *lock; /* Ensure mutually exclusive access */ -}; - -/************************************************************************************ - * Public Data - ************************************************************************************/ - -/************************************************************************************ +/**************************************************************************** * Public Functions - ************************************************************************************/ - -/* The STM32 LTDC driver uses the common framebuffer interfaces declared in - * include/nuttx/video/fb.h. - */ + ****************************************************************************/ /************************************************************************************ * Name: stm32_ltdcreset @@ -601,9 +61,9 @@ struct stm32_ltdc_s * ************************************************************************************/ - void stm32_ltdcreset(void); +void stm32_ltdcreset(void); -/************************************************************************************ +/***************************************************************************** * Name: stm32_ltdcinitialize * * Description: @@ -612,54 +72,46 @@ struct stm32_ltdc_s * Returned Value: * OK * - ************************************************************************************/ + ****************************************************************************/ int stm32_ltdcinitialize(void); -FAR struct fb_vtable_s *stm32_ltdcgetvplane(int vplane); + +/***************************************************************************** + * Name: stm32_ltdcuninitialize + * + * Description: + * Unitialize the ltdc controller + * + ****************************************************************************/ + void stm32_ltdcuninitialize(void); -/************************************************************************************ - * Name: stm32_ltdcgetlayer +/***************************************************************************** + * Name: stm32_ltdcgetvplane * * Description: - * Get the ltdc layer structure to perform hardware layer operation + * Get video plane reference used by framebuffer interface * - * Input Parameters: - * lid - Layer identifier + * Parameter: + * vplane - Video plane * * Returned Value: - * Reference to the layer control structure on success or Null if parameter - * invalid. + * Video plane reference * - ************************************************************************************/ + ****************************************************************************/ -FAR struct ltdc_layer_s *stm32_ltdcgetlayer(int lid); +FAR struct fb_vtable_s *stm32_ltdcgetvplane(int vplane); -/************************************************************************************ - * Name: stm32_lcdclear - * - * Description: - * This is a non-standard LCD interface just for the STM32 LTDC. Clearing the - * display in the normal way by writing a sequences of runs that covers the - * entire display can be slow. Here the display is cleared by simply setting - * all video memory to the specified color. - * - ************************************************************************************/ - -void stm32_lcdclear(nxgl_mxpixel_t color); - -/************************************************************************************ +/**************************************************************************** * Name: stm32_lcd_backlight * * Description: - * If CONFIG_STM32F7_LCD_BACKLIGHT is defined, then the board-specific logic must - * provide this interface to turn the backlight on and off. + * If CONFIG_STM32F7_LCD_BACKLIGHT is defined, then the board-specific logic + * must provide this interface to turn the backlight on and off. * - ************************************************************************************/ + ****************************************************************************/ #ifdef CONFIG_STM32F7_LCD_BACKLIGHT void stm32_backlight(bool blon); #endif - -#endif /* CONFIG_STM32F7_LTDC */ #endif /* __ARCH_ARM_SRC_STM32F7_STM32_LTDC_H */