[RFC,4/5] ARM: dts: stm32: support display on stm32f469-disco board

Message ID 20230903205703.662080-5-dario.binacchi@amarulasolutions.com
State New
Headers show
Series
  • Support display on stm32f469-disco board
Related show

Commit Message

Dario Binacchi Sept. 3, 2023, 8:57 p.m. UTC
Add support to Orise Tech OTM8009A display on stm32f469-disco board.

It was necessary to retrieve the framebuffer address from the device tree
because the address returned by the video-uclass driver pointed to a memory
area that was not usable.

Furthermore, unlike Linux, the DSI driver requires the LTDC clock to be
properly probed. Hence, the changes made to the DSI node in
stm32f469-disco-u-boot.dtsi.

Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
---

 arch/arm/dts/stm32f469-disco-u-boot.dtsi |  4 +++
 configs/stm32f469-discovery_defconfig    | 13 +++++++++
 drivers/video/stm32/stm32_ltdc.c         | 37 +++++++++++++++++++++++-
 3 files changed, 53 insertions(+), 1 deletion(-)

Comments

Patrice CHOTARD Sept. 27, 2023, 6:19 a.m. UTC | #1
On 9/3/23 22:57, Dario Binacchi wrote:
> Add support to Orise Tech OTM8009A display on stm32f469-disco board.
> 
> It was necessary to retrieve the framebuffer address from the device tree
> because the address returned by the video-uclass driver pointed to a memory
> area that was not usable.
> 
> Furthermore, unlike Linux, the DSI driver requires the LTDC clock to be
> properly probed. Hence, the changes made to the DSI node in
> stm32f469-disco-u-boot.dtsi.
> 
> Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
> ---
> 
>  arch/arm/dts/stm32f469-disco-u-boot.dtsi |  4 +++
>  configs/stm32f469-discovery_defconfig    | 13 +++++++++
>  drivers/video/stm32/stm32_ltdc.c         | 37 +++++++++++++++++++++++-
>  3 files changed, 53 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm/dts/stm32f469-disco-u-boot.dtsi b/arch/arm/dts/stm32f469-disco-u-boot.dtsi
> index 8e781c5a7b23..47ba9fa4a783 100644
> --- a/arch/arm/dts/stm32f469-disco-u-boot.dtsi
> +++ b/arch/arm/dts/stm32f469-disco-u-boot.dtsi
> @@ -92,7 +92,9 @@
>  
>  &dsi {
>  	clocks = <&rcc 0 STM32F4_APB2_CLOCK(DSI)>,
> +		 <&rcc 0 STM32F4_APB2_CLOCK(LTDC)>,
>  		 <&clk_hse>;
> +	clock-names = "pclk", "px_clk", "ref";
>  };
>  
>  &gpioa {
> @@ -140,6 +142,8 @@
>  };
>  
>  &ltdc {
> +	bootph-all;
> +
>  	clocks = <&rcc 0 STM32F4_APB2_CLOCK(LTDC)>;
>  };
>  
> diff --git a/configs/stm32f469-discovery_defconfig b/configs/stm32f469-discovery_defconfig
> index 35d18d58be6f..9796b8f2d9a5 100644
> --- a/configs/stm32f469-discovery_defconfig
> +++ b/configs/stm32f469-discovery_defconfig
> @@ -21,6 +21,7 @@ CONFIG_CMD_GPT=y
>  # CONFIG_RANDOM_UUID is not set
>  CONFIG_CMD_MMC=y
>  # CONFIG_CMD_SETEXPR is not set
> +CONFIG_CMD_BMP=y
>  CONFIG_CMD_CACHE=y
>  CONFIG_CMD_TIMER=y
>  # CONFIG_ISO_PARTITION is not set
> @@ -40,3 +41,15 @@ CONFIG_SPI_FLASH_STMICRO=y
>  CONFIG_SPI=y
>  CONFIG_DM_SPI=y
>  CONFIG_STM32_QSPI=y
> +CONFIG_VIDEO=y
> +CONFIG_BACKLIGHT_GPIO=y
> +CONFIG_VIDEO_LCD_ORISETECH_OTM8009A=y
> +CONFIG_VIDEO_STM32=y
> +CONFIG_VIDEO_STM32_DSI=y
> +CONFIG_VIDEO_STM32_MAX_XRES=480
> +CONFIG_VIDEO_STM32_MAX_YRES=800
> +CONFIG_BMP_16BPP=y
> +CONFIG_BMP_24BPP=y
> +CONFIG_BMP_32BPP=y
> +CONFIG_DM_REGULATOR=y
> +CONFIG_DM_REGULATOR_FIXED=y
> diff --git a/drivers/video/stm32/stm32_ltdc.c b/drivers/video/stm32/stm32_ltdc.c
> index f48badc517a8..428b0addc43c 100644
> --- a/drivers/video/stm32/stm32_ltdc.c
> +++ b/drivers/video/stm32/stm32_ltdc.c
> @@ -494,6 +494,34 @@ static void stm32_ltdc_set_layer1(struct stm32_ltdc_priv *priv, ulong fb_addr)
>  	setbits_le32(priv->regs + LTDC_L1CR, LXCR_LEN);
>  }
>  
> +#if IS_ENABLED(CONFIG_TARGET_STM32F469_DISCOVERY)

