[U-Boot] [PATCH v1 0/7] splash screen on the stm32f746 disco board

This serie contains all patchsets needed for displaying a splash screen on the stm32f746 disco board & some display features (reset, blending & line interrupt position).
Philippe CORNU (1): arm: dts: stm32: add ltdc for STM32F746
yannick fertre (6): video: stm32: stm32_ltdc: add reset video: stm32: stm32_ltdc: update file header & footer video: stm32: stm32_ltdc: set rate of the pixel clock video: stm32: stm32_ltdc: missing set of line interrupt position video: stm32: stm32_ltdc: set the blending factor arm: dts: stm32: add display for STM32F746 disco board
arch/arm/dts/stm32f746-disco.dts | 70 +++++++++++++++++++++++ arch/arm/dts/stm32f746.dtsi | 9 +++ drivers/video/stm32/stm32_ltdc.c | 117 +++++++++++++++++++++++++++------------ 3 files changed, 161 insertions(+), 35 deletions(-)

Add reset of LTDC display controller.
Signed-off-by: yannick fertre yannick.fertre@st.com --- drivers/video/stm32/stm32_ltdc.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/drivers/video/stm32/stm32_ltdc.c b/drivers/video/stm32/stm32_ltdc.c index b417ac2..d8784f1 100644 --- a/drivers/video/stm32/stm32_ltdc.c +++ b/drivers/video/stm32/stm32_ltdc.c @@ -11,6 +11,7 @@ #include <clk.h> #include <dm.h> #include <panel.h> +#include <reset.h> #include <video.h> #include <asm/io.h> #include <asm/arch/gpio.h> @@ -302,6 +303,7 @@ static int stm32_ltdc_probe(struct udevice *dev) struct stm32_ltdc_priv *priv = dev_get_priv(dev); struct udevice *panel; struct clk pclk, pxclk; + struct reset_ctl rst; int ret;
priv->regs = (void *)dev_read_addr(dev); @@ -316,6 +318,15 @@ static int stm32_ltdc_probe(struct udevice *dev) return ret; }
+ ret = reset_get_by_index(dev, 0, &rst); + if (ret) { + debug("%s: missing ltdc hardware reset\n", __func__); + return -ENODEV; + } + + /* Reset */ + reset_deassert(&rst); + ret = panel_enable_backlight(panel); if (ret) { debug("%s: panel %s enable backlight error %d\n",

Modified copyright & driver name.
Signed-off-by: yannick fertre yannick.fertre@st.com --- drivers/video/stm32/stm32_ltdc.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-)
diff --git a/drivers/video/stm32/stm32_ltdc.c b/drivers/video/stm32/stm32_ltdc.c index d8784f1..8d89b58 100644 --- a/drivers/video/stm32/stm32_ltdc.c +++ b/drivers/video/stm32/stm32_ltdc.c @@ -1,8 +1,7 @@ /* - * Copyright (C) STMicroelectronics SA 2017 - * - * Authors: Philippe Cornu philippe.cornu@st.com - * Yannick Fertre yannick.fertre@st.com + * Copyright (C) 2017-2018 STMicroelectronics - All Rights Reserved + * Author(s): Philippe Cornu philippe.cornu@st.com for STMicroelectronics. + * Yannick Fertre yannick.fertre@st.com for STMicroelectronics. * * SPDX-License-Identifier: GPL-2.0+ */ @@ -408,10 +407,10 @@ static const struct udevice_id stm32_ltdc_ids[] = { };
U_BOOT_DRIVER(stm32_ltdc) = { - .name = "stm32_ltdc", - .id = UCLASS_VIDEO, - .of_match = stm32_ltdc_ids, - .probe = stm32_ltdc_probe, - .bind = stm32_ltdc_bind, + .name = "stm32_display", + .id = UCLASS_VIDEO, + .of_match = stm32_ltdc_ids, + .probe = stm32_ltdc_probe, + .bind = stm32_ltdc_bind, .priv_auto_alloc_size = sizeof(struct stm32_ltdc_priv), };

pxclk is useless to set pixel clock.
Signed-off-by: yannick fertre yannick.fertre@st.com --- drivers/video/stm32/stm32_ltdc.c | 52 ++++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 23 deletions(-)
diff --git a/drivers/video/stm32/stm32_ltdc.c b/drivers/video/stm32/stm32_ltdc.c index 8d89b58..08e0afc 100644 --- a/drivers/video/stm32/stm32_ltdc.c +++ b/drivers/video/stm32/stm32_ltdc.c @@ -301,9 +301,9 @@ static int stm32_ltdc_probe(struct udevice *dev) struct video_priv *uc_priv = dev_get_uclass_priv(dev); struct stm32_ltdc_priv *priv = dev_get_priv(dev); struct udevice *panel; - struct clk pclk, pxclk; + struct clk pclk; struct reset_ctl rst; - int ret; + int rate, ret;
priv->regs = (void *)dev_read_addr(dev); if ((fdt_addr_t)priv->regs == FDT_ADDR_T_NONE) { @@ -311,9 +311,16 @@ static int stm32_ltdc_probe(struct udevice *dev) return -EINVAL; }
- ret = uclass_first_device(UCLASS_PANEL, &panel); + ret = clk_get_by_index(dev, 0, &pclk); if (ret) { - debug("%s: panel device error %d\n", __func__, ret); + debug("%s: peripheral clock get error %d\n", __func__, ret); + return ret; + } + + ret = clk_enable(&pclk); + if (ret) { + debug("%s: peripheral clock enable error %d\n", + __func__, ret); return ret; }
@@ -326,6 +333,12 @@ static int stm32_ltdc_probe(struct udevice *dev) /* Reset */ reset_deassert(&rst);
+ ret = uclass_first_device(UCLASS_PANEL, &panel); + if (ret) { + debug("%s: panel device error %d\n", __func__, ret); + return ret; + } + ret = panel_enable_backlight(panel); if (ret) { debug("%s: panel %s enable backlight error %d\n", @@ -333,31 +346,24 @@ static int stm32_ltdc_probe(struct udevice *dev) return ret; }
- ret = fdtdec_decode_display_timing(gd->fdt_blob, dev_of_offset(dev), - 0, &priv->timing); + ret = fdtdec_decode_display_timing(gd->fdt_blob, + dev_of_offset(dev), 0, + &priv->timing); if (ret) { - debug("%s: decode display timing error %d\n", __func__, ret); + debug("%s: decode display timing error %d\n", + __func__, ret); return -EINVAL; }
- ret = clk_get_by_name(dev, "pclk", &pclk); - if (ret) { - debug("%s: peripheral clock get error %d\n", __func__, ret); - return ret; + rate = clk_set_rate(&pclk, priv->timing.pixelclock.typ); + if (rate < 0) { + debug("%s: fail to set pixel clock %d hz %d hz\n", + __func__, priv->timing.pixelclock.typ, rate); + return rate; }
- ret = clk_enable(&pclk); - if (ret) { - debug("%s: peripheral clock enable error %d\n", __func__, ret); - return ret; - } - - /* Verify pixel clock value if any & inform user accordingly */ - ret = clk_get_by_name(dev, "pxclk", &pxclk); - if (!ret) { - if (clk_get_rate(&pxclk) != priv->timing.pixelclock.typ) - printf("Warning: please adjust ltdc pixel clock\n"); - } + debug("%s: Set pixel clock req %d hz get %d hz\n", __func__, + priv->timing.pixelclock.typ, rate);
/* TODO Below parameters are hard-coded for the moment... */ priv->l2bpp = VIDEO_BPP16;

Set LIPCR (line interrupt position conf) register with line length.
Signed-off-by: yannick fertre yannick.fertre@st.com --- drivers/video/stm32/stm32_ltdc.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/video/stm32/stm32_ltdc.c b/drivers/video/stm32/stm32_ltdc.c index 08e0afc..6c3557b 100644 --- a/drivers/video/stm32/stm32_ltdc.c +++ b/drivers/video/stm32/stm32_ltdc.c @@ -219,6 +219,8 @@ static void stm32_ltdc_set_mode(struct stm32_ltdc_priv *priv) val = (total_w << 16) | total_h; clrsetbits_le32(regs + LTDC_TWCR, TWCR_TOTALH | TWCR_TOTALW, val);
+ setbits_le32(regs + LTDC_LIPCR, acc_act_h + 1); + /* Signal polarities */ val = 0; debug("%s: timing->flags 0x%08x\n", __func__, timing->flags);

Set the blending factor regarding the pixel format
Signed-off-by: yannick fertre yannick.fertre@st.com --- drivers/video/stm32/stm32_ltdc.c | 41 ++++++++++++++++++++++++++++++++++------ 1 file changed, 35 insertions(+), 6 deletions(-)
diff --git a/drivers/video/stm32/stm32_ltdc.c b/drivers/video/stm32/stm32_ltdc.c index 6c3557b..e160c77 100644 --- a/drivers/video/stm32/stm32_ltdc.c +++ b/drivers/video/stm32/stm32_ltdc.c @@ -138,7 +138,9 @@ struct stm32_ltdc_priv { #define LXCFBLNR_CFBLN GENMASK(10, 0) /* Color Frame Buffer Line Number */
#define BF1_PAXCA 0x600 /* Pixel Alpha x Constant Alpha */ +#define BF1_CA 0x400 /* Constant Alpha */ #define BF2_1PAXCA 0x007 /* 1 - (Pixel Alpha x Constant Alpha) */ +#define BF2_1CA 0x005 /* 1 - Constant Alpha */
enum stm32_ltdc_pix_fmt { PF_ARGB8888 = 0, @@ -161,11 +163,17 @@ static u32 stm32_ltdc_get_pixel_format(enum video_log2_bpp l2bpp) pf = PF_RGB565; break;
+ case VIDEO_BPP32: + pf = PF_ARGB8888; + break; + + case VIDEO_BPP8: + pf = PF_L8; + break; + case VIDEO_BPP1: case VIDEO_BPP2: case VIDEO_BPP4: - case VIDEO_BPP8: - case VIDEO_BPP32: default: debug("%s: warning %dbpp not supported yet, %dbpp instead\n", __func__, VNBITS(l2bpp), VNBITS(VIDEO_BPP16)); @@ -178,6 +186,23 @@ static u32 stm32_ltdc_get_pixel_format(enum video_log2_bpp l2bpp) return (u32)pf; }
+static bool has_alpha(u32 fmt) +{ + switch (fmt) { + case PF_ARGB8888: + case PF_ARGB1555: + case PF_ARGB4444: + case PF_AL44: + case PF_AL88: + return true; + case PF_RGB888: + case PF_RGB565: + case PF_L8: + default: + return false; + } +} + static void stm32_ltdc_enable(struct stm32_ltdc_priv *priv) { /* Reload configuration immediately & enable LTDC */ @@ -247,6 +272,7 @@ static void stm32_ltdc_set_layer1(struct stm32_ltdc_priv *priv, ulong fb_addr) u32 line_length; u32 bus_width; u32 val, tmp, bpp; + u32 format;
x0 = priv->crop_x; x1 = priv->crop_x + priv->crop_w - 1; @@ -277,15 +303,18 @@ static void stm32_ltdc_set_layer1(struct stm32_ltdc_priv *priv, ulong fb_addr) clrsetbits_le32(regs + LTDC_L1CFBLR, LXCFBLR_CFBLL | LXCFBLR_CFBP, val);
/* Pixel format */ - val = stm32_ltdc_get_pixel_format(priv->l2bpp); - clrsetbits_le32(regs + LTDC_L1PFCR, LXPFCR_PF, val); + format = stm32_ltdc_get_pixel_format(priv->l2bpp); + clrsetbits_le32(regs + LTDC_L1PFCR, LXPFCR_PF, format);
/* Constant alpha value */ clrsetbits_le32(regs + LTDC_L1CACR, LXCACR_CONSTA, priv->alpha);
+ /* Specifies the blending factors : with or without pixel alpha */ + /* Manage hw-specific capabilities */ + val = has_alpha(format) ? BF1_PAXCA | BF2_1PAXCA : BF1_CA | BF2_1CA; + /* Blending factors */ - clrsetbits_le32(regs + LTDC_L1BFCR, LXBFCR_BF2 | LXBFCR_BF1, - BF1_PAXCA | BF2_1PAXCA); + clrsetbits_le32(regs + LTDC_L1BFCR, LXBFCR_BF2 | LXBFCR_BF1, val);
/* Frame buffer line number */ clrsetbits_le32(regs + LTDC_L1CFBLNR, LXCFBLNR_CFBLN, priv->crop_h);

From: Philippe CORNU philippe.cornu@st.com
Add display controller node in device-tree.
Signed-off-by: yannick fertre yannick.fertre@st.com --- arch/arm/dts/stm32f746.dtsi | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/arch/arm/dts/stm32f746.dtsi b/arch/arm/dts/stm32f746.dtsi index 46d148e..e4d32bf 100644 --- a/arch/arm/dts/stm32f746.dtsi +++ b/arch/arm/dts/stm32f746.dtsi @@ -323,6 +323,15 @@ pinctrl-names = "default", "opendrain"; max-frequency = <48000000>; }; + + ltdc: display-controller@40016800 { + compatible = "st,stm32-ltdc"; + reg = <0x40016800 0x200>; + resets = <&rcc STM32F7_APB2_RESET(LTDC)>; + clocks = <&rcc 0 STM32F7_APB2_CLOCK(LTDC)>; + u-boot,dm-pre-reloc; + status = "disabled"; + }; }; };

Enable the display controller , panel & backlight. Set panel display timings & set the RGB data bus.
Signed-off-by: yannick fertre yannick.fertre@st.com --- arch/arm/dts/stm32f746-disco.dts | 70 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+)
diff --git a/arch/arm/dts/stm32f746-disco.dts b/arch/arm/dts/stm32f746-disco.dts index 9e8d2a0..bbde947 100644 --- a/arch/arm/dts/stm32f746-disco.dts +++ b/arch/arm/dts/stm32f746-disco.dts @@ -89,6 +89,37 @@ compatible = "st,button1"; button-gpio = <&gpioi 11 0>; }; + + backlight: backlight { + compatible = "gpio-backlight"; + gpios = <&gpiok 3 0>; + status = "okay"; + }; + + panel: panel { + compatible = "simple-panel"; + backlight = <&backlight>; + enable-gpios = <&gpioi 12 0>; + status = "okay"; + + display-timings { + timing@0 { + clock-frequency = <9000000>; + hactive = <480>; + vactive = <272>; + hfront-porch = <2>; + hback-porch = <2>; + hsync-len = <41>; + vfront-porch = <2>; + vback-porch = <2>; + vsync-len = <10>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <0>; + pixelclk-active = <1>; + }; + }; + }; };
&clk_hse { @@ -183,6 +214,40 @@ slew-rate = <2>; }; }; + + ltdc_pins: ltdc@0 { + pins { + pinmux = <STM32F746_PE4_FUNC_LCD_B0>, + <STM32F746_PG12_FUNC_LCD_B4>, + <STM32F746_PI9_FUNC_LCD_VSYNC>, + <STM32F746_PI10_FUNC_LCD_HSYNC>, + <STM32F746_PI14_FUNC_LCD_CLK>, + <STM32F746_PI15_FUNC_LCD_R0>, + <STM32F746_PJ0_FUNC_LCD_R1>, + <STM32F746_PJ1_FUNC_LCD_R2>, + <STM32F746_PJ2_FUNC_LCD_R3>, + <STM32F746_PJ3_FUNC_LCD_R4>, + <STM32F746_PJ4_FUNC_LCD_R5>, + <STM32F746_PJ5_FUNC_LCD_R6>, + <STM32F746_PJ6_FUNC_LCD_R7>, + <STM32F746_PJ7_FUNC_LCD_G0>, + <STM32F746_PJ8_FUNC_LCD_G1>, + <STM32F746_PJ9_FUNC_LCD_G2>, + <STM32F746_PJ10_FUNC_LCD_G3>, + <STM32F746_PJ11_FUNC_LCD_G4>, + <STM32F746_PJ13_FUNC_LCD_B1>, + <STM32F746_PJ14_FUNC_LCD_B2>, + <STM32F746_PJ15_FUNC_LCD_B3>, + <STM32F746_PK0_FUNC_LCD_G5>, + <STM32F746_PK1_FUNC_LCD_G6>, + <STM32F746_PK2_FUNC_LCD_G7>, + <STM32F746_PK4_FUNC_LCD_B5>, + <STM32F746_PK5_FUNC_LCD_B6>, + <STM32F746_PK6_FUNC_LCD_B7>, + <STM32F746_PK7_FUNC_LCD_DE>; + slew-rate = <2>; + }; + }; };
&usart1 { @@ -250,3 +315,8 @@ bus-width = <4>; max-frequency = <25000000>; }; + +<dc { + status = "okay"; + pinctrl-0 = <<dc_pins>; +};
participants (1)
-
yannick fertre