Hi Yannick
On 03/02/2018 04:44 PM, yannick fertre wrote:
Manage a bridge insert between the display controller & a panel.
Signed-off-by: yannick fertre yannick.fertre@st.com
drivers/video/stm32/stm32_ltdc.c | 107 ++++++++++++++++++++++++++------------- 1 file changed, 71 insertions(+), 36 deletions(-)
diff --git a/drivers/video/stm32/stm32_ltdc.c b/drivers/video/stm32/stm32_ltdc.c index e160c77..bd9c0de 100644 --- a/drivers/video/stm32/stm32_ltdc.c +++ b/drivers/video/stm32/stm32_ltdc.c @@ -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,
{ void __iomem *regs = priv->regs;struct display_timing *timings)
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__);
I would replace debug by dev_err() here.
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
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),
if (ret) { debug("%s: decode display timing error %d\n", __func__, ret);0, &timings);
return -EINVAL;
Ditto
}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
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__);
Ditto
return ret;
}
- } else {
ret = panel_enable_backlight(panel);
if (ret) {
debug("%s: panel %s enable backlight error %d\n",
__func__, panel->name, ret);
Ditto
return ret;
}
- }
+#else
- ret = panel_enable_backlight(panel);
- if (ret) {
debug("%s: panel %s enable backlight error %d\n",
__func__, panel->name, ret);
Ditto
return ret;
- }
+#endif video_set_flush_dcache(dev, true);
return 0;