We want to avoid this kind of #define specific to a particular target

> +static int stm32_ltdc_get_fb_addr(struct udevice *dev, ulong *base, uint size,
> +				  uint align)
> +{
> +	phys_addr_t cpu;
> +	dma_addr_t bus;
> +	u64 dma_size;
> +	int ret;
> +
> +	ret = dev_get_dma_range(dev, &cpu, &bus, &dma_size);
> +	if (ret) {
> +		dev_err(dev, "failed to get dma address\n");
> +		return ret;
> +	}
> +
> +	*base = bus + 0x1000000 - ALIGN(size, align);

Why adding 0x1000000 ? avoid to insert const whithout any description and use a #define instead.

> +	return 0;
> +}
> +#else
> +static int stm32_ltdc_get_fb_addr(struct udevice *dev, ulong *base, uint size,
> +				  uint align)
> +{
> +	/* Delegate framebuffer allocation to video-uclass */
> +	*base = 0;
> +	return 0;
> +}
> +#endif
> +
>  static int stm32_ltdc_probe(struct udevice *dev)
>  {
>  	struct video_uc_plat *uc_plat = dev_get_uclass_plat(dev);
> @@ -504,7 +532,7 @@ static int stm32_ltdc_probe(struct udevice *dev)
>  	struct display_timing timings;
>  	struct clk pclk;
>  	struct reset_ctl rst;
> -	ulong rate;
> +	ulong rate, fb_base;
>  	int ret;
>  
>  	priv->regs = dev_read_addr_ptr(dev);
> @@ -604,6 +632,13 @@ static int stm32_ltdc_probe(struct udevice *dev)
>  	priv->crop_h = timings.vactive.typ;
>  	priv->alpha = 0xFF;
>  
> +	ret = stm32_ltdc_get_fb_addr(dev, &fb_base, uc_plat->size,
> +				     uc_plat->align);
> +	if (ret)
> +		return ret;
> +
> +	uc_plat->base = fb_base;
> +

It breaks display on stm32f746-disco and also on stm32f769-disco.

Thanks
Patrice

>  	dev_dbg(dev, "%dx%d %dbpp frame buffer at 0x%lx\n",
>  		timings.hactive.typ, timings.vactive.typ,
>  		VNBITS(priv->l2bpp), uc_plat->base);
Dario Binacchi Oct. 8, 2023, 3:41 p.m. UTC | #2
Hello Patrice,

On Wed, Sep 27, 2023 at 8:19 AM Patrice CHOTARD
<patrice.chotard@foss.st.com> wrote:
>
>
>
> On 9/3/23 22:57, Dario Binacchi wrote:
> > Add support to Orise Tech OTM8009A display on stm32f469-disco board.
> >
> > It was necessary to retrieve the framebuffer address from the device tree
> > because the address returned by the video-uclass driver pointed to a memory
> > area that was not usable.
> >
> > Furthermore, unlike Linux, the DSI driver requires the LTDC clock to be
> > properly probed. Hence, the changes made to the DSI node in
> > stm32f469-disco-u-boot.dtsi.
> >
> > Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
> > ---
> >
> >  arch/arm/dts/stm32f469-disco-u-boot.dtsi |  4 +++
> >  configs/stm32f469-discovery_defconfig    | 13 +++++++++
> >  drivers/video/stm32/stm32_ltdc.c         | 37 +++++++++++++++++++++++-
> >  3 files changed, 53 insertions(+), 1 deletion(-)
> >
> > diff --git a/arch/arm/dts/stm32f469-disco-u-boot.dtsi b/arch/arm/dts/stm32f469-disco-u-boot.dtsi
> > index 8e781c5a7b23..47ba9fa4a783 100644
> > --- a/arch/arm/dts/stm32f469-disco-u-boot.dtsi
> > +++ b/arch/arm/dts/stm32f469-disco-u-boot.dtsi
> > @@ -92,7 +92,9 @@
> >
> >  &dsi {
> >       clocks = <&rcc 0 STM32F4_APB2_CLOCK(DSI)>,
> > +              <&rcc 0 STM32F4_APB2_CLOCK(LTDC)>,
> >                <&clk_hse>;
> > +     clock-names = "pclk", "px_clk", "ref";
> >  };
> >
> >  &gpioa {
> > @@ -140,6 +142,8 @@
> >  };
> >
> >  &ltdc {
> > +     bootph-all;
> > +
> >       clocks = <&rcc 0 STM32F4_APB2_CLOCK(LTDC)>;
> >  };
> >
> > diff --git a/configs/stm32f469-discovery_defconfig b/configs/stm32f469-discovery_defconfig
> > index 35d18d58be6f..9796b8f2d9a5 100644
> > --- a/configs/stm32f469-discovery_defconfig
> > +++ b/configs/stm32f469-discovery_defconfig
> > @@ -21,6 +21,7 @@ CONFIG_CMD_GPT=y
> >  # CONFIG_RANDOM_UUID is not set
> >  CONFIG_CMD_MMC=y
> >  # CONFIG_CMD_SETEXPR is not set
> > +CONFIG_CMD_BMP=y
> >  CONFIG_CMD_CACHE=y
> >  CONFIG_CMD_TIMER=y
> >  # CONFIG_ISO_PARTITION is not set
> > @@ -40,3 +41,15 @@ CONFIG_SPI_FLASH_STMICRO=y
> >  CONFIG_SPI=y
> >  CONFIG_DM_SPI=y
> >  CONFIG_STM32_QSPI=y
> > +CONFIG_VIDEO=y
> > +CONFIG_BACKLIGHT_GPIO=y
> > +CONFIG_VIDEO_LCD_ORISETECH_OTM8009A=y
> > +CONFIG_VIDEO_STM32=y
> > +CONFIG_VIDEO_STM32_DSI=y
> > +CONFIG_VIDEO_STM32_MAX_XRES=480
> > +CONFIG_VIDEO_STM32_MAX_YRES=800
> > +CONFIG_BMP_16BPP=y
> > +CONFIG_BMP_24BPP=y
> > +CONFIG_BMP_32BPP=y
> > +CONFIG_DM_REGULATOR=y
> > +CONFIG_DM_REGULATOR_FIXED=y
> > diff --git a/drivers/video/stm32/stm32_ltdc.c b/drivers/video/stm32/stm32_ltdc.c
> > index f48badc517a8..428b0addc43c 100644
> > --- a/drivers/video/stm32/stm32_ltdc.c
> > +++ b/drivers/video/stm32/stm32_ltdc.c
> > @@ -494,6 +494,34 @@ static void stm32_ltdc_set_layer1(struct stm32_ltdc_priv *priv, ulong fb_addr)
> >       setbits_le32(priv->regs + LTDC_L1CR, LXCR_LEN);
> >  }
> >
> > +#if IS_ENABLED(CONFIG_TARGET_STM32F469_DISCOVERY)
>
> We want to avoid this kind of #define specific to a particular target

