[PATCH 3/4] drm/sun4i: dsi: Add burst support

Maxime Ripard maxime.ripard at bootlin.com
Thu Feb 7 06:27:32 PST 2019


Hi,

On Wed, Feb 06, 2019 at 02:28:39AM +0800, Chen-Yu Tsai wrote:
> > +static u16 sun6i_dsi_get_drq_edge1(struct sun6i_dsi *dsi,
> > +                                  struct drm_display_mode *mode,
> > +                                  u16 line_num)
> > +{
> > +       struct mipi_dsi_device *device = dsi->device;
> > +       unsigned Bpp = mipi_dsi_pixel_format_to_bpp(device->format) / 8;
> > +       unsigned hbp = mode->htotal - mode->hsync_end;
> 
> Allwinner's hbp is actually horizontal back porch plus sync pulse.
> So this should be
> 
>     hbp = mode->htotal - mode->hsync_start;

So I've tested this and it actually adds a margin on the left side of
the panel, which seems to indicate that one of the porches isn't
right. I've applied Jagan's patches to fix the backporch and front
porch inversions, and it doesn't fix anything, so even though I don't
really know why, this seems to be the actual backporch.

It's really hard to tell without a DSI analyzer though, but that's not
really affordable...

> > +       u16 edge1;
> > +
> > +
> > +       edge1 = SUN6I_DSI_SYNC_POINT;
> > +       edge1 += mode->hdisplay + hbp + 20;
> > +       edge1 = edge1 * Bpp / device->lanes;
> 
> Compared to the A64 BSP, this seems to be incorrect. The original code was
> 
>     edge1 = sync_point +
>                 (panel->lcd_x + panel->lcd_hbp + 20) *
>                 dsi_pixel_bits[panel->lcd_dsi_format] /
>                 (8 * panel->lcd_dsi_lane);
> 
> Note that sync_point is outside of the parentheses and should not be
> multiplied and divided.
> 
> This would make sense if sync_point is a fixed delay that is needed
> regardless of the timings.

Good catch, thanks!

> > -       if ((mode->hsync_end - mode->hdisplay) > 20) {
> > +               regmap_write(dsi->regs, SUN6I_DSI_BURST_DRQ_REG,
> > +                            SUN6I_DSI_BURST_DRQ_EDGE0(edge0) |
> > +                            SUN6I_DSI_BURST_DRQ_EDGE1(edge1));
> > +
> > +               regmap_write(dsi->regs, SUN6I_DSI_BURST_LINE_REG,
> > +                            SUN6I_DSI_BURST_LINE_NUM(line_num) |
> > +                            SUN6I_DSI_BURST_LINE_SYNC_POINT(SUN6I_DSI_SYNC_POINT));
> > +
> > +               tcon0_drq = SUN6I_DSI_TCON_DRQ_ENABLE_MODE;
> > +       } else if ((mode->hsync_end - mode->hdisplay) > 20) {
> >                 /* Maaaaaagic */
> >                 u16 drq = (mode->hsync_end - mode->hdisplay) - 20;
> 
> This and the above if clause should use hsync_start instead of hsync_end.
> 
> The A64 BSP specifies drq = vfp - 20.

Indeed, I'll fix it.

> >  #define HSA_PACKET_OVERHEAD    10
> > -       hsa = max((unsigned int)HSA_PACKET_OVERHEAD,
> > -                 (mode->hsync_end - mode->hsync_start) * Bpp - HSA_PACKET_OVERHEAD);
> > -
> > -       /*
> > -        * The backporch is set using a blanking packet (4 bytes +
> > -        * payload + 2 bytes). Its minimal size is therefore 6 bytes
> > -        */
> > +               hsa = max((unsigned int)HSA_PACKET_OVERHEAD,
> > +                         (mode->hsync_end - mode->hsync_start) * Bpp -
> > +                         HSA_PACKET_OVERHEAD);
> 
> I believe for all these packets, that minimum value is not needed. The
> WC field of the long command packet refers to the length of the payload
> only. The payload is used to pad the packet to the desired length, but
> is otherwise useless. Likewise, the CRC value is only calculated against
> the payload.
> 
> Specifying a minimum means you are likely skewing the timings.

This code was here already, but it's a valid point. I'm not sure what
the DSI spec tells in that case. I'll have a look.

> >  #define HFP_PACKET_OVERHEAD    6
> > -       hfp = max((unsigned int)HFP_PACKET_OVERHEAD,
> > -                 (mode->htotal - mode->hsync_end) * Bpp - HFP_PACKET_OVERHEAD);
> > -
> > -       /*
> > -        * hblk seems to be the line + porches length.
> > -        */
> > -       hblk = mode->htotal * Bpp - hsa;
> > -
> > -       /*
> > -        * And I'm not entirely sure what vblk is about. The driver in
> > -        * Allwinner BSP is using a rather convoluted calculation
> > -        * there only for 4 lanes. However, using 0 (the !4 lanes
> > -        * case) even with a 4 lanes screen seems to work...
> > -        */
> > -       vblk = 0;
> > +               hfp = max((unsigned int)HFP_PACKET_OVERHEAD,
> > +                         (mode->htotal - mode->hsync_end) * Bpp - HFP_PACKET_OVERHEAD);
> > +
> > +               /*
> > +                * hblk seems to be the line + porches length.
> > +                */
> > +               hblk = mode->htotal * Bpp - hsa;
> 
> Based on the timing diagram in section 8.11 of the MIPI DSI spec, hblk is
> supposed to take up the remainder of the scan line after the sync event or
> sync pulse during the vertical inactive period. It is the BLLP portion.
> This seems like the correct value, though it is somewhat simplified.
> The packet overhead is gone (cancelled out with the one from hsa).

I actually found out that Allwinner tells that it's the total - the
sync pulse - the blank overhead (so 10 bytes).

I'll update it.

Thanks!
Maxime

-- 
Maxime Ripard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com



More information about the linux-arm-kernel mailing list