Skip to contentSkip to conversation

splash screen on the stm32f769 disco board

PATCH Superseded yannick fertre 6 participants 28 messages Mar 2, 2018 – Mar 13, 2018

Subsystems (3)

v2 of 3 Superseded Latest is v3 →

lore
Share & tools
lore
#0 lore raw

v2 cover splash screen on the stm32f769 disco board

Version 2:
- Replace debug log by pr_error, pr_warn or pr_info.
- Rework bridge between ltdc & dsi panel
- Rework backligh management (with or witout gpio)
- Rework panel otm8009a
- Add new panel raydium rm68200

Version 1:
- Initial commit

This serie contains all patchsets needed for displaying a splash screen on the stm32f769 disco board.

yannick fertre (10):
video: stm32: stm32_ltdc: add bridge to display controller
video: stm32: stm32_ltdc: update debug log
video: add support of MIPI DSI interface
video: add support of panel OTM8009A
video: add MIPI DSI host controller bridge
video: add support of STM32 MIPI DSI controller driver
video: add support of panel rm68200
arm: dts: stm32: add dsi for STM32F746
arm: dts: stm32: add display for STM32F769 disco board
board: Add STM32F769 SoC, discovery board support

 arch/arm/dts/stm32f746.dtsi        |  12 +
 arch/arm/dts/stm32f769-disco.dts   |  71 ++++
 configs/stm32f769-disco_defconfig  |  63 +++
 drivers/video/Kconfig              |  32 ++
 drivers/video/Makefile             |   4 +
 drivers/video/dw_mipi_dsi.c        | 822 +++++++++++++++++++++++++++++++++++++
 drivers/video/mipi_display.c       | 807 ++++++++++++++++++++++++++++++++++++
 drivers/video/orisetech_otm8009a.c | 329 +++++++++++++++
 drivers/video/raydium-rm68200.c    | 329 +++++++++++++++
 drivers/video/stm32/Kconfig        |  10 +
 drivers/video/stm32/Makefile       |   1 +
 drivers/video/stm32/stm32_dsi.c    | 427 +++++++++++++++++++
 drivers/video/stm32/stm32_ltdc.c   | 144 ++++---
 include/dw_mipi_dsi.h              |  32 ++
 include/mipi_display.h             | 257 +++++++++++-
 15 files changed, 3285 insertions(+), 55 deletions(-)
 create mode 100644 configs/stm32f769-disco_defconfig
 create mode 100644 drivers/video/dw_mipi_dsi.c
 create mode 100644 drivers/video/mipi_display.c
 create mode 100644 drivers/video/orisetech_otm8009a.c
 create mode 100644 drivers/video/raydium-rm68200.c
 create mode 100644 drivers/video/stm32/stm32_dsi.c
 create mode 100644 include/dw_mipi_dsi.h
Signature · 1 line
1.9.1
#1 lore raw

PATCH v2 1/10 video: stm32: stm32_ltdc: add bridge to display controller

Manage a bridge insert between the display controller & a panel.

---
 drivers/video/stm32/stm32_ltdc.c | 107 ++++++++++++++++++++++++++-------------
 1 file changed, 71 insertions(+), 36 deletions(-)
drivers/video/stm32/stm32_ltdc.c +71 -36
index e160c77..bd9c0de 100644
@@ -8,6 +8,7 @@
 
 #include <common.h>
 #include <clk.h>
+#include <display.h>
 #include <dm.h>
 #include <panel.h>
 #include <reset.h>
@@ -15,12 +16,12 @@
 #include <asm/io.h>
 #include <asm/arch/gpio.h>
 #include <dm/device-internal.h>
+#include <video_bridge.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
 struct stm32_ltdc_priv {
 	void __iomem *regs;
-	struct display_timing timing;
 	enum video_log2_bpp l2bpp;
 	u32 bg_col_argb;
 	u32 crop_x, crop_y, crop_w, crop_h;
@@ -210,23 +211,23 @@ static void stm32_ltdc_enable(struct stm32_ltdc_priv *priv)
 	setbits_le32(priv->regs + LTDC_GCR, GCR_LTDCEN);
 }
 
-static void stm32_ltdc_set_mode(struct stm32_ltdc_priv *priv)
+static void stm32_ltdc_set_mode(struct stm32_ltdc_priv *priv,
+				struct display_timing *timings)
 {
 	void __iomem *regs = priv->regs;
-	struct display_timing *timing = &priv->timing;
 	u32 hsync, vsync, acc_hbp, acc_vbp, acc_act_w, acc_act_h;
 	u32 total_w, total_h;
 	u32 val;
 
 	/* Convert video timings to ltdc timings */
-	hsync = timing->hsync_len.typ - 1;
-	vsync = timing->vsync_len.typ - 1;
-	acc_hbp = hsync + timing->hback_porch.typ;
-	acc_vbp = vsync + timing->vback_porch.typ;
-	acc_act_w = acc_hbp + timing->hactive.typ;
-	acc_act_h = acc_vbp + timing->vactive.typ;
-	total_w = acc_act_w + timing->hfront_porch.typ;
-	total_h = acc_act_h + timing->vfront_porch.typ;
+	hsync = timings->hsync_len.typ - 1;
+	vsync = timings->vsync_len.typ - 1;
+	acc_hbp = hsync + timings->hback_porch.typ;
+	acc_vbp = vsync + timings->vback_porch.typ;
+	acc_act_w = acc_hbp + timings->hactive.typ;
+	acc_act_h = acc_vbp + timings->vactive.typ;
+	total_w = acc_act_w + timings->hfront_porch.typ;
+	total_h = acc_act_h + timings->vfront_porch.typ;
 
 	/* Synchronization sizes */
 	val = (hsync << 16) | vsync;
@@ -248,14 +249,14 @@ static void stm32_ltdc_set_mode(struct stm32_ltdc_priv *priv)
 
 	/* Signal polarities */
 	val = 0;
-	debug("%s: timing->flags 0x%08x\n", __func__, timing->flags);
-	if (timing->flags & DISPLAY_FLAGS_HSYNC_HIGH)
+	debug("%s: timing->flags 0x%08x\n", __func__, timings->flags);
+	if (timings->flags & DISPLAY_FLAGS_HSYNC_HIGH)
 		val |= GCR_HSPOL;
-	if (timing->flags & DISPLAY_FLAGS_VSYNC_HIGH)
+	if (timings->flags & DISPLAY_FLAGS_VSYNC_HIGH)
 		val |= GCR_VSPOL;
-	if (timing->flags & DISPLAY_FLAGS_DE_HIGH)
+	if (timings->flags & DISPLAY_FLAGS_DE_HIGH)
 		val |= GCR_DEPOL;
-	if (timing->flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE)
+	if (timings->flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE)
 		val |= GCR_PCPOL;
 	clrsetbits_le32(regs + LTDC_GCR,
 			GCR_HSPOL | GCR_VSPOL | GCR_DEPOL | GCR_PCPOL, val);
@@ -331,7 +332,11 @@ static int stm32_ltdc_probe(struct udevice *dev)
 	struct video_uc_platdata *uc_plat = dev_get_uclass_platdata(dev);
 	struct video_priv *uc_priv = dev_get_uclass_priv(dev);
 	struct stm32_ltdc_priv *priv = dev_get_priv(dev);
-	struct udevice *panel;
+#ifdef CONFIG_VIDEO_BRIDGE
+	struct udevice *bridge = NULL;
+#endif
+	struct udevice *panel = NULL;
+	struct display_timing timings;
 	struct clk pclk;
 	struct reset_ctl rst;
 	int rate, ret;
@@ -364,63 +369,93 @@ static int stm32_ltdc_probe(struct udevice *dev)
 	/* Reset */
 	reset_deassert(&rst);
 
-	ret = uclass_first_device(UCLASS_PANEL, &panel);
+#ifdef CONFIG_VIDEO_BRIDGE
+	ret = uclass_get_device(UCLASS_VIDEO_BRIDGE, 0, &bridge);
 	if (ret) {
-		debug("%s: panel device error %d\n", __func__, ret);
-		return ret;
+		debug("%s: No video bridge, or no backlight on bridge\n",
+		      __func__);
 	}
 
-	ret = panel_enable_backlight(panel);
+	if (bridge) {
+		ret = video_bridge_attach(bridge);
+		if (ret) {
+			debug("%s: fail to attach bridge\n", __func__);
+			return ret;
+		}
+	}
+#endif
+	ret = uclass_first_device(UCLASS_PANEL, &panel);
 	if (ret) {
-		debug("%s: panel %s enable backlight error %d\n",
-		      __func__, panel->name, ret);
+		debug("%s: panel device error %d\n", __func__, ret);
 		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(panel),
+					   0, &timings);
 	if (ret) {
 		debug("%s: decode display timing error %d\n",
 		      __func__, ret);
-		return -EINVAL;
+		return ret;
 	}
 
-	rate = clk_set_rate(&pclk, priv->timing.pixelclock.typ);
+	rate = clk_set_rate(&pclk, timings.pixelclock.typ);
 	if (rate < 0) {
 		debug("%s: fail to set pixel clock %d hz %d hz\n",
-		      __func__, priv->timing.pixelclock.typ, rate);
+		      __func__, timings.pixelclock.typ, rate);
 		return rate;
 	}
 
 	debug("%s: Set pixel clock req %d hz get %d hz\n", __func__,
-	      priv->timing.pixelclock.typ, rate);
+	      timings.pixelclock.typ, rate);
 
 	/* TODO Below parameters are hard-coded for the moment... */
 	priv->l2bpp = VIDEO_BPP16;
 	priv->bg_col_argb = 0xFFFFFFFF; /* white no transparency */
 	priv->crop_x = 0;
 	priv->crop_y = 0;
-	priv->crop_w = priv->timing.hactive.typ;
-	priv->crop_h = priv->timing.vactive.typ;
+	priv->crop_w = timings.hactive.typ;
+	priv->crop_h = timings.vactive.typ;
 	priv->alpha = 0xFF;
 
 	debug("%s: %dx%d %dbpp frame buffer at 0x%lx\n", __func__,
-	      priv->timing.hactive.typ, priv->timing.vactive.typ,
+	      timings.hactive.typ, timings.vactive.typ,
 	      VNBITS(priv->l2bpp), uc_plat->base);
 	debug("%s: crop %d,%d %dx%d bg 0x%08x alpha %d\n", __func__,
 	      priv->crop_x, priv->crop_y, priv->crop_w, priv->crop_h,
 	      priv->bg_col_argb, priv->alpha);
 
 	/* Configure & start LTDC */
-	stm32_ltdc_set_mode(priv);
+	stm32_ltdc_set_mode(priv, &timings);
 	stm32_ltdc_set_layer1(priv, uc_plat->base);
 	stm32_ltdc_enable(priv);
 
-	uc_priv->xsize = priv->timing.hactive.typ;
-	uc_priv->ysize = priv->timing.vactive.typ;
+	uc_priv->xsize = timings.hactive.typ;
+	uc_priv->ysize = timings.vactive.typ;
 	uc_priv->bpix = priv->l2bpp;
 
+#ifdef CONFIG_VIDEO_BRIDGE
+	if (bridge) {
+		ret = video_bridge_set_backlight(bridge, 80);
+		if (ret) {
+			debug("%s: fail to set backlight\n", __func__);
+			return ret;
+		}
+	} else {
+		ret = panel_enable_backlight(panel);
+		if (ret) {
+			debug("%s: panel %s enable backlight error %d\n",
+			      __func__, panel->name, ret);
+			return ret;
+		}
+	}
+#else
+	ret = panel_enable_backlight(panel);
+	if (ret) {
+		debug("%s: panel %s enable backlight error %d\n",
+		      __func__, panel->name, ret);
+		return ret;
+	}
+#endif
 	video_set_flush_dcache(dev, true);
 
 	return 0;
Signature · 1 line
1.9.1
#2 lore raw

Re: [PATCH v2 01/10] video: stm32: stm32_ltdc: add bridge to display controller

Hi Yannick

Quoted 109 lines · yannick fertre

Manage a bridge insert between the display controller & a panel.

---
  drivers/video/stm32/stm32_ltdc.c | 107 ++++++++++++++++++++++++++-------------
  1 file changed, 71 insertions(+), 36 deletions(-)
drivers/video/stm32/stm32_ltdc.c +24 -19
index e160c77..bd9c0de 100644
@@ -8,6 +8,7 @@
 
  #include <common.h>
  #include <clk.h>
+#include <display.h>
  #include <dm.h>
  #include <panel.h>
  #include <reset.h>
@@ -15,12 +16,12 @@
  #include <asm/io.h>
  #include <asm/arch/gpio.h>
  #include <dm/device-internal.h>
+#include <video_bridge.h>
 
  DECLARE_GLOBAL_DATA_PTR;
 
  struct stm32_ltdc_priv {
  	void __iomem *regs;
-	struct display_timing timing;
  	enum video_log2_bpp l2bpp;
  	u32 bg_col_argb;
  	u32 crop_x, crop_y, crop_w, crop_h;
@@ -210,23 +211,23 @@ static void stm32_ltdc_enable(struct stm32_ltdc_priv *priv)
  	setbits_le32(priv->regs + LTDC_GCR, GCR_LTDCEN);
  }
 
-static void stm32_ltdc_set_mode(struct stm32_ltdc_priv *priv)
+static void stm32_ltdc_set_mode(struct stm32_ltdc_priv *priv,
+				struct display_timing *timings)
  {
  	void __iomem *regs = priv->regs;
-	struct display_timing *timing = &priv->timing;
  	u32 hsync, vsync, acc_hbp, acc_vbp, acc_act_w, acc_act_h;
  	u32 total_w, total_h;
  	u32 val;
 
  	/* Convert video timings to ltdc timings */
-	hsync = timing->hsync_len.typ - 1;
-	vsync = timing->vsync_len.typ - 1;
-	acc_hbp = hsync + timing->hback_porch.typ;
-	acc_vbp = vsync + timing->vback_porch.typ;
-	acc_act_w = acc_hbp + timing->hactive.typ;
-	acc_act_h = acc_vbp + timing->vactive.typ;
-	total_w = acc_act_w + timing->hfront_porch.typ;
-	total_h = acc_act_h + timing->vfront_porch.typ;
+	hsync = timings->hsync_len.typ - 1;
+	vsync = timings->vsync_len.typ - 1;
+	acc_hbp = hsync + timings->hback_porch.typ;
+	acc_vbp = vsync + timings->vback_porch.typ;
+	acc_act_w = acc_hbp + timings->hactive.typ;
+	acc_act_h = acc_vbp + timings->vactive.typ;
+	total_w = acc_act_w + timings->hfront_porch.typ;
+	total_h = acc_act_h + timings->vfront_porch.typ;
 
  	/* Synchronization sizes */
  	val = (hsync << 16) | vsync;
@@ -248,14 +249,14 @@ static void stm32_ltdc_set_mode(struct stm32_ltdc_priv *priv)
 
  	/* Signal polarities */
  	val = 0;
-	debug("%s: timing->flags 0x%08x\n", __func__, timing->flags);
-	if (timing->flags & DISPLAY_FLAGS_HSYNC_HIGH)
+	debug("%s: timing->flags 0x%08x\n", __func__, timings->flags);
+	if (timings->flags & DISPLAY_FLAGS_HSYNC_HIGH)
  		val |= GCR_HSPOL;
-	if (timing->flags & DISPLAY_FLAGS_VSYNC_HIGH)
+	if (timings->flags & DISPLAY_FLAGS_VSYNC_HIGH)
  		val |= GCR_VSPOL;
-	if (timing->flags & DISPLAY_FLAGS_DE_HIGH)
+	if (timings->flags & DISPLAY_FLAGS_DE_HIGH)
  		val |= GCR_DEPOL;
-	if (timing->flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE)
+	if (timings->flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE)
  		val |= GCR_PCPOL;
  	clrsetbits_le32(regs + LTDC_GCR,
  			GCR_HSPOL | GCR_VSPOL | GCR_DEPOL | GCR_PCPOL, val);
@@ -331,7 +332,11 @@ static int stm32_ltdc_probe(struct udevice *dev)
  	struct video_uc_platdata *uc_plat = dev_get_uclass_platdata(dev);
  	struct video_priv *uc_priv = dev_get_uclass_priv(dev);
  	struct stm32_ltdc_priv *priv = dev_get_priv(dev);
-	struct udevice *panel;
+#ifdef CONFIG_VIDEO_BRIDGE
+	struct udevice *bridge = NULL;
+#endif
+	struct udevice *panel = NULL;
+	struct display_timing timings;
  	struct clk pclk;
  	struct reset_ctl rst;
  	int rate, ret;
@@ -364,63 +369,93 @@ static int stm32_ltdc_probe(struct udevice *dev)
  	/* Reset */
  	reset_deassert(&rst);
 
-	ret = uclass_first_device(UCLASS_PANEL, &panel);
+#ifdef CONFIG_VIDEO_BRIDGE
+	ret = uclass_get_device(UCLASS_VIDEO_BRIDGE, 0, &bridge);
  	if (ret) {
-		debug("%s: panel device error %d\n", __func__, ret);

drivers/video/stm32/stm32_ltdc.c static int stm32_ltdc_probe(struct udevice *dev) · line 382

Quoted 10 lines
drivers/video/stm32/stm32_ltdc.c +6 -2
-		return ret;
+		debug("%s: No video bridge, or no backlight on bridge\n",
+		      __func__);
  	}
 
-	ret = panel_enable_backlight(panel);
+	if (bridge) {
+		ret = video_bridge_attach(bridge);
+		if (ret) {
+			debug("%s: fail to attach bridge\n", __func__);

I would replace debug by dev_err() here.

drivers/video/stm32/stm32_ltdc.c static int stm32_ltdc_probe(struct udevice *dev) · line 389

Quoted 9 lines
drivers/video/stm32/stm32_ltdc.c +6 -2
+			return ret;
+		}
+	}
+#endif
+	ret = uclass_first_device(UCLASS_PANEL, &panel);
  	if (ret) {
-		debug("%s: panel %s enable backlight error %d\n",
-		      __func__, panel->name, ret);
+		debug("%s: panel device error %d\n", __func__, ret);

Ditto

drivers/video/stm32/stm32_ltdc.c static int stm32_ltdc_probe(struct udevice *dev) · line 386

Quoted 12 lines
drivers/video/stm32/stm32_ltdc.c +2 -4
  		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(panel),
+					   0, &timings);
  	if (ret) {
  		debug("%s: decode display timing error %d\n",
  		      __func__, ret);
-		return -EINVAL;

Ditto

drivers/video/stm32/stm32_ltdc.c static int stm32_ltdc_probe(struct udevice *dev) · line 404

Quoted 9 lines
drivers/video/stm32/stm32_ltdc.c +3 -2
+		return ret;
  	}
 
-	rate = clk_set_rate(&pclk, priv->timing.pixelclock.typ);
+	rate = clk_set_rate(&pclk, timings.pixelclock.typ);
  	if (rate < 0) {
  		debug("%s: fail to set pixel clock %d hz %d hz\n",
-		      __func__, priv->timing.pixelclock.typ, rate);
+		      __func__, timings.pixelclock.typ, rate);

Ditto

Quoted 33 lines
drivers/video/stm32/stm32_ltdc.c +5 -6
  		return rate;
  	}
 
  	debug("%s: Set pixel clock req %d hz get %d hz\n", __func__,
-	      priv->timing.pixelclock.typ, rate);
+	      timings.pixelclock.typ, rate);
 
  	/* TODO Below parameters are hard-coded for the moment... */
  	priv->l2bpp = VIDEO_BPP16;
  	priv->bg_col_argb = 0xFFFFFFFF; /* white no transparency */
  	priv->crop_x = 0;
  	priv->crop_y = 0;
