lkml.org 
[lkml]   [2018]   [Mar]   [13]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    From
    SubjectRe: [PATCH v2 01/10] video: stm32: stm32_ltdc: add bridge to display controller
    Date
    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,
    > + 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__);

    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),
    > + 0, &timings);
    > if (ret) {
    > debug("%s: decode display timing error %d\n",
    > __func__, ret);
    > - 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;
    >
    \
     
     \ /
      Last update: 2018-03-13 09:45    [W:5.041 / U:0.004 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site