From f7905512be0a2fdf3fe435d0bce015c8b2020db3 Mon Sep 17 00:00:00 2001 From: raiden00pl Date: Wed, 12 Jul 2023 10:09:35 +0200 Subject: [PATCH] stm32h7: add LTDC support --- arch/arm/src/stm32h7/Kconfig | 227 ++ arch/arm/src/stm32h7/Make.defs | 4 + arch/arm/src/stm32h7/hardware/stm32_ltdc.h | 366 ++ .../src/stm32h7/hardware/stm32h7x3xx_pinmap.h | 208 +- arch/arm/src/stm32h7/stm32_ltdc.c | 3137 +++++++++++++++++ arch/arm/src/stm32h7/stm32_ltdc.h | 100 + arch/arm/src/stm32h7/stm32h7x3xx_rcc.c | 12 +- 7 files changed, 3949 insertions(+), 105 deletions(-) create mode 100644 arch/arm/src/stm32h7/hardware/stm32_ltdc.h create mode 100644 arch/arm/src/stm32h7/stm32_ltdc.c create mode 100644 arch/arm/src/stm32h7/stm32_ltdc.h diff --git a/arch/arm/src/stm32h7/Kconfig b/arch/arm/src/stm32h7/Kconfig index 7177fcb2ee..fc0a3b599d 100644 --- a/arch/arm/src/stm32h7/Kconfig +++ b/arch/arm/src/stm32h7/Kconfig @@ -348,6 +348,7 @@ config STM32H7_STM32H7X3XX select ARMV7M_HAVE_DCACHE select ARMV7M_HAVE_ITCM select ARMV7M_HAVE_DTCM + select STM32H7_HAVE_LTDC select STM32H7_HAVE_ETHERNET select STM32H7_HAVE_FMC select STM32H7_HAVE_GPIOF if !STM32H7_IO_CONFIG_V @@ -382,6 +383,7 @@ config STM32H7_STM32H7X5XX select ARMV7M_HAVE_DCACHE select ARMV7M_HAVE_ITCM select ARMV7M_HAVE_DTCM + select STM32H7_HAVE_LTDC select STM32H7_HAVE_ETHERNET select STM32H7_HAVE_FMC select STM32H7_HAVE_GPIOF if !STM32H7_IO_CONFIG_V @@ -399,6 +401,7 @@ config STM32H7_STM32H7X7XX select ARMV7M_HAVE_DCACHE select ARMV7M_HAVE_ITCM select ARMV7M_HAVE_DTCM + select STM32H7_HAVE_LTDC select STM32H7_HAVE_ETHERNET select STM32H7_HAVE_FMC select STM32H7_HAVE_GPIOF @@ -535,6 +538,10 @@ menu "STM32H7 Peripheral Selection" # These "hidden" settings determine whether a peripheral option is available # for the selected MCU +config STM32H7_HAVE_LTDC + bool + default n + config STM32H7_HAVE_ETHERNET bool default n @@ -822,6 +829,20 @@ config STM32H7_I2C4 endmenu # STM32H7 I2C Selection +config STM32H7_LTDC + bool "LTDC" + default n + select FB + depends on STM32H7_HAVE_LTDC + ---help--- + The STM32 LTDC is an LCD-TFT Display Controller available on + the STM32H7 devices. + It features a standard RGB888 parallel video interface (along + with HSYNC, VSYNC, etc.) for controlling TFT LCD displays. + In some STM32H7 devices the graphics signals can optionally + be output via DSI instead of the parallel interface: + See config options STM32H7_DSIHOST and STM32H7_LTDC_USE_DSI. + menu "STM32H7 SPI Selection" config STM32H7_SPI1 @@ -5433,6 +5454,212 @@ config STM32H7_ETHMAC_REGDEBUG endmenu # Ethernet MAC configuration +if STM32H7_LTDC + +menu "LTDC Configuration" + +config STM32H7_LTDC_USE_DSI + bool "Use DSI as display connection" + default n + depends on STM32H7_DSIHOST + ---help--- + Select this if your display is connected via DSI. + Deselect option if your display is connected via digital + RGB+HSYNC+VSYNC + +config STM32H7_LTDC_BACKLIGHT + bool "Backlight support" + default y + +config STM32H7_LTDC_DEFBACKLIGHT + hex "Default backlight level" + default 0xf0 + +config STM32H7_LTDC_BACKCOLOR + hex "Background color" + default 0x0 + ---help--- + This is the background color that will be used as the LTDC + background layer color. It is an RGB888 format value, + which gets written unmodified to register LTDC_BCCR. + +config STM32H7_LTDC_DITHER + bool "Dither support" + default n + +config STM32H7_LTDC_DITHER_RED + depends on STM32H7_LTDC_DITHER + int "Dither red width" + range 0 7 + default 2 + ---help--- + This is the dither red width. + +config STM32H7_LTDC_DITHER_GREEN + depends on STM32H7_LTDC_DITHER + int "Dither green width" + range 0 7 + default 2 + ---help--- + This is the dither green width. + +config STM32H7_LTDC_DITHER_BLUE + depends on STM32H7_LTDC_DITHER + int "Dither blue width" + range 0 7 + default 2 + ---help--- + This is the dither blue width. + +config STM32H7_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 + be in the SRAM or SDRAM memory region of the FMC. + +config STM32H7_LTDC_FB_SIZE + int "Framebuffer memory size (bytes)" + default 0 + ---help--- + Must be the whole size of the active LTDC layer. + +config STM32H7_LTDC_L1_CHROMAKEYEN + bool "Enable chromakey support for layer 1" + default y + +config STM32H7_LTDC_L1_CHROMAKEY + hex "Layer L1 initial chroma key" + default 0x00000000 + +config STM32H7_LTDC_L1_COLOR + hex "Layer L1 default color" + default 0x00000000 + +choice + prompt "Layer 1 color format" + default STM32H7_LTDC_L1_RGB565 + +config STM32H7_LTDC_L1_L8 + bool "8 bpp L8 (8-bit CLUT)" + depends on STM32H7_FB_CMAP + +config STM32H7_LTDC_L1_AL44 + bool "8 bpp AL44 (4-bit alpha + 4-bit CLUT)" + depends on STM32H7_FB_CMAP + +config STM32H7_LTDC_L1_AL88 + bool "16 bpp AL88 (8-bit alpha + 8-bit CLUT)" + depends on STM32H7_FB_CMAP + +config STM32H7_LTDC_L1_RGB565 + bool "16 bpp RGB 565" + depends on !STM32H7_FB_CMAP + +config STM32H7_LTDC_L1_ARGB4444 + bool "16 bpp ARGB 4444" + depends on !STM32H7_FB_CMAP + +config STM32H7_LTDC_L1_ARGB1555 + bool "16 bpp ARGB 1555" + depends on !STM32H7_FB_CMAP + +config STM32H7_LTDC_L1_RGB888 + bool "24 bpp RGB 888" + depends on !STM32H7_FB_CMAP + +config STM32H7_LTDC_L1_ARGB8888 + bool "32 bpp ARGB 8888" + depends on !STM32H7_FB_CMAP + +endchoice # Layer 1 color format + +config STM32H7_LTDC_L2 + bool "Enable Layer 2 support" + default y + +if STM32H7_LTDC_L2 + +config STM32H7_LTDC_L2_COLOR + hex "Layer L2 default color" + default 0x00000000 + +config STM32H7_LTDC_L2_CHROMAKEYEN + bool "Enable chromakey support for layer 2" + default y + +config STM32H7_LTDC_L2_CHROMAKEY + hex "Layer L2 initial chroma key" + default 0x00000000 + +choice + prompt "Layer 2 (top layer) color format" + default STM32H7_LTDC_L2_RGB565 + +config STM32H7_LTDC_L2_L8 + depends on STM32H7_LTDC_L1_L8 + bool "8 bpp L8 (8-bit CLUT)" + +config STM32H7_LTDC_L2_AL44 + depends on STM32H7_LTDC_L1_AL44 + bool "8 bpp AL44 (4-bit alpha + 4-bit CLUT)" + +config STM32H7_LTDC_L2_AL88 + depends on STM32H7_LTDC_L1_AL88 + bool "16 bpp AL88 (8-bit alpha + 8-bit CLUT)" + +config STM32H7_LTDC_L2_RGB565 + depends on STM32H7_LTDC_L1_RGB565 + bool "16 bpp RGB 565" + +config STM32H7_LTDC_L2_ARGB4444 + depends on STM32H7_LTDC_L1_ARGB4444 + bool "16 bpp ARGB 4444" + +config STM32H7_LTDC_L2_ARGB1555 + depends on STM32H7_LTDC_L1_ARGB1555 + bool "16 bpp ARGB 1555" + +config STM32H7_LTDC_L2_RGB888 + depends on STM32H7_LTDC_L1_RGB888 + bool "24 bpp RGB 888" + +config STM32H7_LTDC_L2_ARGB8888 + depends on STM32H7_LTDC_L1_ARGB8888 + bool "32 bpp ARGB 8888" + +endchoice # Layer 2 color format + +endif # STM32H7_LTDC_L2 + +config STM32H7_FB_CMAP + bool "Color map support" + default y + select FB_CMAP + ---help--- + EnablingEnablescolor map support is necessary for ltdc L8 format. + +config STM32H7_FB_TRANSPARENCY + bool "Transparency color map support" + default y + depends on STM32H7_FB_CMAP + select FB_TRANSPARENCY + ---help--- + Enables transparency color map support is necessary for ltdc L8 format. + +config STM32H7_LTDC_REGDEBUG + bool "Enable LTDC register value debug messages" + default n + ---help--- + This gives additional messages for LTDC related register values. + Additionally, you have to select "Low-level LCD Debug Features" + to enable the debug messages. + +endmenu + +endif # STM32H7_LTDC + menu "QEncoder Driver" depends on SENSORS_QENCODER depends on STM32H7_TIM1 || STM32H7_TIM2 || STM32H7_TIM3 || STM32H7_TIM4 || STM32H7_TIM5 || STM32H7_TIM8 diff --git a/arch/arm/src/stm32h7/Make.defs b/arch/arm/src/stm32h7/Make.defs index 5b38888238..8d1433e69f 100644 --- a/arch/arm/src/stm32h7/Make.defs +++ b/arch/arm/src/stm32h7/Make.defs @@ -122,6 +122,10 @@ ifeq ($(CONFIG_TIMER),y) CHIP_CSRCS += stm32_tim_lowerhalf.c endif +ifeq ($(CONFIG_STM32H7_LTDC),y) +CHIP_CSRCS += stm32_ltdc.c +endif + ifeq ($(CONFIG_USBDEV),y) CHIP_CSRCS += stm32_otgdev.c endif diff --git a/arch/arm/src/stm32h7/hardware/stm32_ltdc.h b/arch/arm/src/stm32h7/hardware/stm32_ltdc.h new file mode 100644 index 0000000000..190f63e947 --- /dev/null +++ b/arch/arm/src/stm32h7/hardware/stm32_ltdc.h @@ -0,0 +1,366 @@ +/**************************************************************************** + * arch/arm/src/stm32h7/hardware/stm32_ltdc.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32H7_HARDWARE_STM32_LTDC_H +#define __ARCH_ARM_SRC_STM32H7_HARDWARE_STM32_LTDC_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include "hardware/stm32_memorymap.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define STM32_LTDC_NCLUT 256 /* Number of entries in the CLUTs */ + +/* LCDC Register Offsets ****************************************************/ + +#define STM32_LTDC_SSCR_OFFSET 0x0008 /* LTDC Synchronization Size Config Register */ +#define STM32_LTDC_BPCR_OFFSET 0x000c /* LTDC Back Porch Configuration Register */ +#define STM32_LTDC_AWCR_OFFSET 0x0010 /* LTDC Active Width Configuration Register */ +#define STM32_LTDC_TWCR_OFFSET 0x0014 /* LTDC Total Width Configuration Register */ +#define STM32_LTDC_GCR_OFFSET 0x0018 /* LTDC Global Control Register */ + /* 0x0020 Reserved */ +#define STM32_LTDC_SRCR_OFFSET 0x0024 /* LTDC Shadow Reload Configuration Register */ + /* 0x0028 Reserved */ +#define STM32_LTDC_BCCR_OFFSET 0x002c /* LTDC Background Color Configuration Register */ + /* 0x0030 Reserved */ +#define STM32_LTDC_IER_OFFSET 0x0034 /* LTDC Interrupt Enable Register */ +#define STM32_LTDC_ISR_OFFSET 0x0038 /* LTDC Interrupt Status Register */ +#define STM32_LTDC_ICR_OFFSET 0x003c /* LTDC Interrupt Clear Register */ +#define STM32_LTDC_LIPCR_OFFSET 0x0040 /* LTDC Line Interrupt Position Config Register */ +#define STM32_LTDC_CPSR_OFFSET 0x0044 /* LTDC Current Position Status Register */ +#define STM32_LTDC_CDSR_OFFSET 0x0048 /* LTDC Current Display Status Register */ + /* 0x004c-0x0080 Reserved */ + +#define STM32_LTDC_L1CR_OFFSET 0x0084 /* LTDC Layer 1 Control Register */ +#define STM32_LTDC_L1WHPCR_OFFSET 0x0088 /* LTDC Layer 1 Window Horiz Pos Config Register */ +#define STM32_LTDC_L1WVPCR_OFFSET 0x008c /* LTDC Layer 1 Window Vert Pos Config Register */ +#define STM32_LTDC_L1CKCR_OFFSET 0x0090 /* LTDC Layer 1 Color Keying Config Register */ +#define STM32_LTDC_L1PFCR_OFFSET 0x0094 /* LTDC Layer 1 Pixel Format Configuration Register */ +#define STM32_LTDC_L1CACR_OFFSET 0x0098 /* LTDC Layer 1 Constant Alpha Config Register */ +#define STM32_LTDC_L1DCCR_OFFSET 0x009c /* LTDC Layer 1 Default Color Config Register */ +#define STM32_LTDC_L1BFCR_OFFSET 0x00a0 /* LTDC Layer 1 Blending Factors Config Register */ + /* 0x00A4-0x00A8 Reserved */ +#define STM32_LTDC_L1CFBAR_OFFSET 0x00ac /* LTDC Layer 1 Color Frame Buffer Address Register */ +#define STM32_LTDC_L1CFBLR_OFFSET 0x00b0 /* LTDC Layer 1 Color Frame Buffer Length Register */ +#define STM32_LTDC_L1CFBLNR_OFFSET 0x00b4 /* LTDC Layer 1 Color Frame Buffer Line Number Register */ + /* 0x00B8-0x00C0 Reserved */ +#define STM32_LTDC_L1CLUTWR_OFFSET 0x00c4 /* LTDC Layer 1 CLUT Write Register */ + /* 0x00C8-0x0100 Reserved */ +#define STM32_LTDC_L2CR_OFFSET 0x0104 /* LTDC Layer 2 Control Register */ +#define STM32_LTDC_L2WHPCR_OFFSET 0x0108 /* LTDC Layer 2 Window Horiz Pos Config Register */ +#define STM32_LTDC_L2WVPCR_OFFSET 0x010c /* LTDC Layer 2 Window Vert Pos Config Register */ +#define STM32_LTDC_L2CKCR_OFFSET 0x0110 /* LTDC Layer 2 Color Keying Config Register */ +#define STM32_LTDC_L2PFCR_OFFSET 0x0114 /* LTDC Layer 2 Pixel Format Configuration Register */ +#define STM32_LTDC_L2CACR_OFFSET 0x0118 /* LTDC Layer 2 Constant Alpha Config Register */ +#define STM32_LTDC_L2DCCR_OFFSET 0x011c /* LTDC Layer 2 Default Color Config Register */ +#define STM32_LTDC_L2BFCR_OFFSET 0x0120 /* LTDC Layer 2 Blending Factors Config Register */ + /* 0x0124-0x0128 Reserved */ +#define STM32_LTDC_L2CFBAR_OFFSET 0x012c /* LTDC Layer 2 Color Frame Buffer Address Register */ +#define STM32_LTDC_L2CFBLR_OFFSET 0x0130 /* LTDC Layer 2 Color Frame Buffer Length Register */ +#define STM32_LTDC_L2CFBLNR_OFFSET 0x0134 /* LTDC Layer 2 Color Frame Buffer Line Number Register */ + /* 0x0138-0x0130 Reserved */ +#define STM32_LTDC_L2CLUTWR_OFFSET 0x0144 /* LTDC Layer 2 CLUT Write Register */ + /* 0x0148-0x03ff Reserved */ + +/* LTDC Register Addresses **************************************************/ + +#define STM32_LTDC_SSCR (STM32_LTDC_BASE + STM32_LTDC_SSCR_OFFSET) +#define STM32_LTDC_BPCR (STM32_LTDC_BASE + STM32_LTDC_BPCR_OFFSET) +#define STM32_LTDC_AWCR (STM32_LTDC_BASE + STM32_LTDC_AWCR_OFFSET) +#define STM32_LTDC_TWCR (STM32_LTDC_BASE + STM32_LTDC_TWCR_OFFSET) +#define STM32_LTDC_GCR (STM32_LTDC_BASE + STM32_LTDC_GCR_OFFSET) +#define STM32_LTDC_SRCR (STM32_LTDC_BASE + STM32_LTDC_SRCR_OFFSET) +#define STM32_LTDC_BCCR (STM32_LTDC_BASE + STM32_LTDC_BCCR_OFFSET) +#define STM32_LTDC_IER (STM32_LTDC_BASE + STM32_LTDC_IER_OFFSET) +#define STM32_LTDC_ISR (STM32_LTDC_BASE + STM32_LTDC_ISR_OFFSET) +#define STM32_LTDC_ICR (STM32_LTDC_BASE + STM32_LTDC_ICR_OFFSET) +#define STM32_LTDC_LIPCR (STM32_LTDC_BASE + STM32_LTDC_LIPCR_OFFSET) +#define STM32_LTDC_CPSR (STM32_LTDC_BASE + STM32_LTDC_CPSR_OFFSET) +#define STM32_LTDC_CDSR (STM32_LTDC_BASE + STM32_LTDC_CDSR_OFFSET) + +#define STM32_LTDC_L1CR (STM32_LTDC_BASE + STM32_LTDC_L1CR_OFFSET) +#define STM32_LTDC_L1WHPCR (STM32_LTDC_BASE + STM32_LTDC_L1WHPCR_OFFSET) +#define STM32_LTDC_L1WVPCR (STM32_LTDC_BASE + STM32_LTDC_L1WVPCR_OFFSET) +#define STM32_LTDC_L1CKCR (STM32_LTDC_BASE + STM32_LTDC_L1CKCR_OFFSET) +#define STM32_LTDC_L1PFCR (STM32_LTDC_BASE + STM32_LTDC_L1PFCR_OFFSET) +#define STM32_LTDC_L1CACR (STM32_LTDC_BASE + STM32_LTDC_L1CACR_OFFSET) +#define STM32_LTDC_L1DCCR (STM32_LTDC_BASE + STM32_LTDC_L1DCCR_OFFSET) +#define STM32_LTDC_L1BFCR (STM32_LTDC_BASE + STM32_LTDC_L1BFCR_OFFSET) +#define STM32_LTDC_L1CFBAR (STM32_LTDC_BASE + STM32_LTDC_L1CFBAR_OFFSET) +#define STM32_LTDC_L1CFBLR (STM32_LTDC_BASE + STM32_LTDC_L1CFBLR_OFFSET) +#define STM32_LTDC_L1CFBLNR (STM32_LTDC_BASE + STM32_LTDC_L1CFBLNR_OFFSET) +#define STM32_LTDC_L1CLUTWR (STM32_LTDC_BASE + STM32_LTDC_L1CLUTWR_OFFSET) + +#define STM32_LTDC_L2CR (STM32_LTDC_BASE + STM32_LTDC_L2CR_OFFSET) +#define STM32_LTDC_L2WHPCR (STM32_LTDC_BASE + STM32_LTDC_L2WHPCR_OFFSET) +#define STM32_LTDC_L2WVPCR (STM32_LTDC_BASE + STM32_LTDC_L2WVPCR_OFFSET) +#define STM32_LTDC_L2CKCR (STM32_LTDC_BASE + STM32_LTDC_L2CKCR_OFFSET) +#define STM32_LTDC_L2PFCR (STM32_LTDC_BASE + STM32_LTDC_L2PFCR_OFFSET) +#define STM32_LTDC_L2CACR (STM32_LTDC_BASE + STM32_LTDC_L2CACR_OFFSET) +#define STM32_LTDC_L2DCCR (STM32_LTDC_BASE + STM32_LTDC_L2DCCR_OFFSET) +#define STM32_LTDC_L2BFCR (STM32_LTDC_BASE + STM32_LTDC_L2BFCR_OFFSET) +#define STM32_LTDC_L2CFBAR (STM32_LTDC_BASE + STM32_LTDC_L2CFBAR_OFFSET) +#define STM32_LTDC_L2CFBLR (STM32_LTDC_BASE + STM32_LTDC_L2CFBLR_OFFSET) +#define STM32_LTDC_L2CFBLNR (STM32_LTDC_BASE + STM32_LTDC_L2CFBLNR_OFFSET) +#define STM32_LTDC_L2CLUTWR (STM32_LTDC_BASE + STM32_LTDC_L2CLUTWR_OFFSET) + +/* LTDC Register Bit Definitions ********************************************/ + +/* LTDC Synchronization Size Configuration Register */ + +#define LTDC_SSCR_VSH_SHIFT (0) /* Bits 0-10: Vertical Sync Height (scan lines) */ +#define LTDC_SSCR_VSH_MASK (0x7ff << LTDC_SSCR_VSH_SHIFT) +# define LTDC_SSCR_VSH(n) ((uint32_t)(n) << LTDC_SSCR_VSH_SHIFT) +#define LTDC_SSCR_HSW_SHIFT (16) /* Bits 16-27: Horizontal Sync Width (pixel clocks) */ +#define LTDC_SSCR_HSW_MASK (0xfff << LTDC_SSCR_HSW_SHIFT) +# define LTDC_SSCR_HSW(n) ((uint32_t)(n) << LTDC_SSCR_HSW_SHIFT) + +/* LTDC Back Porch Configuration Register */ + +#define LTDC_BPCR_AVBP_SHIFT (0) /* Bits 0-10: Accumulated Vertical back porch (scan lines) */ +#define LTDC_BPCR_AVBP_MASK (0x7ff << LTDC_BPCR_AVBP_SHIFT) +# define LTDC_BPCR_AVBP(n) ((uint32_t)(n) << LTDC_BPCR_AVBP_SHIFT) +#define LTDC_BPCR_AHBP_SHIFT (16) /* Bits 16-27: Accumulated Horizontal back porch (pixel clocks) */ +#define LTDC_BPCR_AHBP_MASK (0xfff << LTDC_BPCR_AVBP_SHIFT) +# define LTDC_BPCR_AHBP(n) ((uint32_t)(n) << LTDC_BPCR_AHBP_SHIFT) + +/* LTDC Active Width Configuration Register */ + +#define LTDC_AWCR_AAH_SHIFT (0) /* Bits 0-10: Accumulated Active Height (scan lines) */ +#define LTDC_AWCR_AAH_MASK (0x7ff << LTDC_AWCR_AAH_SHIFT) +# define LTDC_AWCR_AAH(n) ((uint32_t)(n) << LTDC_AWCR_AAH_SHIFT) +#define LTDC_AWCR_AAW_SHIFT (16) /* Bits 16-27: Accumulated Active Width (pixel clocks) */ +#define LTDC_AWCR_AAW_MASK (0xfff << LTDC_AWCR_AAW_SHIFT) +# define LTDC_AWCR_AAW(n) ((uint32_t)(n) << LTDC_AWCR_AAW_SHIFT) + +/* LTDC Total Width Configuration Register */ + +#define LTDC_TWCR_TOTALH_SHIFT (0) /* Bits 0-10: Total Height (scan lines) */ +#define LTDC_TWCR_TOTALH_MASK (0x7ff << LTDC_TWCR_TOTALH_SHIFT) +# define LTDC_TWCR_TOTALH(n) ((uint32_t)(n) << LTDC_TWCR_TOTALH_SHIFT) +#define LTDC_TWCR_TOTALW_SHIFT (16) /* Bits 16-27: Total Width (pixel clocks) */ +#define LTDC_TWCR_TOTALW_MASK (0xfff << LTDC_TWCR_TOTALW_SHIFT) +# define LTDC_TWCR_TOTALW(n) ((uint32_t)(n) << LTDC_TWCR_TOTALW_SHIFT) + +/* LTDC Global Control Register */ + +#define LTDC_GCR_LTDCEN (1 << 0) /* Bit 0: LCD-TFT Controller Enable Bit */ +#define LTDC_GCR_DBW_SHIFT (4) /* Bits 4-6: Dither Blue Width */ +#define LTDC_GCR_DBW_MASK (0x7 << LTDC_GCR_DBW_SHIFT) +# define LTDC_GCR_DBW(n) ((uint32_t)(n) << LTDC_GCR_DBW_SHIFT) +#define LTDC_GCR_DGW_SHIFT (8) /* Bits 8-10: Dither Green Width */ +#define LTDC_GCR_DGW_MASK (0x7 << LTDC_GCR_DGW_SHIFT) +# define LTDC_GCR_DGW(n) ((uint32_t)(n) << LTDC_GCR_DGW_SHIFT) +#define LTDC_GCR_DRW_SHIFT (12) /* Bits 12-14: Dither Red Width */ +#define LTDC_GCR_DRW_MASK (0x7 << LTDC_GCR_DRW_SHIFT) +# define LTDC_GCR_DRW(n) ((uint32_t)(n) << LTDC_GCR_DRW_SHIFT) +#define LTDC_GCR_DEN (1 << 16) /* Bit 16: Dither Enable */ +#define LTDC_GCR_PCPOL (1 << 28) /* Bit 28: Pixel Clock Polarity */ +#define LTDC_GCR_DEPOL (1 << 29) /* Bit 29: Not(Data Enable) Polarity */ +#define LTDC_GCR_VSPOL (1 << 30) /* Bit 30: Vertical Sync Polarity */ +#define LTDC_GCR_HSPOL (1 << 31) /* Bit 31: Horizontal Sync Polarity */ + +/* LTDC Shadow Reload Configuration Register */ + +#define LTDC_SRCR_IMR (1 << 0) /* Bit 0: Immediate Reload */ +#define LTDC_SRCR_VBR (1 << 1) /* Bit 1: Vertical Blanking Reload */ + +/* LTDC Background Color Configuration Register */ + +#define LTDC_BCCR_BCBLUE_SHIFT (0) /* Bits 0-7: Background Color Blue Value */ +#define LTDC_BCCR_BCBLUE_MASK (0xff << LTDC_BCCR_BCBLUE_SHIFT) +# define LTDC_BCCR_BCBLUE(n) ((uint32_t)(n) << LTDC_BCCR_BCBLUE_SHIFT) +#define LTDC_BCCR_BCGREEN_SHIFT (8) /* Bits 8-15: Background Color Green Value */ +#define LTDC_BCCR_BCGREEN_MASK (0xff << LTDC_BCCR_BCGREEN_SHIFT) +# define LTDC_BCCR_BCGREEN(n) ((uint32_t)(n) << LTDC_BCCR_BCGREEN_SHIFT) +#define LTDC_BCCR_BCRED_SHIFT (16) /* Bits 16-23: Background Color Red Value */ +#define LTDC_BCCR_BCRED_MASK (0xff << LTDC_BCCR_BCRED_SHIFT) +# define LTDC_BCCR_BCRED(n) ((uint32_t)(n) << LTDC_BCCR_BCRED_SHIFT) + +/* LTDC Interrupt Enable Register */ + +#define LTDC_IER_LIE (1 << 0) /* Bit 0: Line Interrupt Enable */ +#define LTDC_IER_FUIE (1 << 1) /* Bit 1: FIFO Underrun Interrupt Enable */ +#define LTDC_IER_TERRIE (1 << 2) /* Bit 2: Transfer Error Interrupt Enable */ +#define LTDC_IER_RRIE (1 << 3) /* Bit 3: Register Reload Interrupt Enable */ + +/* LTDC Interrupt Status Register */ + +#define LTDC_ISR_LIF (1 << 0) /* Bit 0: Line Interrupt Flag */ +#define LTDC_ISR_FUIF (1 << 1) /* Bit 1: FIFO Underrun Interrupt Flag */ +#define LTDC_IER_TERRIF (1 << 2) /* Bit 2: Transfer Error Interrupt Flag */ +#define LTDC_ISR_RRIF (1 << 3) /* Bit 3: Register Reload Interrupt Flag */ + +/* LTDC Interrupt Clear Register */ + +#define LTDC_ICR_CLIF (1 << 0) /* Bit 0: Clear Line Interrupt Flag */ +#define LTDC_ICR_CFUIF (1 << 1) /* Bit 1: Clear FIFO Underrun Interrupt Flag */ +#define LTDC_ICR_CTERRIF (1 << 2) /* Bit 2: Clear Transfer Error Interrupt Flag */ +#define LTDC_ICR_CRRIF (1 << 3) /* Bit 3: Clear Register Reload Interrupt Flag */ + +/* LTDC Line Interrupt Posittion Configuration Register */ + +#define LTDC_LIPCR_LIPOS_SHIFT (0) /* Bits 0-10: Line Interrupt Position */ +#define LTDC_LIPCR_LIPOS_MASK (0x7ff << LTDC_LIPCR_LIPOS_SHIFT) +# define LTDC_LIPCR_LIPOS(n) ((uint32_t)(n) << LTDC_LIPCR_LIPOS_SHIFT) + +/* LTDC Current Position Status Register */ + +#define LTDC_CPSR_CYPOS_SHIFT (0) /* Bits 0-15: Current Y Position */ +#define LTDC_CPSR_CYPOS_MASK (0xFFFF << LTDC_CPSR_CYPOS_SHIFT) +# define LTDC_CPSR_CYPOS(n) ((uint32_t)(n) << LTDC_CPSR_CYPOS_SHIFT) +#define LTDC_CPSR_CXPOS_SHIFT (16) /* Bits 15-31: Current X Position */ +#define LTDC_CPSR_CXPOS_MASK (0xFFFF << LTDC_CPSR_CXPOS_SHIFT) +# define LTDC_CPSR_CXPOS(n) ((uint32_t)(n) << LTDC_CPSR_CXPOS_SHIFT) + +/* LTDC Current Display Status Register */ + +#define LTDC_CDSR_VDES (1 << 0) /* Bit 0: Vertical Data Enable display Status */ +#define LTDC_CDSR_HDES (1 << 1) /* Bit 1: Horizontal Data Enable display Status */ +#define LTDC_CDSR_VSYNCS (1 << 2) /* Bit 2: Vertical Sync display Status */ +#define LTDC_CDSR_HSYNCS (1 << 3) /* Bit 3: Horizontal Sync display Status */ + +/* LTDC Layer x Control Register */ + +#define LTDC_LXCR_LEN (1 << 0) /* Bit 0: Layer Enable */ +#define LTDC_LXCR_COLKEN (1 << 1) /* Bit 1: Color Keying Enable */ +#define LTDC_LXCR_CLUTEN (1 << 4) /* Bit 4: Color Look-Up Table Enable */ + +/* LTDC Layer x Window Horizontal Position Configuration Register */ + +#define LTDC_LXWHPCR_WHSTPOS_SHIFT (0) /* Bits 0-11: Window Horizontal Start Position */ +#define LTDC_LXWHPCR_WHSTPOS_MASK (0xfff << LTDC_LXWHPCR_WHSTPOS_SHIFT) +# define LTDC_LXWHPCR_WHSTPOS(n) ((uint32_t)(n) << LTDC_LXWHPCR_WHSTPOS_SHIFT) +#define LTDC_LXWHPCR_WHSPPOS_SHIFT (16) /* Bits 16-27: Window Horizontal Stop Position */ +#define LTDC_LXWHPCR_WHSPPOS_MASK (0xfff << LTDC_LXWHPCR_WHSPPOS_SHIFT) +# define LTDC_LXWHPCR_WHSPPOS(n) ((uint32_t)(n) << LTDC_LXWHPCR_WHSPPOS_SHIFT) + +/* LTDC Layer x Window Vertical Position Configuration Register */ + +#define LTDC_LXWVPCR_WVSTPOS_SHIFT (0) /* Bits 0-10: Window Vertical Start Position */ +#define LTDC_LXWVPCR_WVSTPOS_MASK (0x7ff << LTDC_LXWVPCR_WVSTPOS_SHIFT) +# define LTDC_LXWVPCR_WVSTPOS(n) ((uint32_t)(n) << LTDC_LXWVPCR_WVSTPOS_SHIFT) +#define LTDC_LXWVPCR_WVSPPOS_SHIFT (16) /* Bits 16-26: Window Vertical Stop Position */ +#define LTDC_LXWVPCR_WVSPPOS_MASK (0x7ff << LTDC_LXWVPCR_WVSPPOS_SHIFT) +# define LTDC_LXWVPCR_WVSPPOS(n) ((uint32_t)(n) << LTDC_LXWVPCR_WVSPPOS_SHIFT) + +/* LTDC Layer x Color Keying Configuration Register */ + +#define LTDC_LXCKCR_CKBLUE_SHIFT (0) /* Bits 0-7: Color Key Blue Value */ +#define LTDC_LXCKCR_CKBLUE_MASK (0xff << LTDC_LXCKCR_CKBLUE_SHIFT) +# define LTDC_LXCKCR_CKBLUE(n) ((uint32_t)(n) << LTDC_LXCKCR_CKBLUE_SHIFT) +#define LTDC_LXCKCR_CKGREEN_SHIFT (8) /* Bits 8-15: Color Key Green Value */ +#define LTDC_LXCKCR_CKGREEN_MASK (0xff << LTDC_LXCKCR_CKGREEN_SHIFT) +# define LTDC_LXCKCR_CKGREEN(n) ((uint32_t)(n) << LTDC_LXCKCR_CKGREEN_SHIFT) +#define LTDC_LXCKCR_CKRED_SHIFT (16) /* Bits 16-23: Color Key Red Value */ +#define LTDC_LXCKCR_CKRED_MASK (0xff << LTDC_LXCKCR_CKRED_SHIFT) +# define LTDC_LXCKCR_CKRED(n) ((uint32_t)(n) << LTDC_LXCKCR_CKRED_SHIFT) + +/* LTDC Layer x Pixel Format Configuration Register */ + +#define LTDC_LXPFCR_PF_SHIFT (0) /* Bits 0-2: Pixel Format */ +#define LTDC_LXPFCR_PF_MASK (0x7 << LTDC_LXPFCR_PF_SHIFT) +# define LTDC_LXPFCR_PF(n) ((uint32_t)(n) << LTDC_LXPFCR_PF_SHIFT) + +#define LTDC_PF_ARGB8888 0 +#define LTDC_PF_RGB888 1 +#define LTDC_PF_RGB565 2 +#define LTDC_PF_ARGB1555 3 +#define LTDC_PF_ARGB4444 4 +#define LTDC_PF_L8 5 /* 8-bit Luninance (CLUT lookup) */ +#define LTDC_PF_AL44 6 /* 4-bit Alpha, 4-bit Luminance */ +#define LTDC_PF_AL88 7 /* 8-bit Alpha, 8-bit Luminance */ + +/* LTDC Layer x Constant Alpha Configuration Register */ + +#define LTDC_LXCACR_CONSTA_SHIFT (0) /* Bits 0-7: Constant Alpha */ +#define LTDC_LXCACR_CONSTA_MASK (0x7 << LTDC_LXCACR_CONSTA_SHIFT) +# define LTDC_LXCACR_CONSTA(n) ((uint32_t)(n) << LTDC_LXCACR_CONSTA_SHIFT) + +/* LTDC Layer x Default Color Configuration Register */ + +#define LTDC_LXDCCR_DCBLUE_SHIFT (0) /* Bits 0-7: Default Color Blue Value */ +#define LTDC_LXDCCR_DCBLUE_MASK (0xff << LTDC_LXDCCR_DCBLUE_SHIFT) +# define LTDC_LXDCCR_DCBLUE(n) ((uint32_t)(n) << LTDC_LXDCCR_DCBLUE_SHIFT) +#define LTDC_LXDCCR_DCGREEN_SHIFT (8) /* Bits 8-15: Default Color Green Value */ +#define LTDC_LXDCCR_DCGREEN_MASK (0xff << LTDC_LXDCCR_DCGREEN_SHIFT) +# define LTDC_LXDCCR_DCGREEN(n) ((uint32_t)(n) << LTDC_LXDCCR_DCGREEN_SHIFT) +#define LTDC_LXDCCR_DCRED_SHIFT (16) /* Bits 16-23: Default Color Red Value */ +#define LTDC_LXDCCR_DCRED_MASK (0xff << LTDC_LXDCCR_DCRED_SHIFT) +# define LTDC_LXDCCR_DCRED(n) ((uint32_t)(n) << LTDC_LXDCCR_DCRED_SHIFT) +#define LTDC_LXDCCR_DCALPHA_SHIFT (24) /* Bits 24-31: Default Color Alpha Value */ +#define LTDC_LXDCCR_DCALPHA_MASK (0xff << LTDC_LXDCCR_DCALPHA_SHIFT) +# define LTDC_LXDCCR_DCALPHA(n) ((uint32_t)(n) << LTDC_LXDCCR_DCALPHA_SHIFT) + +/* LTDC Layer x Blending Factors Configuration Register */ + +#define LTDC_LXBFCR_BF2_SHIFT (0) /* Bits 0-2: Blending Factor 2 */ +#define LTDC_LXBFCR_BF2_MASK (0x7 << LTDC_LXBFCR_BF2_SHIFT) +# define LTDC_LXBFCR_BF2(n) ((uint32_t)(n) << LTDC_LXBFCR_BF2_SHIFT) +#define LTDC_LXBFCR_BF1_SHIFT (8) /* Bits 8-10: Blending Factor 1 */ +#define LTDC_LXBFCR_BF1_MASK (0x7 << LTDC_LXBFCR_BF1_SHIFT) +# define LTDC_LXBFCR_BF1(n) ((uint32_t)(n) << LTDC_LXBFCR_BF1_SHIFT) + +#define LTDC_BF1_CONST_ALPHA 0x04 /* Constant Alpha */ +#define LTDC_BF1_PIXEL_ALPHA 0x06 /* Pixel Alpha x Constant Alpha */ +#define LTDC_BF2_CONST_ALPHA 0x05 /* Constant Alpha */ +#define LTDC_BF2_PIXEL_ALPHA 0x07 /* Pixel Alpha x Constant Alpha */ + +/* LTDC Layer x Color Frame Buffer Length Configuration Register */ + +#define LTDC_LXCFBLR_CFBLL_SHIFT (0) /* Bits 0-12: Color Frame Buffer Line Length */ +#define LTDC_LXCFBLR_CFBLL_MASK (0x1fff << LTDC_LXCFBLR_CFBLL_SHIFT) +# define LTDC_LXCFBLR_CFBLL(n) ((uint32_t)(n) << LTDC_LXCFBLR_CFBLL_SHIFT) +#define LTDC_LXCFBLR_CFBP_SHIFT (16) /* Bits 16-28: Color Frame Buffer Pitch */ +#define LTDC_LXCFBLR_CFBP_MASK (0x1fff << LTDC_LXCFBLR_CFBP_SHIFT) +# define LTDC_LXCFBLR_CFBP(n) ((uint32_t)(n) << LTDC_LXCFBLR_CFBP_SHIFT) + +/* LTDC Layer x Color Frame Buffer Line Number Register */ + +#define LTDC_LXCFBLNR_LN_SHIFT (0) /* Bits 0-10: Color Frame Buffer Line Number */ +#define LTDC_LXCFBLNR_LN_MASK (0x7ff << LTDC_LXCFBLNR_LN_SHIFT) +# define LTDC_LXCFBLNR_LN(n) ((uint32_t)(n) << LTDC_LXCFBLNR_LN_SHIFT) + +/* LTDC Layer x CLUT Write Register */ + +#define LTDC_LXCLUTWR_BLUE_SHIFT (0) /* Bits 0-7: Default Color Blue Value */ +#define LTDC_LXCLUTWR_BLUE_MASK (0xff << LTDC_LXCLUTWR_BLUE_SHIFT) +# define LTDC_LXCLUTWR_BLUE(n) ((uint32_t)(n) << LTDC_LXCLUTWR_BLUE_SHIFT) +#define LTDC_LXCLUTWR_GREEN_SHIFT (8) /* Bits 8-15: Default Color Green Value */ +#define LTDC_LXCLUTWR_GREEN_MASK (0xff << LTDC_LXCLUTWR_GREEN_SHIFT) +# define LTDC_LXCLUTWR_GREEN(n) ((uint32_t)(n) << LTDC_LXCLUTWR_GREEN_SHIFT) +#define LTDC_LXCLUTWR_RED_SHIFT (16) /* Bits 16-23: Default Color Red Value */ +#define LTDC_LXCLUTWR_RED_MASK (0xff << LTDC_LXCLUTWR_RED_SHIFT) +# define LTDC_LXCLUTWR_RED(n) ((uint32_t)(n) << LTDC_LXCLUTWR_RED_SHIFT) +#define LTDC_LXCLUTWR_CLUTADD_SHIFT (24) /* Bits 24-31: CLUT Address */ +#define LTDC_LXCLUTWR_CLUTADD_MASK (0xff << LTDC_LXCLUTWR_CLUTADD_SHIFT) +# define LTDC_LXCLUTWR_CLUTADD(n) ((uint32_t)(n) << LTDC_LXCLUTWR_CLUTADD_SHIFT) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +#endif /* __ARCH_ARM_SRC_STM32H7_HARDWARE_STM32_LTDC_H */ diff --git a/arch/arm/src/stm32h7/hardware/stm32h7x3xx_pinmap.h b/arch/arm/src/stm32h7/hardware/stm32h7x3xx_pinmap.h index a483a2157d..ae0c89d9d0 100644 --- a/arch/arm/src/stm32h7/hardware/stm32h7x3xx_pinmap.h +++ b/arch/arm/src/stm32h7/hardware/stm32h7x3xx_pinmap.h @@ -570,116 +570,116 @@ /* LCD-TFT Display Controller (LTDC) */ -#define GPIO_LCD_B0_1 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN4) -#define GPIO_LCD_B0_2 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN14) -#define GPIO_LCD_B0_3 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTJ|GPIO_PIN12) -#define GPIO_LCD_B1_1 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN10) -#define GPIO_LCD_B1_2 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN12) -#define GPIO_LCD_B1_3 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTJ|GPIO_PIN13) -#define GPIO_LCD_B2_1 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN9) -#define GPIO_LCD_B2_2 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN6) -#define GPIO_LCD_B2_3 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN10) -#define GPIO_LCD_B2_4 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTJ|GPIO_PIN14) -#define GPIO_LCD_B2_5 (GPIO_ALT|GPIO_AF9|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN3) -#define GPIO_LCD_B3_1 (GPIO_ALT|GPIO_AF13|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN8) -#define GPIO_LCD_B3_2 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN10) -#define GPIO_LCD_B3_3 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN11) -#define GPIO_LCD_B3_4 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTJ|GPIO_PIN15) -#define GPIO_LCD_B4_1 (GPIO_ALT|GPIO_AF12|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN10) -#define GPIO_LCD_B4_2 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN12) -#define GPIO_LCD_B4_3 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN4) -#define GPIO_LCD_B4_4 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTK|GPIO_PIN3) -#define GPIO_LCD_B4_5 (GPIO_ALT|GPIO_AF9|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN12) -#define GPIO_LCD_B4_6 (GPIO_ALT|GPIO_AF9|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTJ|GPIO_PIN13) -#define GPIO_LCD_B5_1 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN3) -#define GPIO_LCD_B5_2 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN5) -#define GPIO_LCD_B5_3 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTK|GPIO_PIN4) -#define GPIO_LCD_B6_1 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN8) -#define GPIO_LCD_B6_2 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN6) -#define GPIO_LCD_B6_3 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTK|GPIO_PIN5) -#define GPIO_LCD_B7_1 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN9) -#define GPIO_LCD_B7_2 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN7) -#define GPIO_LCD_B7_3 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTK|GPIO_PIN6) +#define GPIO_LTDC_B0_1 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN4) +#define GPIO_LTDC_B0_2 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN14) +#define GPIO_LTDC_B0_3 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTJ|GPIO_PIN12) +#define GPIO_LTDC_B1_1 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN10) +#define GPIO_LTDC_B1_2 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN12) +#define GPIO_LTDC_B1_3 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTJ|GPIO_PIN13) +#define GPIO_LTDC_B2_1 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN9) +#define GPIO_LTDC_B2_2 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN6) +#define GPIO_LTDC_B2_3 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN10) +#define GPIO_LTDC_B2_4 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTJ|GPIO_PIN14) +#define GPIO_LTDC_B2_5 (GPIO_ALT|GPIO_AF9|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN3) +#define GPIO_LTDC_B3_1 (GPIO_ALT|GPIO_AF13|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN8) +#define GPIO_LTDC_B3_2 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN10) +#define GPIO_LTDC_B3_3 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN11) +#define GPIO_LTDC_B3_4 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTJ|GPIO_PIN15) +#define GPIO_LTDC_B4_1 (GPIO_ALT|GPIO_AF12|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN10) +#define GPIO_LTDC_B4_2 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN12) +#define GPIO_LTDC_B4_3 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN4) +#define GPIO_LTDC_B4_4 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTK|GPIO_PIN3) +#define GPIO_LTDC_B4_5 (GPIO_ALT|GPIO_AF9|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN12) +#define GPIO_LTDC_B4_6 (GPIO_ALT|GPIO_AF9|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTJ|GPIO_PIN13) +#define GPIO_LTDC_B5_1 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN3) +#define GPIO_LTDC_B5_2 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN5) +#define GPIO_LTDC_B5_3 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTK|GPIO_PIN4) +#define GPIO_LTDC_B6_1 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN8) +#define GPIO_LTDC_B6_2 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN6) +#define GPIO_LTDC_B6_3 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTK|GPIO_PIN5) +#define GPIO_LTDC_B7_1 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN9) +#define GPIO_LTDC_B7_2 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN7) +#define GPIO_LTDC_B7_3 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTK|GPIO_PIN6) -#define GPIO_LCD_CLK_1 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN14) -#define GPIO_LCD_CLK_2 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN7) -#define GPIO_LCD_CLK_3 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN14) +#define GPIO_LTDC_CLK_1 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN14) +#define GPIO_LTDC_CLK_2 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN7) +#define GPIO_LTDC_CLK_3 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN14) -#define GPIO_LCD_DE_1 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN13) -#define GPIO_LCD_DE_2 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTF|GPIO_PIN10) -#define GPIO_LCD_DE_3 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTK|GPIO_PIN7) +#define GPIO_LTDC_DE_1 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN13) +#define GPIO_LTDC_DE_2 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTF|GPIO_PIN10) +#define GPIO_LTDC_DE_3 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTK|GPIO_PIN7) -#define GPIO_LCD_G0_1 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN1) -#define GPIO_LCD_G0_2 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN5) -#define GPIO_LCD_G0_3 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTJ|GPIO_PIN7) -#define GPIO_LCD_G1_1 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN0) -#define GPIO_LCD_G1_2 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN6) -#define GPIO_LCD_G1_3 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTJ|GPIO_PIN8) -#define GPIO_LCD_G2_1 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN6) -#define GPIO_LCD_G2_2 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN13) -#define GPIO_LCD_G2_3 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTJ|GPIO_PIN9) -#define GPIO_LCD_G2_4 (GPIO_ALT|GPIO_AF9|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN15) -#define GPIO_LCD_G3_1 (GPIO_ALT|GPIO_AF10|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN9) -#define GPIO_LCD_G3_2 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN11) -#define GPIO_LCD_G3_3 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN14) -#define GPIO_LCD_G3_4 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTJ|GPIO_PIN10) -#define GPIO_LCD_G3_5 (GPIO_ALT|GPIO_AF9|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN10) -#define GPIO_LCD_G3_6 (GPIO_ALT|GPIO_AF9|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTJ|GPIO_PIN12) -#define GPIO_LCD_G4_1 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN10) -#define GPIO_LCD_G4_2 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN15) -#define GPIO_LCD_G4_3 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN4) -#define GPIO_LCD_G4_4 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTJ|GPIO_PIN11) -#define GPIO_LCD_G5_1 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN11) -#define GPIO_LCD_G5_2 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN0) -#define GPIO_LCD_G5_3 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTK|GPIO_PIN0) -#define GPIO_LCD_G5_4 (GPIO_ALT|GPIO_AF9|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN4) -#define GPIO_LCD_G6_1 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN7) -#define GPIO_LCD_G6_2 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN1) -#define GPIO_LCD_G6_3 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTK|GPIO_PIN1) -#define GPIO_LCD_G6_4 (GPIO_ALT|GPIO_AF9|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN11) -#define GPIO_LCD_G7_1 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN3) -#define GPIO_LCD_G7_2 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN8) -#define GPIO_LCD_G7_3 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN2) -#define GPIO_LCD_G7_4 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTK|GPIO_PIN2) +#define GPIO_LTDC_G0_1 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN1) +#define GPIO_LTDC_G0_2 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN5) +#define GPIO_LTDC_G0_3 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTJ|GPIO_PIN7) +#define GPIO_LTDC_G1_1 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN0) +#define GPIO_LTDC_G1_2 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN6) +#define GPIO_LTDC_G1_3 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTJ|GPIO_PIN8) +#define GPIO_LTDC_G2_1 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN6) +#define GPIO_LTDC_G2_2 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN13) +#define GPIO_LTDC_G2_3 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTJ|GPIO_PIN9) +#define GPIO_LTDC_G2_4 (GPIO_ALT|GPIO_AF9|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN15) +#define GPIO_LTDC_G3_1 (GPIO_ALT|GPIO_AF10|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN9) +#define GPIO_LTDC_G3_2 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN11) +#define GPIO_LTDC_G3_3 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN14) +#define GPIO_LTDC_G3_4 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTJ|GPIO_PIN10) +#define GPIO_LTDC_G3_5 (GPIO_ALT|GPIO_AF9|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN10) +#define GPIO_LTDC_G3_6 (GPIO_ALT|GPIO_AF9|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTJ|GPIO_PIN12) +#define GPIO_LTDC_G4_1 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN10) +#define GPIO_LTDC_G4_2 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN15) +#define GPIO_LTDC_G4_3 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN4) +#define GPIO_LTDC_G4_4 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTJ|GPIO_PIN11) +#define GPIO_LTDC_G5_1 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN11) +#define GPIO_LTDC_G5_2 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN0) +#define GPIO_LTDC_G5_3 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTK|GPIO_PIN0) +#define GPIO_LTDC_G5_4 (GPIO_ALT|GPIO_AF9|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN4) +#define GPIO_LTDC_G6_1 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN7) +#define GPIO_LTDC_G6_2 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN1) +#define GPIO_LTDC_G6_3 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTK|GPIO_PIN1) +#define GPIO_LTDC_G6_4 (GPIO_ALT|GPIO_AF9|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN11) +#define GPIO_LTDC_G7_1 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN3) +#define GPIO_LTDC_G7_2 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN8) +#define GPIO_LTDC_G7_3 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN2) +#define GPIO_LTDC_G7_4 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTK|GPIO_PIN2) -#define GPIO_LCD_HSYNC_1 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN6) -#define GPIO_LCD_HSYNC_2 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN10) -#define GPIO_LCD_HSYNC_3 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN12) +#define GPIO_LTDC_HSYNC_1 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN6) +#define GPIO_LTDC_HSYNC_2 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN10) +#define GPIO_LTDC_HSYNC_3 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN12) -#define GPIO_LCD_R0_1 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN13) -#define GPIO_LCD_R0_2 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN2) -#define GPIO_LCD_R0_3 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN15) -#define GPIO_LCD_R1_1 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN2) -#define GPIO_LCD_R1_2 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN3) -#define GPIO_LCD_R1_3 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTJ|GPIO_PIN0) -#define GPIO_LCD_R2_1 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN1) -#define GPIO_LCD_R2_2 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN10) -#define GPIO_LCD_R2_3 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN8) -#define GPIO_LCD_R2_4 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTJ|GPIO_PIN1) -#define GPIO_LCD_R3_1 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN9) -#define GPIO_LCD_R3_2 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTJ|GPIO_PIN2) -#define GPIO_LCD_R3_3 (GPIO_ALT|GPIO_AF9|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN0) -#define GPIO_LCD_R4_1 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN11) -#define GPIO_LCD_R4_2 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN5) -#define GPIO_LCD_R4_3 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN10) -#define GPIO_LCD_R4_4 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTJ|GPIO_PIN3) -#define GPIO_LCD_R5_1 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN12) -#define GPIO_LCD_R5_2 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN9) -#define GPIO_LCD_R5_3 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN0) -#define GPIO_LCD_R5_4 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN11) -#define GPIO_LCD_R5_5 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTJ|GPIO_PIN4) -#define GPIO_LCD_R6_1 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN8) -#define GPIO_LCD_R6_2 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN12) -#define GPIO_LCD_R6_3 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTJ|GPIO_PIN5) -#define GPIO_LCD_R6_4 (GPIO_ALT|GPIO_AF9|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN1) -#define GPIO_LCD_R7_1 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN15) -#define GPIO_LCD_R7_2 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN6) -#define GPIO_LCD_R7_3 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTJ|GPIO_PIN6) -#define GPIO_LCD_R7_4 (GPIO_ALT|GPIO_AF9|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTJ|GPIO_PIN0) +#define GPIO_LTDC_R0_1 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN13) +#define GPIO_LTDC_R0_2 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN2) +#define GPIO_LTDC_R0_3 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN15) +#define GPIO_LTDC_R1_1 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN2) +#define GPIO_LTDC_R1_2 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN3) +#define GPIO_LTDC_R1_3 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTJ|GPIO_PIN0) +#define GPIO_LTDC_R2_1 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN1) +#define GPIO_LTDC_R2_2 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN10) +#define GPIO_LTDC_R2_3 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN8) +#define GPIO_LTDC_R2_4 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTJ|GPIO_PIN1) +#define GPIO_LTDC_R3_1 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN9) +#define GPIO_LTDC_R3_2 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTJ|GPIO_PIN2) +#define GPIO_LTDC_R3_3 (GPIO_ALT|GPIO_AF9|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN0) +#define GPIO_LTDC_R4_1 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN11) +#define GPIO_LTDC_R4_2 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN5) +#define GPIO_LTDC_R4_3 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN10) +#define GPIO_LTDC_R4_4 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTJ|GPIO_PIN3) +#define GPIO_LTDC_R5_1 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN12) +#define GPIO_LTDC_R5_2 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN9) +#define GPIO_LTDC_R5_3 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN0) +#define GPIO_LTDC_R5_4 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN11) +#define GPIO_LTDC_R5_5 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTJ|GPIO_PIN4) +#define GPIO_LTDC_R6_1 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN8) +#define GPIO_LTDC_R6_2 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN12) +#define GPIO_LTDC_R6_3 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTJ|GPIO_PIN5) +#define GPIO_LTDC_R6_4 (GPIO_ALT|GPIO_AF9|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN1) +#define GPIO_LTDC_R7_1 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN15) +#define GPIO_LTDC_R7_2 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN6) +#define GPIO_LTDC_R7_3 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTJ|GPIO_PIN6) +#define GPIO_LTDC_R7_4 (GPIO_ALT|GPIO_AF9|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTJ|GPIO_PIN0) -#define GPIO_LCD_VSYNC_1 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN4) -#define GPIO_LCD_VSYNC_2 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN13) -#define GPIO_LCD_VSYNC_3 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN9) +#define GPIO_LTDC_VSYNC_1 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN4) +#define GPIO_LTDC_VSYNC_2 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN13) +#define GPIO_LTDC_VSYNC_3 (GPIO_ALT|GPIO_AF14|GPIO_PULLUP|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN9) /* Low Power Timer */ diff --git a/arch/arm/src/stm32h7/stm32_ltdc.c b/arch/arm/src/stm32h7/stm32_ltdc.c new file mode 100644 index 0000000000..62082c3495 --- /dev/null +++ b/arch/arm/src/stm32h7/stm32_ltdc.c @@ -0,0 +1,3137 @@ +/**************************************************************************** + * arch/arm/src/stm32h7/stm32_ltdc.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/* References: + * STM32F429 Technical Reference Manual and Data Sheet + */ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "arm_internal.h" + +#include "hardware/stm32_ltdc.h" +#include "stm32_rcc.h" +#include "stm32_gpio.h" +#include "stm32_ltdc.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Register definition ******************************************************/ + +#ifndef BOARD_LTDC_WIDTH +# error BOARD_LTDC_WIDTH must be defined in the board.h header file +#endif + +#ifndef BOARD_LTDC_HEIGHT +# error BOARD_LTDC_HEIGHT must be defined in the board.h header file +#endif + +#define STM32_LTDC_HEIGHT BOARD_LTDC_HEIGHT +#define STM32_LTDC_WIDTH BOARD_LTDC_WIDTH + +/* Configure LTDC register */ + +/* LTDC_LxWHPCR register */ + +#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) + +/* 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) + +/* 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) + +/* 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) + +/* 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) + +/* LTDC_TWCR register */ + +#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 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_TWCR_TOTALW) + +/* Configuration ************************************************************/ + +#ifndef CONFIG_STM32H7_LTDC_DEFBACKLIGHT +# define CONFIG_STM32H7_LTDC_DEFBACKLIGHT 0xf0 +#endif +#define STM32_LTDC_BACKLIGHT_OFF 0x00 + +/* Color/video formats */ + +/* Layer 1 format */ + +#if defined(CONFIG_STM32H7_LTDC_L1_L8) +# 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_STM32H7_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) +# define STM32_LTDC_L1_DMA2D_PF DMA2D_PF_RGB565 +#elif defined(CONFIG_STM32H7_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_STM32H7_LTDC_L1_ARGB8888) +# define STM32_LTDC_L1_BPP 32 +# 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 */ + +#ifdef CONFIG_STM32H7_LTDC_L2 +# if defined(CONFIG_STM32H7_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_STM32H7_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_STM32H7_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_STM32H7_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_STM32H7_LTDC_L2 */ + +/* Framebuffer sizes in bytes */ + +#if STM32_LTDC_L1_BPP == 8 +# define STM32_LTDC_L1_STRIDE (STM32_LTDC_WIDTH) +#elif STM32_LTDC_L1_BPP == 16 +# define STM32_LTDC_L1_STRIDE ((STM32_LTDC_WIDTH * 16 + 7) / 8) +#elif STM32_LTDC_L1_BPP == 24 +# define STM32_LTDC_L1_STRIDE ((STM32_LTDC_WIDTH * 24 + 7) / 8) +#elif STM32_LTDC_L1_BPP == 32 +# 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_L1_FBSIZE (STM32_LTDC_L1_STRIDE * STM32_LTDC_HEIGHT) + +#ifdef CONFIG_STM32H7_LTDC_L2 +# ifndef CONFIG_STM32H7_LTDC_L2_WIDTH +# define CONFIG_STM32H7_LTDC_L2_WIDTH STM32_LTDC_WIDTH +# endif + +# if CONFIG_STM32H7_LTDC_L2_WIDTH > STM32_LTDC_WIDTH +# error Width of Layer 2 exceeds the width of the display +# endif + +# ifndef CONFIG_STM32H7_LTDC_L2_HEIGHT +# define CONFIG_STM32H7_LTDC_L2_HEIGHT STM32_LTDC_HEIGHT +# endif + +# if CONFIG_STM32H7_LTDC_L2_HEIGHT > STM32_LTDC_HEIGHT +# error Height of Layer 2 exceeds the height of the display +# endif + +# if STM32_LTDC_L2_BPP == 8 +# define STM32_LTDC_L2_STRIDE (CONFIG_STM32H7_LTDC_L2_WIDTH) +# elif STM32_LTDC_L2_BPP == 16 +# define STM32_LTDC_L2_STRIDE ((CONFIG_STM32H7_LTDC_L2_WIDTH * 16 + 7) / 8) +# elif STM32_LTDC_L2_BPP == 24 +# define STM32_LTDC_L2_STRIDE ((CONFIG_STM32H7_LTDC_L2_WIDTH * 24 + 7) / 8) +# elif STM32_LTDC_L2_BPP == 32 +# define STM32_LTDC_L2_STRIDE ((CONFIG_STM32H7_LTDC_L2_WIDTH * 32 + 7) / 8) +# else +# error Undefined or unrecognized base resolution +# endif + +# define STM32_LTDC_L2_FBSIZE (STM32_LTDC_L2_STRIDE * \ + CONFIG_STM32H7_LTDC_L2_HEIGHT) + +#else +# define STM32_LTDC_L2_FBSIZE (0) +# define STM32_LTDC_L2_BPP 0 +#endif + +/* Total memory used for framebuffers */ + +#define STM32_LTDC_TOTAL_FBSIZE (STM32_LTDC_L1_FBSIZE + \ + STM32_LTDC_L2_FBSIZE) + +/* Debug option */ + +#ifdef CONFIG_STM32H7_LTDC_REGDEBUG +# define regerr lcderr +# define reginfo lcdinfo +#else +# define regerr(x...) +# define reginfo(x...) +#endif + +/* Preallocated LTDC framebuffers */ + +/* Position the framebuffer memory in the center of the memory set aside. + * We will use any skirts before or after the framebuffer memory as a guard + * against wild framebuffer writes. + */ + +#define STM32_LTDC_BUFFER_SIZE CONFIG_STM32H7_LTDC_FB_SIZE +#define STM32_LTDC_BUFFER_FREE (STM32_LTDC_BUFFER_SIZE - \ + STM32_LTDC_TOTAL_FBSIZE) +#define STM32_LTDC_BUFFER_START (CONFIG_STM32H7_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" +#endif + +/* Layer frame buffer */ + +#define STM32_LTDC_BUFFER_L1 STM32_LTDC_BUFFER_START +#define STM32_LTDC_ENDBUF_L1 (STM32_LTDC_BUFFER_L1 + \ + STM32_LTDC_L1_FBSIZE) + +#ifdef CONFIG_STM32H7_LTDC_L2 +# 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 +#endif + +/* LTDC layer */ + +#ifdef CONFIG_STM32H7_LTDC_L2 +# define LTDC_NLAYERS 2 +#else +# define LTDC_NLAYERS 1 +#endif + +/* DMA2D layer */ + +#ifdef CONFIG_STM32H7_DMA2D +# define DMA2D_NLAYERS CONFIG_STM32H7_DMA2D_NLAYERS +# if DMA2D_NLAYERS < 1 +# error "DMA2D must at least support 1 overlay" +# endif + +#define STM32_DMA2D_WIDTH CONFIG_STM32H7_DMA2D_LAYER_PPLINE + +# if defined(CONFIG_STM32H7_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_STM32H7_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_STM32H7_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_STM32H7_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_STM32H7_DMA2D_LAYER_SHARED +# define STM32_DMA2D_FBSIZE CONFIG_STM32H7_DMA2D_FB_SIZE +# define STM32_DMA2D_LAYER_SIZE 0 +# else +# define STM32_DMA2D_FBSIZE CONFIG_STM32H7_DMA2D_FB_SIZE / DMA2D_NLAYERS +# define STM32_DMA2D_LAYER_SIZE STM32_DMA2D_FBSIZE +# if STM32_DMA2D_FBSIZE * DMA2D_NLAYERS > CONFIG_STM32H7_DMA2D_FB_SIZE +# error "DMA2D framebuffer size to small for configured number of overlays" +# endif +# endif /* CONFIG_STM32H7_DMA2D_LAYER_SHARED */ + +# define STM32_DMA2D_HEIGHT STM32_DMA2D_FBSIZE / STM32_DMA2D_STRIDE + +# define STM32_DMA2D_BUFFER_START CONFIG_STM32H7_DMA2D_FB_BASE +#else +# define DMA2D_NLAYERS 0 +#endif /* CONFIG_STM32H7_DMA2D */ + +#define LTDC_NOVERLAYS LTDC_NLAYERS + DMA2D_NLAYERS + +/* Dithering */ + +#ifndef CONFIG_STM32H7_LTDC_DITHER_RED +# define STM32_LTDC_DITHER_RED 0 +#else +# define STM32_LTDC_DITHER_RED CONFIG_STM32H7_LTDC_DITHER_RED +#endif +#ifndef CONFIG_STM32H7_LTDC_DITHER_GREEN +# define STM32_LTDC_DITHER_GREEN 0 +#else +# define STM32_LTDC_DITHER_GREEN CONFIG_STM32H7_LTDC_DITHER_GREEN +#endif +#ifndef CONFIG_STM32H7_LTDC_DITHER_BLUE +# define STM32_LTDC_DITHER_BLUE 0 +#else +# define STM32_LTDC_DITHER_BLUE CONFIG_STM32H7_LTDC_DITHER_BLUE +#endif + +/* Background color */ + +#ifndef CONFIG_STM32H7_LTDC_BACKCOLOR +# define STM32_LTDC_BACKCOLOR 0 +#else +# define STM32_LTDC_BACKCOLOR CONFIG_STM32H7_LTDC_BACKCOLOR +#endif + +/* Layer default color */ + +#ifdef CONFIG_STM32H7_LTDC_L1_COLOR +# define STM32_LTDC_L1_COLOR CONFIG_STM32H7_LTDC_L1_COLOR +#else +# define STM32_LTDC_L1_COLOR 0x000000 +#endif + +#ifdef CONFIG_STM32H7_LTDC_L2 +# ifdef CONFIG_STM32H7_LTDC_L2_COLOR +# define STM32_LTDC_L2_COLOR CONFIG_STM32H7_LTDC_L2_COLOR +# else +# define STM32_LTDC_L2_COLOR 0x000000 +# endif +#endif + +/* Internal operation flags */ + +#define LTDC_LAYER_SETAREA (1 << 0) /* Change visible area */ +#define LTDC_LAYER_SETALPHAVALUE (1 << 1) /* Change constant alpha value */ +#define LTDC_LAYER_SETBLENDMODE (1 << 2) /* Change blendmode */ +#define LTDC_LAYER_SETCOLORKEY (1 << 3) /* Change color key */ +#define LTDC_LAYER_ENABLECOLORKEY (1 << 4) /* Enable colorkey */ +#define LTDC_LAYER_SETCOLOR (1 << 5) /* Change default color */ +#define LTDC_LAYER_SETENABLE (1 << 6) /* Change enabled state */ +#define LTDC_LAYER_ENABLE (1 << 7) /* Enable the layer */ + +/* Layer initializing state */ + +#define LTDC_LAYER_INIT LTDC_LAYER_SETAREA | \ + LTDC_LAYER_SETALPHAVALUE | \ + LTDC_LAYER_SETBLENDMODE | \ + LTDC_LAYER_SETCOLORKEY | \ + LTDC_LAYER_SETCOLOR | \ + LTDC_LAYER_SETENABLE | \ + LTDC_LAYER_ENABLE + +/* Blendfactor reset values for flip operation */ + +#define STM32_LTDC_BF1_RESET 6 +#define STM32_LTDC_BF2_RESET 7 + +/* Check pixel format support by DMA2D driver */ + +#ifdef CONFIG_STM32H7_DMA2D +# if defined(CONFIG_STM32H7_LTDC_L1_L8) || \ + defined(CONFIG_STM32H7_LTDC_L2_L8) +# if !defined(CONFIG_STM32H7_DMA2D_L8) +# error "DMA2D must support FB_FMT_RGB8 pixel format" +# endif +# endif +# if defined(CONFIG_STM32H7_LTDC_L1_RGB565) || \ + defined(CONFIG_STM32H7_LTDC_L2_RGB565) +# if !defined(CONFIG_STM32H7_DMA2D_RGB565) +# error "DMA2D must support FB_FMT_RGB16_565 pixel format" +# endif +# endif +# if defined(CONFIG_STM32H7_LTDC_L1_RGB888) || \ + defined(CONFIG_STM32H7_LTDC_L2_RGB888) +# if !defined(CONFIG_STM32H7_DMA2D_RGB888) +# error "DMA2D must support FB_FMT_RGB24 pixel format" +# endif +# endif +# if defined(CONFIG_STM32H7_LTDC_L1_ARGB8888) || \ + defined(CONFIG_STM32H7_LTDC_L2_ARGB8888) +# if !defined(CONFIG_STM32H7_DMA2D_ARGB8888) +# error "DMA2D must support FB_FMT_RGB32 pixel format" +# endif +# endif +#endif + +/* Calculate the size of the layers clut table */ + +#ifdef CONFIG_STM32H7_FB_CMAP +# if defined(CONFIG_STM32H7_DMA2D) && !defined(CONFIG_STM32H7_DMA2D_L8) +# error "DMA2D must also support L8 CLUT pixel format if supported by LTDC" +# endif +# ifdef STM32_LTDC_L1CMAP +# ifdef CONFIG_STM32H7_FB_TRANSPARENCY +# define STM32_LAYER_CLUT_SIZE STM32_LTDC_NCLUT * sizeof(uint32_t) +# else +# 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_STM32H7_FB_TRANSPARENCY +# 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 +# endif +# endif +#endif + +#ifndef CONFIG_STM32H7_FB_CMAP +# if defined(STM32_LTDC_L1CMAP) || defined(STM32_LTDC_L2CMAP) +# undef STM32_LTDC_L1CMAP +# undef STM32_LTDC_L2CMAP +# error "Enable cmap to support the configured layer format!" +# endif +#endif + +/* Layer clut rgb value positioning */ + +#define LTDC_L1CLUT_REDOFFSET 0 +#define LTDC_L1CLUT_GREENOFFSET 256 +#define LTDC_L1CLUT_BLUEOFFSET 512 +#define LTDC_L2CLUT_REDOFFSET 768 +#define LTDC_L2CLUT_GREENOFFSET 1024 +#define LTDC_L2CLUT_BLUEOFFSET 1280 + +/* Layer argb clut register position */ + +#define LTDC_CLUT_ADD(n) ((uint32_t)(n) << 24) +#define LTDC_CLUT_ALPHA(n) LTDC_CLUT_ADD(n) +#define LTDC_CLUT_RED(n) ((uint32_t)(n) << 16) +#define LTDC_CLUT_GREEN(n) ((uint32_t)(n) << 8) +#define LTDC_CLUT_BLUE(n) ((uint32_t)(n) << 0) +#define LTDC_CLUT_RGB888_MASK 0xffffff + +/* Layer argb cmap conversion */ + +#define LTDC_CMAP_ALPHA(n) ((uint32_t)(n) >> 24) +#define LTDC_CMAP_RED(n) ((uint32_t)(n) >> 16) +#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_STM32H7_LTDC_L1_CHROMAKEYEN +# define STM32_LTDC_L1_CHROMAEN true +# define STM32_LTDC_L1_CHROMAKEY CONFIG_STM32H7_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_STM32H7_LTDC_L2_CHROMAKEYEN +# define STM32_LTDC_L2_CHROMAEN true +# define STM32_LTDC_L2_CHROMAKEY CONFIG_STM32H7_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_STM32H7_DMA2D +# ifdef CONFIG_FB_OVERLAY_BLIT +# ifdef CONFIG_STM32H7_FB_CMAP +# define LTDC_BLIT_ACCL FB_ACCL_BLIT +# else +# define LTDC_BLIT_ACCL FB_ACCL_BLIT | FB_ACCL_BLEND +# endif /* CONFIG_STM32H7_FB_CMAP */ +# else +# define LTDC_BLIT_ACCL 0 +# endif /* CONFIG_FB_OVERLAY_BLIT */ + +# ifdef CONFIG_STM32H7_FB_CMAP +# define LTDC_DMA2D_ACCL LTDC_BLIT_ACCL +# else +# define LTDC_DMA2D_ACCL FB_ACCL_COLOR | LTDC_BLIT_ACCL +# endif /* CONFIG_STM32H7_FB_CMAP */ +#else +# define LTDC_DMA2D_ACCL 0 +#endif /* CONFIG_STM32H7_DMA2D */ + +#define LTDC_L1_ACCL LTDC_LTDC_ACCL_L1 | LTDC_DMA2D_ACCL +#ifdef CONFIG_STM32H7_LTDC_L2 +# define LTDC_L2_ACCL LTDC_LTDC_ACCL_L2 | LTDC_DMA2D_ACCL +#endif + +/* Acceleration support for DMA2D overlays */ + +#ifdef CONFIG_STM32H7_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_STM32H7_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 + ****************************************************************************/ + +/* This enumeration names each layer supported by the hardware */ + +enum stm32_layer_e +{ + LTDC_LAYER_L1 = 0, /* LCD Layer 1 */ + LTDC_LAYER_L2, /* LCD Layer 2 */ +}; + +/* LTDC General layer information */ + +struct stm32_ltdc_s +{ + int layerno; /* layer number */ + +#ifdef CONFIG_FB_OVERLAY + struct fb_overlayinfo_s oinfo; /* Overlay info */ +#endif + +#ifdef CONFIG_STM32H7_DMA2D + struct stm32_dma2d_overlay_s dma2dinfo; /* Overlay info for DMA2D */ +#endif + + 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_STM32H7_FB_CMAP + struct fb_cmap_s cmap; +#endif + + /* Layer information */ + + struct stm32_ltdc_s layer[LTDC_NOVERLAYS]; + +#ifdef CONFIG_STM32H7_DMA2D + /* Interface to the dma2d controller */ + + FAR struct dma2d_layer_s *dma2d; +#endif +}; + +/* Interrupt handling */ + +struct stm32_interrupt_s +{ + int irq; /* irq number */ + int error; /* Interrupt error */ + sem_t *sem; /* Semaphore for waiting for irq */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Overal LTDC helper */ + +static void stm32_ltdc_enable(bool enable); +static void stm32_ltdc_gpioconfig(void); +static void stm32_ltdc_periphconfig(void); +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 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); + +/* Helper for layer register configuration */ + +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_STM32H7_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 + +#ifdef CONFIG_STM32H7_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_lclear(uint8_t overlayno); + +/* Framebuffer interface */ + +static int stm32_getvideoinfo(FAR struct fb_vtable_s *vtable, + FAR struct fb_videoinfo_s *vinfo); +static int stm32_getplaneinfo(FAR struct fb_vtable_s *vtable, + int planeno, + FAR struct fb_planeinfo_s *pinfo); + +/* The following is provided only if the video hardware supports RGB color + * mapping + */ + +#ifdef CONFIG_STM32H7_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 + +/* The following is provided only if the video hardware signals vertical + * synchronisation + */ + +#ifdef CONFIG_FB_SYNC +static int stm32_waitforvsync(FAR struct fb_vtable_s *vtable); +#endif + +/* The following is provided only if the video hardware supports overlays */ + +#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 + ****************************************************************************/ + +/* PIO pin configurations */ + +static const uint32_t g_ltdcpins[] = +{ + GPIO_LTDC_R4, GPIO_LTDC_R5, GPIO_LTDC_R6, GPIO_LTDC_R7, + GPIO_LTDC_G4, GPIO_LTDC_G5, GPIO_LTDC_G6, GPIO_LTDC_G7, + 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 + GPIO_LTDC_R2, GPIO_LTDC_B2, +# 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 + GPIO_LTDC_VSYNC, GPIO_LTDC_HSYNC, GPIO_LTDC_DE, GPIO_LTDC_CLK +}; + +#define STM32_LTDC_NPINCONFIGS (sizeof(g_ltdcpins) / sizeof(uint32_t)) + +#ifdef CONFIG_STM32H7_FB_CMAP +/* The layers clut table entries */ + +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_STM32H7_FB_TRANSPARENCY +static uint8_t g_transpclut[STM32_LTDC_NCLUT]; +# endif +#endif /* CONFIG_STM32H7_FB_CMAP */ + +/* The LTDC semaphore that enforces mutually exclusive access */ + +static sem_t g_lock; + +/* The semaphore for interrupt handling */ + +static sem_t g_semirq; + +/* This structure provides irq handling */ + +static struct stm32_interrupt_s g_interrupt = +{ + .irq = STM32_IRQ_LTDC, + .error = OK, + .sem = &g_semirq +}; + +/* This structure provides the internal interface */ + +static struct stm32_ltdcdev_s g_vtable = +{ + .vtable = + { + .getvideoinfo = stm32_getvideoinfo, + .getplaneinfo = stm32_getplaneinfo +#ifdef CONFIG_FB_SYNC + , + .waitforvsync = stm32_waitforvsync +#endif + +#ifdef CONFIG_STM32H7_FB_CMAP + , + .getcmap = stm32_getcmap, + .putcmap = stm32_putcmap +#endif + +#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_STM32H7_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_STM32H7_LTDC_L2 */ + , +#ifdef CONFIG_STM32H7_FB_CMAP + .cmap = + { + .first = 0, + .len = STM32_LTDC_NCLUT, + .red = g_redclut, + .green = g_greenclut, + .blue = g_blueclut, +# ifdef CONFIG_STM32H7_FB_TRANSPARENCY + .transp = g_transpclut +# endif + } + , +#endif + .layer[LTDC_LAYER_L1] = + { + .layerno = LTDC_LAYER_L1, +#ifdef CONFIG_FB_OVERLAY + .oinfo = + { + .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 = + { + .transp = 0xff, + .transp_mode = FB_CONST_ALPHA + }, + .sarea = + { + .x = 0, + .y = 0, + .w = STM32_LTDC_WIDTH, + .h = STM32_LTDC_HEIGHT + }, + .accl = LTDC_L1_ACCL + }, +#endif + +#ifdef CONFIG_STM32H7_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_STM32H7_LTDC_L2 + , + .layer[LTDC_LAYER_L2] = + { + .layerno = LTDC_LAYER_L2, +#ifdef CONFIG_FB_OVERLAY + .oinfo = + { + .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 = + { + .transp = 0xff, + .transp_mode = FB_CONST_ALPHA + }, + .sarea = + { + .x = 0, + .y = 0, + .w = STM32_LTDC_WIDTH, + .h = STM32_LTDC_HEIGHT + }, + .accl = LTDC_L2_ACCL + }, +#endif + +#ifdef CONFIG_STM32H7_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 +}; + +/* Configuration lookup tables */ + +/* LTDC width */ + +static const uint32_t stm32_width_layer_t[LTDC_NLAYERS] = +{ + STM32_LTDC_WIDTH +#ifdef CONFIG_STM32H7_LTDC_L2 + , STM32_LTDC_WIDTH +#endif +}; + +/* LTDC height */ + +static const uint32_t stm32_height_layer_t[LTDC_NLAYERS] = +{ + STM32_LTDC_HEIGHT +#ifdef CONFIG_STM32H7_LTDC_L2 + , STM32_LTDC_HEIGHT +#endif +}; + +/* LTDC stride */ + +static const uint32_t stm32_stride_layer_t[LTDC_NLAYERS] = +{ + STM32_LTDC_L1_STRIDE +#ifdef CONFIG_STM32H7_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_STM32H7_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_STM32H7_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_STM32H7_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_STM32H7_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_STM32H7_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_STM32H7_LTDC_L2 + , STM32_LTDC_L2_CHROMAEN +#endif +}; + +/* LTDC pixel format lookup table */ + +static const uint32_t stm32_fmt_layer_t[LTDC_NLAYERS] = +{ + STM32_LTDC_L1PFCR_PF +#ifdef CONFIG_STM32H7_LTDC_L2 + , STM32_LTDC_L2PFCR_PF +#endif +}; + +/* Register lookup tables */ + +/* LTDC_LxCR */ + +static const uintptr_t stm32_cr_layer_t[LTDC_NLAYERS] = +{ + STM32_LTDC_L1CR +#ifdef CONFIG_STM32H7_LTDC_L2 + , STM32_LTDC_L2CR +#endif +}; + +/* LTDC_LxWHPCR */ + +static const uintptr_t stm32_whpcr_layer_t[LTDC_NLAYERS] = +{ + STM32_LTDC_L1WHPCR +#ifdef CONFIG_STM32H7_LTDC_L2 + , STM32_LTDC_L2WHPCR +#endif +}; + +/* LTDC_LxWVPCR */ + +static const uintptr_t stm32_wvpcr_layer_t[LTDC_NLAYERS] = +{ + STM32_LTDC_L1WVPCR +#ifdef CONFIG_STM32H7_LTDC_L2 + , STM32_LTDC_L2WVPCR +#endif +}; + +/* LTDC_LxPFCR */ + +static const uintptr_t stm32_pfcr_layer_t[LTDC_NLAYERS] = +{ + STM32_LTDC_L1PFCR +#ifdef CONFIG_STM32H7_LTDC_L2 + , STM32_LTDC_L2PFCR +#endif +}; + +/* LTDC_LxDCCR */ + +static const uintptr_t stm32_dccr_layer_t[LTDC_NLAYERS] = +{ + STM32_LTDC_L1DCCR +#ifdef CONFIG_STM32H7_LTDC_L2 + , STM32_LTDC_L2DCCR +#endif +}; + +/* LTDC_LxCKCR */ + +static const uintptr_t stm32_ckcr_layer_t[LTDC_NLAYERS] = +{ + STM32_LTDC_L1CKCR +#ifdef CONFIG_STM32H7_LTDC_L2 + , STM32_LTDC_L2CKCR +#endif +}; + +/* LTDC_LxCACR */ + +static const uintptr_t stm32_cacr_layer_t[LTDC_NLAYERS] = +{ + STM32_LTDC_L1CACR +#ifdef CONFIG_STM32H7_LTDC_L2 + , STM32_LTDC_L2CACR +#endif +}; + +/* LTDC_LxBFCR */ + +static const uintptr_t stm32_bfcr_layer_t[LTDC_NLAYERS] = +{ + STM32_LTDC_L1BFCR +#ifdef CONFIG_STM32H7_LTDC_L2 + , STM32_LTDC_L2BFCR +#endif +}; + +/* LTDC_LxCFBAR */ + +static const uintptr_t stm32_cfbar_layer_t[LTDC_NLAYERS] = +{ + STM32_LTDC_L1CFBAR +#ifdef CONFIG_STM32H7_LTDC_L2 + , STM32_LTDC_L2CFBAR +#endif +}; + +/* LTDC_LxCFBLR */ + +static const uintptr_t stm32_cfblr_layer_t[LTDC_NLAYERS] = +{ + STM32_LTDC_L1CFBLR +#ifdef CONFIG_STM32H7_LTDC_L2 + , STM32_LTDC_L2CFBLR +#endif +}; + +/* LTDC_LxCFBLNR */ + +static const uintptr_t stm32_cfblnr_layer_t[LTDC_NLAYERS] = +{ + STM32_LTDC_L1CFBLNR +#ifdef CONFIG_STM32H7_LTDC_L2 + , STM32_LTDC_L2CFBLNR +#endif +}; + +/* LTDC_LxCLUTWR */ + +#ifdef CONFIG_STM32H7_FB_CMAP +static const uintptr_t stm32_clutwr_layer_t[LTDC_NLAYERS] = +{ + STM32_LTDC_L1CLUTWR +# ifdef CONFIG_STM32H7_LTDC_L2 + , STM32_LTDC_L2CLUTWR +# endif +}; +#endif /* CONFIG_STM32H7_FB_CMAP */ + +/* The initialized state of the driver */ + +static bool g_initialized; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_ltdc_gpioconfig + * + * Description: + * Configure GPIO pins for use with the LTDC + * + ****************************************************************************/ + +static void stm32_ltdc_gpioconfig(void) +{ + int i; + + lcdinfo("Configuring pins\n"); + + /* Configure each pin */ + + for (i = 0; i < STM32_LTDC_NPINCONFIGS; i++) + { + reginfo("set gpio%d = %08x\n", i, g_ltdcpins[i]); + stm32_configgpio(g_ltdcpins[i]); + } +} + +/**************************************************************************** + * Name: stm32_ltdc_periphconfig + * + * Description: + * Configures the synchronous timings + * Configures the synchronous signals and clock polarity + * + ****************************************************************************/ + +static void stm32_ltdc_periphconfig(void) +{ + uint32_t regval; + + /* Configure GPIO's */ + + stm32_ltdc_gpioconfig(); + + /* Configure APB3 LTDC clock external */ + + reginfo("configured RCC_APB3ENR=%08x\n", getreg32(STM32_RCC_APB3ENR)); + + /* Configure LTDC_SSCR */ + + regval = (STM32_LTDC_SSCR_VSH | STM32_LTDC_SSCR_HSW); + reginfo("set LTDC_SSCR=%08x\n", regval); + putreg32(regval, STM32_LTDC_SSCR); + reginfo("configured LTDC_SSCR=%08x\n", getreg32(STM32_LTDC_SSCR)); + + /* Configure LTDC_BPCR */ + + regval = (STM32_LTDC_BPCR_AVBP | STM32_LTDC_BPCR_AHBP); + reginfo("set LTDC_BPCR=%08x\n", regval); + putreg32(regval, STM32_LTDC_BPCR); + reginfo("configured LTDC_BPCR=%08x\n", getreg32(STM32_LTDC_BPCR)); + + /* Configure LTDC_AWCR */ + + regval = (STM32_LTDC_AWCR_AAH | STM32_LTDC_AWCR_AAW); + reginfo("set LTDC_AWCR=%08x\n", regval); + putreg32(regval, STM32_LTDC_AWCR); + reginfo("configured LTDC_AWCR=%08x\n", getreg32(STM32_LTDC_AWCR)); + + /* Configure LTDC_TWCR */ + + regval = (STM32_LTDC_TWCR_TOTALH | STM32_LTDC_TWCR_TOTALW); + reginfo("set LTDC_TWCR=%08x\n", regval); + putreg32(regval, STM32_LTDC_TWCR); + reginfo("configured LTDC_TWCR=%08x\n", getreg32(STM32_LTDC_TWCR)); + + /* Configure LTDC_GCR */ + + regval = getreg32(STM32_LTDC_GCR); + 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 + * + * Description: + * Configures background color of the LCD controller. + * + * Input Parameters: + * rgb - RGB888 background color + * + ****************************************************************************/ + +static void stm32_ltdc_bgcolor(uint32_t rgb) +{ + reginfo("set LTDC_BCCR=%08x\n", rgb); + putreg32(rgb, STM32_LTDC_BCCR); + reginfo("configured LTDC_BCCR=%08x\n", getreg32(STM32_LTDC_BCCR)); +} + +/**************************************************************************** + * Name: stm32_ltdc_dither + * + * Description: + * Configures dither settings of the LCD controller. + * + * Input Parameters: + * enable - Enable dithering + * red - Red dither width + * green - Green dither width + * blue - Blue dither width + * + ****************************************************************************/ + +static void stm32_ltdc_dither(bool enable, uint8_t red, + uint8_t green, uint8_t blue) +{ + uint32_t regval; + + regval = getreg32(STM32_LTDC_GCR); + + if (enable == true) + { + regval |= LTDC_GCR_DEN; + } + else + { + regval &= ~LTDC_GCR_DEN; + } + + regval &= ~(LTDC_GCR_DBW_MASK | LTDC_GCR_DGW_MASK | LTDC_GCR_DRW_MASK); + regval |= (LTDC_GCR_DRW(red) | LTDC_GCR_DGW(green) | LTDC_GCR_DBW(blue)); + + 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_linepos + * + * Description: + * Configures line position register + * + ****************************************************************************/ + +static void stm32_ltdc_linepos(void) +{ + /* Configure LTDC_LIPCR */ + + reginfo("set LTDC_LIPCR=%08x\n", STM32_LTDC_LIPCR_LIPOS); + putreg32(STM32_LTDC_LIPCR_LIPOS, STM32_LTDC_LIPCR); + reginfo("configured LTDC_LIPCR=%08x\n", getreg32(STM32_LTDC_LIPCR)); +} + +/**************************************************************************** + * Name: stm32_ltdc_irqctrl + * + * Description: + * Control interrupts generated by the ltdc controller + * + * Input Parameters: + * setirqs - set interrupt mask + * clrirqs - clear interrupt mask + * + ****************************************************************************/ + +static void stm32_ltdc_irqctrl(uint32_t setirqs, uint32_t clrirqs) +{ + uint32_t regval; + + regval = getreg32(STM32_LTDC_IER); + regval &= ~clrirqs; + regval |= setirqs; + reginfo("set LTDC_IER=%08x\n", regval); + putreg32(regval, STM32_LTDC_IER); + reginfo("configured LTDC_IER=%08x\n", getreg32(STM32_LTDC_IER)); +} + +/**************************************************************************** + * Name: stm32_ltdcirq + * + * Description: + * LTDC interrupt handler + * + ****************************************************************************/ + +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); + + if (regval & LTDC_ISR_RRIF) + { + /* Register reload interrupt */ + + /* 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 */ + + /* Clear the interrupt status register */ + + reginfo("Line interrupt\n"); + putreg32(LTDC_ICR_CLIF, STM32_LTDC_ICR); + priv->error = OK; + } + else if (regval & LTDC_IER_TERRIE) + { + /* Transfer error interrupt */ + + /* Clear the interrupt status register */ + + reginfo("Error transfer\n"); + putreg32(LTDC_ICR_CTERRIF, STM32_LTDC_ICR); + priv->error = -ECANCELED; + } + else if (regval & LTDC_IER_FUIE) + { + /* Fifo underrun error interrupt */ + + /* Clear the interrupt status register */ + + reginfo("Error fifo underrun\n"); + putreg32(LTDC_ICR_CFUIF, STM32_LTDC_ICR); + priv->error = -ECANCELED; + } + else + { + DEBUGASSERT("Unknown interrupt"); + } + + /* Unlock the semaphore if locked */ + + ret = nxsem_post(priv->sem); + + if (ret < 0) + { + lcderr("ERROR: nxsem_post() failed\n"); + } + + return OK; +} + +/**************************************************************************** + * Name: stm32_ltdc_waitforirq + * + * Description: + * Helper waits until the ltdc irq occurs. In the current design That means + * that a register reload was been completed. + * Note! The caller must use this function within a critical section. + * + * Returned Value: + * OK - On success otherwise ERROR + * + ****************************************************************************/ + +static int stm32_ltdc_waitforirq(void) +{ + int ret = OK; + FAR struct stm32_interrupt_s *priv = &g_interrupt; + + ret = nxsem_wait(priv->sem); + + if (ret < 0) + { + lcderr("ERROR: nxsem_wait() failed\n"); + } + + ret = priv->error; + + return ret; +} + +/**************************************************************************** + * Name: stm32_ltdc_reload + * + * Description: + * Reload the layer shadow register and make layer changes visible. + * Note! The caller must ensure that a previous register reloading has been + * completed. + * + * Input Parameters: + * value - Reload flag (e.g. upon vertical blank or immediately) + * waitvblank - Wait until register reload is finished + * + ****************************************************************************/ + +static int stm32_ltdc_reload(uint8_t value, bool waitvblank) +{ + int ret = OK; + + /* Reloads the shadow register. + * Note! This will not trigger an register reload interrupt if + * immediately reload is set. + */ + + reginfo("set LTDC_SRCR=%08x\n", value); + putreg32(value, STM32_LTDC_SRCR); + reginfo("configured LTDC_SRCR=%08x\n", getreg32(STM32_LTDC_SRCR)); + + if (value == LTDC_SRCR_VBR && waitvblank) + { + /* Wait upon vertical blanking period */ + + ret = stm32_ltdc_waitforirq(); + } + else + { + /* Wait until register reload hase been done */ + + while (getreg32(STM32_LTDC_SRCR) & value); + } + + return ret; +} + +/**************************************************************************** + * Name: stm32_ltdc_irqconfig + * + * Description: + * Configure interrupts + * + ****************************************************************************/ + +static void stm32_ltdc_irqconfig(void) +{ + /* Initialize the LTDC semaphore that enforces mutually exclusive access */ + + nxsem_init(&g_lock, 0, 1); + + /* Initialize the semaphore for interrupt handling. This waitsem + * semaphore is used for signaling and, hence, should not have priority + * inheritance enabled. + */ + + nxsem_init(g_interrupt.sem, 0, 0); + nxsem_set_protocol(g_interrupt.sem, SEM_PRIO_NONE); + + /* Attach LTDC interrupt vector */ + + irq_attach(g_interrupt.irq, stm32_ltdcirq, NULL); + + /* Enable the IRQ at the NVIC */ + + up_enable_irq(g_interrupt.irq); + + /* Enable interrupts expect line interrupt */ + + stm32_ltdc_irqctrl(LTDC_IER_RRIE | + LTDC_IER_TERRIE | + LTDC_IER_FUIE, + LTDC_IER_LIE); + + /* Configure line interrupt */ + + stm32_ltdc_linepos(); +} + +/**************************************************************************** + * Name: stm32_ltdc_globalconfig + * + * Description: + * Configure background color + * Configure dithering + * + ****************************************************************************/ + +static void stm32_ltdc_globalconfig(void) +{ + /* Configure dither */ + + stm32_ltdc_dither( +#ifdef CONFIG_STM32H7_LTDC_DITHER + true, +#else + false, +#endif + STM32_LTDC_DITHER_RED, + STM32_LTDC_DITHER_GREEN, + STM32_LTDC_DITHER_BLUE); + + /* Configure background color */ + + stm32_ltdc_bgcolor(STM32_LTDC_BACKCOLOR); +} + +/**************************************************************************** + * Name: stm32_ltdc_enable + * + * Description: + * Disable the LCD peripheral + * + * Input Parameters: + * enable - Enable or disable + * + ****************************************************************************/ + +static void stm32_ltdc_enable(bool enable) +{ + uint32_t regval; + + regval = getreg32(STM32_LTDC_GCR); + reginfo("get LTDC_GCR=%08x\n", regval); + + if (enable == true) + { + regval |= LTDC_GCR_LTDCEN; + } + else + { + regval &= ~LTDC_GCR_LTDCEN; + } + + 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_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_STM32H7_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/Disable 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 + * + * Description: + * Disable or enable the layer clut support + * + * Input Parameters: + * layer - Reference to the layer control structure + * enable - Enable or disable + * + ****************************************************************************/ + +#ifdef CONFIG_STM32H7_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->oinfo.overlay]); + reginfo("get LTDC_L%dCR=%08x\n", layer->oinfo.overlay + 1, regval); + + /* Disable the clut support during update the color table */ + + if (enable == true) + { + regval |= LTDC_LXCR_CLUTEN; + } + else + { + regval &= ~LTDC_LXCR_CLUTEN; + } + + reginfo("set LTDC_L%dCR=%08x\n", layer->oinfo.overlay, regval); + putreg32(regval, stm32_cr_layer_t[layer->oinfo.overlay]); + + /* Reload shadow register */ + + stm32_ltdc_reload(LTDC_SRCR_IMR, false); +} + +/**************************************************************************** + * Name: stm32_ltdc_lputclut + * + * Description: + * Update the clut layer register during blank period. + * Note! The clut register is no shadow register. + * + * Input Parameters: + * layer - Reference to the layer control structure + * cmap - Color map + * + ****************************************************************************/ + +static void stm32_ltdc_lputclut(FAR struct stm32_ltdc_s *layer, + FAR const struct fb_cmap_s *cmap) +{ + int n; + irqstate_t flags; + + /* Disable clut during register update */ + + stm32_ltdc_lclutenable(layer, false); + + /* Update the clut registers. Ensure operation is atomic or in interrupt + * protected context. + */ + + flags = enter_critical_section(); + + for (n = cmap->first; n < cmap->len && n < STM32_LTDC_NCLUT; n++) + { + uint32_t regval; + + 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]); + + 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 after register update */ + + stm32_ltdc_lclutenable(layer, true); + + /* Reload shadow control register */ + + stm32_ltdc_reload(LTDC_SRCR_IMR, false); +} + +/**************************************************************************** + * Name: stm32_ltdc_lgetclut + * + * Description: + * Copy the layers color lookup table. + * + * Input Parameters: + * layer - Reference to the layer control structure + * cmap - Color map + * + ****************************************************************************/ + +static void stm32_ltdc_lgetclut(FAR struct stm32_ltdc_s * layer, + FAR struct fb_cmap_s * cmap) +{ + int n; + FAR struct fb_cmap_s *priv_cmap = &g_vtable.cmap; + + /* Copy from internal cmap */ + + for (n = cmap->first; n < cmap->len && n < STM32_LTDC_NCLUT; n++) + { +# ifdef CONFIG_STM32H7_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_STM32H7_FB_TRANSPARENCY + cmap->transp[n], +# endif + cmap->red[n], + cmap->green[n], + cmap->blue[n]); + } +} +#endif /* CONFIG_STM32H7_FB_CMAP */ + +/**************************************************************************** + * Name: stm32_ltdc_lclear + * + * Description: + * Clear the whole layer + * + * Input Parameters: + * overlayno - Number overlay + * + ****************************************************************************/ + +static void stm32_ltdc_lclear(uint8_t overlayno) +{ + 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_STM32H7_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_STM32H7_DMA2D) && defined(CONFIG_FB_OVERLAY_BLIT) */ + +/**************************************************************************** + * Name: stm32_ltdc_linit + * + * Description: + * Initialize layer to their default states. + * + * Initialize: + * - 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_STM32H7_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 chromakey + * - layer transparency + * - layer clut + * + * Input Parameters: + * layer - Reference to the layer control structure + * + ****************************************************************************/ + +#ifdef CONFIG_STM32H7_DMA2D +static void stm32_ltdc_dma2dlinit(void) +{ + int n; + FAR struct stm32_ltdcdev_s *dev = &g_vtable; + + for (n = 0; n < DMA2D_NLAYERS; n++) + { + 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 /* CONFIG_STM32H7_DMA2D */ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_getvideoinfo + * + * Description: + * Entrypoint ioctl FBIOGET_VIDEOINFO + * Get the videoinfo for the framebuffer + * + * Input Parameters: + * vtable - The framebuffer driver object + * vinfo - the videoinfo object + * + * Returned Value: + * On success - OK + * On error - -EINVAL + * + ****************************************************************************/ + +static int stm32_getvideoinfo(struct fb_vtable_s *vtable, + struct fb_videoinfo_s *vinfo) +{ + FAR struct stm32_ltdcdev_s *priv = (FAR struct stm32_ltdcdev_s *)vtable; + + 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: + * vtable - The framebuffer driver object + * pinfo - the planeinfo object + * + * Returned Value: + * On success - OK + * On error - -EINVAL + * + ****************************************************************************/ + +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 (planeno == 0) + { + memcpy(pinfo, &priv->pinfo, sizeof(struct fb_planeinfo_s)); + return OK; + } + + lcderr("ERROR: Returning EINVAL\n"); + return -EINVAL; +} + +/**************************************************************************** + * Name: stm32_getcmap + * + * Description: + * Entrypoint ioctl FBIOGET_CMAP + * Get a range of CLUT values for the LCD + * + * Input Parameters: + * vtable - The framebuffer driver object + * cmap - the color table + * + * Returned Value: + * On success - OK + * On error - -EINVAL + * + ****************************************************************************/ + +#ifdef CONFIG_STM32H7_FB_CMAP +static int stm32_getcmap(struct fb_vtable_s *vtable, + struct fb_cmap_s *cmap) +{ + 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_STM32H7_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: + * vtable - The framebuffer driver object + * cmap - the color table + * + * Returned Value: + * On success - OK + * On error - -EINVAL + * + ****************************************************************************/ + +static int stm32_putcmap(struct fb_vtable_s *vtable, + const struct fb_cmap_s *cmap) +{ + 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, but is shared + * for now. + */ + + 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++) + { + priv_cmap->red[n] = cmap->red[n]; + priv_cmap->green[n] = cmap->green[n]; + priv_cmap->blue[n] = cmap->blue[n]; +# ifdef CONFIG_STM32H7_FB_TRANSPARENCY + /* Not supported by LTDC */ + + priv_cmap->transp[n] = cmap->transp[n]; +# endif + } + + 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++) + { + FAR struct stm32_ltdc_s * layer = &priv->layer[n]; + stm32_ltdc_lputclut(layer, priv_cmap); + } + +# ifdef CONFIG_STM32H7_DMA2D + /* Update dma2d cmap */ + + priv->dma2d->setclut(cmap); +# endif + nxsem_post(&g_lock); + + ret = OK; + } + + return ret; +} +#endif /* CONFIG_STM32H7_FB_CMAP */ + +/**************************************************************************** + * Name: stm32_ioctl_waitforvsync + * Description: + * Entrypoint ioctl FBIO_WAITFORSYNC + ****************************************************************************/ + +#ifdef CONFIG_FB_SYNC +static int stm32_waitforvsync(FAR struct fb_vtable_s *vtable) +{ + int ret; + + DEBUGASSERT(vtable != NULL && vtable == &g_vtable.vtable); + + /* Wait upon vertical synchronization. */ + + ret = stm32_ltdc_reload(LTDC_SRCR_VBR, true); + + return ret; +} +#endif /* CONFIG_FB_SYNC */ + +/**************************************************************************** + * Name: stm32_getoverlayinfo + * Description: + * Entrypoint ioctl FBIOGET_OVERLAYINFO + ****************************************************************************/ + +#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_ltdcdev_s *priv = (FAR struct stm32_ltdcdev_s *)vtable; + + lcdinfo("vtable=%p overlay=%d oinfo=%p\n", vtable, overlayno, oinfo); + DEBUGASSERT(vtable != NULL && priv == &g_vtable); + + if (overlayno < LTDC_NOVERLAYS) + { + FAR struct stm32_ltdc_s * layer = &priv->layer[overlayno]; + memcpy(oinfo, &layer->oinfo, sizeof(struct fb_overlayinfo_s)); + return OK; + } + + lcderr("ERROR: Returning EINVAL\n"); + return -EINVAL; +} + +/**************************************************************************** + * Name: stm32_settransp + * Description: + * Entrypoint ioctl FBIOSET_TRANSP + ****************************************************************************/ + +static int stm32_settransp(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; + + 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 (oinfo->transp.transp_mode > 1) + { + 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_STM32H7_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; + } + + lcderr("ERROR: Returning EINVAL\n"); + return -EINVAL; +} + +/**************************************************************************** + * Name: stm32_setchromakey + * Description: + * Entrypoint ioctl FBIOSET_CHROMAKEY + ****************************************************************************/ + +static int stm32_setchromakey(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; + + DEBUGASSERT(vtable != NULL && priv == &g_vtable && oinfo != NULL); + lcdinfo("vtable=%p, overlay=%d, chromakey=%08x\n", vtable, + oinfo->overlay, oinfo->chromakey); + + if (oinfo->overlay < LTDC_NLAYERS) + { + int ret; + FAR struct stm32_ltdc_s * layer = &priv->layer[oinfo->overlay]; + +# ifndef CONFIG_STM32H7_LTDC_L1_CHROMAKEY + if (oinfo->overlay == LTDC_LAYER_L1) + { + return -ENOSYS; + } +# endif + +# ifndef CONFIG_STM32H7_LTDC_L2_CHROMAKEY + if (oinfo->overlay == LTDC_LAYER_L2) + { + return -ENOSYS; + } +# endif + + nxsem_wait(layer->lock); +# ifdef CONFIG_STM32H7_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(layer->lock); + return ret; + } +# ifdef CONFIG_STM32H7_DMA2D + else if (oinfo->overlay < LTDC_NOVERLAYS) + { + /* Chromakey not supported by DMA2D */ + + return -ENOSYS; + } +# endif + + lcderr("ERROR: Returning EINVAL\n"); + return -EINVAL; +} + +/**************************************************************************** + * Name: stm32_setcolor + * Description: + * Entrypoint ioctl FBIOSET_COLOR + ****************************************************************************/ + +static int stm32_setcolor(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, color=%08x\n", vtable, oinfo->color); + + if (oinfo->overlay < LTDC_NOVERLAYS) + { +# ifdef CONFIG_STM32H7_DMA2D + + /* Set color within the active overlay is not supported by LTDC. So use + * DMA2D controller instead when configured. + */ + + 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; + + DEBUGASSERT(&layer->oinfo == poverlay); + + nxsem_wait(layer->lock); + poverlay->color = oinfo->color; + ret = priv->dma2d->fillcolor(&layer->dma2dinfo, &poverlay->sarea, + poverlay->color); + nxsem_post(layer->lock); + + return ret; +# else + /* Coloring not supported by LTDC */ + + return -ENOSYS; +# endif + } + + lcderr("ERROR: Returning EINVAL\n"); + return -EINVAL; +} + +/**************************************************************************** + * Name: stm32_setblank + * Description: + * Entrypoint ioctl FBIOSET_BLANK + ****************************************************************************/ + +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; + + DEBUGASSERT(vtable != NULL && priv == &g_vtable && oinfo != NULL); + lcdinfo("vtable=%p, overlay=%d, blank=%02x\n", vtable, oinfo->blank); + + if (oinfo->overlay < LTDC_NLAYERS) + { + FAR struct stm32_ltdc_s * layer = &priv->layer[oinfo->overlay]; + + nxsem_wait(layer->lock); + layer->oinfo.blank = oinfo->blank; + + /* Enable or disable layer */ + + stm32_ltdc_lenable(layer, (layer->oinfo.blank == 0)); + nxsem_post(layer->lock); + + return OK; + } +# ifdef CONFIG_STM32H7_DMA2D + else if (oinfo->overlay < LTDC_NOVERLAYS) + { + /* DMA2D overlays are non visible */ + + return OK; + } +# endif + + lcderr("ERROR: Returning EINVAL\n"); + return -EINVAL; +} + +/**************************************************************************** + * 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_STM32H7_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: + * Entrypoint ioctl FBIOSET_BLIT + ****************************************************************************/ + +# ifdef CONFIG_FB_OVERLAY_BLIT +static int stm32_blit(FAR struct fb_vtable_s *vtable, + FAR const struct fb_overlayblit_s *blit) +{ + DEBUGASSERT(vtable != NULL && vtable == &g_vtable.vtable && blit != NULL); + lcdinfo("vtable = %p, blit = %p\n", vtable, blit); + + if (blit->dest.overlay < LTDC_NOVERLAYS && + blit->src.overlay < LTDC_NOVERLAYS) + { +# ifdef CONFIG_STM32H7_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]; + + 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: + * Entrypoint ioctl FBIOSET_BLEND + ****************************************************************************/ + +static int stm32_blend(FAR struct fb_vtable_s *vtable, + FAR const struct fb_overlayblend_s *blend) +{ + DEBUGASSERT(vtable != NULL && vtable == &g_vtable.vtable && blend != NULL); + lcdinfo("vtable = %p, blend = %p\n", vtable, blend); + + if (blend->dest.overlay < LTDC_NOVERLAYS && + blend->foreground.overlay < LTDC_NOVERLAYS && + blend->background.overlay < LTDC_NOVERLAYS) + { +# ifdef CONFIG_STM32H7_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]; + + 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; +} +# endif /* CONFIG_FB_OVERLAY_BLIT */ +#endif /* CONFIG_FB_OVERLAY */ + +/**************************************************************************** + * Name: stm32_ltdcreset + * + * Description: + * Reset LTDC via APB2RSTR + * + ****************************************************************************/ + +void stm32_ltdcreset(void) +{ + uint32_t regval = getreg32(STM32_RCC_APB3RSTR); + putreg32(regval | RCC_APB3RSTR_LTDCRST, STM32_RCC_APB3RSTR); + putreg32(regval & ~RCC_APB3RSTR_LTDCRST, STM32_RCC_APB3RSTR); +} + +/**************************************************************************** + * Name: stm32_ltdcinitialize + * + * Description: + * Initialize the ltdc controller + * + * Returned Value: + * OK + * + ****************************************************************************/ + +int stm32_ltdcinitialize(void) +{ + int ret = OK; + + lcdinfo("Initialize LTDC driver\n"); + + if (g_initialized == true) + { + return ret; + } + + /* Disable the LCD */ + + stm32_ltdc_enable(false); + + lcdinfo("Configuring the LCD controller\n"); + + /* Configure LCD periphery */ + + 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_ltdc_globalconfig(); + +#ifdef CONFIG_STM32H7_DMA2D + /* Initialize the dma2d controller */ + + 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_STM32H7_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_STM32H7_FB_TRANSPARENCY + memset(&g_transpclut, 0, STM32_LTDC_NCLUT); +# endif +#endif /* CONFIG_STM32H7_FB_CMAP */ + + /* Initialize ltdc layer */ + + lcdinfo("Initialize ltdc layer\n"); + stm32_ltdc_linit(LTDC_LAYER_L1); +#ifdef CONFIG_STM32H7_LTDC_L2 + stm32_ltdc_linit(LTDC_LAYER_L2); +#endif + +#ifdef CONFIG_STM32H7_DMA2D + stm32_ltdc_dma2dlinit(); +#endif + /* Enable the backlight */ + +#ifdef CONFIG_STM32H7_LCD_BACKLIGHT + stm32_backlight(true); +#endif + + /* Reload shadow register */ + + lcdinfo("Reload shadow register\n"); + stm32_ltdc_reload(LTDC_SRCR_IMR, false); + + /* Turn the LCD on */ + + lcdinfo("Enabling the display\n"); + stm32_ltdc_enable(true); + + /* Set initialized state */ + + g_initialized = true; + return ret; +} + +/**************************************************************************** + * Name: stm32_ltdcgetvplane + * + * Description: + * Return a a reference to the framebuffer object for the specified video + * plane. + * + * Input Parameters: + * None + * + * Returned Value: + * Reference to the framebuffer object (NULL on failure) + * + ****************************************************************************/ + +struct fb_vtable_s *stm32_ltdcgetvplane(int vplane) +{ + lcdinfo("vplane: %d\n", vplane); + + if (vplane == 0) + { + return &g_vtable.vtable; + } + + return NULL; +} + +/**************************************************************************** + * Name: stm32_ltdcuninitialize + * + * Description: + * Uninitialize the framebuffer driver. Bad things will happen if you + * call this without first calling fb_initialize()! + * + ****************************************************************************/ + +void stm32_ltdcuninitialize(void) +{ + /* Disable all ltdc interrupts */ + + stm32_ltdc_irqctrl(0, LTDC_IER_RRIE | LTDC_IER_TERRIE | + LTDC_IER_FUIE | LTDC_IER_LIE); + + up_disable_irq(g_interrupt.irq); + irq_detach(g_interrupt.irq); + + /* Disable the LCD controller */ + + stm32_ltdc_enable(false); + + /* Set initialized state */ + + g_initialized = false; +} + +/**************************************************************************** + * Name: stm32_lcd_backlight + * + * Description: + * Provide this interface to turn the backlight on and off. + * + * Input Parameters: + * blon - Enable or disable the lcd backlight + * + ****************************************************************************/ + +#ifdef CONFIG_STM32H7_LCD_BACKLIGHT +void stm32_backlight(bool blon) +{ + /* Set default backlight level CONFIG_STM32H7_LTDC_DEFBACKLIGHT */ + + lcderr("ERROR: Not supported\n"); +} +#endif diff --git a/arch/arm/src/stm32h7/stm32_ltdc.h b/arch/arm/src/stm32h7/stm32_ltdc.h new file mode 100644 index 0000000000..72dae60c48 --- /dev/null +++ b/arch/arm/src/stm32h7/stm32_ltdc.h @@ -0,0 +1,100 @@ +/**************************************************************************** + * arch/arm/src/stm32h7/stm32_ltdc.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32F7_STM32_LTDC_H +#define __ARCH_ARM_SRC_STM32F7_STM32_LTDC_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_ltdcreset + * + * Description: + * Reset LTDC via APB2RSTR + * + ****************************************************************************/ + +void stm32_ltdcreset(void); + +/**************************************************************************** + * Name: stm32_ltdcinitialize + * + * Description: + * Initialize the ltdc controller + * + * Returned Value: + * OK + * + ****************************************************************************/ + +int stm32_ltdcinitialize(void); + +/**************************************************************************** + * Name: stm32_ltdcuninitialize + * + * Description: + * Uninitialize the ltdc controller + * + ****************************************************************************/ + +void stm32_ltdcuninitialize(void); + +/**************************************************************************** + * Name: stm32_ltdcgetvplane + * + * Description: + * Get video plane reference used by framebuffer interface + * + * Parameter: + * vplane - Video plane + * + * Returned Value: + * Video plane reference + * + ****************************************************************************/ + +FAR struct fb_vtable_s *stm32_ltdcgetvplane(int vplane); + +/**************************************************************************** + * 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. + * + ****************************************************************************/ + +#ifdef CONFIG_STM32F7_LCD_BACKLIGHT +void stm32_backlight(bool blon); +#endif +#endif /* __ARCH_ARM_SRC_STM32F7_STM32_LTDC_H */ diff --git a/arch/arm/src/stm32h7/stm32h7x3xx_rcc.c b/arch/arm/src/stm32h7/stm32h7x3xx_rcc.c index 40692f7971..ca9b629ec2 100644 --- a/arch/arm/src/stm32h7/stm32h7x3xx_rcc.c +++ b/arch/arm/src/stm32h7/stm32h7x3xx_rcc.c @@ -326,6 +326,12 @@ static inline void rcc_enableahb3(void) regval |= RCC_AHB3ENR_FMCEN; #endif +#if defined(CONFIG_STM32H7_LTDC) && defined(CONFIG_STM32H7_DMA2D) + /* Enable DMA2D */ + + regval |= RCC_AHB3ENR_DMA2DEN; +#endif + /* TODO: ... */ putreg32(regval, STM32_RCC_AHB3ENR); /* Enable peripherals */ @@ -543,7 +549,11 @@ static inline void rcc_enableapb3(void) regval = getreg32(STM32_RCC_APB3ENR); - /* TODO: ... */ +#ifdef CONFIG_STM32H7_LTDC + /* LTDC clock enable */ + + regval |= RCC_APB3ENR_LTDCEN; +#endif putreg32(regval, STM32_RCC_APB3ENR); /* Enable peripherals */ }