All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] drm/bridge: dw-mipi-dsi: use the lane rate for lbcc when lanes run faster
@ 2026-10-25 14:26 ` Romain TISSERAND
  0 siblings, 0 replies; 7+ messages in thread
From: Romain TISSERAND @ 2026-10-25 14:26 UTC (permalink / raw)
  To: Andrzej Hajda, Neil Armstrong, Robert Foss
  Cc: Laurent Pinchart, Jonas Karlman, Jernej Skrabec, Luca Ceresoli,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter, Heiko Stuebner, Liu Ying, dri-devel,
	linux-rockchip, linux-arm-kernel, linux-kernel

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 <romain.tisserand@gmail.com>
---
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.
- 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
-- 
2.43.0


_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH] drm/bridge: dw-mipi-dsi: use the lane rate for lbcc when lanes run faster
@ 2026-10-25 14:26 ` Romain TISSERAND
  0 siblings, 0 replies; 7+ messages in thread
From: Romain TISSERAND @ 2026-10-25 14:26 UTC (permalink / raw)
  To: Andrzej Hajda, Neil Armstrong, Robert Foss
  Cc: Laurent Pinchart, Jonas Karlman, Jernej Skrabec, Luca Ceresoli,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter, Heiko Stuebner, Liu Ying, dri-devel,
	linux-rockchip, linux-arm-kernel, linux-kernel

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 <romain.tisserand@gmail.com>
---
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.
- 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
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH] drm/bridge: dw-mipi-dsi: use the lane rate for lbcc when lanes run faster
  2026-10-25 14:26 ` Romain TISSERAND
  (?)
@ 2026-10-25 14:38 ` sashiko-bot
  2026-10-25 15:24     ` Romain TISSERAND
  -1 siblings, 1 reply; 7+ messages in thread
From: sashiko-bot @ 2026-10-25 14:38 UTC (permalink / raw)
  To: Romain TISSERAND; +Cc: dri-devel

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Medium] drm/bridge: dw-mipi-dsi: wrong lane count in dw_mipi_dsi_get_hcomponent_lbcc()
- [Medium] drm/bridge: dw-mipi-dsi: 1/8 margin check in dw_mipi_dsi_get_hcomponent_lbcc()
--

commit 6499adefdc008cafd18dfe3208439c2abd0174aa
Author: Romain TISSERAND <romain.tisserand@gmail.com>

drm/bridge: dw-mipi-dsi: use the lane rate for lbcc when lanes run faster

This commit updates dw_mipi_dsi_get_hcomponent_lbcc() to calculate horizontal
timing values from the DSI lane rate rather than the pixel clock whenever the
lane rate exceeds the pixel bandwidth by more than 1/8, fixing DPI payload
FIFO overflows on glues such as Rockchip that run the lanes faster in
non-burst video modes.

> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
> index 22d1b8cbe1d57..b026b602abc0f 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) {

[Severity: Medium]
Can the 1/8 margin check miss panels where the lane rate runs faster than the
pixel bandwidth by less than 12.5%?

In drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c,
dw_mipi_dsi_get_lane_mbps() computes the default lane rate using integer
division for (bpp / lanes):

	mpclk = DIV_ROUND_UP(mode->clock, MSEC_PER_SEC);
	if (mpclk) {
		/* take 1 / 0.8, since mbps must big than bandwidth of RGB */
		tmp = mpclk * (bpp / lanes) * 10 / 8;

For a 4-lane non-burst panel using MIPI_DSI_FMT_RGB666_PACKED (bpp = 18),
(bpp / lanes) truncates from 4.5 to 4, giving a lane rate of 5 * mpclk Mbps.
That is only 11.1% (1/9) above the 4.5 * mode->clock pixel bandwidth, rather
than 25%.

For any pixel clock >= 16 MHz on such a panel (or when a panel's requested
hs_rate or max_mbps clamp puts dsi->lane_mbps between +1 MHz and +12.5% above
pixel_kbps), (u64)dsi->lane_mbps * MSEC_PER_SEC > pixel_kbps + pixel_kbps / 8
evaluates to false. Wouldn't that fall back to the pixel-clock formula and
program DSI_VID_HLINE_TIME, DSI_VID_HSA_TIME, and DSI_VID_HBP_TIME shorter
than the DPI line period, triggering the same DPI payload FIFO overflow?

If the slack is only meant to ignore lane_mbps being rounded up to the next
MHz, should the check compare dsi->lane_mbps against
DIV_ROUND_UP_ULL(pixel_kbps, MSEC_PER_SEC) instead of adding 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);

[Severity: Medium]
Should pixel_kbps and the pixel-clock lbcc calculation divide by
dw_mipi_dsi_get_lanes(dsi) instead of dsi->lanes to handle dual-DSI panels?

In dw_mipi_dsi_bridge_atomic_pre_enable() -> dw_mipi_dsi_mode_set(),
dsi->lane_mbps is obtained by passing the combined master and slave lane
count from dw_mipi_dsi_get_lanes(dsi) along with the full-panel
adjusted_mode:

	u32 lanes = dw_mipi_dsi_get_lanes(dsi);

	clk_prepare_enable(dsi->pclk);

	ret = phy_ops->get_lane_mbps(priv_data, adjusted_mode, dsi->mode_flags,
				     lanes, dsi->format, &dsi->lane_mbps);

When a dual-DSI panel is attached in non-burst video mode via
dw_mipi_dsi_set_slave() (such as innolux,p097pfg on rk3399-gru-scarlet with
4 + 4 lanes), dsi->lane_mbps is the per-lane rate across all 8 lanes, whereas
dividing mode->clock * bpp by dsi->lanes (4) makes pixel_kbps twice the
actual per-lane pixel bandwidth.

Because pixel_kbps is doubled, the condition
(u64)dsi->lane_mbps * MSEC_PER_SEC > pixel_kbps + pixel_kbps / 8 evaluates to
false, and the else branch then also divides by dsi->lanes (4) instead of
dw_mipi_dsi_get_lanes(dsi) (8), programming DSI_VID_HLINE_TIME,
DSI_VID_HSA_TIME, and DSI_VID_HBP_TIME for twice the per-lane pixel bandwidth
rather than the actual lane rate.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261025142639.3454322-1-romain.tisserand@gmail.com?part=1

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] drm/bridge: dw-mipi-dsi: use the lane rate for lbcc when lanes run faster
  2026-10-25 14:38 ` sashiko-bot