-	priv->crop_w = priv->timing.hactive.typ;
-	priv->crop_h = priv->timing.vactive.typ;
+	priv->crop_w = timings.hactive.typ;
+	priv->crop_h = timings.vactive.typ;
  	priv->alpha = 0xFF;
 
  	debug("%s: %dx%d %dbpp frame buffer at 0x%lx\n", __func__,
-	      priv->timing.hactive.typ, priv->timing.vactive.typ,
+	      timings.hactive.typ, timings.vactive.typ,
  	      VNBITS(priv->l2bpp), uc_plat->base);
  	debug("%s: crop %d,%d %dx%d bg 0x%08x alpha %d\n", __func__,
  	      priv->crop_x, priv->crop_y, priv->crop_w, priv->crop_h,
  	      priv->bg_col_argb, priv->alpha);
 
  	/* Configure & start LTDC */
-	stm32_ltdc_set_mode(priv);
+	stm32_ltdc_set_mode(priv, &timings);
  	stm32_ltdc_set_layer1(priv, uc_plat->base);
  	stm32_ltdc_enable(priv);
 
-	uc_priv->xsize = priv->timing.hactive.typ;

drivers/video/stm32/stm32_ltdc.c static int stm32_ltdc_probe(struct udevice *dev) · line 440

Quoted 10 lines
drivers/video/stm32/stm32_ltdc.c +7 -1
-	uc_priv->ysize = priv->timing.vactive.typ;
+	uc_priv->xsize = timings.hactive.typ;
+	uc_priv->ysize = timings.vactive.typ;
  	uc_priv->bpix = priv->l2bpp;
 
+#ifdef CONFIG_VIDEO_BRIDGE
+	if (bridge) {
+		ret = video_bridge_set_backlight(bridge, 80);
+		if (ret) {
+			debug("%s: fail to set backlight\n", __func__);

Ditto

drivers/video/stm32/stm32_ltdc.c static int stm32_ltdc_probe(struct udevice *dev) · line 447

Quoted 7 lines
drivers/video/stm32/stm32_ltdc.c +7 -0
+			return ret;
+		}
+	} else {
+		ret = panel_enable_backlight(panel);
+		if (ret) {
+			debug("%s: panel %s enable backlight error %d\n",
+			      __func__, panel->name, ret);

Ditto

drivers/video/stm32/stm32_ltdc.c static int stm32_ltdc_probe(struct udevice *dev) · line 455

Quoted 8 lines
drivers/video/stm32/stm32_ltdc.c +8 -0
+			return ret;
+		}
+	}
+#else
+	ret = panel_enable_backlight(panel);
+	if (ret) {
+		debug("%s: panel %s enable backlight error %d\n",
+		      __func__, panel->name, ret);

Ditto

drivers/video/stm32/stm32_ltdc.c static int stm32_ltdc_probe(struct udevice *dev) · line 461

Quoted 7 lines
drivers/video/stm32/stm32_ltdc.c +3 -0
+		return ret;
+	}
+#endif
  	video_set_flush_dcache(dev, true);
 
  	return 0;

_______________________________________________
U-Boot mailing list
[email protected]
https://lists.denx.de/listinfo/u-boot

#3 lore raw

PATCH v2 2/10 video: stm32: stm32_ltdc: update debug log

In reply to yannick fertre

Replace macro debug by pr_error, pr_warn or pr_info.

---
 drivers/video/stm32/stm32_ltdc.c | 62 ++++++++++++++++++++--------------------
 1 file changed, 31 insertions(+), 31 deletions(-)
drivers/video/stm32/stm32_ltdc.c +31 -31
index bd9c0de..e95f35c 100644
@@ -176,13 +176,13 @@ static u32 stm32_ltdc_get_pixel_format(enum video_log2_bpp l2bpp)
 	case VIDEO_BPP2:
 	case VIDEO_BPP4:
 	default:
-		debug("%s: warning %dbpp not supported yet, %dbpp instead\n",
-		      __func__, VNBITS(l2bpp), VNBITS(VIDEO_BPP16));
+		pr_warn("%s: warning %dbpp not supported yet, %dbpp instead\n",
+			__func__, VNBITS(l2bpp), VNBITS(VIDEO_BPP16));
 		pf = PF_RGB565;
 		break;
 	}
 
-	debug("%s: %d bpp -> ltdc pf %d\n", __func__, VNBITS(l2bpp), pf);
+	pr_info("%s: %d bpp -> ltdc pf %d\n", __func__, VNBITS(l2bpp), pf);
 
 	return (u32)pf;
 }
@@ -249,7 +249,7 @@ static void stm32_ltdc_set_mode(struct stm32_ltdc_priv *priv,
 
 	/* Signal polarities */
 	val = 0;
-	debug("%s: timing->flags 0x%08x\n", __func__, timings->flags);
+	pr_info("%s: timing->flags 0x%08x\n", __func__, timings->flags);
 	if (timings->flags & DISPLAY_FLAGS_HSYNC_HIGH)
 		val |= GCR_HSPOL;
 	if (timings->flags & DISPLAY_FLAGS_VSYNC_HIGH)
@@ -343,26 +343,26 @@ static int stm32_ltdc_probe(struct udevice *dev)
 
 	priv->regs = (void *)dev_read_addr(dev);
 	if ((fdt_addr_t)priv->regs == FDT_ADDR_T_NONE) {
-		debug("%s: ltdc dt register address error\n", __func__);
+		pr_err("%s: ltdc dt register address error\n", __func__);
 		return -EINVAL;
 	}
 
 	ret = clk_get_by_index(dev, 0, &pclk);
 	if (ret) {
-		debug("%s: peripheral clock get error %d\n", __func__, ret);
+		pr_err("%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);
+		pr_err("%s: peripheral clock enable error %d\n",
+		       __func__, ret);
 		return ret;
 	}
 
 	ret = reset_get_by_index(dev, 0, &rst);
 	if (ret) {
-		debug("%s: missing ltdc hardware reset\n", __func__);
+		pr_err("%s: missing ltdc hardware reset\n", __func__);
 		return -ENODEV;
 	}
 
@@ -372,41 +372,40 @@ static int stm32_ltdc_probe(struct udevice *dev)
 #ifdef CONFIG_VIDEO_BRIDGE
 	ret = uclass_get_device(UCLASS_VIDEO_BRIDGE, 0, &bridge);
 	if (ret) {
-		debug("%s: No video bridge, or no backlight on bridge\n",
-		      __func__);
+		pr_info("%s: No video bridge, or no backlight on bridge\n",
+			__func__);
 	}
 
 	if (bridge) {
 		ret = video_bridge_attach(bridge);
 		if (ret) {
-			debug("%s: fail to attach bridge\n", __func__);
+			pr_err("%s: fail to attach bridge\n", __func__);
 			return ret;
 		}
 	}
 #endif
 	ret = uclass_first_device(UCLASS_PANEL, &panel);
 	if (ret) {
-		debug("%s: panel device error %d\n", __func__, ret);
+		pr_err("%s: panel device error %d\n", __func__, ret);
 		return ret;
 	}
 
 	ret = fdtdec_decode_display_timing(gd->fdt_blob, dev_of_offset(panel),
 					   0, &timings);
 	if (ret) {
-		debug("%s: decode display timing error %d\n",
-		      __func__, ret);
+		pr_err("%s: decode display timing error %d\n", __func__, ret);
 		return ret;
 	}
 
 	rate = clk_set_rate(&pclk, timings.pixelclock.typ);
 	if (rate < 0) {
-		debug("%s: fail to set pixel clock %d hz %d hz\n",
-		      __func__, timings.pixelclock.typ, rate);
+		pr_err("%s: fail to set pixel clock %d hz %d hz\n",
+		       __func__, timings.pixelclock.typ, rate);
 		return rate;
 	}
 
-	debug("%s: Set pixel clock req %d hz get %d hz\n", __func__,
-	      timings.pixelclock.typ, rate);
+	pr_info("%s: Set pixel clock req %d hz get %d hz\n", __func__,
+		timings.pixelclock.typ, rate);
 
 	/* TODO Below parameters are hard-coded for the moment... */
 	priv->l2bpp = VIDEO_BPP16;
@@ -417,12 +416,12 @@ static int stm32_ltdc_probe(struct udevice *dev)
 	priv->crop_h = timings.vactive.typ;
 	priv->alpha = 0xFF;
 
-	debug("%s: %dx%d %dbpp frame buffer at 0x%lx\n", __func__,
-	      timings.hactive.typ, timings.vactive.typ,
-	      VNBITS(priv->l2bpp), uc_plat->base);
-	debug("%s: crop %d,%d %dx%d bg 0x%08x alpha %d\n", __func__,
-	      priv->crop_x, priv->crop_y, priv->crop_w, priv->crop_h,
-	      priv->bg_col_argb, priv->alpha);
+	pr_info("%s: %dx%d %dbpp frame buffer at 0x%lx\n", __func__,
+		timings.hactive.typ, timings.vactive.typ,
+		VNBITS(priv->l2bpp), uc_plat->base);
+	pr_info("%s: crop %d,%d %dx%d bg 0x%08x alpha %d\n", __func__,
+		priv->crop_x, priv->crop_y, priv->crop_w, priv->crop_h,
+		priv->bg_col_argb, priv->alpha);
 
 	/* Configure & start LTDC */
 	stm32_ltdc_set_mode(priv, &timings);
@@ -437,22 +436,22 @@ static int stm32_ltdc_probe(struct udevice *dev)
 	if (bridge) {
 		ret = video_bridge_set_backlight(bridge, 80);
 		if (ret) {
-			debug("%s: fail to set backlight\n", __func__);
+			pr_err("%s: fail to set backlight\n", __func__);
 			return ret;
 		}
 	} else {
 		ret = panel_enable_backlight(panel);
 		if (ret) {
-			debug("%s: panel %s enable backlight error %d\n",
-			      __func__, panel->name, ret);
+			pr_err("%s: panel %s enable backlight error %d\n",
+			       __func__, panel->name, ret);
 			return ret;
 		}
 	}
 #else
 	ret = panel_enable_backlight(panel);
 	if (ret) {
-		debug("%s: panel %s enable backlight error %d\n",
-		      __func__, panel->name, ret);
+		pr_err("%s: panel %s enable backlight error %d\n",
+		       __func__, panel->name, ret);
 		return ret;
 	}
 #endif
@@ -468,7 +467,8 @@ static int stm32_ltdc_bind(struct udevice *dev)
 	uc_plat->size = CONFIG_VIDEO_STM32_MAX_XRES *
 			CONFIG_VIDEO_STM32_MAX_YRES *
 			(CONFIG_VIDEO_STM32_MAX_BPP >> 3);
-	debug("%s: frame buffer max size %d bytes\n", __func__, uc_plat->size);
+	pr_info("%s: frame buffer max size %d bytes\n", __func__,
+		uc_plat->size);
 
 	return 0;
 }
Signature · 1 line
1.9.1
#4 lore raw

Re: [PATCH v2 02/10] video: stm32: stm32_ltdc: update debug log

Hi Yannick

Quoted 38 lines · yannick fertre

Replace macro debug by pr_error, pr_warn or pr_info.

---
  drivers/video/stm32/stm32_ltdc.c | 62 ++++++++++++++++++++--------------------
  1 file changed, 31 insertions(+), 31 deletions(-)
drivers/video/stm32/stm32_ltdc.c +4 -4
index bd9c0de..e95f35c 100644
@@ -176,13 +176,13 @@ static u32 stm32_ltdc_get_pixel_format(enum video_log2_bpp l2bpp)
  	case VIDEO_BPP2:
  	case VIDEO_BPP4:
  	default:
-		debug("%s: warning %dbpp not supported yet, %dbpp instead\n",
-		      __func__, VNBITS(l2bpp), VNBITS(VIDEO_BPP16));
+		pr_warn("%s: warning %dbpp not supported yet, %dbpp instead\n",
+			__func__, VNBITS(l2bpp), VNBITS(VIDEO_BPP16));
  		pf = PF_RGB565;
  		break;
  	}
 
-	debug("%s: %d bpp -> ltdc pf %d\n", __func__, VNBITS(l2bpp), pf);
+	pr_info("%s: %d bpp -> ltdc pf %d\n", __func__, VNBITS(l2bpp), pf);
 
  	return (u32)pf;
  }
