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