From: Yu Zhang <[email protected]>

The TRANS_HSYNC register programming and dual-link hsync halving is
placed inside the is_vid_mode() guard, so it only runs for video mode.
Command mode dual-link DSI also needs this:

1. Without TRANS_HSYNC written, the hardware retains an inconsistent
   state, leading to errors on modeset:

   [drm] *ERROR* mismatch in hw.pipe_mode.crtc_hsync_start
   (expected 2762, found 1380)

2. The hsync_start/end are not halved for each link, so the hardware
   stores per-link values while the software expects full values.

Fix this by moving the dual-link hsync halving and TRANS_HSYNC write
outside the is_vid_mode() guard, making them unconditional for all
DSI modes.

Fixes: d1aeb5f399d9 ("drm/i915/icl: Configure DSI transcoder timings")
Cc: [email protected]
Signed-off-by: Yu Zhang <[email protected]>
---
 drivers/gpu/drm/i915/display/icl_dsi.c | 21 ++++++++++-----------
 1 file changed, 10 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c 
b/drivers/gpu/drm/i915/display/icl_dsi.c
index 951f30a64..c667d5941 100644
--- a/drivers/gpu/drm/i915/display/icl_dsi.c
+++ b/drivers/gpu/drm/i915/display/icl_dsi.c
@@ -950,7 +950,6 @@ gen11_dsi_set_transcoder_timings(struct intel_encoder 
*encoder,
                               HACTIVE(hactive - 1) | HTOTAL(htotal - 1));
        }
 
-       /* TRANS_HSYNC register to be programmed only for video mode */
        if (is_vid_mode(intel_dsi)) {
                if (intel_dsi->video_mode == NON_BURST_SYNC_PULSE) {
                        /* BSPEC: hsync size should be atleast 16 pixels */
@@ -961,18 +960,18 @@ gen11_dsi_set_transcoder_timings(struct intel_encoder 
*encoder,
 
                if (hback_porch < 16)
                        drm_err(display->drm, "hback porch < 16 pixels\n");
+       }
 
-               if (intel_dsi->dual_link) {
-                       hsync_start /= 2;
-                       hsync_end /= 2;
-               }
+       if (intel_dsi->dual_link) {
+               hsync_start /= 2;
+               hsync_end /= 2;
+       }
 
-               for_each_dsi_port(port, intel_dsi->ports) {
-                       dsi_trans = dsi_port_to_transcoder(port);
-                       intel_de_write(display,
-                                      TRANS_HSYNC(display, dsi_trans),
-                                      HSYNC_START(hsync_start - 1) | 
HSYNC_END(hsync_end - 1));
-               }
+       for_each_dsi_port(port, intel_dsi->ports) {
+               dsi_trans = dsi_port_to_transcoder(port);
+               intel_de_write(display,
+                              TRANS_HSYNC(display, dsi_trans),
+                              HSYNC_START(hsync_start - 1) | 
HSYNC_END(hsync_end - 1));
        }
 
        /* program TRANS_VTOTAL register */
-- 
2.43.0

Reply via email to