@@ -249,7 +249,7 @@ static void stm32_ltdc_set_mode(struct stm32_ltdc_priv *priv,
 
  	/* Signal polarities */
  	val = 0;
-	debug("%s: timing->flags 0x%08x\n", __func__, timings->flags);
+	pr_info("%s: timing->flags 0x%08x\n", __func__, timings->flags);
  	if (timings->flags & DISPLAY_FLAGS_HSYNC_HIGH)
  		val |= GCR_HSPOL;
  	if (timings->flags & DISPLAY_FLAGS_VSYNC_HIGH)

drivers/video/stm32/stm32_ltdc.c static int stm32_ltdc_probe(struct udevice *dev) · line 346

Quoted 5 lines
drivers/video/stm32/stm32_ltdc.c +1 -1
@@ -343,26 +343,26 @@ static int stm32_ltdc_probe(struct udevice *dev)
 
  	priv->regs = (void *)dev_read_addr(dev);
  	if ((fdt_addr_t)priv->regs == FDT_ADDR_T_NONE) {
-		debug("%s: ltdc dt register address error\n", __func__);
+		pr_err("%s: ltdc dt register address error\n", __func__);

As you get access to the struct udevice, prefer dev_err() here.

drivers/video/stm32/stm32_ltdc.c static int stm32_ltdc_probe(struct udevice *dev) · line 352

Quoted 7 lines
drivers/video/stm32/stm32_ltdc.c +1 -1
  		return -EINVAL;
  	}
 
  	ret = clk_get_by_index(dev, 0, &pclk);
  	if (ret) {
-		debug("%s: peripheral clock get error %d\n", __func__, ret);
+		pr_err("%s: peripheral clock get error %d\n", __func__, ret);

ditto

drivers/video/stm32/stm32_ltdc.c static int stm32_ltdc_probe(struct udevice *dev) · line 359

Quoted 9 lines
drivers/video/stm32/stm32_ltdc.c +2 -2
  		return ret;
  	}
 
  	ret = clk_enable(&pclk);
  	if (ret) {
-		debug("%s: peripheral clock enable error %d\n",
-		      __func__, ret);
+		pr_err("%s: peripheral clock enable error %d\n",
+		       __func__, ret);

ditto

drivers/video/stm32/stm32_ltdc.c static int stm32_ltdc_probe(struct udevice *dev) · line 365

Quoted 7 lines
drivers/video/stm32/stm32_ltdc.c +1 -1
  		return ret;
  	}
 
  	ret = reset_get_by_index(dev, 0, &rst);
  	if (ret) {
-		debug("%s: missing ltdc hardware reset\n", __func__);
+		pr_err("%s: missing ltdc hardware reset\n", __func__);

ditto

drivers/video/stm32/stm32_ltdc.c static int stm32_ltdc_probe(struct udevice *dev) · line 376

Quoted 11 lines
drivers/video/stm32/stm32_ltdc.c +2 -2
  		return -ENODEV;
  	}
 
@@ -372,41 +372,40 @@ static int stm32_ltdc_probe(struct udevice *dev)
  #ifdef CONFIG_VIDEO_BRIDGE
  	ret = uclass_get_device(UCLASS_VIDEO_BRIDGE, 0, &bridge);
  	if (ret) {
-		debug("%s: No video bridge, or no backlight on bridge\n",
-		      __func__);
+		pr_info("%s: No video bridge, or no backlight on bridge\n",
+			__func__);

dev_info()

drivers/video/stm32/stm32_ltdc.c static int stm32_ltdc_probe(struct udevice *dev) · line 382

Quoted 7 lines
drivers/video/stm32/stm32_ltdc.c +1 -1
  	}
 
  	if (bridge) {
  		ret = video_bridge_attach(bridge);
  		if (ret) {
-			debug("%s: fail to attach bridge\n", __func__);
+			pr_err("%s: fail to attach bridge\n", __func__);

dev_err()

drivers/video/stm32/stm32_ltdc.c static int stm32_ltdc_probe(struct udevice *dev) · line 389

Quoted 8 lines
drivers/video/stm32/stm32_ltdc.c +1 -1
  			return ret;
  		}
  	}
  #endif
  	ret = uclass_first_device(UCLASS_PANEL, &panel);
  	if (ret) {
-		debug("%s: panel device error %d\n", __func__, ret);
+		pr_err("%s: panel device error %d\n", __func__, ret);

ditto

drivers/video/stm32/stm32_ltdc.c static int stm32_ltdc_probe(struct udevice *dev) · line 396

Quoted 9 lines
drivers/video/stm32/stm32_ltdc.c +1 -2
  		return ret;
  	}
 
  	ret = fdtdec_decode_display_timing(gd->fdt_blob, dev_of_offset(panel),
  					   0, &timings);
  	if (ret) {
-		debug("%s: decode display timing error %d\n",
-		      __func__, ret);
+		pr_err("%s: decode display timing error %d\n", __func__, ret);

ditto

drivers/video/stm32/stm32_ltdc.c static int stm32_ltdc_probe(struct udevice *dev) · line 403

Quoted 9 lines
drivers/video/stm32/stm32_ltdc.c +2 -2
  		return ret;
  	}
 
  	rate = clk_set_rate(&pclk, timings.pixelclock.typ);
  	if (rate < 0) {
-		debug("%s: fail to set pixel clock %d hz %d hz\n",
-		      __func__, timings.pixelclock.typ, rate);
+		pr_err("%s: fail to set pixel clock %d hz %d hz\n",
+		       __func__, timings.pixelclock.typ, rate);

ditto

Quoted 16 lines
drivers/video/stm32/stm32_ltdc.c +2 -4
  		return rate;
  	}
 
-	debug("%s: Set pixel clock req %d hz get %d hz\n", __func__,
-	      timings.pixelclock.typ, rate);
+	pr_info("%s: Set pixel clock req %d hz get %d hz\n", __func__,
+		timings.pixelclock.typ, rate);
 
  	/* TODO Below parameters are hard-coded for the moment... */
  	priv->l2bpp = VIDEO_BPP16;
@@ -417,12 +416,12 @@ static int stm32_ltdc_probe(struct udevice *dev)
  	priv->crop_h = timings.vactive.typ;
  	priv->alpha = 0xFF;
 
-	debug("%s: %dx%d %dbpp frame buffer at 0x%lx\n", __func__,
-	      timings.hactive.typ, timings.vactive.typ,

drivers/video/stm32/stm32_ltdc.c static int stm32_ltdc_probe(struct udevice *dev) · line 424

Quoted 10 lines
drivers/video/stm32/stm32_ltdc.c +6 -4
-	      VNBITS(priv->l2bpp), uc_plat->base);
-	debug("%s: crop %d,%d %dx%d bg 0x%08x alpha %d\n", __func__,
-	      priv->crop_x, priv->crop_y, priv->crop_w, priv->crop_h,
-	      priv->bg_col_argb, priv->alpha);
+	pr_info("%s: %dx%d %dbpp frame buffer at 0x%lx\n", __func__,
+		timings.hactive.typ, timings.vactive.typ,
+		VNBITS(priv->l2bpp), uc_plat->base);
+	pr_info("%s: crop %d,%d %dx%d bg 0x%08x alpha %d\n", __func__,
+		priv->crop_x, priv->crop_y, priv->crop_w, priv->crop_h,
+		priv->bg_col_argb, priv->alpha);

dev_info()

drivers/video/stm32/stm32_ltdc.c static int stm32_ltdc_probe(struct udevice *dev) · line 439

Quoted 9 lines
drivers/video/stm32/stm32_ltdc.c +1 -1
  	/* Configure & start LTDC */
  	stm32_ltdc_set_mode(priv, &timings);
@@ -437,22 +436,22 @@ static int stm32_ltdc_probe(struct udevice *dev)
  	if (bridge) {
  		ret = video_bridge_set_backlight(bridge, 80);
  		if (ret) {
-			debug("%s: fail to set backlight\n", __func__);
+			pr_err("%s: fail to set backlight\n", __func__);

dev_err()

drivers/video/stm32/stm32_ltdc.c static int stm32_ltdc_probe(struct udevice *dev) · line 446

Quoted 9 lines
drivers/video/stm32/stm32_ltdc.c +2 -2
  			return ret;
  		}
  	} else {
  		ret = panel_enable_backlight(panel);
  		if (ret) {
-			debug("%s: panel %s enable backlight error %d\n",
-			      __func__, panel->name, ret);
+			pr_err("%s: panel %s enable backlight error %d\n",
+			       __func__, panel->name, ret);

ditto

drivers/video/stm32/stm32_ltdc.c static int stm32_ltdc_probe(struct udevice *dev) · line 454

Quoted 10 lines
drivers/video/stm32/stm32_ltdc.c +2 -2
  			return ret;
  		}
  	}
  #else
  	ret = panel_enable_backlight(panel);
  	if (ret) {
-		debug("%s: panel %s enable backlight error %d\n",
-		      __func__, panel->name, ret);
+		pr_err("%s: panel %s enable backlight error %d\n",
+		       __func__, panel->name, ret);

ditto

drivers/video/stm32/stm32_ltdc.c static int stm32_ltdc_bind(struct udevice *dev) · line 470

Quoted 9 lines
drivers/video/stm32/stm32_ltdc.c +1 -1
  		return ret;
  	}
  #endif
@@ -468,7 +467,8 @@ static int stm32_ltdc_bind(struct udevice *dev)
  	uc_plat->size = CONFIG_VIDEO_STM32_MAX_XRES *
  			CONFIG_VIDEO_STM32_MAX_YRES *
  			(CONFIG_VIDEO_STM32_MAX_BPP >> 3);
-	debug("%s: frame buffer max size %d bytes\n", __func__, uc_plat->size);
+	pr_info("%s: frame buffer max size %d bytes\n", __func__,

dev_info()

drivers/video/stm32/stm32_ltdc.c static int stm32_ltdc_bind(struct udevice *dev) · line 474

Quoted 5 lines
drivers/video/stm32/stm32_ltdc.c +1 -0
+		uc_plat->size);
 
  	return 0;
  }

Thanks

Patrice
_______________________________________________
U-Boot mailing list
[email protected]
https://lists.denx.de/listinfo/u-boot

#5 lore raw

PATCH v2 3/10 video: add support of MIPI DSI interface

In reply to yannick fertre

Mipi_display.c contains a set of dsi helpers. This file is a copy of file drm_mipi_dsi.c (linux kernel).

---
 drivers/video/Kconfig        |   7 +
 drivers/video/Makefile       |   1 +
 drivers/video/mipi_display.c | 807 +++++++++++++++++++++++++++++++++++++++++++
 include/mipi_display.h       | 257 +++++++++++++-
 4 files changed, 1071 insertions(+), 1 deletion(-)
 create mode 100644 drivers/video/mipi_display.c
drivers/video/Kconfig +7 -0
index 2fc0def..1981298 100644
@@ -75,6 +75,13 @@ config VIDEO_ANSI
 	  Enable ANSI escape sequence decoding for a more fully functional
 	  console.
 
+config VIDEO_MIPI_DSI
+	bool "Support MIPI DSI interface"
+	depends on DM_VIDEO
+	default y if DM_VIDEO
+	help
+	  Support MIPI DSI interface for driving a MIPI compatible LCD panel.
+
 config CONSOLE_NORMAL
 	bool "Support a simple text console"
 	depends on DM_VIDEO
drivers/video/Makefile +1 -0
index dfafe08..6f42cca 100644
@@ -52,6 +52,7 @@ obj-$(CONFIG_FORMIKE) += formike.o
 obj-$(CONFIG_LG4573) += lg4573.o
 obj-$(CONFIG_AM335X_LCD) += am335x-fb.o
 obj-$(CONFIG_VIDEO_DW_HDMI) += dw_hdmi.o
+obj-${CONFIG_VIDEO_MIPI_DSI} += mipi_display.o
 obj-$(CONFIG_VIDEO_SIMPLE) += simplefb.o
 obj-${CONFIG_VIDEO_TEGRA124} += tegra124/
 obj-${CONFIG_EXYNOS_FB} += exynos/
drivers/video/mipi_display.c new file +807 -0

807 lines not on this page · raw message

include/mipi_display.h +256 -1

278 lines not on this page · raw message

Signature · 1 line
1.9.1
#6 lore raw

PATCH v2 4/10 video: add support of panel OTM8009A

In reply to yannick fertre

Support for Orise Tech otm8009a 480p dsi 2dl video mode panel.

---
 drivers/video/Kconfig              |   8 +
 drivers/video/Makefile             |   1 +
 drivers/video/orisetech_otm8009a.c | 329 +++++++++++++++++++++++++++++++++++++
 3 files changed, 338 insertions(+)
 create mode 100644 drivers/video/orisetech_otm8009a.c
drivers/video/Kconfig +8 -0
index 1981298..b5fc535 100644
@@ -320,6 +320,14 @@ config VIDEO_LCD_ANX9804
 	from a parallel LCD interface and translate it on the fy into a DP
 	interface for driving eDP TFT displays. It uses I2C for configuration.
 
+config VIDEO_LCD_ORISETECH_OTM8009A
+	bool "OTM8009A DSI LCD panel support"
+	depends on DM_VIDEO
+	select VIDEO_MIPI_DSI
+	default n
+	---help---
+	Support for Orise Tech otm8009a 480p dsi 2dl video mode panel.
+
 config VIDEO_LCD_SSD2828
 	bool "SSD2828 bridge chip"
 	default n
drivers/video/Makefile +1 -0
index 6f42cca..65002af 100644
@@ -37,6 +37,7 @@ obj-$(CONFIG_VIDEO_COREBOOT) += coreboot.o
 obj-$(CONFIG_VIDEO_DA8XX) += da8xx-fb.o videomodes.o
 obj-$(CONFIG_VIDEO_LCD_ANX9804) += anx9804.o
 obj-$(CONFIG_VIDEO_LCD_HITACHI_TX18D42VM) += hitachi_tx18d42vm_lcd.o
+obj-$(CONFIG_VIDEO_LCD_ORISETECH_OTM8009A) += orisetech_otm8009a.o
 obj-$(CONFIG_VIDEO_LCD_SSD2828) += ssd2828.o
 obj-$(CONFIG_VIDEO_MB862xx) += mb862xx.o videomodes.o
 obj-$(CONFIG_VIDEO_MX3) += mx3fb.o videomodes.o
drivers/video/orisetech_otm8009a.c new file +329 -0

329 lines not on this page · raw message

Signature · 1 line
1.9.1
#7 lore raw

Re: [PATCH v2 04/10] video: add support of panel OTM8009A

Hi Yannick

Quoted 114 lines · yannick fertre

Support for Orise Tech otm8009a 480p dsi 2dl video mode panel.

---
  drivers/video/Kconfig              |   8 +
  drivers/video/Makefile             |   1 +
  drivers/video/orisetech_otm8009a.c | 329 +++++++++++++++++++++++++++++++++++++
  3 files changed, 338 insertions(+)

create mode 100644 drivers/video/orisetech_otm8009a.c

drivers/video/Kconfig +8 -0
index 1981298..b5fc535 100644
@@ -320,6 +320,14 @@ config VIDEO_LCD_ANX9804
  	from a parallel LCD interface and translate it on the fy into a DP
  	interface for driving eDP TFT displays. It uses I2C for configuration.
 
+config VIDEO_LCD_ORISETECH_OTM8009A
+	bool "OTM8009A DSI LCD panel support"
+	depends on DM_VIDEO
+	select VIDEO_MIPI_DSI
+	default n
+	---help---
+	Support for Orise Tech otm8009a 480p dsi 2dl video mode panel.
+
  config VIDEO_LCD_SSD2828
  	bool "SSD2828 bridge chip"
  	default n
drivers/video/Makefile +1 -0
index 6f42cca..65002af 100644
@@ -37,6 +37,7 @@ obj-$(CONFIG_VIDEO_COREBOOT) += coreboot.o
  obj-$(CONFIG_VIDEO_DA8XX) += da8xx-fb.o videomodes.o
  obj-$(CONFIG_VIDEO_LCD_ANX9804) += anx9804.o
  obj-$(CONFIG_VIDEO_LCD_HITACHI_TX18D42VM) += hitachi_tx18d42vm_lcd.o
+obj-$(CONFIG_VIDEO_LCD_ORISETECH_OTM8009A) += orisetech_otm8009a.o
  obj-$(CONFIG_VIDEO_LCD_SSD2828) += ssd2828.o
  obj-$(CONFIG_VIDEO_MB862xx) += mb862xx.o videomodes.o
  obj-$(CONFIG_VIDEO_MX3) += mx3fb.o videomodes.o
