Hi Romain,

On 10/25/2026 10:26 PM, Romain TISSERAND wrote:
> Commit ac87d23694f4 ("drm/bridge: synopsys: dw-mipi-dsi: Use pixel clock
> rate to calculate lbcc") counts HSA, HBP and HLINE from the pixel clock,
> which is only right when the lanes run at the pixel bandwidth (pixel
> clock * bpp / lanes). Commit 93e82bb4de01 ("drm/bridge: synopsys:
> dw-mipi-dsi: Fix hcomponent lbcc for burst mode") went back to the lane
> rate for burst mode, where the lanes are faster on purpose.
> 
> The Rockchip glue runs the lanes faster in every mode: it adds 25% to
> the pixel bandwidth, or uses the rate the panel asks for. In non-burst
> video mode the line programmed in lane byte clocks is then shorter than
> the DPI line. On the GPD XD (RK3288, ILI9881C panel, 4 lanes at
> 752 Mbps, 59.5 MHz pixel clock, htotal 747) HLINE was 561 lane byte
> clocks (6.0 us) for a 12.55 us line: the DPI payload FIFO overflows
> (dpi_pld_wr_err in DSI_INT_ST1) and the panel shows garbage as soon as
> a client page-flips.
> 
> Use the lane rate when it is clearly above the pixel bandwidth (more
> than 1/8), and keep the pixel clock formula when both match, as on
> i.MX93, Meson and STM in non-burst mode, where lane_mbps is the pixel
> bandwidth rounded up to the next MHz. On the GPD XD this gives HLINE
> 1181, HSA 21 and HBP 7, and the picture is stable.
> 
> Fixes: ac87d23694f4 ("drm/bridge: synopsys: dw-mipi-dsi: Use pixel clock rate 
> to calculate lbcc")
> Signed-off-by: Romain TISSERAND <[email protected]>
> ---
> Notes for reviewers (not for the changelog):
> - The 1/8 threshold separates glues that report the pixel bandwidth
>   rounded up to the next MHz (i.MX93, Meson; STM in non-burst mode) from
>   Rockchip, which adds 25% in every mode. If a per-glue flag is
>   preferred instead of a threshold, I can rework it that way.

Adding different glue code for each implementation seems like a good
idea.

Maybe you should try to add a new callback in dw_mipi_dsi_plat_data ?

> - Testing: built with W=1 for arm (multi_v7) and arm64 (defconfig),
>   DRM_DW_MIPI_DSI=y and =m, no warnings. Tested live on the GPD XD
>   (RK3288, ILI9881C, non-burst with sync pulses), 6.18.54 with this
>   exact change applied: HLINE 1181, HSA 21, HBP 7 read back from the
>   DSI host, no dpi_pld_wr_err in DSI_INT_ST1 while the UI page-flips,
>   and a clean picture in the UI and in games (before the change: garbage
>   as soon as a client page-flips).
>   Not tested on i.MX93, Meson or STM hardware; for them the computation
>   is unchanged unless the lane rate is more than 1/8 above the pixel
>   bandwidth.
> - Tool disclosure: this patch was prepared with Claude Opus 5.5
>   (Anthropic) as a coding assistant, in an interactive session where I
>   asked it to bring up the GPD XD display and then to prepare the fix
>   for upstream. It located the cause from the DSI host registers, went
>   through the history of the lbcc computation (ac87d23694f4,
>   93e82bb4de01) and the lane rates of the other dw-mipi-dsi glues, and
>   drafted the code change and the changelog. I reviewed and understand
>   both, and tested the patch on the GPD XD as described above.
> 
>  drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c | 23 +++++++++++++------
>  1 file changed, 16 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c 
> b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
> index 22d1b8cbe1..b026b602ab 100644
> --- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
> +++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
> @@ -781,19 +781,28 @@ static u32 dw_mipi_dsi_get_hcomponent_lbcc(struct 
> dw_mipi_dsi *dsi,
>                                          u32 hcomponent)
>  {
>       u32 frac, lbcc, minimum_lbcc;
> +     u64 pixel_kbps;
>       int bpp;
>  
> -     if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST) {
> +     bpp = mipi_dsi_pixel_format_to_bpp(dsi->format);
> +     if (bpp < 0) {
> +             dev_err(dsi->dev, "failed to get bpp\n");
> +             return 0;
> +     }
> +
> +     /*
> +      * Use the lane rate when it is above the pixel bandwidth (burst, or
> +      * glues adding margin in all modes); the 1/8 slack ignores lane_mbps
> +      * being rounded up to the next MHz. Otherwise the pixel clock is more
> +      * precise.
> +      */
> +     pixel_kbps = div_u64((u64)mode->clock * bpp, dsi->lanes);
> +     if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST ||
> +         (u64)dsi->lane_mbps * MSEC_PER_SEC > pixel_kbps + pixel_kbps / 8) {
>               /* lbcc based on lane_mbps */
>               lbcc = hcomponent * dsi->lane_mbps * MSEC_PER_SEC / 8;
>       } else {
>               /* lbcc based on pixel clock rate */
> -             bpp = mipi_dsi_pixel_format_to_bpp(dsi->format);
> -             if (bpp < 0) {
> -                     dev_err(dsi->dev, "failed to get bpp\n");
> -                     return 0;
> -             }
> -
>               lbcc = div_u64((u64)hcomponent * mode->clock * bpp, dsi->lanes 
> * 8);
>       }
>  
> 
> base-commit: cf61bef3801c3c9d0d8c39026b7b2fb242898a3a

-- 
Best, 
Chaoyi

Reply via email to