[PATCH v2] [PATCH v2] drm/i915/dsi: Fix command mode line time calculation

Jinman Ma <[email protected]>
Newsgroups org.freedesktop.lists.intel-gfx,org.freedesktop.lists.dri-devel,org.freedesktop.lists.intel-xe,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
Thank you for the review. I verified both reported issues and addressed
them in v2.

For dual-link DSI configurations, intel_dsi->pclk and afe_clk() describe
the per-link bandwidth, while the previous calculation used the full
horizontal total. This made the calculated line time twice the actual
per-link line time and provided only about half of the required 400 us
vertical blanking interval.

v2 now calculates the line time using a per-link horizontal total by
dividing htotal by two for dual-link configurations.

The second DIV_ROUND_UP_ULL() call also used line_time_ns, a u64 value,
as its divisor. This does not match the macro's u32 divisor contract.
v2 replaces it with DIV64_U64_ROUND_UP(), which supports a 64-bit
numerator and divisor.

The changes were tested on a Huawei MateBook E with a Tiger Lake GPU and
a 2560x1600 RGB888 dual-link front-back command-mode DSI panel.

Before v2, the driver programmed a vtotal below vsync_end and reported:

i915 0000:00:02.0: [drm] *ERROR* Invalid vsync_end value
i915 0000:00:02.0: [drm] *ERROR*
[CRTC:171:pipe A] mismatch in hw.pipe_mode.crtc_vtotal
(expected 1710, found 1622)

With v2, the per-link line time is approximately 8.18 us. The driver
requests 49 blanking lines, providing approximately 400.9 us of vertical
blanking and programming vtotal to 1649.

After a clean build and boot:

  - vtotal is programmed to 1649
  - Invalid vsync_end is no longer reported
  - no divide error or kernel Oops occurs
  - no FIFO underrun, GPU hang, or atomic update failure is reported
  - the DSI connector and display pipe initialize successfully

The existing modeset verification differences between the mode timings
and command-mode transcoder timings remain unchanged and are outside the
scope of this patch.


Signed-off-by: Jinman Ma <[email protected]>
---

Changes in v2:
  - Use the per-link htotal when calculating dual-link DSI line time.
  - Use DIV64_U64_ROUND_UP() when dividing by the u64 line_time_ns.
  - Preserve the existing bpp selection for compressed and uncompressed
      configurations.

Testing notes:

The corrected dual-link calculation removes the Invalid vsync_end error
and provides the required 400 us vertical blanking interval. A slight
intermittent display jitter is still visible, so the dual-link line-time
error was not the sole cause of the previously reported jitter.

TTY switching and suspend/resume can also leave the internal panel
blank. These appear to involve separate fbcon and DSI command-mode
resume paths and are not addressed by this patch. They will be reported
and investigated separately.

 drivers/gpu/drm/i915/display/icl_dsi.c | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c
index ea0cdb782..0f942cc6e 100644
--- a/drivers/gpu/drm/i915/display/icl_dsi.c
+++ b/drivers/gpu/drm/i915/display/icl_dsi.c
@@ -917,16 +917,24 @@ gen11_dsi_set_transcoder_timings(struct intel_encoder *encoder,
 	if (is_vid_mode(intel_dsi)) {
 		vtotal = adjusted_mode->crtc_vtotal;
 	} else {
-		int bpp, line_time_us, byte_clk_period_ns;
+		int bpp;
+		u64 line_time_ns;
+		u16 link_htotal = htotal;
+
+		if (intel_dsi->dual_link)
+			link_htotal /= 2;
 
 		if (crtc_state->dsc.compression_enable)
 			bpp = fxp_q4_to_int(crtc_state->dsc.compressed_bpp_x16);
 		else
 			bpp = mipi_dsi_pixel_format_to_bpp(intel_dsi->pixel_format);
+		line_time_ns =
+			DIV_ROUND_UP_ULL((u64)link_htotal * bpp * 1000000,
+					afe_clk(encoder, crtc_state) *
+					intel_dsi->lane_count);
 
-		byte_clk_period_ns = 1000000 / afe_clk(encoder, crtc_state);
-		line_time_us = (htotal * (bpp / 8) * byte_clk_period_ns) / (1000 * intel_dsi->lane_count);
-		vtotal = vactive + DIV_ROUND_UP(400, line_time_us);
+		vtotal = vactive +
+			DIV64_U64_ROUND_UP(400000ULL, line_time_ns);
 	}
 	vsync_start = adjusted_mode->crtc_vsync_start;
 	vsync_end = adjusted_mode->crtc_vsync_end;
-- 
2.55.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.