drivers/video/orisetech_otm8009a.c new file +67 -0
new file mode 100644
index 0000000..79f2da8
@@ -0,0 +1,329 @@
+/*
+ * Copyright (C) 2018 STMicroelectronics - All Rights Reserved
+ * Author(s): Yannick Fertre <[email protected]> for STMicroelectronics.
+ *	      Philippe Cornu <[email protected]> for STMicroelectronics.
+ *
+ * This otm8009a panel driver is based on the panel driver from
+ * drivers/gpu/drm/panel/panel-orisetech-otm8009a.c (kernel linux)
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+#include <asm/gpio.h>
+#include <backlight.h>
+#include <common.h>
+#include <dm.h>
+#include <panel.h>
+#include <power/regulator.h>
+#include <mipi_display.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define DRV_NAME "orisetech_otm8009a"
+
+#define OTM8009A_BACKLIGHT_DEFAULT	240
+#define OTM8009A_BACKLIGHT_MAX		255
+
+/* Manufacturer Command Set */
+#define MCS_ADRSFT	0x0000	/* Address Shift Function */
+#define MCS_PANSET	0xB3A6	/* Panel Type Setting */
+#define MCS_SD_CTRL	0xC0A2	/* Source Driver Timing Setting */
+#define MCS_P_DRV_M	0xC0B4	/* Panel Driving Mode */
+#define MCS_OSC_ADJ	0xC181	/* Oscillator Adjustment for Idle/Normal mode */
+#define MCS_RGB_VID_SET	0xC1A1	/* RGB Video Mode Setting */
+#define MCS_SD_PCH_CTRL	0xC480	/* Source Driver Precharge Control */
+#define MCS_NO_DOC1	0xC48A	/* Command not documented */
+#define MCS_PWR_CTRL1	0xC580	/* Power Control Setting 1 */
+#define MCS_PWR_CTRL2	0xC590	/* Power Control Setting 2 for Normal Mode */
+#define MCS_PWR_CTRL4	0xC5B0	/* Power Control Setting 4 for DC Voltage */
+#define MCS_PANCTRLSET1	0xCB80	/* Panel Control Setting 1 */
+#define MCS_PANCTRLSET2	0xCB90	/* Panel Control Setting 2 */
+#define MCS_PANCTRLSET3	0xCBA0	/* Panel Control Setting 3 */
+#define MCS_PANCTRLSET4	0xCBB0	/* Panel Control Setting 4 */
+#define MCS_PANCTRLSET5	0xCBC0	/* Panel Control Setting 5 */
+#define MCS_PANCTRLSET6	0xCBD0	/* Panel Control Setting 6 */
+#define MCS_PANCTRLSET7	0xCBE0	/* Panel Control Setting 7 */
+#define MCS_PANCTRLSET8	0xCBF0	/* Panel Control Setting 8 */
+#define MCS_PANU2D1	0xCC80	/* Panel U2D Setting 1 */
+#define MCS_PANU2D2	0xCC90	/* Panel U2D Setting 2 */
+#define MCS_PANU2D3	0xCCA0	/* Panel U2D Setting 3 */
+#define MCS_PAND2U1	0xCCB0	/* Panel D2U Setting 1 */
+#define MCS_PAND2U2	0xCCC0	/* Panel D2U Setting 2 */
+#define MCS_PAND2U3	0xCCD0	/* Panel D2U Setting 3 */
+#define MCS_GOAVST	0xCE80	/* GOA VST Setting */
+#define MCS_GOACLKA1	0xCEA0	/* GOA CLKA1 Setting */
+#define MCS_GOACLKA3	0xCEB0	/* GOA CLKA3 Setting */
+#define MCS_GOAECLK	0xCFC0	/* GOA ECLK Setting */
+#define MCS_NO_DOC2	0xCFD0	/* Command not documented */
+#define MCS_GVDDSET	0xD800	/* GVDD/NGVDD */
+#define MCS_VCOMDC	0xD900	/* VCOM Voltage Setting */
+#define MCS_GMCT2_2P	0xE100	/* Gamma Correction 2.2+ Setting */
+#define MCS_GMCT2_2N	0xE200	/* Gamma Correction 2.2- Setting */
+#define MCS_NO_DOC3	0xF5B6	/* Command not documented */
+#define MCS_CMD2_ENA1	0xFF00	/* Enable Access Command2 "CMD2" */
+#define MCS_CMD2_ENA2	0xFF80	/* Enable Access Orise Command2 */
+
+struct otm8009a_panel_priv {
+	struct udevice *reg;
+	struct gpio_desc reset;

drivers/video/orisetech_otm8009a.c line 77

Quoted 10 lines
drivers/video/orisetech_otm8009a.c new file +10 -0
+};
+
+static void otm8009a_dcs_write_buf(struct udevice *dev, const void *data,
+				   size_t len)
+{
+	struct mipi_dsi_panel_plat *plat = dev_get_platdata(dev);
+	struct mipi_dsi_device *device = plat->device;
+
+	if (mipi_dsi_dcs_write_buffer(device, data, len) < 0)
+		pr_err("mipi dsi dcs write buffer failed\n");

dev_err()

Quoted 152 lines
drivers/video/orisetech_otm8009a.c new file +152 -0
+}
+
+#define dcs_write_seq(dev, seq...)				\
+({								\
+	static const u8 d[] = { seq };				\
+	otm8009a_dcs_write_buf(dev, d, ARRAY_SIZE(d));		\
+})
+
+#define dcs_write_cmd_at(dev, cmd, seq...)		\
+({							\
+	static const u16 c = cmd;			\
+	struct udevice *device = dev;			\
+	dcs_write_seq(device, MCS_ADRSFT, (c) & 0xFF);	\
+	dcs_write_seq(device, (c) >> 8, seq);		\
+})
+
+static int otm8009a_init_sequence(struct udevice *dev)
+{
+	struct mipi_dsi_panel_plat *plat = dev_get_platdata(dev);
+	struct mipi_dsi_device *device = plat->device;
+	int ret;
+
+	/* Enter CMD2 */
+	dcs_write_cmd_at(dev, MCS_CMD2_ENA1, 0x80, 0x09, 0x01);
+
+	/* Enter Orise Command2 */
+	dcs_write_cmd_at(dev, MCS_CMD2_ENA2, 0x80, 0x09);
+
+	dcs_write_cmd_at(dev, MCS_SD_PCH_CTRL, 0x30);
+	mdelay(10);
+
+	dcs_write_cmd_at(dev, MCS_NO_DOC1, 0x40);
+	mdelay(10);
+
+	dcs_write_cmd_at(dev, MCS_PWR_CTRL4 + 1, 0xA9);
+	dcs_write_cmd_at(dev, MCS_PWR_CTRL2 + 1, 0x34);
+	dcs_write_cmd_at(dev, MCS_P_DRV_M, 0x50);
+	dcs_write_cmd_at(dev, MCS_VCOMDC, 0x4E);
+	dcs_write_cmd_at(dev, MCS_OSC_ADJ, 0x66); /* 65Hz */
+	dcs_write_cmd_at(dev, MCS_PWR_CTRL2 + 2, 0x01);
+	dcs_write_cmd_at(dev, MCS_PWR_CTRL2 + 5, 0x34);
+	dcs_write_cmd_at(dev, MCS_PWR_CTRL2 + 4, 0x33);
+	dcs_write_cmd_at(dev, MCS_GVDDSET, 0x79, 0x79);
+	dcs_write_cmd_at(dev, MCS_SD_CTRL + 1, 0x1B);
+	dcs_write_cmd_at(dev, MCS_PWR_CTRL1 + 2, 0x83);
+	dcs_write_cmd_at(dev, MCS_SD_PCH_CTRL + 1, 0x83);
+	dcs_write_cmd_at(dev, MCS_RGB_VID_SET, 0x0E);
+	dcs_write_cmd_at(dev, MCS_PANSET, 0x00, 0x01);
+
+	dcs_write_cmd_at(dev, MCS_GOAVST, 0x85, 0x01, 0x00, 0x84, 0x01, 0x00);
+	dcs_write_cmd_at(dev, MCS_GOACLKA1, 0x18, 0x04, 0x03, 0x39, 0x00, 0x00,
+			 0x00, 0x18, 0x03, 0x03, 0x3A, 0x00, 0x00, 0x00);
+	dcs_write_cmd_at(dev, MCS_GOACLKA3, 0x18, 0x02, 0x03, 0x3B, 0x00, 0x00,
+			 0x00, 0x18, 0x01, 0x03, 0x3C, 0x00, 0x00, 0x00);
+	dcs_write_cmd_at(dev, MCS_GOAECLK, 0x01, 0x01, 0x20, 0x20, 0x00, 0x00,
+			 0x01, 0x02, 0x00, 0x00);
+
+	dcs_write_cmd_at(dev, MCS_NO_DOC2, 0x00);
+
+	dcs_write_cmd_at(dev, MCS_PANCTRLSET1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+	dcs_write_cmd_at(dev, MCS_PANCTRLSET2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+			 0, 0, 0, 0, 0);
+	dcs_write_cmd_at(dev, MCS_PANCTRLSET3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+			 0, 0, 0, 0, 0);
+	dcs_write_cmd_at(dev, MCS_PANCTRLSET4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+	dcs_write_cmd_at(dev, MCS_PANCTRLSET5, 0, 4, 4, 4, 4, 4, 0, 0, 0, 0,
+			 0, 0, 0, 0, 0);
+	dcs_write_cmd_at(dev, MCS_PANCTRLSET6, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4,
+			 4, 0, 0, 0, 0);
+	dcs_write_cmd_at(dev, MCS_PANCTRLSET7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+	dcs_write_cmd_at(dev, MCS_PANCTRLSET8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+			 0xFF, 0xFF, 0xFF, 0xFF, 0xFF);
+
+	dcs_write_cmd_at(dev, MCS_PANU2D1, 0x00, 0x26, 0x09, 0x0B, 0x01, 0x25,
+			 0x00, 0x00, 0x00, 0x00);
+	dcs_write_cmd_at(dev, MCS_PANU2D2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x0A, 0x0C, 0x02);
+	dcs_write_cmd_at(dev, MCS_PANU2D3, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00,
+			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
+	dcs_write_cmd_at(dev, MCS_PAND2U1, 0x00, 0x25, 0x0C, 0x0A, 0x02, 0x26,
+			 0x00, 0x00, 0x00, 0x00);
+	dcs_write_cmd_at(dev, MCS_PAND2U2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0x0B, 0x09, 0x01);
+	dcs_write_cmd_at(dev, MCS_PAND2U3, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00,
+			 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
+
+	dcs_write_cmd_at(dev, MCS_PWR_CTRL1 + 1, 0x66);
+
+	dcs_write_cmd_at(dev, MCS_NO_DOC3, 0x06);
+
+	dcs_write_cmd_at(dev, MCS_GMCT2_2P, 0x00, 0x09, 0x0F, 0x0E, 0x07, 0x10,
+			 0x0B, 0x0A, 0x04, 0x07, 0x0B, 0x08, 0x0F, 0x10, 0x0A,
+			 0x01);
+	dcs_write_cmd_at(dev, MCS_GMCT2_2N, 0x00, 0x09, 0x0F, 0x0E, 0x07, 0x10,
+			 0x0B, 0x0A, 0x04, 0x07, 0x0B, 0x08, 0x0F, 0x10, 0x0A,
+			 0x01);
+
+	/* Exit CMD2 */
+	dcs_write_cmd_at(dev, MCS_CMD2_ENA1, 0xFF, 0xFF, 0xFF);
+
+	ret =  mipi_dsi_dcs_nop(device);
+	if (ret)
+		return ret;
+
+	ret = mipi_dsi_dcs_exit_sleep_mode(device);
+	if (ret)
+		return ret;
+
+	/* Wait for sleep out exit */
+	mdelay(120);
+
+	/* Default portrait 480x800 rgb24 */
+	dcs_write_seq(dev, MIPI_DCS_SET_ADDRESS_MODE, 0x00);
+
+	ret =  mipi_dsi_dcs_set_column_address(device, 0, 479);
+	if (ret)
+		return ret;
+
+	ret =  mipi_dsi_dcs_set_page_address(device, 0, 799);
+	if (ret)
+		return ret;
+
+	/* See otm8009a driver documentation for pixel format descriptions */
+	ret =  mipi_dsi_dcs_set_pixel_format(device, MIPI_DCS_PIXEL_FMT_24BIT |
+					     MIPI_DCS_PIXEL_FMT_24BIT << 4);
+	if (ret)
+		return ret;
+
+	/* Disable CABC feature */
+	dcs_write_seq(dev, MIPI_DCS_WRITE_POWER_SAVE, 0x00);
+
+	ret = mipi_dsi_dcs_set_display_on(device);
+	if (ret)
+		return ret;
+
+	ret = mipi_dsi_dcs_nop(device);
+	if (ret)
+		return ret;
+
+	/* Send Command GRAM memory write (no parameters) */
+	dcs_write_seq(dev, MIPI_DCS_WRITE_MEMORY_START);
+
+	return 0;
+}
+
+static int otm8009a_panel_enable_backlight(struct udevice *dev)
+{
+	struct mipi_dsi_panel_plat *plat = dev_get_platdata(dev);
+	struct mipi_dsi_device *device = plat->device;
+	int ret;
+
+	device->lanes = 2;

drivers/video/orisetech_otm8009a.c line 239

Quoted 10 lines
drivers/video/orisetech_otm8009a.c new file +10 -0
+	device->format = MIPI_DSI_FMT_RGB888;
+	device->mode_flags = MIPI_DSI_MODE_VIDEO |
+			     MIPI_DSI_MODE_VIDEO_BURST |
+			     MIPI_DSI_MODE_LPM;
+
+	ret = mipi_dsi_attach(device);
+	if (ret < 0)
+		return ret;
+
+	pr_info("%s: initialize panel\n", __func__);

Is it useful to print this each time the backligth is enabled ?

drivers/video/orisetech_otm8009a.c line 249

Quoted 10 lines
drivers/video/orisetech_otm8009a.c new file +10 -0
+	ret = otm8009a_init_sequence(dev);
+	if (ret)
+		return ret;
+
+	/*
+	 * Power on the backlight with the requested brightness
+	 * Note We can not use mipi_dsi_dcs_set_display_brightness()
+	 * as otm8009a driver support only 8-bit brightness (1 param).
+	 */
+	pr_info("%s: start, backlight\n", __func__);

ditto

Quoted 14 lines
drivers/video/orisetech_otm8009a.c new file +14 -0
+
+	dcs_write_seq(dev, MIPI_DCS_SET_DISPLAY_BRIGHTNESS,
+		      OTM8009A_BACKLIGHT_DEFAULT);
+
+	/* Update Brightness Control & Backlight */
+	dcs_write_seq(dev, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x24);
+
+	/*  need to wait a few time before set the DSI bridge in video mode */
+	mdelay(10);
+
+	return 0;
+}
+
+static int otm8009a_panel_ofdata_to_platdata(struct udevice *dev)

drivers/video/orisetech_otm8009a.c line 273

Quoted 10 lines
drivers/video/orisetech_otm8009a.c new file +10 -0
+{
+	struct otm8009a_panel_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	if (IS_ENABLED(CONFIG_DM_REGULATOR)) {
+		ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev,
+						   "power-supply", &priv->reg);
+		if (ret) {
+			pr_err("%s: Warning: cannot get power supply\n",
+			       __func__);

dev_err()

drivers/video/orisetech_otm8009a.c line 282

Quoted 9 lines
drivers/video/orisetech_otm8009a.c new file +9 -0
+			if (ret != -ENOENT)
+				return ret;
+		}
+	}
+
+	ret = gpio_request_by_name(dev, "reset-gpios", 0, &priv->reset,
+				   GPIOD_IS_OUT);
+	if (ret) {
+		pr_err("%s: Warning: cannot get reset GPIO\n", __func__);

ditto

Quoted 8 lines
drivers/video/orisetech_otm8009a.c new file +8 -0
+		if (ret != -ENOENT)
+			return ret;
+	}
+
+	/* reset panel must be done before probe */
+	dm_gpio_set_value(&priv->reset, true);
+
+	return 0;

drivers/video/orisetech_otm8009a.c line 300

Quoted 10 lines
drivers/video/orisetech_otm8009a.c new file +10 -0
+}
+
+static int otm8009a_panel_probe(struct udevice *dev)
+{
+	struct otm8009a_panel_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	if (IS_ENABLED(CONFIG_DM_REGULATOR) && priv->reg) {
+		pr_err("%s: Enable regulator '%s'\n", __func__,
+		       priv->reg->name);

debug() ?

Quoted 20 lines
drivers/video/orisetech_otm8009a.c new file +19 -0
+		ret = regulator_set_enable(priv->reg, true);
+		if (ret)
+			return ret;
+	}
+
+	dm_gpio_set_value(&priv->reset, false);
+
+	return 0;
+}
+
+static const struct panel_ops otm8009a_panel_ops = {
+	.enable_backlight = otm8009a_panel_enable_backlight,
+};
+
+static const struct udevice_id otm8009a_panel_ids[] = {
+	{ .compatible = "orisetech,otm8009a" },
+	{ }
+};
+

drivers/video/orisetech_otm8009a.c line 329

Quoted 10 lines
drivers/video/orisetech_otm8009a.c new file +10 -0
+U_BOOT_DRIVER(otm8009a_panel) = {
+	.name			  = "otm8009a_panel",
+	.id			  = UCLASS_PANEL,
+	.of_match		  = otm8009a_panel_ids,
+	.ops			  = &otm8009a_panel_ops,
+	.ofdata_to_platdata	  = otm8009a_panel_ofdata_to_platdata,
+	.probe			  = otm8009a_panel_probe,
+	.platdata_auto_alloc_size = sizeof(struct mipi_dsi_panel_plat),
+	.priv_auto_alloc_size	= sizeof(struct otm8009a_panel_priv),
+};

_______________________________________________
U-Boot mailing list
[email protected]
https://lists.denx.de/listinfo/u-boot

#8 lore raw

PATCH v2 5/10 video: add MIPI DSI host controller bridge

In reply to yannick fertre

Add a Synopsys Designware MIPI DSI host bridge driver, based on the Rockchip version from rockchip/dw-mipi-dsi.c with phy & bridge APIs.

---
 drivers/video/Kconfig       |   9 +
 drivers/video/Makefile      |   1 +
 drivers/video/dw_mipi_dsi.c | 822 ++++++++++++++++++++++++++++++++++++++++++++
 include/dw_mipi_dsi.h       |  32 ++
 4 files changed, 864 insertions(+)
 create mode 100644 drivers/video/dw_mipi_dsi.c
 create mode 100644 include/dw_mipi_dsi.h
drivers/video/Kconfig +9 -0
index b5fc535..0f641d7 100644
@@ -657,6 +657,15 @@ config VIDEO_DW_HDMI
 	  rather requires a SoC-specific glue driver to call it), it
 	  can not be enabled from the configuration menu.
 
+config VIDEO_DW_MIPI_DSI
+	bool
+	help
+	  Enables the common driver code for the Designware MIPI DSI
+	  block found in SoCs from various vendors.
+	  As this does not provide any functionality by itself (but
+	  rather requires a SoC-specific glue driver to call it), it
+	  can not be enabled from the configuration menu.
+
 config VIDEO_SIMPLE
 	bool "Simple display driver for preconfigured display"
 	help
drivers/video/Makefile +1 -0
index 65002af..50be569 100644
@@ -53,6 +53,7 @@ obj-$(CONFIG_FORMIKE) += formike.o
 obj-$(CONFIG_LG4573) += lg4573.o
 obj-$(CONFIG_AM335X_LCD) += am335x-fb.o
 obj-$(CONFIG_VIDEO_DW_HDMI) += dw_hdmi.o
+obj-$(CONFIG_VIDEO_DW_MIPI_DSI) += dw_mipi_dsi.o
 obj-${CONFIG_VIDEO_MIPI_DSI} += mipi_display.o
 obj-$(CONFIG_VIDEO_SIMPLE) += simplefb.o
 obj-${CONFIG_VIDEO_TEGRA124} += tegra124/
drivers/video/dw_mipi_dsi.c new file +822 -0

822 lines not on this page · raw message

include/dw_mipi_dsi.h new file +32 -0
new file mode 100644
index 0000000..8c33ec2
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2017-2018, STMicroelectronics - All Rights Reserved
+ *
+ * Authors: Yannick Fertre <[email protected]>
+ *          Philippe Cornu <[email protected]>
+ *
+ * Modified by Yannick Fertre <[email protected]>
+ * This generic Synopsys DesignWare MIPI DSI host driver is based on the
+ * bridge synopsys from include/drm/bridge/dw_mipi_dsi.h (kernel linux).
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#ifndef __DW_MIPI_DSI__
+#define __DW_MIPI_DSI__
+
+struct dw_mipi_dsi_phy_ops {
+	int (*init)(void *priv_data);
+	int (*get_lane_mbps)(void *priv_data, struct display_timing *timings,
+			     u32 lanes, u32 format, unsigned int *lane_mbps);
+};
+
+struct dw_mipi_dsi_plat_data {
+	unsigned int max_data_lanes;
+	const struct dw_mipi_dsi_phy_ops *phy_ops;
+	struct udevice *panel;
+};
+
+int dw_mipi_dsi_init_bridge(struct mipi_dsi_device *device);
+void dw_mipi_dsi_bridge_enable(struct mipi_dsi_device *device);
+
+#endif /* __DW_MIPI_DSI__ */
Signature · 1 line
1.9.1
#9 lore raw

Re: [PATCH v2 05/10] video: add MIPI DSI host controller bridge

Hi,

Quoted 2 lines · yannick fertre

Add a Synopsys Designware MIPI DSI host bridge driver, based on the Rockchip version from rockchip/dw-mipi-dsi.c with phy & bridge APIs.

How many times are we going to allow copy-and-pasting the same driver? Last time we wanted to modify the Rockchip driver, we were told "consolidate", because ST had already forked our driver. This nearly halted all progress. I'm going to be real disappointed if we see another fork get merged.

(IOW, I would say "over my dead body," but I have no power here.)

And why can't you use DRM?

Brian

#10 lore raw

Re: [PATCH v2 05/10] video: add MIPI DSI host controller bridge

Quoted 12 lines · Brian Norris

Hi,

Quoted 2 lines · yannick fertre

Add a Synopsys Designware MIPI DSI host bridge driver, based on the Rockchip version from rockchip/dw-mipi-dsi.c with phy & bridge APIs.

How many times are we going to allow copy-and-pasting the same driver? Last time we wanted to modify the Rockchip driver, we were told "consolidate", because ST had already forked our driver. This nearly halted all progress. I'm going to be real disappointed if we see another fork get merged.

Quoted 3 lines

(IOW, I would say "over my dead body," but I have no power here.)

And why can't you use DRM?

...wait a second...this looks like it's a u-boot driver. There's a surprising amount of similarity between U-boot and Linux drivers (no coincidence I'm sure), including <linux/...> headers.

Since when do U-Boot patches go to LKML and dri-devel?

Anyway, I'll try my best to ignore this series.

Brian

#11 lore raw

PATCH v2 6/10 video: add support of STM32 MIPI DSI controller driver

In reply to yannick fertre

Add the STM32 DSI controller driver that uses the Synopsys DesignWare MIPI DSI host controller bridge.

---
 drivers/video/stm32/Kconfig     |  10 +
 drivers/video/stm32/Makefile    |   1 +
 drivers/video/stm32/stm32_dsi.c | 427 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 438 insertions(+)
 create mode 100644 drivers/video/stm32/stm32_dsi.c
drivers/video/stm32/Kconfig +10 -0
index 113a2bb..2ea6f18 100644
@@ -15,6 +15,16 @@ menuconfig VIDEO_STM32
 	  DSI. This option enables these supports which can be used on
 	  devices which have RGB TFT or DSI display connected.
 
+config VIDEO_STM32_DSI
+	bool "Enable STM32 DSI video support"
+	depends on VIDEO_STM32
+	select VIDEO_MIPI_DSI
+	select VIDEO_BRIDGE
+	select VIDEO_DW_MIPI_DSI
+	help
+	  This option enables support DSI internal bridge which can be used on
+	  devices which have DSI display connected.
+
 config VIDEO_STM32_MAX_XRES
 	int "Maximum horizontal resolution (for memory allocation purposes)"
 	depends on VIDEO_STM32
drivers/video/stm32/Makefile +1 -0
index 372a2e1..f8c3ff7 100644
@@ -8,3 +8,4 @@
 #
 
 obj-${CONFIG_VIDEO_STM32} = stm32_ltdc.o
+obj-${CONFIG_VIDEO_STM32_DSI} += stm32_dsi.o
drivers/video/stm32/stm32_dsi.c new file +427 -0

427 lines not on this page · raw message

Signature · 1 line
1.9.1
#12 lore raw

Re: [PATCH v2 06/10] video: add support of STM32 MIPI DSI controller driver

Hi yannick

Quoted 253 lines · yannick fertre

Add the STM32 DSI controller driver that uses the Synopsys DesignWare MIPI DSI host controller bridge.

---
  drivers/video/stm32/Kconfig     |  10 +
  drivers/video/stm32/Makefile    |   1 +
  drivers/video/stm32/stm32_dsi.c | 427 ++++++++++++++++++++++++++++++++++++++++
  3 files changed, 438 insertions(+)

create mode 100644 drivers/video/stm32/stm32_dsi.c

drivers/video/stm32/Kconfig +10 -0
index 113a2bb..2ea6f18 100644
@@ -15,6 +15,16 @@ menuconfig VIDEO_STM32
  	  DSI. This option enables these supports which can be used on
  	  devices which have RGB TFT or DSI display connected.
 
+config VIDEO_STM32_DSI
+	bool "Enable STM32 DSI video support"
+	depends on VIDEO_STM32
+	select VIDEO_MIPI_DSI
+	select VIDEO_BRIDGE
+	select VIDEO_DW_MIPI_DSI
+	help
+	  This option enables support DSI internal bridge which can be used on
+	  devices which have DSI display connected.
+
  config VIDEO_STM32_MAX_XRES
  	int "Maximum horizontal resolution (for memory allocation purposes)"
  	depends on VIDEO_STM32
drivers/video/stm32/Makefile +1 -0
index 372a2e1..f8c3ff7 100644
@@ -8,3 +8,4 @@
  #
 
  obj-${CONFIG_VIDEO_STM32} = stm32_ltdc.o
+obj-${CONFIG_VIDEO_STM32_DSI} += stm32_dsi.o
drivers/video/stm32/stm32_dsi.c new file +206 -0
new file mode 100644
index 0000000..3e26433
@@ -0,0 +1,427 @@
+/*
+ * Copyright (C) 2018 STMicroelectronics - All Rights Reserved
+ * Author(s): Philippe Cornu <[email protected]> for STMicroelectronics.
+ *	      Yannick Fertre <[email protected]> for STMicroelectronics.
+ *
+ * This driver is based on the mipi dsi driver from
+ * drivers/gpu/drm/stm/dw_mipi_dsi-stm.c (kernel linux).
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <asm/io.h>
+#include <asm/arch/gpio.h>
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <dm/device-internal.h>
+#include <mipi_display.h>
+#include <dw_mipi_dsi.h>
+#include <linux/iopoll.h>
+#include <panel.h>
+#include <reset.h>
+#include <video.h>
+#include <video_bridge.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define HWVER_130			0x31333000	/* IP version 1.30 */
+#define HWVER_131			0x31333100	/* IP version 1.31 */
+
+/* DSI digital registers & bit definitions */
+#define DSI_VERSION			0x00
+#define VERSION				GENMASK(31, 8)
+
+/*
+ * DSI wrapper registers & bit definitions
+ * Note: registers are named as in the Reference Manual
+ */
+#define DSI_WCFGR	0x0400		/* Wrapper ConFiGuration Reg */
+#define WCFGR_DSIM	BIT(0)		/* DSI Mode */
+#define WCFGR_COLMUX	GENMASK(3, 1)	/* COLor MUltipleXing */
+
+#define DSI_WCR		0x0404		/* Wrapper Control Reg */
+#define WCR_DSIEN	BIT(3)		/* DSI ENable */
+
+#define DSI_WISR	0x040C		/* Wrapper Interrupt and Status Reg */
+#define WISR_PLLLS	BIT(8)		/* PLL Lock Status */
+#define WISR_RRS	BIT(12)		/* Regulator Ready Status */
+
+#define DSI_WPCR0	0x0418		/* Wrapper Phy Conf Reg 0 */
+#define WPCR0_UIX4	GENMASK(5, 0)	/* Unit Interval X 4 */
+#define WPCR0_TDDL	BIT(16)		/* Turn Disable Data Lanes */
+
+#define DSI_WRPCR	0x0430		/* Wrapper Regulator & Pll Ctrl Reg */
+#define WRPCR_PLLEN	BIT(0)		/* PLL ENable */
+#define WRPCR_NDIV	GENMASK(8, 2)	/* pll loop DIVision Factor */
+#define WRPCR_IDF	GENMASK(14, 11)	/* pll Input Division Factor */
+#define WRPCR_ODF	GENMASK(17, 16)	/* pll Output Division Factor */
+#define WRPCR_REGEN	BIT(24)		/* REGulator ENable */
+#define WRPCR_BGREN	BIT(28)		/* BandGap Reference ENable */
+#define IDF_MIN		1
+#define IDF_MAX		7
+#define NDIV_MIN	10
+#define NDIV_MAX	125
+#define ODF_MIN		1
+#define ODF_MAX		8
+
+/* dsi color format coding according to the datasheet */
+enum dsi_color {
+	DSI_RGB565_CONF1,
+	DSI_RGB565_CONF2,
+	DSI_RGB565_CONF3,
+	DSI_RGB666_CONF1,
+	DSI_RGB666_CONF2,
+	DSI_RGB888,
+};
+
+#define LANE_MIN_KBPS	31250
+#define LANE_MAX_KBPS	500000
+
+/* Timeout for regulator on/off, pll lock/unlock & fifo empty */
+#define TIMEOUT_US	200000
+
+struct stm32_dsi_priv {
+	struct mipi_dsi_device device;
+	void __iomem *base;
+	struct udevice *panel;
+	u32 pllref_clk;
+	u32 hw_version;
+	int lane_min_kbps;
+	int lane_max_kbps;
+};
+
+static inline void dsi_write(struct stm32_dsi_priv *dsi, u32 reg, u32 val)
+{
+	writel(val, dsi->base + reg);
+}
+
+static inline u32 dsi_read(struct stm32_dsi_priv *dsi, u32 reg)
+{
+	return readl(dsi->base + reg);
+}
+
+static inline void dsi_set(struct stm32_dsi_priv *dsi, u32 reg, u32 mask)
+{
+	dsi_write(dsi, reg, dsi_read(dsi, reg) | mask);
+}
+
+static inline void dsi_clear(struct stm32_dsi_priv *dsi, u32 reg, u32 mask)
+{
+	dsi_write(dsi, reg, dsi_read(dsi, reg) & ~mask);
+}
+
+static inline void dsi_update_bits(struct stm32_dsi_priv *dsi, u32 reg,
+				   u32 mask, u32 val)
+{
+	dsi_write(dsi, reg, (dsi_read(dsi, reg) & ~mask) | val);
+}
+
+static enum dsi_color dsi_color_from_mipi(u32 fmt)
+{
+	switch (fmt) {
+	case MIPI_DSI_FMT_RGB888:
+		return DSI_RGB888;
+	case MIPI_DSI_FMT_RGB666:
+		return DSI_RGB666_CONF2;
+	case MIPI_DSI_FMT_RGB666_PACKED:
+		return DSI_RGB666_CONF1;
+	case MIPI_DSI_FMT_RGB565:
+		return DSI_RGB565_CONF1;
+	default:
+		pr_err("MIPI color invalid, so we use rgb888\n");
+	}
+	return DSI_RGB888;
+}
+
+static int dsi_pll_get_clkout_khz(int clkin_khz, int idf, int ndiv, int odf)
+{
+	int divisor = idf * odf;
+
+	/* prevent from division by 0 */
+	if (!divisor)
+		return 0;
+
+	return DIV_ROUND_CLOSEST(clkin_khz * ndiv, divisor);
+}
+
+static int dsi_pll_get_params(struct stm32_dsi_priv *dsi,
+			      int clkin_khz, int clkout_khz,
+			      int *idf, int *ndiv, int *odf)
+{
+	int i, o, n, n_min, n_max;
+	int fvco_min, fvco_max, delta, best_delta; /* all in khz */
+
+	/* Early checks preventing division by 0 & odd results */
+	if (clkin_khz <= 0 || clkout_khz <= 0)
+		return -EINVAL;
+
+	fvco_min = dsi->lane_min_kbps * 2 * ODF_MAX;
+	fvco_max = dsi->lane_max_kbps * 2 * ODF_MIN;
+
+	best_delta = 1000000; /* big started value (1000000khz) */
+
+	for (i = IDF_MIN; i <= IDF_MAX; i++) {
+		/* Compute ndiv range according to Fvco */
+		n_min = ((fvco_min * i) / (2 * clkin_khz)) + 1;
+		n_max = (fvco_max * i) / (2 * clkin_khz);
+
+		/* No need to continue idf loop if we reach ndiv max */
+		if (n_min >= NDIV_MAX)
+			break;
+
+		/* Clamp ndiv to valid values */
+		if (n_min < NDIV_MIN)
+			n_min = NDIV_MIN;
+		if (n_max > NDIV_MAX)
+			n_max = NDIV_MAX;
+
+		for (o = ODF_MIN; o <= ODF_MAX; o *= 2) {
+			n = DIV_ROUND_CLOSEST(i * o * clkout_khz, clkin_khz);
+			/* Check ndiv according to vco range */
+			if (n < n_min || n > n_max)
+				continue;
+			/* Check if new delta is better & saves parameters */
+			delta = dsi_pll_get_clkout_khz(clkin_khz, i, n, o) -
+				clkout_khz;
+			if (delta < 0)
+				delta = -delta;
+			if (delta < best_delta) {
+				*idf = i;
+				*ndiv = n;
+				*odf = o;
+				best_delta = delta;
+			}
+			/* fast return in case of "perfect result" */
+			if (!delta)
+				return 0;
+		}
+	}
+
+	return 0;
+}
+
+static int dsi_phy_init(void *priv_data)
+{
+	struct mipi_dsi_device *device = priv_data;

drivers/video/stm32/stm32_dsi.c line 216

Quoted 10 lines
drivers/video/stm32/stm32_dsi.c new file +10 -0
+	struct stm32_dsi_priv *dsi = dev_get_priv(device->dev);
+	u32 val;
+	int ret;
+
+	/* Enable the regulator */
+	dsi_set(dsi, DSI_WRPCR, WRPCR_REGEN | WRPCR_BGREN);
+	ret = readl_poll_timeout(dsi->base + DSI_WISR, val, val & WISR_RRS,
+				 TIMEOUT_US);
+	if (ret) {
+		pr_err("!TIMEOUT! waiting REGU\n");

dev_err()

drivers/video/stm32/stm32_dsi.c line 225

Quoted 9 lines
drivers/video/stm32/stm32_dsi.c new file +9 -0
+		return ret;
+	}
+
+	/* Enable the DSI PLL & wait for its lock */
+	dsi_set(dsi, DSI_WRPCR, WRPCR_PLLEN);
+	ret = readl_poll_timeout(dsi->base + DSI_WISR, val, val & WISR_PLLLS,
+				 TIMEOUT_US);
+	if (ret) {
+		pr_err("!TIMEOUT! waiting PLL\n");

dev_err()

Quoted 41 lines
drivers/video/stm32/stm32_dsi.c new file +41 -0
+		return ret;
+	}
+
+	/* Enable the DSI wrapper */
+	dsi_set(dsi, DSI_WCR, WCR_DSIEN);
+
+	return 0;
+}
+
+static int dsi_get_lane_mbps(void *priv_data, struct display_timing *timings,
+			     u32 lanes, u32 format, unsigned int *lane_mbps)
+{
+	struct mipi_dsi_device *device = priv_data;
+	struct stm32_dsi_priv *dsi = dev_get_priv(device->dev);
+	int idf, ndiv, odf, pll_in_khz, pll_out_khz;
+	int ret, bpp;
+	u32 val;
+
+	/* Update lane capabilities according to hw version */
+	dsi->hw_version = dsi_read(dsi, DSI_VERSION) & VERSION;
+	dsi->lane_min_kbps = LANE_MIN_KBPS;
+	dsi->lane_max_kbps = LANE_MAX_KBPS;
+	if (dsi->hw_version == HWVER_131) {
+		dsi->lane_min_kbps *= 2;
+		dsi->lane_max_kbps *= 2;
+	}
+
+	pll_in_khz = dsi->pllref_clk / 1000;
+
+	/* Compute requested pll out */
+	bpp = mipi_dsi_pixel_format_to_bpp(format);
+	pll_out_khz = (timings->pixelclock.typ / 1000) * bpp / lanes;
+	/* Add 20% to pll out to be higher than pixel bw (burst mode only) */
+	pll_out_khz = (pll_out_khz * 12) / 10;
+	if (pll_out_khz > dsi->lane_max_kbps) {
+		pll_out_khz = dsi->lane_max_kbps;
+		pr_warn("Warning max phy mbps is used\n");
+	}
+	if (pll_out_khz < dsi->lane_min_kbps) {
+		pll_out_khz = dsi->lane_min_kbps;
+		pr_warn("Warning min phy mbps is used\n");

drivers/video/stm32/stm32_dsi.c line 276

Quoted 10 lines
drivers/video/stm32/stm32_dsi.c new file +10 -0
+	}
+
+	/* Compute best pll parameters */
+	idf = 0;
+	ndiv = 0;
+	odf = 0;
+	ret = dsi_pll_get_params(dsi, pll_in_khz, pll_out_khz,
+				 &idf, &ndiv, &odf);
+	if (ret) {
+		pr_warn("Warning dsi_pll_get_params(): bad params\n");

dev_warn() or dev_err() ?

Quoted 15 lines
drivers/video/stm32/stm32_dsi.c new file +15 -0
+		return ret;
+	}
+
+	/* Get the adjusted pll out value */
+	pll_out_khz = dsi_pll_get_clkout_khz(pll_in_khz, idf, ndiv, odf);
+
+	/* Set the PLL division factors */
+	dsi_update_bits(dsi, DSI_WRPCR,	WRPCR_NDIV | WRPCR_IDF | WRPCR_ODF,
+			(ndiv << 2) | (idf << 11) | ((ffs(odf) - 1) << 16));
+
+	/* Compute uix4 & set the bit period in high-speed mode */
+	val = 4000000 / pll_out_khz;
+	dsi_update_bits(dsi, DSI_WPCR0, WPCR0_UIX4, val);
+
+	/* Select video mode by resetting DSIM bit */

drivers/video/stm32/stm32_dsi.c line 301

Quoted 10 lines
drivers/video/stm32/stm32_dsi.c new file +10 -0
+	dsi_clear(dsi, DSI_WCFGR, WCFGR_DSIM);
+
+	/* Select the color coding */
+	dsi_update_bits(dsi, DSI_WCFGR, WCFGR_COLMUX,
+			dsi_color_from_mipi(format) << 1);
+
+	*lane_mbps = pll_out_khz / 1000;
+
+	pr_info("pll_in %ukHz pll_out %ukHz lane_mbps %uMHz\n",
+		pll_in_khz, pll_out_khz, *lane_mbps);

is it useful to print this each time ? or is it for debug purpose ? in this case use debug()

Quoted 12 lines
drivers/video/stm32/stm32_dsi.c new file +12 -0
+
+	return 0;
+}
+
+static const struct dw_mipi_dsi_phy_ops dw_mipi_dsi_stm_phy_ops = {
+	.init = dsi_phy_init,
+	.get_lane_mbps = dsi_get_lane_mbps,
+};
+
+static int stm32_dsi_attach(struct udevice *dev)
+{
+	struct stm32_dsi_priv *priv = dev_get_priv(dev);

drivers/video/stm32/stm32_dsi.c line 323

Quoted 10 lines
drivers/video/stm32/stm32_dsi.c new file +10 -0
+	struct dw_mipi_dsi_plat_data *platdata = dev_get_platdata(dev);
+	struct mipi_dsi_device *device = &priv->device;
+	int ret;
+
+	platdata->max_data_lanes = 2;
+	platdata->phy_ops = &dw_mipi_dsi_stm_phy_ops;
+
+	ret = uclass_first_device(UCLASS_PANEL, &platdata->panel);
+	if (ret) {
+		pr_err("%s: panel device error %d\n", __func__, ret);

dev_err()

drivers/video/stm32/stm32_dsi.c line 329

Quoted 6 lines
drivers/video/stm32/stm32_dsi.c new file +6 -0
+		return ret;
+	}
+
+	ret = dw_mipi_dsi_init_bridge(device);
+	if (ret) {
+		pr_err("Failed to initialize mipi dsi host\n");

ditto

Quoted 12 lines
drivers/video/stm32/stm32_dsi.c new file +12 -0
+		return ret;
+	}
+
+	return 0;
+}
+
+static int stm32_dsi_set_backlight(struct udevice *dev, int percent)
+{
+	struct dw_mipi_dsi_plat_data *dplat = dev_get_platdata(dev);
+	struct stm32_dsi_priv *priv = dev_get_priv(dev);
+	struct mipi_dsi_device *device = &priv->device;
+	struct udevice *panel = dplat->panel;

drivers/video/stm32/stm32_dsi.c line 351

Quoted 10 lines
drivers/video/stm32/stm32_dsi.c new file +10 -0
+	struct mipi_dsi_panel_plat *mplat;
+	int ret;
+
+	mplat = dev_get_platdata(panel);
+	mplat->device = device;
+
+	ret = panel_enable_backlight(panel);
+	if (ret) {
+		pr_err("%s: panel %s enable backlight error %d\n",
+		       __func__, panel->name, ret);

ditto

Quoted 11 lines
drivers/video/stm32/stm32_dsi.c new file +11 -0
+		return ret;
+	}
+
+	dw_mipi_dsi_bridge_enable(device);
+
+	return 0;
+}
+
+static int stm32_dsi_probe(struct udevice *dev)
+{
+	struct stm32_dsi_priv *priv = dev_get_priv(dev);

drivers/video/stm32/stm32_dsi.c line 372

Quoted 10 lines
drivers/video/stm32/stm32_dsi.c new file +10 -0
+	struct mipi_dsi_device *device = &priv->device;
+	struct reset_ctl rst;
+	struct clk clk;
+	int ret;
+
+	device->dev = dev;
+
+	priv->base = (void *)dev_read_addr(dev);
+	if ((fdt_addr_t)priv->base == FDT_ADDR_T_NONE) {
+		pr_err("%s: dsi dt register address error\n", __func__);

ditto

drivers/video/stm32/stm32_dsi.c line 378

Quoted 6 lines
drivers/video/stm32/stm32_dsi.c new file +6 -0
+		return -EINVAL;
+	}
+
+	ret = clk_get_by_name(device->dev, "pclk", &clk);
+	if (ret) {
+		pr_err("%s: peripheral clock get error %d\n", __func__, ret);

ditto

drivers/video/stm32/stm32_dsi.c line 384

Quoted 6 lines
drivers/video/stm32/stm32_dsi.c new file +6 -0
+		return -ENODEV;
+	}
+
+	ret = clk_enable(&clk);
+	if (ret) {
+		pr_err("%s: peripheral clock enable error %d\n", __func__, ret);

ditto

drivers/video/stm32/stm32_dsi.c line 390

Quoted 6 lines
drivers/video/stm32/stm32_dsi.c new file +6 -0
+		return -ENODEV;
+	}
+
+	ret = clk_get_by_name(dev, "ref", &clk);
+	if (ret) {
+		pr_err("%s: pll reference clock get error %d\n", __func__, ret);

ditto

drivers/video/stm32/stm32_dsi.c line 398

Quoted 8 lines
drivers/video/stm32/stm32_dsi.c new file +8 -0
+		return ret;
+	}
+
+	priv->pllref_clk = (unsigned int)clk_get_rate(&clk);
+
+	ret = reset_get_by_index(device->dev, 0, &rst);
+	if (ret) {
+		pr_err("%s: missing dsi hardware reset\n", __func__);

ditto

Quoted 20 lines
drivers/video/stm32/stm32_dsi.c new file +19 -0
+		return -ENODEV;
+	}
+
+	/* Reset */
+	reset_deassert(&rst);
+
+	return 0;
+}
+
+struct video_bridge_ops stm32_dsi_ops = {
+	.attach = stm32_dsi_attach,
+	.set_backlight = stm32_dsi_set_backlight,
+};
+
+static const struct udevice_id stm32_dsi_ids[] = {
+	{ .compatible = "st,stm32-dsi"},
+	{ }
+};
+

drivers/video/stm32/stm32_dsi.c line 427

Quoted 10 lines
drivers/video/stm32/stm32_dsi.c new file +10 -0
+U_BOOT_DRIVER(stm32_dsi) = {
+	.name				= "stm32-display-dsi",
+	.id				= UCLASS_VIDEO_BRIDGE,
+	.of_match			= stm32_dsi_ids,
+	.bind				= dm_scan_fdt_dev,
+	.probe				= stm32_dsi_probe,
+	.ops				= &stm32_dsi_ops,
+	.priv_auto_alloc_size		= sizeof(struct stm32_dsi_priv),
+	.platdata_auto_alloc_size	= sizeof(struct dw_mipi_dsi_plat_data),
+};

_______________________________________________
U-Boot mailing list
[email protected]
https://lists.denx.de/listinfo/u-boot

#13 lore raw

PATCH v2 7/10 video: add support of panel rm68200

In reply to yannick fertre

Support for Raydium rm68200 720p dsi 2dl video mode panel.

---
 drivers/video/Kconfig           |   8 +
 drivers/video/Makefile          |   1 +
 drivers/video/raydium-rm68200.c | 329 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 338 insertions(+)
 create mode 100644 drivers/video/raydium-rm68200.c
drivers/video/Kconfig +8 -0
index 0f641d7..2561c59 100644
@@ -328,6 +328,14 @@ config VIDEO_LCD_ORISETECH_OTM8009A
 	---help---
 	Support for Orise Tech otm8009a 480p dsi 2dl video mode panel.
 
+config VIDEO_LCD_RAYDIUM_RM68200
+	bool "RM68200 DSI LCD panel support"
+	depends on DM_VIDEO
+	select VIDEO_MIPI_DSI
+	default n
+	---help---
+	Support for Raydium rm68200 720x1280 dsi 2dl video mode panel.
+
 config VIDEO_LCD_SSD2828
 	bool "SSD2828 bridge chip"
 	default n
drivers/video/Makefile +1 -0
index 50be569..1a6c8d3 100644
@@ -38,6 +38,7 @@ obj-$(CONFIG_VIDEO_DA8XX) += da8xx-fb.o videomodes.o
 obj-$(CONFIG_VIDEO_LCD_ANX9804) += anx9804.o
 obj-$(CONFIG_VIDEO_LCD_HITACHI_TX18D42VM) += hitachi_tx18d42vm_lcd.o
 obj-$(CONFIG_VIDEO_LCD_ORISETECH_OTM8009A) += orisetech_otm8009a.o
+obj-$(CONFIG_VIDEO_LCD_RAYDIUM_RM68200) += raydium-rm68200.o
 obj-$(CONFIG_VIDEO_LCD_SSD2828) += ssd2828.o
 obj-$(CONFIG_VIDEO_MB862xx) += mb862xx.o videomodes.o
 obj-$(CONFIG_VIDEO_MX3) += mx3fb.o videomodes.o
drivers/video/raydium-rm68200.c new file +329 -0

329 lines not on this page · raw message

Signature · 1 line
1.9.1
#14 lore raw

Re: [PATCH v2 07/10] video: add support of panel rm68200

Hi yannick

Quoted 127 lines · yannick fertre

Support for Raydium rm68200 720p dsi 2dl video mode panel.

---
  drivers/video/Kconfig           |   8 +
  drivers/video/Makefile          |   1 +
  drivers/video/raydium-rm68200.c | 329 ++++++++++++++++++++++++++++++++++++++++
  3 files changed, 338 insertions(+)

create mode 100644 drivers/video/raydium-rm68200.c

drivers/video/Kconfig +8 -0
index 0f641d7..2561c59 100644
@@ -328,6 +328,14 @@ config VIDEO_LCD_ORISETECH_OTM8009A
  	---help---
  	Support for Orise Tech otm8009a 480p dsi 2dl video mode panel.
 
+config VIDEO_LCD_RAYDIUM_RM68200
+	bool "RM68200 DSI LCD panel support"
+	depends on DM_VIDEO
+	select VIDEO_MIPI_DSI
+	default n
+	---help---
+	Support for Raydium rm68200 720x1280 dsi 2dl video mode panel.
+
  config VIDEO_LCD_SSD2828
  	bool "SSD2828 bridge chip"
  	default n
drivers/video/Makefile +1 -0
index 50be569..1a6c8d3 100644
@@ -38,6 +38,7 @@ obj-$(CONFIG_VIDEO_DA8XX) += da8xx-fb.o videomodes.o
  obj-$(CONFIG_VIDEO_LCD_ANX9804) += anx9804.o
  obj-$(CONFIG_VIDEO_LCD_HITACHI_TX18D42VM) += hitachi_tx18d42vm_lcd.o
  obj-$(CONFIG_VIDEO_LCD_ORISETECH_OTM8009A) += orisetech_otm8009a.o
+obj-$(CONFIG_VIDEO_LCD_RAYDIUM_RM68200) += raydium-rm68200.o
  obj-$(CONFIG_VIDEO_LCD_SSD2828) += ssd2828.o
  obj-$(CONFIG_VIDEO_MB862xx) += mb862xx.o videomodes.o
  obj-$(CONFIG_VIDEO_MX3) += mx3fb.o videomodes.o
drivers/video/raydium-rm68200.c new file +80 -0
new file mode 100644
index 0000000..46afb58
@@ -0,0 +1,329 @@
+/*
+ * Copyright (C) 2018 STMicroelectronics - All Rights Reserved
+ * Author(s): Yannick Fertre <[email protected]> for STMicroelectronics.
+ *	      Philippe Cornu <[email protected]> for STMicroelectronics.
+ *
+ * This rm68200 panel driver is based on the panel driver from
+ * drivers/gpu/drm/panel/panel-raydium-rm68200.c (kernel linux)
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+#include <asm/gpio.h>
+#include <backlight.h>
+#include <common.h>
+#include <dm.h>
+#include <panel.h>
+#include <power/regulator.h>
+#include <mipi_display.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define DRV_NAME "raydium_rm68200"
+
+/*** Manufacturer Command Set ***/
+#define MCS_CMD_MODE_SW	0xFE /* CMD Mode Switch */
+#define MCS_CMD1_UCS	0x00 /* User Command Set (UCS = CMD1) */
+#define MCS_CMD2_P0	0x01 /* Manufacture Command Set Page0 (CMD2 P0) */
+#define MCS_CMD2_P1	0x02 /* Manufacture Command Set Page1 (CMD2 P1) */
+#define MCS_CMD2_P2	0x03 /* Manufacture Command Set Page2 (CMD2 P2) */
+#define MCS_CMD2_P3	0x04 /* Manufacture Command Set Page3 (CMD2 P3) */
+
+/* CMD2 P0 commands (Display Options and Power) */
+#define MCS_STBCTR	0x12 /* TE1 Output Setting Zig-Zag Connection */
+#define MCS_SGOPCTR	0x16 /* Source Bias Current */
+#define MCS_SDCTR	0x1A /* Source Output Delay Time */
+#define MCS_INVCTR	0x1B /* Inversion Type */
+#define MCS_EXT_PWR_IC	0x24 /* External PWR IC Control */
+#define MCS_SETAVDD	0x27 /* PFM Control for AVDD Output */
+#define MCS_SETAVEE	0x29 /* PFM Control for AVEE Output */
+#define MCS_BT2CTR	0x2B /* DDVDL Charge Pump Control */
+#define MCS_BT3CTR	0x2F /* VGH Charge Pump Control */
+#define MCS_BT4CTR	0x34 /* VGL Charge Pump Control */
+#define MCS_VCMCTR	0x46 /* VCOM Output Level Control */
+#define MCS_SETVGN	0x52 /* VG M/S N Control */
+#define MCS_SETVGP	0x54 /* VG M/S P Control */
+#define MCS_SW_CTRL	0x5F /* Interface Control for PFM and MIPI */
+
+/* CMD2 P2 commands (GOA Timing Control) - no description in datasheet */
+#define GOA_VSTV1	0x00
+#define GOA_VSTV2	0x07
+#define GOA_VCLK1	0x0E
+#define GOA_VCLK2	0x17
+#define GOA_VCLK_OPT1	0x20
+#define GOA_BICLK1	0x2A
+#define GOA_BICLK2	0x37
+#define GOA_BICLK3	0x44
+#define GOA_BICLK4	0x4F
+#define GOA_BICLK_OPT1	0x5B
+#define GOA_BICLK_OPT2	0x60
+#define MCS_GOA_GPO1	0x6D
+#define MCS_GOA_GPO2	0x71
+#define MCS_GOA_EQ	0x74
+#define MCS_GOA_CLK_GALLON 0x7C
+#define MCS_GOA_FS_SEL0	0x7E
+#define MCS_GOA_FS_SEL1	0x87
+#define MCS_GOA_FS_SEL2	0x91
+#define MCS_GOA_FS_SEL3	0x9B
+#define MCS_GOA_BS_SEL0	0xAC
+#define MCS_GOA_BS_SEL1	0xB5
+#define MCS_GOA_BS_SEL2	0xBF
+#define MCS_GOA_BS_SEL3	0xC9
+#define MCS_GOA_BS_SEL4	0xD3
+
+/* CMD2 P3 commands (Gamma) */
+#define MCS_GAMMA_VP	0x60 /* Gamma VP1~VP16 */
+#define MCS_GAMMA_VN	0x70 /* Gamma VN1~VN16 */
+
+struct rm68200_panel_priv {
+	struct udevice *reg;
+	struct udevice *backlight;
+	struct gpio_desc reset;

drivers/video/raydium-rm68200.c line 90

Quoted 10 lines
drivers/video/raydium-rm68200.c new file +10 -0
+};
+
+static void rm68200_dcs_write_buf(struct udevice *dev, const void *data,
+				  size_t len)
+{
+	struct mipi_dsi_panel_plat *plat = dev_get_platdata(dev);
+	struct mipi_dsi_device *device = plat->device;
+
+	if (mipi_dsi_dcs_write_buffer(device, data, len) < 0)
+		pr_err("mipi dsi dcs write buffer failed\n");

pr_err()

drivers/video/raydium-rm68200.c line 99

Quoted 9 lines
drivers/video/raydium-rm68200.c new file +9 -0
+}
+
+static void rm68200_dcs_write_cmd(struct udevice *dev, u8 cmd, u8 value)
+{
+	struct mipi_dsi_panel_plat *plat = dev_get_platdata(dev);
+	struct mipi_dsi_device *device = plat->device;
+
+	if (mipi_dsi_dcs_write(device, cmd, &value, 1) < 0)
+		pr_err("mipi dsi dcs write failed\n");

ditto

Quoted 119 lines
drivers/video/raydium-rm68200.c new file +119 -0
+}
+
+#define dcs_write_seq(ctx, seq...)				\
+({								\
+	static const u8 d[] = { seq };				\
+	rm68200_dcs_write_buf(ctx, d, ARRAY_SIZE(d));		\
+})
+
+/*
+ * This panel is not able to auto-increment all cmd addresses so for some of
+ * them, we need to send them one by one...
+ */
+#define dcs_write_cmd_seq(ctx, cmd, seq...)			\
+({								\
+	static const u8 d[] = { seq };				\
+	static int i;						\
+	for (i = 0; i < ARRAY_SIZE(d) ; i++)			\
+		rm68200_dcs_write_cmd(ctx, cmd + i, d[i]);	\
+})
+
+static int rm68200_init_sequence(struct udevice *dev)
+{
+	/* Enter CMD2 with page 0 */
+	dcs_write_seq(dev, MCS_CMD_MODE_SW, MCS_CMD2_P0);
+	dcs_write_cmd_seq(dev, MCS_EXT_PWR_IC, 0xC0, 0x53, 0x00);
+	dcs_write_seq(dev, MCS_BT2CTR, 0xE5);
+	dcs_write_seq(dev, MCS_SETAVDD, 0x0A);
+	dcs_write_seq(dev, MCS_SETAVEE, 0x0A);
+	dcs_write_seq(dev, MCS_SGOPCTR, 0x52);
+	dcs_write_seq(dev, MCS_BT3CTR, 0x53);
+	dcs_write_seq(dev, MCS_BT4CTR, 0x5A);
+	dcs_write_seq(dev, MCS_INVCTR, 0x00);
+	dcs_write_seq(dev, MCS_STBCTR, 0x0A);
+	dcs_write_seq(dev, MCS_SDCTR, 0x06);
+	dcs_write_seq(dev, MCS_VCMCTR, 0x56);
+	dcs_write_seq(dev, MCS_SETVGN, 0xA0, 0x00);
+	dcs_write_seq(dev, MCS_SETVGP, 0xA0, 0x00);
+	dcs_write_seq(dev, MCS_SW_CTRL, 0x11); /* 2 data lanes, see doc */
+
+	dcs_write_seq(dev, MCS_CMD_MODE_SW, MCS_CMD2_P2);
+	dcs_write_seq(dev, GOA_VSTV1, 0x05);
+	dcs_write_seq(dev, 0x02, 0x0B);
+	dcs_write_seq(dev, 0x03, 0x0F);
+	dcs_write_seq(dev, 0x04, 0x7D, 0x00, 0x50);
+	dcs_write_cmd_seq(dev, GOA_VSTV2, 0x05, 0x16, 0x0D, 0x11, 0x7D, 0x00,
+			  0x50);
+	dcs_write_cmd_seq(dev, GOA_VCLK1, 0x07, 0x08, 0x01, 0x02, 0x00, 0x7D,
+			  0x00, 0x85, 0x08);
+	dcs_write_cmd_seq(dev, GOA_VCLK2, 0x03, 0x04, 0x05, 0x06, 0x00, 0x7D,
+			  0x00, 0x85, 0x08);
+	dcs_write_seq(dev, GOA_VCLK_OPT1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		      0x00, 0x00, 0x00, 0x00);
+	dcs_write_cmd_seq(dev, GOA_BICLK1, 0x07, 0x08);
+	dcs_write_seq(dev, 0x2D, 0x01);
+	dcs_write_seq(dev, 0x2F, 0x02, 0x00, 0x40, 0x05, 0x08, 0x54, 0x7D,
+		      0x00);
+	dcs_write_cmd_seq(dev, GOA_BICLK2, 0x03, 0x04, 0x05, 0x06, 0x00);
+	dcs_write_seq(dev, 0x3D, 0x40);
+	dcs_write_seq(dev, 0x3F, 0x05, 0x08, 0x54, 0x7D, 0x00);
+	dcs_write_seq(dev, GOA_BICLK3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		      0x00, 0x00, 0x00, 0x00, 0x00);
+	dcs_write_seq(dev, GOA_BICLK4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		      0x00, 0x00);
+	dcs_write_seq(dev, 0x58, 0x00, 0x00, 0x00);
+	dcs_write_seq(dev, GOA_BICLK_OPT1, 0x00, 0x00, 0x00, 0x00, 0x00);
+	dcs_write_seq(dev, GOA_BICLK_OPT2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
+	dcs_write_seq(dev, MCS_GOA_GPO1, 0x00, 0x00, 0x00, 0x00);
+	dcs_write_seq(dev, MCS_GOA_GPO2, 0x00, 0x20, 0x00);
+	dcs_write_seq(dev, MCS_GOA_EQ, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+		      0x00, 0x00);
+	dcs_write_seq(dev, MCS_GOA_CLK_GALLON, 0x00, 0x00);
+	dcs_write_cmd_seq(dev, MCS_GOA_FS_SEL0, 0xBF, 0x02, 0x06, 0x14, 0x10,
+			  0x16, 0x12, 0x08, 0x3F);
+	dcs_write_cmd_seq(dev, MCS_GOA_FS_SEL1, 0x3F, 0x3F, 0x3F, 0x3F, 0x0C,
+			  0x0A, 0x0E, 0x3F, 0x3F, 0x00);
+	dcs_write_cmd_seq(dev, MCS_GOA_FS_SEL2, 0x04, 0x3F, 0x3F, 0x3F, 0x3F,
+			  0x05, 0x01, 0x3F, 0x3F, 0x0F);
+	dcs_write_cmd_seq(dev, MCS_GOA_FS_SEL3, 0x0B, 0x0D, 0x3F, 0x3F, 0x3F,
+			  0x3F);
+	dcs_write_cmd_seq(dev, 0xA2, 0x3F, 0x09, 0x13, 0x17, 0x11, 0x15);
+	dcs_write_cmd_seq(dev, 0xA9, 0x07, 0x03, 0x3F);
+	dcs_write_cmd_seq(dev, MCS_GOA_BS_SEL0, 0x3F, 0x05, 0x01, 0x17, 0x13,
+			  0x15, 0x11, 0x0F, 0x3F);
+	dcs_write_cmd_seq(dev, MCS_GOA_BS_SEL1, 0x3F, 0x3F, 0x3F, 0x3F, 0x0B,
+			  0x0D, 0x09, 0x3F, 0x3F, 0x07);
+	dcs_write_cmd_seq(dev, MCS_GOA_BS_SEL2, 0x03, 0x3F, 0x3F, 0x3F, 0x3F,
+			  0x02, 0x06, 0x3F, 0x3F, 0x08);
+	dcs_write_cmd_seq(dev, MCS_GOA_BS_SEL3, 0x0C, 0x0A, 0x3F, 0x3F, 0x3F,
+			  0x3F, 0x3F, 0x0E, 0x10, 0x14);
+	dcs_write_cmd_seq(dev, MCS_GOA_BS_SEL4, 0x12, 0x16, 0x00, 0x04, 0x3F);
+	dcs_write_seq(dev, 0xDC, 0x02);
+	dcs_write_seq(dev, 0xDE, 0x12);
+
+	dcs_write_seq(dev, MCS_CMD_MODE_SW, 0x0E); /* No documentation */
+	dcs_write_seq(dev, 0x01, 0x75);
+
+	dcs_write_seq(dev, MCS_CMD_MODE_SW, MCS_CMD2_P3);
+	dcs_write_cmd_seq(dev, MCS_GAMMA_VP, 0x00, 0x0C, 0x12, 0x0E, 0x06,
+			  0x12, 0x0E, 0x0B, 0x15, 0x0B, 0x10, 0x07, 0x0F,
+			  0x12, 0x0C, 0x00);
+	dcs_write_cmd_seq(dev, MCS_GAMMA_VN, 0x00, 0x0C, 0x12, 0x0E, 0x06,
+			  0x12, 0x0E, 0x0B, 0x15, 0x0B, 0x10, 0x07, 0x0F,
+			  0x12, 0x0C, 0x00);
+
+	/* Exit CMD2 */
+	dcs_write_seq(dev, MCS_CMD_MODE_SW, MCS_CMD1_UCS);
+
+	return 0;
+}
+
+static int rm68200_panel_enable_backlight(struct udevice *dev)
+{
+	struct mipi_dsi_panel_plat *plat = dev_get_platdata(dev);
+	struct mipi_dsi_device *device = plat->device;
+	struct rm68200_panel_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	device->lanes = 2;

drivers/video/raydium-rm68200.c line 228

Quoted 10 lines
drivers/video/raydium-rm68200.c new file +10 -0
+	device->format = MIPI_DSI_FMT_RGB888;
+	device->mode_flags = MIPI_DSI_MODE_VIDEO |
+			     MIPI_DSI_MODE_VIDEO_BURST |
+			     MIPI_DSI_MODE_LPM;
+
+	ret = mipi_dsi_attach(device);
+	if (ret < 0)
+		return ret;
+
+	pr_info("%s: initialize panel\n", __func__);

debug() ?

Quoted 10 lines
drivers/video/raydium-rm68200.c new file +10 -0
+
+	ret = rm68200_init_sequence(dev);
+	if (ret)
+		return ret;
+
+	ret = mipi_dsi_dcs_exit_sleep_mode(device);
+	if (ret)
+		return ret;
+
+	mdelay(125);

drivers/video/raydium-rm68200.c line 248

Quoted 10 lines
drivers/video/raydium-rm68200.c new file +10 -0
+
+	ret = mipi_dsi_dcs_set_display_on(device);
+	if (ret)
+		return ret;
+
+	mdelay(20);
+
+	pr_info("%s: start, backlight = '%s'\n", __func__,
+		priv->backlight->name);
+

debug() ?

Quoted 8 lines
drivers/video/raydium-rm68200.c new file +8 -0
+	ret = backlight_enable(priv->backlight);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int rm68200_panel_ofdata_to_platdata(struct udevice *dev)

drivers/video/raydium-rm68200.c line 266

Quoted 10 lines
drivers/video/raydium-rm68200.c new file +10 -0
+{
+	struct rm68200_panel_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	if (IS_ENABLED(CONFIG_DM_REGULATOR)) {
+		ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev,
+						   "power-supply", &priv->reg);
+		if (ret) {
+			pr_info("%s: Warning: cannot get power supply\n",
+				__func__);

dev_info()

drivers/video/raydium-rm68200.c line 275

Quoted 9 lines
drivers/video/raydium-rm68200.c new file +9 -0
+			if (ret != -ENOENT)
+				return ret;
+		}
+	}
+
+	ret = gpio_request_by_name(dev, "reset-gpios", 0, &priv->reset,
+				   GPIOD_IS_OUT);
+	if (ret) {
+		pr_info("%s: Warning: cannot get reset GPIO\n", __func__);

ditto

Quoted 8 lines
drivers/video/raydium-rm68200.c new file +8 -0
+		if (ret != -ENOENT)
+			return ret;
+	}
+
+	/* reset panel must be done before probe */
+	dm_gpio_set_value(&priv->reset, true);
+
+	return 0;

drivers/video/raydium-rm68200.c line 293

Quoted 10 lines
drivers/video/raydium-rm68200.c new file +10 -0
+}
+
+static int rm68200_panel_probe(struct udevice *dev)
+{
+	struct rm68200_panel_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	if (IS_ENABLED(CONFIG_DM_REGULATOR) && priv->reg) {
+		pr_info("%s: Enable regulator '%s'\n", __func__,
+			priv->reg->name);

debug() ?

drivers/video/raydium-rm68200.c line 304

Quoted 11 lines
drivers/video/raydium-rm68200.c new file +11 -0
+		ret = regulator_set_enable(priv->reg, true);
+		if (ret)
+			return ret;
+	}
+
+	dm_gpio_set_value(&priv->reset, false);
+
+	ret = uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, dev,
+					   "backlight", &priv->backlight);
+	if (ret) {
+		pr_info("%s: Cannot get backlight: ret=%d\n", __func__, ret);

dev_err()

Quoted 16 lines
drivers/video/raydium-rm68200.c new file +15 -0
+		return ret;
+	}
+
+	return 0;
+}
+
+static const struct panel_ops rm68200_panel_ops = {
+	.enable_backlight = rm68200_panel_enable_backlight,
+};
+
+static const struct udevice_id rm68200_panel_ids[] = {
+	{ .compatible = "raydium,rm68200" },
+	{ }
+};
+

drivers/video/raydium-rm68200.c line 329

Quoted 10 lines
drivers/video/raydium-rm68200.c new file +10 -0
+U_BOOT_DRIVER(rm68200_panel) = {
+	.name			  = "rm68200_panel",
+	.id			  = UCLASS_PANEL,
+	.of_match		  = rm68200_panel_ids,
+	.ops			  = &rm68200_panel_ops,
+	.ofdata_to_platdata	  = rm68200_panel_ofdata_to_platdata,
+	.probe			  = rm68200_panel_probe,
+	.platdata_auto_alloc_size = sizeof(struct mipi_dsi_panel_plat),
+	.priv_auto_alloc_size	= sizeof(struct rm68200_panel_priv),
+};

_______________________________________________
U-Boot mailing list
[email protected]
https://lists.denx.de/listinfo/u-boot

#15 lore raw

PATCH v2 8/10 arm: dts: stm32: add dsi for STM32F746

In reply to yannick fertre

Add mipi dsi bridge node in device-tree.

---
 arch/arm/dts/stm32f746.dtsi | 12 ++++++++++++
 1 file changed, 12 insertions(+)
arch/arm/dts/stm32f746.dtsi +12 -0
index e4d32bf..4ec954d 100644
@@ -332,6 +332,18 @@
 			u-boot,dm-pre-reloc;
 			status = "disabled";
 		};
+
+		dsi: dsi at 40016c00 {
+			compatible = "st,stm32-dsi";
+			reg = <0x40016C00 0x800>;
+			resets = <&rcc STM32F7_APB2_RESET(DSI)>;
+			clocks =  <&rcc 0 STM32F7_APB2_CLOCK(DSI)>,
+				  <&rcc 0 STM32F7_APB2_CLOCK(LTDC)>,
+				  <&clk_hse>;
+			clock-names = "pclk", "px_clk", "ref";
+			u-boot,dm-pre-reloc;
+			status = "disabled";
+		};
 	};
 };
 
Signature · 1 line
1.9.1
#16 lore raw

PATCH v2 9/10 arm: dts: stm32: add display for STM32F769 disco board

In reply to yannick fertre

Enable the display controller, mipi dsi bridge & panel. Set panel display timings.

---
 arch/arm/dts/stm32f769-disco.dts | 71 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 71 insertions(+)
arch/arm/dts/stm32f769-disco.dts +71 -0
index 59c9d31..82985b9 100644
@@ -42,6 +42,7 @@
 
 /dts-v1/;
 #include "stm32f746.dtsi"
+#include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/memory/stm32-sdram.h>
 
 / {
@@ -264,3 +265,73 @@
 	bus-width = <4>;
 	max-frequency = <25000000>;
 };
+
+&ltdc {
+	status = "okay";
+
+	port {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		ltdc_out_dsi: endpoint at 0 {
+			reg = <0>;
+			remote-endpoint = <&dsi_in>;
+		};
+	};
+};
+
+&dsi {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	status = "okay";
+
+	ports {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		port at 0 {
+			reg = <0>;
+			dsi_in: endpoint {
+				remote-endpoint = <&ltdc_out_dsi>;
+			};
+		};
+
+		port at 1 {
+			reg = <1>;
+			dsi_out: endpoint {
+				remote-endpoint = <&dsi_panel_in>;
+			};
+		};
+	};
+
+	panel-dsi at 0 {
+		compatible = "orisetech,otm8009a";
+		reg = <0>; /* dsi virtual channel (0..3) */
+		reset-gpios = <&gpioj 15 GPIO_ACTIVE_LOW>;
+		status = "okay";
+
+		port {
+			dsi_panel_in: endpoint {
+				remote-endpoint = <&dsi_out>;
+			};
+		};
+
+		display-timings {
+			timing at 0 {
+				clock-frequency = <32729000>;
+				hactive = <480>;
+				hfront-porch = <120>;
+				hback-porch = <63>;
+				hsync-len = <120>;
+				vactive = <800>;
+				vfront-porch = <12>;
+				vback-porch = <12>;
+				vsync-len = <12>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <0>;
+				pixelclk-active = <1>;
+			};
+		};
+	};
+};
Signature · 1 line
1.9.1
#17 lore raw

PATCH v2 10/10 board: Add STM32F769 SoC, discovery board support

In reply to yannick fertre
---
 configs/stm32f769-disco_defconfig | 63 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 63 insertions(+)
 create mode 100644 configs/stm32f769-disco_defconfig
configs/stm32f769-disco_defconfig new file +63 -0
new file mode 100644
index 0000000..ac34076
@@ -0,0 +1,63 @@
+CONFIG_ARM=y
+CONFIG_STM32=y
+CONFIG_SYS_MALLOC_F_LEN=0xC00
+CONFIG_STM32F7=y
+CONFIG_TARGET_STM32F746_DISCO=y
+CONFIG_DEFAULT_DEVICE_TREE="stm32f769-disco"
+CONFIG_BOOTDELAY=3
+CONFIG_USE_BOOTARGS=y
+CONFIG_BOOTARGS="console=ttyS0,115200 earlyprintk consoleblank=0 ignore_loglevel"
+# CONFIG_DISPLAY_CPUINFO is not set
+# CONFIG_DISPLAY_BOARDINFO is not set
+CONFIG_BOARD_EARLY_INIT_F=y
+CONFIG_HUSH_PARSER=y
+CONFIG_SYS_PROMPT="U-Boot > "
+CONFIG_AUTOBOOT_KEYED=y
+CONFIG_AUTOBOOT_PROMPT="Hit SPACE in %d seconds to stop autoboot.\n"
+CONFIG_AUTOBOOT_STOP_STR=" "
+CONFIG_CMD_BOOTZ=y
+# CONFIG_CMD_FPGA is not set
+CONFIG_CMD_GPT=y
+# CONFIG_RANDOM_UUID is not set
+CONFIG_CMD_MMC=y
+CONFIG_CMD_SF=y
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_SNTP=y
+CONFIG_CMD_DNS=y
+CONFIG_CMD_LINK_LOCAL=y
+CONFIG_CMD_BMP=y
+CONFIG_CMD_TIMER=y
+CONFIG_CMD_EXT2=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_FS_GENERIC=y
+# CONFIG_DOS_PARTITION is not set
+CONFIG_OF_CONTROL=y
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_NETCONSOLE=y
+# CONFIG_BLK is not set
+CONFIG_DM_MMC=y
+# CONFIG_SPL_DM_MMC is not set
+CONFIG_ARM_PL180_MMCI=y
+CONFIG_MTD=y
+CONFIG_MTD_NOR_FLASH=y
+CONFIG_DM_SPI_FLASH=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_STMICRO=y
+CONFIG_DM_ETH=y
+CONFIG_ETH_DESIGNWARE=y
+# CONFIG_PINCTRL_FULL is not set
+CONFIG_DM_SPI=y
+CONFIG_STM32_QSPI=y
+CONFIG_DM_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_OF_LIBFDT_OVERLAY=y
+# CONFIG_EFI_LOADER is not set
Signature · 1 line
1.9.1
#18 lore raw

Re: [PATCH v2 10/10] board: Add STM32F769 SoC, discovery board support

Hi Yannick

Quoted 1 line · yannick fertre

Can you add a commit message explaining why you add a specific defconfig for this board. FYI, previously, the same defconfig was used for all STM32F7 boards (ie /stm32f746-disco_defconfig).

You will also need to resync with the last master branch regarding defconfig content.

Thanks

Patrice

Quoted 65 lines
---
  configs/stm32f769-disco_defconfig | 63 +++++++++++++++++++++++++++++++++++++++
  1 file changed, 63 insertions(+)

create mode 100644 configs/stm32f769-disco_defconfig

configs/stm32f769-disco_defconfig new file +53 -0
new file mode 100644
index 0000000..ac34076
@@ -0,0 +1,63 @@
+CONFIG_ARM=y
+CONFIG_STM32=y
+CONFIG_SYS_MALLOC_F_LEN=0xC00
+CONFIG_STM32F7=y
+CONFIG_TARGET_STM32F746_DISCO=y
+CONFIG_DEFAULT_DEVICE_TREE="stm32f769-disco"
+CONFIG_BOOTDELAY=3
+CONFIG_USE_BOOTARGS=y
+CONFIG_BOOTARGS="console=ttyS0,115200 earlyprintk consoleblank=0 ignore_loglevel"
+# CONFIG_DISPLAY_CPUINFO is not set
+# CONFIG_DISPLAY_BOARDINFO is not set
+CONFIG_BOARD_EARLY_INIT_F=y
+CONFIG_HUSH_PARSER=y
+CONFIG_SYS_PROMPT="U-Boot > "
+CONFIG_AUTOBOOT_KEYED=y
+CONFIG_AUTOBOOT_PROMPT="Hit SPACE in %d seconds to stop autoboot.\n"
+CONFIG_AUTOBOOT_STOP_STR=" "
+CONFIG_CMD_BOOTZ=y
+# CONFIG_CMD_FPGA is not set
+CONFIG_CMD_GPT=y
+# CONFIG_RANDOM_UUID is not set
+CONFIG_CMD_MMC=y
+CONFIG_CMD_SF=y
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_SNTP=y
+CONFIG_CMD_DNS=y
+CONFIG_CMD_LINK_LOCAL=y
+CONFIG_CMD_BMP=y
+CONFIG_CMD_TIMER=y
+CONFIG_CMD_EXT2=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_FS_GENERIC=y
+# CONFIG_DOS_PARTITION is not set
+CONFIG_OF_CONTROL=y
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_NETCONSOLE=y
+# CONFIG_BLK is not set
+CONFIG_DM_MMC=y
+# CONFIG_SPL_DM_MMC is not set
+CONFIG_ARM_PL180_MMCI=y
+CONFIG_MTD=y
+CONFIG_MTD_NOR_FLASH=y
+CONFIG_DM_SPI_FLASH=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_STMICRO=y
+CONFIG_DM_ETH=y
+CONFIG_ETH_DESIGNWARE=y
+# CONFIG_PINCTRL_FULL is not set
+CONFIG_DM_SPI=y

configs/stm32f769-disco_defconfig line 63

Quoted 10 lines
configs/stm32f769-disco_defconfig new file +10 -0
+CONFIG_STM32_QSPI=y
+CONFIG_DM_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_OF_LIBFDT_OVERLAY=y
+# CONFIG_EFI_LOADER is not set

_______________________________________________
U-Boot mailing list
[email protected]
https://lists.denx.de/listinfo/u-boot

#19 lore raw

v2 cover splash screen on the stm32f769 disco board

In reply to yannick fertre
Quoted 13 lines · On Fri, 2 Mar 2018 16:44:01 +0100 yannick fertre yannick.fertre at st.com wrote:

Version 2:
- Replace debug log by pr_error, pr_warn or pr_info.
- Rework bridge between ltdc & dsi panel
- Rework backligh management (with or witout gpio)
- Rework panel otm8009a
- Add new panel raydium rm68200

Version 1:
- Initial commit

This serie contains all patchsets needed for displaying a splash screen on the stm32f769 disco board.

Quoted 11 lines

yannick fertre (10):
video: stm32: stm32_ltdc: add bridge to display controller
video: stm32: stm32_ltdc: update debug log
video: add support of MIPI DSI interface
video: add support of panel OTM8009A
video: add MIPI DSI host controller bridge
video: add support of STM32 MIPI DSI controller driver
video: add support of panel rm68200
arm: dts: stm32: add dsi for STM32F746
arm: dts: stm32: add display for STM32F769 disco board
board: Add STM32F769 SoC, discovery board support

With this series applied some dtbs fail to build:
...
DTC arch/arm/dts/stm32f746-disco.dtb
DTC arch/arm/dts/stm32f769-disco.dtb
Error: arch/arm/dts/stm32f746.dtsi:339.20-21 syntax error
FATAL ERROR: Unable to parse input tree
scripts/Makefile.lib:329: recipe for target 'arch/arm/dts/stm32f746-disco.dtb' failed make[2]: *** [arch/arm/dts/stm32f746-disco.dtb] Error 1
make[2]: *** Waiting for unfinished jobs....
Error: arch/arm/dts/stm32f746.dtsi:339.20-21 syntax error
FATAL ERROR: Unable to parse input tree
scripts/Makefile.lib:329: recipe for target 'arch/arm/dts/stm32f769-disco.dtb' failed make[2]: *** [arch/arm/dts/stm32f769-disco.dtb] Error 1 dts/Makefile:46: recipe for target 'arch-dtbs' failed
make[1]: *** [arch-dtbs] Error 2
Makefile:880: recipe for target 'dts/dt.dtb' failed
make: *** [dts/dt.dtb] Error 2

There seems to be a dependency on patch for include/dt-bindings/mfd/stm32f7-rcc.h adding some new macros. Is it also submitted to the list?

--
Anatolij

#20 lore raw

v2 cover splash screen on the stm32f769 disco board

Hi Anatolij

Quoted 46 lines · Anatolij Gustschin
Quoted 13 lines · On Fri, 2 Mar 2018 16:44:01 +0100 yannick fertre yannick.fertre at st.com wrote:

Version 2:
- Replace debug log by pr_error, pr_warn or pr_info.
- Rework bridge between ltdc & dsi panel
- Rework backligh management (with or witout gpio)
- Rework panel otm8009a
- Add new panel raydium rm68200

Version 1:
- Initial commit

This serie contains all patchsets needed for displaying a splash screen on the stm32f769 disco board.

Quoted 11 lines

yannick fertre (10):
video: stm32: stm32_ltdc: add bridge to display controller
video: stm32: stm32_ltdc: update debug log
video: add support of MIPI DSI interface
video: add support of panel OTM8009A
video: add MIPI DSI host controller bridge
video: add support of STM32 MIPI DSI controller driver
video: add support of panel rm68200
arm: dts: stm32: add dsi for STM32F746
arm: dts: stm32: add display for STM32F769 disco board
board: Add STM32F769 SoC, discovery board support

With this series applied some dtbs fail to build:
...
DTC arch/arm/dts/stm32f746-disco.dtb
DTC arch/arm/dts/stm32f769-disco.dtb
Error: arch/arm/dts/stm32f746.dtsi:339.20-21 syntax error
FATAL ERROR: Unable to parse input tree
scripts/Makefile.lib:329: recipe for target 'arch/arm/dts/stm32f746-disco.dtb' failed make[2]: *** [arch/arm/dts/stm32f746-disco.dtb] Error 1
make[2]: *** Waiting for unfinished jobs....
Error: arch/arm/dts/stm32f746.dtsi:339.20-21 syntax error
FATAL ERROR: Unable to parse input tree
scripts/Makefile.lib:329: recipe for target 'arch/arm/dts/stm32f769-disco.dtb' failed make[2]: *** [arch/arm/dts/stm32f769-disco.dtb] Error 1 dts/Makefile:46: recipe for target 'arch-dtbs' failed
make[1]: *** [arch-dtbs] Error 2
Makefile:880: recipe for target 'dts/dt.dtb' failed
make: *** [dts/dt.dtb] Error 2

Quoted 2 lines

There seems to be a dependency on patch for include/dt-bindings/mfd/stm32f7-rcc.h adding some new macros. Is it also submitted to the list?

Right, needed patches are already on the list
http://patchwork.ozlabs.org/patch/870938/

Patrice

Quoted 4 lines

--
Anatolij

#21 lore raw

v2 cover splash screen on the stm32f769 disco board

Hi Patrice,

On Tue, 6 Mar 2018 07:50:20 +0000
Patrice CHOTARD patrice.chotard at st.com wrote:
...

Quoted 2 lines

Right, needed patches are already on the list
http://patchwork.ozlabs.org/patch/870938/

Okay, then I'll wait until Tom merges this stm clk series. Thanks!

--
Anatolij

#22 lore raw

v2 cover splash screen on the stm32f769 disco board

In reply to Patrice CHOTARD

Hi Patrice/Yannick,

Quoted 4 lines · Patrice CHOTARD
Quoted 2 lines

There seems to be a dependency on patch for include/dt-bindings/mfd/stm32f7-rcc.h adding some new macros. Is it also submitted to the list?

Right, needed patches are already on the list
http://patchwork.ozlabs.org/patch/870938/

Great addition !

Few points:
it seems above mentioned patchset also has dependency on another patchset http://patchwork.ozlabs.org/patch/870283/
After applying these two dependency patchsets, it creates conflicts with pathch "ARM: dts: stm32: Add timer support for STM32F7". I understand you want to get it reviewed without waiting for other patchset acceptance, it would be good to mention all the dependencies.

Also i observe that without applying f769 display patches, f746 display didn't work. And F769 board display is not working, i see one error log:

Board 1:
stm32_ltdc_probe: decode display timing error -4 & Board 2:
stm32_ltdc_probe: decode display timing error -668998023

Cheers,
Vikas

Quoted 3 lines

Patrice

#23 lore raw

v2 cover splash screen on the stm32f769 disco board

Hi Vikas

+Benjamin

Quoted 5 lines · Vikas Manocha

Hi Patrice/Yannick,

Quoted 2 lines · Patrice CHOTARD
Quoted 2 lines

There seems to be a dependency on patch for include/dt-bindings/mfd/stm32f7-rcc.h adding some new macros. Is it also submitted to the list?

Quoted 8 lines
Quoted 2 lines

Right, needed patches are already on the list
http://patchwork.ozlabs.org/patch/870938/

Great addition !

Few points:
it seems above mentioned patchset also has dependency on another patchset http://patchwork.ozlabs.org/patch/870283/
After applying these two dependency patchsets, it creates conflicts with pathch "ARM: dts: stm32: Add timer support for STM32F7".

If the following series are applied first, there is no issue:

http://patchwork.ozlabs.org/project/uboot/list/?series=27330
http://patchwork.ozlabs.org/project/uboot/list/?series=27607

Quoted 1 line

I understand you want to get it reviewed without waiting for other patchset acceptance, it would be good to mention all the dependencies.

Agree, we will pay attention to that point in the future.

Quoted 2 lines

Also i observe that without applying f769 display patches, f746 display didn't work.

Yes, i observed the same issue, the f769 patch
http://patchwork.ozlabs.org/patch/880593/ fixes the 746 display....

Quoted 6 lines

And F769 board display is not working, i see one error log:

Board 1:
stm32_ltdc_probe: decode display timing error -4 & Board 2:
stm32_ltdc_probe: decode display timing error -668998023

I confirm too, Yannick is the best person to explain why .

Thanks

Patrice

Quoted 7 lines

Cheers,
Vikas

Quoted 3 lines

Patrice

#24 lore raw

v2 cover splash screen on the stm32f769 disco board

In reply to Vikas Manocha

Hi Vikas

Quoted 18 lines · Vikas Manocha

Hi Patrice/Yannick,

Quoted 4 lines · Patrice CHOTARD
Quoted 2 lines

There seems to be a dependency on patch for include/dt-bindings/mfd/stm32f7-rcc.h adding some new macros. Is it also submitted to the list?

Right, needed patches are already on the list
http://patchwork.ozlabs.org/patch/870938/

Great addition !

Few points:
it seems above mentioned patchset also has dependency on another patchset http://patchwork.ozlabs.org/patch/870283/
After applying these two dependency patchsets, it creates conflicts with pathch "ARM: dts: stm32: Add timer support for STM32F7". I understand you want to get it reviewed without waiting for other patchset acceptance, it would be good to mention all the dependencies.

Also i observe that without applying f769 display patches, f746 display didn't work. And F769 board display is not working, i see one error log:

Quoted 11 lines

Board 1:
stm32_ltdc_probe: decode display timing error -4 & Board 2:
stm32_ltdc_probe: decode display timing error -668998023

Cheers,
Vikas

Quoted 3 lines

Patrice

We got a look at this issue with Yannick.

On my side, i got this problem because i used the stm32f746-disco_defconfig by updating CONFIG_DEFAULT_DEVICE_TREE with the following update, (and i suppose you do the same ;-) ):