@ 2026-10-25 15:24     ` Romain TISSERAND
  0 siblings, 0 replies; 7+ messages in thread
From: Romain TISSERAND @ 2026-10-25 15:24 UTC (permalink / raw)
  To: sashiko-reviews
  Cc: Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, Luca Ceresoli, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
	Heiko Stuebner, Liu Ying, dri-devel, linux-rockchip,
	linux-arm-kernel, linux-kernel

On Sun, 25 Oct 2026 14:38:50 +0000, sashiko-bot@kernel.org wrote:
> For a 4-lane non-burst panel using MIPI_DSI_FMT_RGB666_PACKED (bpp = 18),
> (bpp / lanes) truncates from 4.5 to 4, giving a lane rate of 5 * mpclk Mbps.
> That is only 11.1% (1/9) above the 4.5 * mode->clock pixel bandwidth, rather
> than 25%.
[...]
> If the slack is only meant to ignore lane_mbps being rounded up to the next
> MHz, should the check compare dsi->lane_mbps against
> DIV_ROUND_UP_ULL(pixel_kbps, MSEC_PER_SEC) instead of adding pixel_kbps / 8?

Right, the 1/8 slack misses that case. v2 will use the lane rate when
lane_mbps is above the pixel bandwidth rounded up to the next MHz, which
keeps i.MX93, Meson and STM in non-burst mode on the pixel clock formula.

> Should pixel_kbps and the pixel-clock lbcc calculation divide by
> dw_mipi_dsi_get_lanes(dsi) instead of dsi->lanes to handle dual-DSI panels?

With dsi->lanes the patch doesn't change the timing of the dual-DSI Gru
Scarlet panel: its lane rate stays below the per-link pixel bandwidth, so
it keeps the current computation. Switching to the total lane count would
change that timing, and I can't test it, so I'll keep dsi->lanes in this
patch and leave the dual-DSI accounting to a separate one.

I'll send v2 in about a week.

Romain


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] drm/bridge: dw-mipi-dsi: use the lane rate for lbcc when lanes run faster
@ 2026-10-25 15:24     ` Romain TISSERAND
  0 siblings, 0 replies; 7+ messages in thread