If the framebuffer is allocated by the video-uclass module, it is
mapped to the address 0xe00000, which does
not appear to be a correct memory zone. Therefore, for the
stm32f469-disco board, a different method for
framebuffer allocation is required, and this seemed to me the most
suitable way. I have submitted the series
as an RFC, and this is one of the points for which I did it. So, I am
open to considering any suggestions you
may have.

Output in case of applied patch:
stm32_display display-controller@40016800: 480x800 16bpp frame buffer
at 0xc0e00000

Otherwise:
stm32_display display-controller@40016800: 480x800 16bpp frame buffer
at 0xe00000

>
> > +static int stm32_ltdc_get_fb_addr(struct udevice *dev, ulong *base, uint size,
> > +                               uint align)
> > +{
> > +     phys_addr_t cpu;
> > +     dma_addr_t bus;
> > +     u64 dma_size;
> > +     int ret;
> > +
> > +     ret = dev_get_dma_range(dev, &cpu, &bus, &dma_size);
> > +     if (ret) {
> > +             dev_err(dev, "failed to get dma address\n");
> > +             return ret;
> > +     }
> > +
> > +     *base = bus + 0x1000000 - ALIGN(size, align);
>
> Why adding 0x1000000 ? avoid to insert const whithout any description and use a #define instead.

Right, I will add it in version 2.

>
> > +     return 0;
> > +}
> > +#else
> > +static int stm32_ltdc_get_fb_addr(struct udevice *dev, ulong *base, uint size,
> > +                               uint align)
> > +{
> > +     /* Delegate framebuffer allocation to video-uclass */
> > +     *base = 0;
> > +     return 0;
> > +}
> > +#endif
> > +
> >  static int stm32_ltdc_probe(struct udevice *dev)
> >  {
> >       struct video_uc_plat *uc_plat = dev_get_uclass_plat(dev);
> > @@ -504,7 +532,7 @@ static int stm32_ltdc_probe(struct udevice *dev)
> >       struct display_timing timings;
> >       struct clk pclk;
> >       struct reset_ctl rst;
> > -     ulong rate;
> > +     ulong rate, fb_base;
> >       int ret;
> >
> >       priv->regs = dev_read_addr_ptr(dev);
> > @@ -604,6 +632,13 @@ static int stm32_ltdc_probe(struct udevice *dev)
> >       priv->crop_h = timings.vactive.typ;
> >       priv->alpha = 0xFF;
> >
> > +     ret = stm32_ltdc_get_fb_addr(dev, &fb_base, uc_plat->size,
> > +                                  uc_plat->align);
> > +     if (ret)
> > +             return ret;
> > +
> > +     uc_plat->base = fb_base;
> > +
>
> It breaks display on stm32f746-disco and also on stm32f769-disco.

You are right, I will fix it in version 2.

Thanks and regards,

Dario

>
> Thanks
> Patrice
>
> >       dev_dbg(dev, "%dx%d %dbpp frame buffer at 0x%lx\n",
> >               timings.hactive.typ, timings.vactive.typ,
> >               VNBITS(priv->l2bpp), uc_plat->base);

Patch

diff --git a/arch/arm/dts/stm32f469-disco-u-boot.dtsi b/arch/arm/dts/stm32f469-disco-u-boot.dtsi
index 8e781c5a7b23..47ba9fa4a783 100644
--- a/arch/arm/dts/stm32f469-disco-u-boot.dtsi
+++ b/arch/arm/dts/stm32f469-disco-u-boot.dtsi
@@ -92,7 +92,9 @@ 
 
 &dsi {
 	clocks = <&rcc 0 STM32F4_APB2_CLOCK(DSI)>,
+		 <&rcc 0 STM32F4_APB2_CLOCK(LTDC)>,
 		 <&clk_hse>;
+	clock-names = "pclk", "px_clk", "ref";
 };
 
 &gpioa {
@@ -140,6 +142,8 @@ 
 };
 
 &ltdc {
+	bootph-all;
+
 	clocks = <&rcc 0 STM32F4_APB2_CLOCK(LTDC)>;
 };
 
diff --git a/configs/stm32f469-discovery_defconfig b/configs/stm32f469-discovery_defconfig
index 35d18d58be6f..9796b8f2d9a5 100644
--- a/configs/stm32f469-discovery_defconfig
+++ b/configs/stm32f469-discovery_defconfig
@@ -21,6 +21,7 @@  CONFIG_CMD_GPT=y
 # CONFIG_RANDOM_UUID is not set
 CONFIG_CMD_MMC=y
 # CONFIG_CMD_SETEXPR is not set
+CONFIG_CMD_BMP=y
 CONFIG_CMD_CACHE=y
 CONFIG_CMD_TIMER=y
 # CONFIG_ISO_PARTITION is not set
@@ -40,3 +41,15 @@  CONFIG_SPI_FLASH_STMICRO=y
 CONFIG_SPI=y
 CONFIG_DM_SPI=y
 CONFIG_STM32_QSPI=y
+CONFIG_VIDEO=y
+CONFIG_BACKLIGHT_GPIO=y
+CONFIG_VIDEO_LCD_ORISETECH_OTM8009A=y
+CONFIG_VIDEO_STM32=y
+CONFIG_VIDEO_STM32_DSI=y
+CONFIG_VIDEO_STM32_MAX_XRES=480
+CONFIG_VIDEO_STM32_MAX_YRES=800
+CONFIG_BMP_16BPP=y
+CONFIG_BMP_24BPP=y
+CONFIG_BMP_32BPP=y
+CONFIG_DM_REGULATOR=y
+CONFIG_DM_REGULATOR_FIXED=y
diff --git a/drivers/video/stm32/stm32_ltdc.c b/drivers/video/stm32/stm32_ltdc.c
index f48badc517a8..428b0addc43c 100644
--- a/drivers/video/stm32/stm32_ltdc.c
+++ b/drivers/video/stm32/stm32_ltdc.c
@@ -494,6 +494,34 @@  static void stm32_ltdc_set_layer1(struct stm32_ltdc_priv *priv, ulong fb_addr)
 	setbits_le32(priv->regs + LTDC_L1CR, LXCR_LEN);
 }
 