CONFIG_DEFAULT_DEVICE_TREE="stm32f769-disco"

By using the stm32f769-disco_defconfig, everything is working fine. That's why Yannick added a dedicated defconfig file for STM32F769.

Patrice

#25 lore raw

v2 cover splash screen on the stm32f769 disco board

Thanks Patrice,

Quoted 36 lines · Patrice CHOTARD

Hi Vikas

Quoted 18 lines · Vikas Manocha

Hi Patrice/Yannick,

Quoted 4 lines · Patrice CHOTARD
Quoted 2 lines

There seems to be a dependency on patch for include/dt-bindings/mfd/stm32f7-rcc.h adding some new macros. Is it also submitted to the list?

Right, needed patches are already on the list
http://patchwork.ozlabs.org/patch/870938/

Great addition !

Few points:
it seems above mentioned patchset also has dependency on another patchset http://patchwork.ozlabs.org/patch/870283/
After applying these two dependency patchsets, it creates conflicts with pathch "ARM: dts: stm32: Add timer support for STM32F7". I understand you want to get it reviewed without waiting for other patchset acceptance, it would be good to mention all the dependencies.

Also i observe that without applying f769 display patches, f746 display didn't work. And F769 board display is not working, i see one error log:

Quoted 11 lines

Board 1:
stm32_ltdc_probe: decode display timing error -4 & Board 2:
stm32_ltdc_probe: decode display timing error -668998023