From: Romain TISSERAND @ 2026-10-25 15:24 UTC (permalink / raw)
  To: sashiko-reviews
  Cc: Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, Luca Ceresoli, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
	Heiko Stuebner, Liu Ying, dri-devel, linux-rockchip,
	linux-arm-kernel, linux-kernel

On Sun, 25 Oct 2026 14:38:50 +0000, sashiko-bot@kernel.org wrote:
> For a 4-lane non-burst panel using MIPI_DSI_FMT_RGB666_PACKED (bpp = 18),
> (bpp / lanes) truncates from 4.5 to 4, giving a lane rate of 5 * mpclk Mbps.
> That is only 11.1% (1/9) above the 4.5 * mode->clock pixel bandwidth, rather
> than 25%.
[...]
> If the slack is only meant to ignore lane_mbps being rounded up to the next
> MHz, should the check compare dsi->lane_mbps against
> DIV_ROUND_UP_ULL(pixel_kbps, MSEC_PER_SEC) instead of adding pixel_kbps / 8?

Right, the 1/8 slack misses that case. v2 will use the lane rate when
lane_mbps is above the pixel bandwidth rounded up to the next MHz, which
keeps i.MX93, Meson and STM in non-burst mode on the pixel clock formula.

> Should pixel_kbps and the pixel-clock lbcc calculation divide by
> dw_mipi_dsi_get_lanes(dsi) instead of dsi->lanes to handle dual-DSI panels?

With dsi->lanes the patch doesn't change the timing of the dual-DSI Gru
Scarlet panel: its lane rate stays below the per-link pixel bandwidth, so
it keeps the current computation. Switching to the total lane count would
change that timing, and I can't test it, so I'll keep dsi->lanes in this
patch and leave the dual-DSI accounting to a separate one.

I'll send v2 in about a week.

Romain

_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] drm/bridge: dw-mipi-dsi: use the lane rate for lbcc when lanes run faster
  2026-10-25 14:26 ` Romain TISSERAND
@ 2026-10-26  2:17   ` Chaoyi Chen
  -1 siblings, 0 replies; 7+ messages in thread
From: Chaoyi Chen @ 2026-10-26  2:17 UTC (permalink / raw)
  To: Romain TISSERAND
  Cc: Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, Luca Ceresoli, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
	Heiko Stuebner, Liu Ying, dri-devel, linux-rockchip,
	linux-arm-kernel, linux-kernel

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 <romain.tisserand@gmail.com>
> ---
> 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

_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] drm/bridge: dw-mipi-dsi: use the lane rate for lbcc when lanes run faster
@ 2026-10-26  2:17   ` Chaoyi Chen
  0 siblings, 0 replies; 7+ messages in thread
From: Chaoyi Chen @ 2026-10-26  2:17 UTC (permalink / raw)
  To: Romain TISSERAND
  Cc: Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, Luca Ceresoli, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
	Heiko Stuebner, Liu Ying, dri-devel, linux-rockchip,
	linux-arm-kernel, linux-kernel

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 <romain.tisserand@gmail.com>
> ---
> 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


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2026-10-26  2:19 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-25 14:26 [PATCH] drm/bridge: dw-mipi-dsi: use the lane rate for lbcc when lanes run faster Romain TISSERAND
2026-10-25 14:26 ` Romain TISSERAND
2026-10-25 14:38 ` sashiko-bot
2026-10-25 15:24   ` Romain TISSERAND
2026-10-25 15:24     ` Romain TISSERAND
2026-10-26  2:17 ` Chaoyi Chen
2026-10-26  2:17   ` Chaoyi Chen

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.