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

Jinman Ma <[email protected]>
Newsgroups gmane.linux.kernel,gmane.comp.freedesktop.xorg.drivers.intel,gmane.comp.video.dri.devel
Message-ID <[email protected]>
The command mode path in gen11_dsi_set_transcoder_timings() first
truncates the AFE clock period to an integer number of nanoseconds, and
then truncates the resulting line time to microseconds.

At high link rates, 1000000 / afe_clk() can evaluate to zero. Even at
lower rates, the successive integer divisions can make line_time_us
zero. DIV_ROUND_UP(400, line_time_us) then triggers a divide error
during the atomic commit and prevents i915 KMS from initializing.

Calculate the line time directly in nanoseconds using 64-bit arithmetic.
Use bits per pixel with the per-lane AFE bit clock and retain nanosecond
precision until calculating how many lines are needed for 400
microseconds.

Tested on a Huawei MateBook E with an Alder Lake-P GPU and a 2560x1600
dual-link DSI panel. The change prevents the divide error and allows KMS
to reach the display manager.

Signed-off-by: Jinman Ma <[email protected]>
---
This does not completely fix the panel. After entering Plasma, the image
still shows visible tearing or jitter, sometimes with an obvious offset
between the two halves of the dual-link panel. Switching to a text
console can also leave the panel black. I am continuing to investigate
this as a separate timing or synchronization issue.

Please let me know which additional i915 debug logs or register dumps
would be most useful for the remaining issue. I'm pleasured to collect them.
---
 drivers/gpu/drm/i915/display/icl_dsi.c | 11 +++++++----
 1 file changed, 7 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..c89e24de7 100644
--- a/drivers/gpu/drm/i915/display/icl_dsi.c
+++ b/drivers/gpu/drm/i915/display/icl_dsi.c
@@ -917,16 +917,19 @@ 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;
+		u64 line_time_ns;
+		int bpp;
 
 		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);
 
-		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);
+		line_time_ns = DIV_ROUND_UP_ULL((u64)htotal * bpp * 1000000,
+						afe_clk(encoder, crtc_state) *
+						intel_dsi->lane_count);
+		vtotal = vactive +
+			DIV_ROUND_UP_ULL(400 * 1000, 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.