Cheers,
Vikas

Quoted 3 lines

Patrice

We got a look at this issue with Yannick.

Quoted 8 lines

On my side, i got this problem because i used the stm32f746-disco_defconfig by updating CONFIG_DEFAULT_DEVICE_TREE with the following update, (and i suppose you do the same ;-) ):

CONFIG_DEFAULT_DEVICE_TREE="stm32f769-disco"

By using the stm32f769-disco_defconfig, everything is working fine. That's why Yannick added a dedicated defconfig file for STM32F769.

oh, i was also passing DEVICE_TREE during compilation. With the stm32f769 config, it still stops after DRAM size.

"
U-Boot SPL 2018.03-rc4-00055-g0d3c012-dirty (Mar 12 2018 - 11:31:20 -0700) Trying to boot from XIP

U-Boot 2018.03-rc4-00055-g0d3c012-dirty (Mar 12 2018 - 11:31:20 -0700)

Model: STMicroelectronics STM32F769-DISCO board
DRAM:  16 MiB

"

But I don't want to hold on for the series.

Cheers,
Vikas

Quoted 3 lines

Patrice

#26 lore raw
In reply to yannick fertre
Quoted 41 lines · yannick fertre

Version 2:
- Replace debug log by pr_error, pr_warn or pr_info.
- Rework bridge between ltdc & dsi panel
- Rework backligh management (with or witout gpio)
- Rework panel otm8009a
- Add new panel raydium rm68200

