When VRR TG is always enabled and an optimized guardband is used, the pipe
vblank start is derived from the guardband.
Currently TRANS_SET_CONTEXT_LATENCY is programmed with crtc_vblank_start -
crtc_vdisplay, which is ~1 when guardband matches the vblank length.
With shorter guardband this become a large window.

To avoid misprogramming TRANS_SET_CONTEXT_LATENCY, clamp the scl value to 1
when using optimized guardband.

Also update the VRR get config logic to set crtc_vblank_start based on
vtotal - guardband, during readback.

Signed-off-by: Ankit Nautiyal <ankit.k.nauti...@intel.com>
---
 drivers/gpu/drm/i915/display/intel_display.c | 36 ++++++++++++++++----
 drivers/gpu/drm/i915/display/intel_vrr.c     |  9 ++++-
 2 files changed, 38 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index 55bea1374dc4..73aec6d4686a 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -2638,6 +2638,30 @@ transcoder_has_vrr(const struct intel_crtc_state 
*crtc_state)
        return HAS_VRR(display) && !transcoder_is_dsi(cpu_transcoder);
 }
 
+static int intel_set_context_latency(const struct intel_crtc_state *crtc_state,
+                                    int crtc_vblank_start,
+                                    int crtc_vdisplay)
+{
+       struct intel_display *display = to_intel_display(crtc_state);
+
+       /*
+        * When VRR TG is always on and optimized guardband is used,
+        * the pipe vblank start is based on the guardband,
+        * TRANS_SET_CONTEXT_LATENCY cannot be used to configure it.
+        */
+       if (intel_vrr_always_use_vrr_tg(display))
+               return clamp(crtc_vblank_start - crtc_vdisplay, 0, 1);
+
+       /*
+        * VBLANK_START no longer works on ADL+, instead we must use
+        * TRANS_SET_CONTEXT_LATENCY to configure the pipe vblank start.
+        */
+       if (DISPLAY_VER(display) >= 13)
+               return crtc_vblank_start - crtc_vdisplay;
+
+       return 0;
+}
+
 static void intel_set_transcoder_timings(const struct intel_crtc_state 
*crtc_state)
 {
        struct intel_display *display = to_intel_display(crtc_state);
@@ -2671,14 +2695,12 @@ static void intel_set_transcoder_timings(const struct 
intel_crtc_state *crtc_sta
                        vsyncshift += adjusted_mode->crtc_htotal;
        }
 
-       /*
-        * VBLANK_START no longer works on ADL+, instead we must use
-        * TRANS_SET_CONTEXT_LATENCY to configure the pipe vblank start.
-        */
        if (DISPLAY_VER(display) >= 13) {
                intel_de_write(display,
                               TRANS_SET_CONTEXT_LATENCY(display, 
cpu_transcoder),
-                              crtc_vblank_start - crtc_vdisplay);
+                              intel_set_context_latency(crtc_state,
+                                                        crtc_vblank_start,
+                                                        crtc_vdisplay));
 
                /*
                 * VBLANK_START not used by hw, just clear it
@@ -2768,7 +2790,9 @@ static void intel_set_transcoder_timings_lrr(const struct 
intel_crtc_state *crtc
        if (DISPLAY_VER(display) >= 13) {
                intel_de_write(display,
                               TRANS_SET_CONTEXT_LATENCY(display, 
cpu_transcoder),
-                              crtc_vblank_start - crtc_vdisplay);
+                              intel_set_context_latency(crtc_state,
+                                                        crtc_vblank_start,
+                                                        crtc_vdisplay));
 
                /*
                 * VBLANK_START not used by hw, just clear it
diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c 
b/drivers/gpu/drm/i915/display/intel_vrr.c
index 855974174afd..e124ef4e0ff4 100644
--- a/drivers/gpu/drm/i915/display/intel_vrr.c
+++ b/drivers/gpu/drm/i915/display/intel_vrr.c
@@ -749,11 +749,18 @@ void intel_vrr_get_config(struct intel_crtc_state 
*crtc_state)
                 * bits are not filled. Since vrr.vsync_start is computed as:
                 * crtc_vtotal - crtc_vsync_start, we can derive vtotal from
                 * vrr.vsync_start and crtc_vsync_start.
+                *
+                * With Optimized guardband, the vblank start is Vtotal - 
guardband
                 */
-               if (intel_vrr_always_use_vrr_tg(display))
+               if (intel_vrr_always_use_vrr_tg(display)) {
                        crtc_state->hw.adjusted_mode.crtc_vtotal =
                                crtc_state->hw.adjusted_mode.crtc_vsync_start +
                                crtc_state->vrr.vsync_start;
+
+                       crtc_state->hw.adjusted_mode.crtc_vblank_start =
+                               crtc_state->hw.adjusted_mode.crtc_vtotal -
+                               crtc_state->vrr.guardband;
+               }
        }
 
        vrr_enable = trans_vrr_ctl & VRR_CTL_VRR_ENABLE;
-- 
2.45.2

Reply via email to