+#if IS_ENABLED(CONFIG_TARGET_STM32F469_DISCOVERY)
+static int stm32_ltdc_get_fb_addr(struct udevice *dev, ulong *base, uint size,
+				  uint align)
+{
+	phys_addr_t cpu;
+	dma_addr_t bus;
+	u64 dma_size;
+	int ret;
+
+	ret = dev_get_dma_range(dev, &cpu, &bus, &dma_size);
+	if (ret) {
+		dev_err(dev, "failed to get dma address\n");
+		return ret;
+	}
+
+	*base = bus + 0x1000000 - ALIGN(size, align);
+	return 0;
+}
+#else
+static int stm32_ltdc_get_fb_addr(struct udevice *dev, ulong *base, uint size,
+				  uint align)
+{
+	/* Delegate framebuffer allocation to video-uclass */
+	*base = 0;
+	return 0;
+}
+#endif
+
 static int stm32_ltdc_probe(struct udevice *dev)
 {
 	struct video_uc_plat *uc_plat = dev_get_uclass_plat(dev);
@@ -504,7 +532,7 @@  static int stm32_ltdc_probe(struct udevice *dev)
 	struct display_timing timings;
 	struct clk pclk;
 	struct reset_ctl rst;
-	ulong rate;
+	ulong rate, fb_base;
 	int ret;
 
 	priv->regs = dev_read_addr_ptr(dev);
@@ -604,6 +632,13 @@  static int stm32_ltdc_probe(struct udevice *dev)
 	priv->crop_h = timings.vactive.typ;
 	priv->alpha = 0xFF;
 
+	ret = stm32_ltdc_get_fb_addr(dev, &fb_base, uc_plat->size,
+				     uc_plat->align);
+	if (ret)
+		return ret;
+
+	uc_plat->base = fb_base;
+
 	dev_dbg(dev, "%dx%d %dbpp frame buffer at 0x%lx\n",
 		timings.hactive.typ, timings.vactive.typ,
 		VNBITS(priv->l2bpp), uc_plat->base);