Version 1:
- Initial commit

This serie contains all patchsets needed for displaying a splash screen on the stm32f769 disco board.

yannick fertre (10):
video: stm32: stm32_ltdc: add bridge to display controller
video: stm32: stm32_ltdc: update debug log
video: add support of MIPI DSI interface
video: add support of panel OTM8009A
video: add MIPI DSI host controller bridge
video: add support of STM32 MIPI DSI controller driver
video: add support of panel rm68200
arm: dts: stm32: add dsi for STM32F746
arm: dts: stm32: add display for STM32F769 disco board
board: Add STM32F769 SoC, discovery board support

 arch/arm/dts/stm32f746.dtsi        |  12 +
 arch/arm/dts/stm32f769-disco.dts   |  71 ++++
 configs/stm32f769-disco_defconfig  |  63 +++
 drivers/video/Kconfig              |  32 ++
 drivers/video/Makefile             |   4 +
 drivers/video/dw_mipi_dsi.c        | 822 +++++++++++++++++++++++++++++++++++++
 drivers/video/mipi_display.c       | 807 ++++++++++++++++++++++++++++++++++++
 drivers/video/orisetech_otm8009a.c | 329 +++++++++++++++
 drivers/video/raydium-rm68200.c    | 329 +++++++++++++++
 drivers/video/stm32/Kconfig        |  10 +
 drivers/video/stm32/Makefile       |   1 +
 drivers/video/stm32/stm32_dsi.c    | 427 +++++++++++++++++++
 drivers/video/stm32/stm32_ltdc.c   | 144 ++++---
 include/dw_mipi_dsi.h              |  32 ++
 include/mipi_display.h             | 257 +++++++++++-
Quoted 8 lines
 15 files changed, 3285 insertions(+), 55 deletions(-)
 create mode 100644 configs/stm32f769-disco_defconfig
 create mode 100644 drivers/video/dw_mipi_dsi.c
 create mode 100644 drivers/video/mipi_display.c
 create mode 100644 drivers/video/orisetech_otm8009a.c
 create mode 100644 drivers/video/raydium-rm68200.c
 create mode 100644 drivers/video/stm32/stm32_dsi.c
 create mode 100644 include/dw_mipi_dsi.h

Does this use driver model? I cannot see it.

Regards,
Simon

#27 lore raw

v2 cover splash screen on the stm32f769 disco board

Hi Simon,

On Tue, 6 Mar 2018 10:51:29 -0700
Simon Glass sjg at chromium.org wrote:
...

Quoted 1 line

Does this use driver model? I cannot see it.

Panel drivers in patches 4/10 and 7/10 use driver model. MIPI DSI driver in patch 6/10 uses DM, too.

--
Anatolij