From mboxrd@z Thu Jan 1 00:00:00 1970 From: =?UTF-8?q?Yannick=20Fertr=C3=A9?= Date: Fri, 17 Aug 2018 16:38:01 +0200 Subject: [U-Boot] [PATCH v3 01/10] video: stm32: stm32_ltdc: add bridge to display controller In-Reply-To: <1534516690-21106-1-git-send-email-yannick.fertre@st.com> References: <1534516690-21106-1-git-send-email-yannick.fertre@st.com> Message-ID: <1534516690-21106-2-git-send-email-yannick.fertre@st.com> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable To: u-boot@lists.denx.de Manage a bridge insert between the display controller & a panel. Signed-off-by: Yannick Fertr=C3=A9 --- drivers/video/stm32/stm32_ltdc.c | 143 ++++++++++++++++++++++-------------= ---- 1 file changed, 82 insertions(+), 61 deletions(-) diff --git a/drivers/video/stm32/stm32_ltdc.c b/drivers/video/stm32/stm32_l= tdc.c index dc6c889..6d075e3 100644 --- a/drivers/video/stm32/stm32_ltdc.c +++ b/drivers/video/stm32/stm32_ltdc.c @@ -4,22 +4,20 @@ * Author(s): Philippe Cornu for STMicroelectronic= s. * Yannick Fertre for STMicroelectronics. */ - #include #include +#include #include #include #include #include +#include #include #include #include =20 -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; @@ -174,8 +172,8 @@ 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 =3D PF_RGB565; break; } @@ -209,23 +207,23 @@ static void stm32_ltdc_enable(struct stm32_ltdc_priv = *priv) setbits_le32(priv->regs + LTDC_GCR, GCR_LTDCEN); } =20 -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 =3D priv->regs; - struct display_timing *timing =3D &priv->timing; u32 hsync, vsync, acc_hbp, acc_vbp, acc_act_w, acc_act_h; u32 total_w, total_h; u32 val; =20 /* Convert video timings to ltdc timings */ - hsync =3D timing->hsync_len.typ - 1; - vsync =3D timing->vsync_len.typ - 1; - acc_hbp =3D hsync + timing->hback_porch.typ; - acc_vbp =3D vsync + timing->vback_porch.typ; - acc_act_w =3D acc_hbp + timing->hactive.typ; - acc_act_h =3D acc_vbp + timing->vactive.typ; - total_w =3D acc_act_w + timing->hfront_porch.typ; - total_h =3D acc_act_h + timing->vfront_porch.typ; + hsync =3D timings->hsync_len.typ - 1; + vsync =3D timings->vsync_len.typ - 1; + acc_hbp =3D hsync + timings->hback_porch.typ; + acc_vbp =3D vsync + timings->vback_porch.typ; + acc_act_w =3D acc_hbp + timings->hactive.typ; + acc_act_h =3D acc_vbp + timings->vactive.typ; + total_w =3D acc_act_w + timings->hfront_porch.typ; + total_h =3D acc_act_h + timings->vfront_porch.typ; =20 /* Synchronization sizes */ val =3D (hsync << 16) | vsync; @@ -247,14 +245,14 @@ static void stm32_ltdc_set_mode(struct stm32_ltdc_pri= v *priv) =20 /* Signal polarities */ val =3D 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 |=3D GCR_HSPOL; - if (timing->flags & DISPLAY_FLAGS_VSYNC_HIGH) + if (timings->flags & DISPLAY_FLAGS_VSYNC_HIGH) val |=3D GCR_VSPOL; - if (timing->flags & DISPLAY_FLAGS_DE_HIGH) + if (timings->flags & DISPLAY_FLAGS_DE_HIGH) val |=3D GCR_DEPOL; - if (timing->flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE) + if (timings->flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE) val |=3D GCR_PCPOL; clrsetbits_le32(regs + LTDC_GCR, GCR_HSPOL | GCR_VSPOL | GCR_DEPOL | GCR_PCPOL, val); @@ -330,96 +328,119 @@ static int stm32_ltdc_probe(struct udevice *dev) struct video_uc_platdata *uc_plat =3D dev_get_uclass_platdata(dev); struct video_priv *uc_priv =3D dev_get_uclass_priv(dev); struct stm32_ltdc_priv *priv =3D dev_get_priv(dev); - struct udevice *panel; + struct udevice *bridge =3D NULL; + struct udevice *panel =3D NULL; + struct display_timing timings; struct clk pclk; struct reset_ctl rst; - int rate, ret; + int ret; =20 priv->regs =3D (void *)dev_read_addr(dev); if ((fdt_addr_t)priv->regs =3D=3D FDT_ADDR_T_NONE) { - debug("%s: ltdc dt register address error\n", __func__); + dev_err(dev, "ltdc dt register address error\n"); return -EINVAL; } =20 ret =3D clk_get_by_index(dev, 0, &pclk); if (ret) { - debug("%s: peripheral clock get error %d\n", __func__, ret); + dev_err(dev, "peripheral clock get error %d\n", ret); return ret; } =20 ret =3D clk_enable(&pclk); if (ret) { - debug("%s: peripheral clock enable error %d\n", - __func__, ret); + dev_err(dev, "peripheral clock enable error %d\n", ret); return ret; } =20 - ret =3D reset_get_by_index(dev, 0, &rst); + ret =3D uclass_first_device_err(UCLASS_PANEL, &panel); if (ret) { - debug("%s: missing ltdc hardware reset\n", __func__); - return -ENODEV; + dev_err(dev, "panel device error %d\n", ret); + return ret; } =20 - /* Reset */ - reset_deassert(&rst); - - ret =3D uclass_first_device(UCLASS_PANEL, &panel); + ret =3D panel_get_display_timing(panel, &timings); if (ret) { - debug("%s: panel device error %d\n", __func__, ret); - return ret; + ret =3D fdtdec_decode_display_timing(gd->fdt_blob, + dev_of_offset(panel), + 0, &timings); + if (ret) { + dev_err(dev, "decode display timing error %d\n", ret); + return ret; + } } =20 - ret =3D panel_enable_backlight(panel); + ret =3D clk_set_rate(&pclk, timings.pixelclock.typ); + if (ret) + dev_warn(dev, "fail to set pixel clock %d hz\n", + timings.pixelclock.typ); + + debug("%s: Set pixel clock req %d hz get %ld hz\n", __func__, + timings.pixelclock.typ, clk_get_rate(&pclk)); + + ret =3D reset_get_by_index(dev, 0, &rst); if (ret) { - debug("%s: panel %s enable backlight error %d\n", - __func__, panel->name, ret); + dev_err(dev, "missing ltdc hardware reset\n"); return ret; } =20 - ret =3D fdtdec_decode_display_timing(gd->fdt_blob, - dev_of_offset(dev), 0, - &priv->timing); - if (ret) { - debug("%s: decode display timing error %d\n", - __func__, ret); - return -EINVAL; - } + /* Reset */ + reset_deassert(&rst); =20 - rate =3D clk_set_rate(&pclk, priv->timing.pixelclock.typ); - if (rate < 0) { - debug("%s: fail to set pixel clock %d hz %d hz\n", - __func__, priv->timing.pixelclock.typ, rate); - return rate; + if (IS_ENABLED(CONFIG_VIDEO_BRIDGE)) { + ret =3D uclass_get_device(UCLASS_VIDEO_BRIDGE, 0, &bridge); + if (ret) + debug("No video bridge, or no backlight on bridge\n"); + + if (bridge) { + ret =3D video_bridge_attach(bridge); + if (ret) { + dev_err(dev, "fail to attach bridge\n"); + return ret; + } + } } =20 - debug("%s: Set pixel clock req %d hz get %d hz\n", __func__, - priv->timing.pixelclock.typ, rate); - /* TODO Below parameters are hard-coded for the moment... */ priv->l2bpp =3D VIDEO_BPP16; priv->bg_col_argb =3D 0xFFFFFFFF; /* white no transparency */ priv->crop_x =3D 0; priv->crop_y =3D 0; - priv->crop_w =3D priv->timing.hactive.typ; - priv->crop_h =3D priv->timing.vactive.typ; + priv->crop_w =3D timings.hactive.typ; + priv->crop_h =3D timings.vactive.typ; priv->alpha =3D 0xFF; =20 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); =20 /* 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); =20 - uc_priv->xsize =3D priv->timing.hactive.typ; - uc_priv->ysize =3D priv->timing.vactive.typ; + uc_priv->xsize =3D timings.hactive.typ; + uc_priv->ysize =3D timings.vactive.typ; uc_priv->bpix =3D priv->l2bpp; =20 + if (!bridge) { + ret =3D panel_enable_backlight(panel); + if (ret) { + dev_err(dev, "panel %s enable backlight error %d\n", + panel->name, ret); + return ret; + } + } else if (IS_ENABLED(CONFIG_VIDEO_BRIDGE)) { + ret =3D video_bridge_set_backlight(bridge, 80); + if (ret) { + dev_err(dev, "fail to set backlight\n"); + return ret; + } + } + video_set_flush_dcache(dev, true); =20 return 0; --=20 2.7.4