* [PATCH 01/14] drm/i915/vrr: Use crtc_vsync_start/end for computing vrr.vsync_start/end
2025-09-07 7:32 [PATCH 00/14] Optimize vrr.guardband and fix LRR Ankit Nautiyal
@ 2025-09-07 7:32 ` Ankit Nautiyal
2025-09-08 8:08 ` Shankar, Uma
2025-09-07 7:32 ` [PATCH 02/14] drm/i915/skl_watermark: Fix the scaling factor for chroma subsampling Ankit Nautiyal
` (13 subsequent siblings)
14 siblings, 1 reply; 22+ messages in thread
From: Ankit Nautiyal @ 2025-09-07 7:32 UTC (permalink / raw)
To: intel-gfx, intel-xe; +Cc: ville.syrjala, Ankit Nautiyal
Use adjusted_mode->crtc_vsync_start/end instead of
adjusted_mode->vsync_start while computing vrr.vsync_start/end.
For most modes, these are same but for 3D/stereo modes the
crtc_vsync_start is different than vsync_start.
Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
---
drivers/gpu/drm/i915/display/intel_vrr.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c
index 3eed37f271b0..266cf5e1859d 100644
--- a/drivers/gpu/drm/i915/display/intel_vrr.c
+++ b/drivers/gpu/drm/i915/display/intel_vrr.c
@@ -406,10 +406,10 @@ intel_vrr_compute_config(struct intel_crtc_state *crtc_state,
if (HAS_AS_SDP(display)) {
crtc_state->vrr.vsync_start =
(crtc_state->hw.adjusted_mode.crtc_vtotal -
- crtc_state->hw.adjusted_mode.vsync_start);
+ crtc_state->hw.adjusted_mode.crtc_vsync_start);
crtc_state->vrr.vsync_end =
(crtc_state->hw.adjusted_mode.crtc_vtotal -
- crtc_state->hw.adjusted_mode.vsync_end);
+ crtc_state->hw.adjusted_mode.crtc_vsync_end);
}
}
--
2.45.2
^ permalink raw reply related [flat|nested] 22+ messages in thread* RE: [PATCH 01/14] drm/i915/vrr: Use crtc_vsync_start/end for computing vrr.vsync_start/end
2025-09-07 7:32 ` [PATCH 01/14] drm/i915/vrr: Use crtc_vsync_start/end for computing vrr.vsync_start/end Ankit Nautiyal
@ 2025-09-08 8:08 ` Shankar, Uma
0 siblings, 0 replies; 22+ messages in thread
From: Shankar, Uma @ 2025-09-08 8:08 UTC (permalink / raw)
To: Nautiyal, Ankit K, intel-gfx@lists.freedesktop.org,
intel-xe@lists.freedesktop.org
Cc: ville.syrjala@linux.intel.com, Nautiyal, Ankit K
> -----Original Message-----
> From: Intel-xe <intel-xe-bounces@lists.freedesktop.org> On Behalf Of Ankit
> Nautiyal
> Sent: Sunday, September 7, 2025 1:02 PM
> To: intel-gfx@lists.freedesktop.org; intel-xe@lists.freedesktop.org
> Cc: ville.syrjala@linux.intel.com; Nautiyal, Ankit K <ankit.k.nautiyal@intel.com>
> Subject: [PATCH 01/14] drm/i915/vrr: Use crtc_vsync_start/end for computing
> vrr.vsync_start/end
>
> Use adjusted_mode->crtc_vsync_start/end instead of adjusted_mode-
> >vsync_start while computing vrr.vsync_start/end.
> For most modes, these are same but for 3D/stereo modes the crtc_vsync_start is
> different than vsync_start.
Looks Good to me.
Reviewed-by: Uma Shankar <uma.shankar@intel.com>
> Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
> ---
> drivers/gpu/drm/i915/display/intel_vrr.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c
> b/drivers/gpu/drm/i915/display/intel_vrr.c
> index 3eed37f271b0..266cf5e1859d 100644
> --- a/drivers/gpu/drm/i915/display/intel_vrr.c
> +++ b/drivers/gpu/drm/i915/display/intel_vrr.c
> @@ -406,10 +406,10 @@ intel_vrr_compute_config(struct intel_crtc_state
> *crtc_state,
> if (HAS_AS_SDP(display)) {
> crtc_state->vrr.vsync_start =
> (crtc_state->hw.adjusted_mode.crtc_vtotal -
> - crtc_state->hw.adjusted_mode.vsync_start);
> + crtc_state->hw.adjusted_mode.crtc_vsync_start);
> crtc_state->vrr.vsync_end =
> (crtc_state->hw.adjusted_mode.crtc_vtotal -
> - crtc_state->hw.adjusted_mode.vsync_end);
> + crtc_state->hw.adjusted_mode.crtc_vsync_end);
> }
> }
>
> --
> 2.45.2
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH 02/14] drm/i915/skl_watermark: Fix the scaling factor for chroma subsampling
2025-09-07 7:32 [PATCH 00/14] Optimize vrr.guardband and fix LRR Ankit Nautiyal
2025-09-07 7:32 ` [PATCH 01/14] drm/i915/vrr: Use crtc_vsync_start/end for computing vrr.vsync_start/end Ankit Nautiyal
@ 2025-09-07 7:32 ` Ankit Nautiyal
2025-09-07 7:32 ` [PATCH 03/14] drm/i915/skl_watermark: Pass linetime as argument to latency helpers Ankit Nautiyal
` (12 subsequent siblings)
14 siblings, 0 replies; 22+ messages in thread
From: Ankit Nautiyal @ 2025-09-07 7:32 UTC (permalink / raw)
To: intel-gfx, intel-xe; +Cc: ville.syrjala, Ankit Nautiyal, Mitul Golani
The Bspec:70151, mentions Chroma subsampling is a 2x downscale
operation. This means that the downscale factor is 2 in each direction.
So correct the downscaling factor to 4.
Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
Reviewed-by: Mitul Golani <mitulkumar.ajitkumar.golani@intel.com>
---
drivers/gpu/drm/i915/display/skl_watermark.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c
index d74cbb43ae6f..51548447f4aa 100644
--- a/drivers/gpu/drm/i915/display/skl_watermark.c
+++ b/drivers/gpu/drm/i915/display/skl_watermark.c
@@ -2185,7 +2185,7 @@ dsc_prefill_latency(const struct intel_crtc_state *crtc_state)
crtc_state->hw.adjusted_mode.clock);
int num_scaler_users = hweight32(scaler_state->scaler_users);
int chroma_downscaling_factor =
- crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420 ? 2 : 1;
+ crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420 ? 4 : 1;
u32 dsc_prefill_latency = 0;
if (!crtc_state->dsc.compression_enable ||
@@ -2228,7 +2228,7 @@ scaler_prefill_latency(const struct intel_crtc_state *crtc_state)
u64 hscale_k = max(1000, mul_u32_u32(scaler_state->scalers[0].hscale, 1000) >> 16);
u64 vscale_k = max(1000, mul_u32_u32(scaler_state->scalers[0].vscale, 1000) >> 16);
int chroma_downscaling_factor =
- crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420 ? 2 : 1;
+ crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420 ? 4 : 1;
int latency;
latency = DIV_ROUND_UP_ULL((4 * linetime * hscale_k * vscale_k *
--
2.45.2
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH 03/14] drm/i915/skl_watermark: Pass linetime as argument to latency helpers
2025-09-07 7:32 [PATCH 00/14] Optimize vrr.guardband and fix LRR Ankit Nautiyal
2025-09-07 7:32 ` [PATCH 01/14] drm/i915/vrr: Use crtc_vsync_start/end for computing vrr.vsync_start/end Ankit Nautiyal
2025-09-07 7:32 ` [PATCH 02/14] drm/i915/skl_watermark: Fix the scaling factor for chroma subsampling Ankit Nautiyal
@ 2025-09-07 7:32 ` Ankit Nautiyal
2025-09-07 7:32 ` [PATCH 04/14] drm/i915/skl_scaler: Introduce helper for chroma downscale factor Ankit Nautiyal
` (11 subsequent siblings)
14 siblings, 0 replies; 22+ messages in thread
From: Ankit Nautiyal @ 2025-09-07 7:32 UTC (permalink / raw)
To: intel-gfx, intel-xe; +Cc: ville.syrjala, Ankit Nautiyal, Mitul Golani
Refactor dsc_prefill_latency and scaler_prefill_latency to take
linetime as an explicit parameter instead of computing it internally.
This avoids redundant calculations and simplifies scanline conversion
logic in skl_is_vblank_too_short().
This change also facilitates future extraction of these helpers for use
cases where latencies are computed for an optimized guardband, based on the
highest resolution mode, rather than the current mode.
Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
Reviewed-by: Mitul Golani <mitulkumar.ajitkumar.golani@intel.com>
---
drivers/gpu/drm/i915/display/skl_watermark.c | 18 ++++++++----------
1 file changed, 8 insertions(+), 10 deletions(-)
diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c
index 51548447f4aa..49d424f5b305 100644
--- a/drivers/gpu/drm/i915/display/skl_watermark.c
+++ b/drivers/gpu/drm/i915/display/skl_watermark.c
@@ -2176,13 +2176,11 @@ cdclk_prefill_adjustment(const struct intel_crtc_state *crtc_state)
}
static int
-dsc_prefill_latency(const struct intel_crtc_state *crtc_state)
+dsc_prefill_latency(const struct intel_crtc_state *crtc_state, int linetime)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
const struct intel_crtc_scaler_state *scaler_state =
&crtc_state->scaler_state;
- int linetime = DIV_ROUND_UP(1000 * crtc_state->hw.adjusted_mode.htotal,
- crtc_state->hw.adjusted_mode.clock);
int num_scaler_users = hweight32(scaler_state->scaler_users);
int chroma_downscaling_factor =
crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420 ? 4 : 1;
@@ -2206,18 +2204,16 @@ dsc_prefill_latency(const struct intel_crtc_state *crtc_state)
dsc_prefill_latency *= cdclk_prefill_adjustment(crtc_state);
- return intel_usecs_to_scanlines(&crtc_state->hw.adjusted_mode, dsc_prefill_latency);
+ return dsc_prefill_latency;
}
static int
-scaler_prefill_latency(const struct intel_crtc_state *crtc_state)
+scaler_prefill_latency(const struct intel_crtc_state *crtc_state, int linetime)
{
const struct intel_crtc_scaler_state *scaler_state =
&crtc_state->scaler_state;
int num_scaler_users = hweight32(scaler_state->scaler_users);
int scaler_prefill_latency = 0;
- int linetime = DIV_ROUND_UP(1000 * crtc_state->hw.adjusted_mode.htotal,
- crtc_state->hw.adjusted_mode.clock);
if (!num_scaler_users)
return scaler_prefill_latency;
@@ -2238,7 +2234,7 @@ scaler_prefill_latency(const struct intel_crtc_state *crtc_state)
scaler_prefill_latency *= cdclk_prefill_adjustment(crtc_state);
- return intel_usecs_to_scanlines(&crtc_state->hw.adjusted_mode, scaler_prefill_latency);
+ return scaler_prefill_latency;
}
static bool
@@ -2247,11 +2243,13 @@ skl_is_vblank_too_short(const struct intel_crtc_state *crtc_state,
{
const struct drm_display_mode *adjusted_mode =
&crtc_state->hw.adjusted_mode;
+ int linetime = DIV_ROUND_UP(1000 * adjusted_mode->htotal,
+ adjusted_mode->clock);
return crtc_state->framestart_delay +
intel_usecs_to_scanlines(adjusted_mode, latency) +
- scaler_prefill_latency(crtc_state) +
- dsc_prefill_latency(crtc_state) +
+ DIV_ROUND_UP(scaler_prefill_latency(crtc_state, linetime), linetime) +
+ DIV_ROUND_UP(dsc_prefill_latency(crtc_state, linetime), linetime) +
wm0_lines >
adjusted_mode->crtc_vtotal - adjusted_mode->crtc_vblank_start;
}
--
2.45.2
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH 04/14] drm/i915/skl_scaler: Introduce helper for chroma downscale factor
2025-09-07 7:32 [PATCH 00/14] Optimize vrr.guardband and fix LRR Ankit Nautiyal
` (2 preceding siblings ...)
2025-09-07 7:32 ` [PATCH 03/14] drm/i915/skl_watermark: Pass linetime as argument to latency helpers Ankit Nautiyal
@ 2025-09-07 7:32 ` Ankit Nautiyal
2025-09-07 7:32 ` [PATCH 05/14] drm/i915/display: Extract helpers to set dsc/scaler prefill latencies Ankit Nautiyal
` (10 subsequent siblings)
14 siblings, 0 replies; 22+ messages in thread
From: Ankit Nautiyal @ 2025-09-07 7:32 UTC (permalink / raw)
To: intel-gfx, intel-xe; +Cc: ville.syrjala, Ankit Nautiyal, Mitul Golani
For 444 to 420 output format conversion, scaler uses 2x downscaling in
each direction. Introduce skl_scaler_chroma_downscale_factor() to
encapsulate the chroma subsampling adjustment used in scaler/dsc
pre-fill latency calculations.
Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
Reviewed-by: Mitul Golani <mitulkumar.ajitkumar.golani@intel.com>
---
drivers/gpu/drm/i915/display/skl_scaler.c | 5 +++++
drivers/gpu/drm/i915/display/skl_scaler.h | 3 +++
drivers/gpu/drm/i915/display/skl_watermark.c | 7 +++----
3 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/i915/display/skl_scaler.c b/drivers/gpu/drm/i915/display/skl_scaler.c
index c6cccf170ff1..af2cbd54c32e 100644
--- a/drivers/gpu/drm/i915/display/skl_scaler.c
+++ b/drivers/gpu/drm/i915/display/skl_scaler.c
@@ -968,3 +968,8 @@ void adl_scaler_ecc_unmask(const struct intel_crtc_state *crtc_state)
1);
intel_de_write(display, XELPD_DISPLAY_ERR_FATAL_MASK, 0);
}
+
+int skl_scaler_chroma_downscale_factor(const struct intel_crtc_state *crtc_state)
+{
+ return crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420 ? 4 : 1;
+}
diff --git a/drivers/gpu/drm/i915/display/skl_scaler.h b/drivers/gpu/drm/i915/display/skl_scaler.h
index 12a19016c5f6..257330d4c329 100644
--- a/drivers/gpu/drm/i915/display/skl_scaler.h
+++ b/drivers/gpu/drm/i915/display/skl_scaler.h
@@ -45,4 +45,7 @@ skl_scaler_mode_valid(struct intel_display *display,
void adl_scaler_ecc_mask(const struct intel_crtc_state *crtc_state);
void adl_scaler_ecc_unmask(const struct intel_crtc_state *crtc_state);
+
+int skl_scaler_chroma_downscale_factor(const struct intel_crtc_state *crtc_state);
+
#endif
diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c
index 49d424f5b305..3d322c39ce21 100644
--- a/drivers/gpu/drm/i915/display/skl_watermark.c
+++ b/drivers/gpu/drm/i915/display/skl_watermark.c
@@ -30,6 +30,7 @@
#include "intel_plane.h"
#include "intel_wm.h"
#include "skl_universal_plane_regs.h"
+#include "skl_scaler.h"
#include "skl_watermark.h"
#include "skl_watermark_regs.h"
@@ -2182,8 +2183,7 @@ dsc_prefill_latency(const struct intel_crtc_state *crtc_state, int linetime)
const struct intel_crtc_scaler_state *scaler_state =
&crtc_state->scaler_state;
int num_scaler_users = hweight32(scaler_state->scaler_users);
- int chroma_downscaling_factor =
- crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420 ? 4 : 1;
+ int chroma_downscaling_factor = skl_scaler_chroma_downscale_factor(crtc_state);
u32 dsc_prefill_latency = 0;
if (!crtc_state->dsc.compression_enable ||
@@ -2223,8 +2223,7 @@ scaler_prefill_latency(const struct intel_crtc_state *crtc_state, int linetime)
if (num_scaler_users > 1) {
u64 hscale_k = max(1000, mul_u32_u32(scaler_state->scalers[0].hscale, 1000) >> 16);
u64 vscale_k = max(1000, mul_u32_u32(scaler_state->scalers[0].vscale, 1000) >> 16);
- int chroma_downscaling_factor =
- crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420 ? 4 : 1;
+ int chroma_downscaling_factor = skl_scaler_chroma_downscale_factor(crtc_state);
int latency;
latency = DIV_ROUND_UP_ULL((4 * linetime * hscale_k * vscale_k *
--
2.45.2
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH 05/14] drm/i915/display: Extract helpers to set dsc/scaler prefill latencies
2025-09-07 7:32 [PATCH 00/14] Optimize vrr.guardband and fix LRR Ankit Nautiyal
` (3 preceding siblings ...)
2025-09-07 7:32 ` [PATCH 04/14] drm/i915/skl_scaler: Introduce helper for chroma downscale factor Ankit Nautiyal
@ 2025-09-07 7:32 ` Ankit Nautiyal
2025-09-07 7:32 ` [PATCH 06/14] drm/i915/dp: Add SDP latency computation helper Ankit Nautiyal
` (9 subsequent siblings)
14 siblings, 0 replies; 22+ messages in thread
From: Ankit Nautiyal @ 2025-09-07 7:32 UTC (permalink / raw)
To: intel-gfx, intel-xe; +Cc: ville.syrjala, Ankit Nautiyal, Mitul Golani
Currently dsc/scaler prefill latencies are handled during watermark
calculations. With the optimized guardband, we need to compute the
latencies to find the minimum guardband that works for most cases.
Extract the helpers to compute these latencies, so that they can be used
while computing vrr guardband.
While at it, put declarations in reverse xmas tree order for better
redability.
v2: Initialize {h,v}scale_k to 0, and simplify the check in
intel_display_scaler_prefill_latency(). (Mitul)
v3: Move helpers from intel_display.c to intel_vrr.c as they are specific
to account for latencies to program vrr guardband. (Jani)
Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
Reviewed-by: Mitul Golani <mitulkumar.ajitkumar.golani@intel.com>
---
drivers/gpu/drm/i915/display/intel_vrr.c | 33 ++++++++++++++
drivers/gpu/drm/i915/display/intel_vrr.h | 8 ++++
drivers/gpu/drm/i915/display/skl_watermark.c | 47 +++++++++-----------
3 files changed, 63 insertions(+), 25 deletions(-)
diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c
index 266cf5e1859d..fd690de5b45b 100644
--- a/drivers/gpu/drm/i915/display/intel_vrr.c
+++ b/drivers/gpu/drm/i915/display/intel_vrr.c
@@ -772,3 +772,36 @@ void intel_vrr_get_config(struct intel_crtc_state *crtc_state)
if (crtc_state->vrr.enable)
crtc_state->mode_flags |= I915_MODE_FLAG_VRR;
}
+
+int intel_vrr_guardband_scaler_latency(int num_scaler_users, u64 hscale, u64 vscale,
+ int chroma_downscaling_factor,
+ int cdclk_prefill_adjustment,
+ int linetime)
+{
+ int scaler_prefill_latency;
+
+ scaler_prefill_latency = 4 * linetime +
+ DIV_ROUND_UP_ULL((4 * linetime * hscale * vscale *
+ chroma_downscaling_factor), 1000000);
+
+ scaler_prefill_latency *= cdclk_prefill_adjustment;
+
+ return scaler_prefill_latency;
+}
+
+int intel_vrr_guardband_dsc_latency(int num_scaler_users, u64 *hscale, u64 *vscale,
+ int chroma_downscaling_factor,
+ int cdclk_prefill_adjustment,
+ int linetime)
+{
+ int dsc_prefill_latency;
+
+ dsc_prefill_latency = DIV_ROUND_UP(15 * linetime * chroma_downscaling_factor, 10);
+
+ for (int i = 0; i < num_scaler_users; i++)
+ dsc_prefill_latency = DIV_ROUND_UP_ULL(dsc_prefill_latency * hscale[i] * vscale[i],
+ 1000000);
+ dsc_prefill_latency *= cdclk_prefill_adjustment;
+
+ return dsc_prefill_latency;
+}
diff --git a/drivers/gpu/drm/i915/display/intel_vrr.h b/drivers/gpu/drm/i915/display/intel_vrr.h
index 38bf9996b883..950041647e47 100644
--- a/drivers/gpu/drm/i915/display/intel_vrr.h
+++ b/drivers/gpu/drm/i915/display/intel_vrr.h
@@ -41,5 +41,13 @@ void intel_vrr_transcoder_enable(const struct intel_crtc_state *crtc_state);
void intel_vrr_transcoder_disable(const struct intel_crtc_state *crtc_state);
void intel_vrr_set_fixed_rr_timings(const struct intel_crtc_state *crtc_state);
bool intel_vrr_always_use_vrr_tg(struct intel_display *display);
+int intel_vrr_guardband_scaler_latency(int num_scaler_users, u64 hscale, u64 vscale,
+ int chroma_downscaling_factor,
+ int cdclk_prefill_adjustment,
+ int linetime);
+int intel_vrr_guardband_dsc_latency(int num_scaler_users, u64 *hscale, u64 *vscale,
+ int chroma_downscaling_factor,
+ int cdclk_prefill_adjustment,
+ int linetime);
#endif /* __INTEL_VRR_H__ */
diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c
index 3d322c39ce21..1ff2b4d9a35e 100644
--- a/drivers/gpu/drm/i915/display/skl_watermark.c
+++ b/drivers/gpu/drm/i915/display/skl_watermark.c
@@ -28,6 +28,7 @@
#include "intel_flipq.h"
#include "intel_pcode.h"
#include "intel_plane.h"
+#include "intel_vrr.h"
#include "intel_wm.h"
#include "skl_universal_plane_regs.h"
#include "skl_scaler.h"
@@ -2179,11 +2180,12 @@ cdclk_prefill_adjustment(const struct intel_crtc_state *crtc_state)
static int
dsc_prefill_latency(const struct intel_crtc_state *crtc_state, int linetime)
{
+ const struct intel_crtc_scaler_state *scaler_state = &crtc_state->scaler_state;
+ int chroma_downscaling_factor = skl_scaler_chroma_downscale_factor(crtc_state);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
- const struct intel_crtc_scaler_state *scaler_state =
- &crtc_state->scaler_state;
int num_scaler_users = hweight32(scaler_state->scaler_users);
- int chroma_downscaling_factor = skl_scaler_chroma_downscale_factor(crtc_state);
+ u64 hscale_k[ARRAY_SIZE(scaler_state->scalers)];
+ u64 vscale_k[ARRAY_SIZE(scaler_state->scalers)];
u32 dsc_prefill_latency = 0;
if (!crtc_state->dsc.compression_enable ||
@@ -2191,18 +2193,16 @@ dsc_prefill_latency(const struct intel_crtc_state *crtc_state, int linetime)
num_scaler_users > crtc->num_scalers)
return dsc_prefill_latency;
- dsc_prefill_latency = DIV_ROUND_UP(15 * linetime * chroma_downscaling_factor, 10);
-
for (int i = 0; i < num_scaler_users; i++) {
- u64 hscale_k, vscale_k;
-
- hscale_k = max(1000, mul_u32_u32(scaler_state->scalers[i].hscale, 1000) >> 16);
- vscale_k = max(1000, mul_u32_u32(scaler_state->scalers[i].vscale, 1000) >> 16);
- dsc_prefill_latency = DIV_ROUND_UP_ULL(dsc_prefill_latency * hscale_k * vscale_k,
- 1000000);
+ hscale_k[i] = max(1000, mul_u32_u32(scaler_state->scalers[i].hscale, 1000) >> 16);
+ vscale_k[i] = max(1000, mul_u32_u32(scaler_state->scalers[i].vscale, 1000) >> 16);
}
- dsc_prefill_latency *= cdclk_prefill_adjustment(crtc_state);
+ dsc_prefill_latency =
+ intel_vrr_guardband_dsc_latency(num_scaler_users, hscale_k, vscale_k,
+ chroma_downscaling_factor,
+ cdclk_prefill_adjustment(crtc_state),
+ linetime);
return dsc_prefill_latency;
}
@@ -2210,28 +2210,25 @@ dsc_prefill_latency(const struct intel_crtc_state *crtc_state, int linetime)
static int
scaler_prefill_latency(const struct intel_crtc_state *crtc_state, int linetime)
{
- const struct intel_crtc_scaler_state *scaler_state =
- &crtc_state->scaler_state;
+ const struct intel_crtc_scaler_state *scaler_state = &crtc_state->scaler_state;
+ int chroma_downscaling_factor = skl_scaler_chroma_downscale_factor(crtc_state);
int num_scaler_users = hweight32(scaler_state->scaler_users);
+ u64 hscale_k = 0, vscale_k = 0;
int scaler_prefill_latency = 0;
if (!num_scaler_users)
return scaler_prefill_latency;
- scaler_prefill_latency = 4 * linetime;
-
if (num_scaler_users > 1) {
- u64 hscale_k = max(1000, mul_u32_u32(scaler_state->scalers[0].hscale, 1000) >> 16);
- u64 vscale_k = max(1000, mul_u32_u32(scaler_state->scalers[0].vscale, 1000) >> 16);
- int chroma_downscaling_factor = skl_scaler_chroma_downscale_factor(crtc_state);
- int latency;
-
- latency = DIV_ROUND_UP_ULL((4 * linetime * hscale_k * vscale_k *
- chroma_downscaling_factor), 1000000);
- scaler_prefill_latency += latency;
+ hscale_k = max(1000, mul_u32_u32(scaler_state->scalers[0].hscale, 1000) >> 16);
+ vscale_k = max(1000, mul_u32_u32(scaler_state->scalers[0].vscale, 1000) >> 16);
}
- scaler_prefill_latency *= cdclk_prefill_adjustment(crtc_state);
+ scaler_prefill_latency =
+ intel_vrr_guardband_scaler_latency(num_scaler_users, hscale_k, vscale_k,
+ chroma_downscaling_factor,
+ cdclk_prefill_adjustment(crtc_state),
+ linetime);
return scaler_prefill_latency;
}
--
2.45.2
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH 06/14] drm/i915/dp: Add SDP latency computation helper
2025-09-07 7:32 [PATCH 00/14] Optimize vrr.guardband and fix LRR Ankit Nautiyal
` (4 preceding siblings ...)
2025-09-07 7:32 ` [PATCH 05/14] drm/i915/display: Extract helpers to set dsc/scaler prefill latencies Ankit Nautiyal
@ 2025-09-07 7:32 ` Ankit Nautiyal
2025-09-07 7:32 ` [PATCH 07/14] drm/i915/alpm: Add function to compute max link-wake latency Ankit Nautiyal
` (8 subsequent siblings)
14 siblings, 0 replies; 22+ messages in thread
From: Ankit Nautiyal @ 2025-09-07 7:32 UTC (permalink / raw)
To: intel-gfx, intel-xe; +Cc: ville.syrjala, Ankit Nautiyal, Mitul Golani
Add a helper to compute vblank time needed for transmitting specific
DisplayPort SDPs like PPS, GAMUT_METADATA, and VSC_EXT. Latency is
based on line count per packet type and current line time.
Used to ensure adequate vblank when features like DSC/HDR are enabled.
Bspec: 70151
Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
Reviewed-by: Mitul Golani <mitulkumar.ajitkumar.golani@intel.com>
---
drivers/gpu/drm/i915/display/intel_dp.c | 47 +++++++++++++++++++++++++
drivers/gpu/drm/i915/display/intel_dp.h | 1 +
2 files changed, 48 insertions(+)
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 2eab591a8ef5..d5d30bdc6848 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -6857,3 +6857,50 @@ void intel_dp_mst_resume(struct intel_display *display)
}
}
}
+
+static
+int intel_dp_get_sdp_latency(u32 type, int linetime_us)
+{
+ int lines;
+
+ switch (type) {
+ case DP_SDP_VSC_EXT_VESA:
+ case DP_SDP_VSC_EXT_CEA:
+ lines = 10;
+ break;
+ case HDMI_PACKET_TYPE_GAMUT_METADATA:
+ lines = 8;
+ break;
+ case DP_SDP_PPS:
+ lines = 6;
+ break;
+ default:
+ lines = 0;
+ break;
+ }
+
+ return lines * linetime_us;
+}
+
+int intel_dp_compute_sdp_latency(struct intel_crtc_state *crtc_state,
+ bool assume_all_enabled)
+{
+ const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
+ int sdp_latency = 0;
+ int linetime_us;
+
+ linetime_us = DIV_ROUND_UP(adjusted_mode->crtc_htotal * 1000,
+ adjusted_mode->crtc_clock);
+ if (assume_all_enabled ||
+ crtc_state->infoframes.enable &
+ intel_hdmi_infoframe_enable(HDMI_PACKET_TYPE_GAMUT_METADATA))
+ sdp_latency = max(sdp_latency,
+ intel_dp_get_sdp_latency(HDMI_PACKET_TYPE_GAMUT_METADATA,
+ linetime_us));
+
+ if (assume_all_enabled || crtc_state->dsc.compression_enable)
+ sdp_latency = max(sdp_latency,
+ intel_dp_get_sdp_latency(DP_SDP_PPS, linetime_us));
+
+ return sdp_latency;
+}
diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h
index f90cfd1dbbd0..bfd1bd448672 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.h
+++ b/drivers/gpu/drm/i915/display/intel_dp.h
@@ -215,5 +215,6 @@ int intel_dp_compute_min_hblank(struct intel_crtc_state *crtc_state,
int intel_dp_dsc_bpp_step_x16(const struct intel_connector *connector);
void intel_dp_dpcd_set_probe(struct intel_dp *intel_dp, bool force_on_external);
bool intel_dp_in_hdr_mode(const struct drm_connector_state *conn_state);
+int intel_dp_compute_sdp_latency(struct intel_crtc_state *crtc_state, bool assume_all_enabled);
#endif /* __INTEL_DP_H__ */
--
2.45.2
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH 07/14] drm/i915/alpm: Add function to compute max link-wake latency
2025-09-07 7:32 [PATCH 00/14] Optimize vrr.guardband and fix LRR Ankit Nautiyal
` (5 preceding siblings ...)
2025-09-07 7:32 ` [PATCH 06/14] drm/i915/dp: Add SDP latency computation helper Ankit Nautiyal
@ 2025-09-07 7:32 ` Ankit Nautiyal
2025-09-07 7:32 ` [PATCH 08/14] drm/i915/vrr: Use vrr.sync_start for getting vtotal Ankit Nautiyal
` (7 subsequent siblings)
14 siblings, 0 replies; 22+ messages in thread
From: Ankit Nautiyal @ 2025-09-07 7:32 UTC (permalink / raw)
To: intel-gfx, intel-xe; +Cc: ville.syrjala, Ankit Nautiyal, Mitul Golani
Introduce a helper to compute the max link wake latency when using
Auxless/Aux wake mechanism for PSR/Panel Replay/LOBF features.
This will be used to compute the minimum guardband so that the link wake
latencies are accounted and these features work smoothly for higher
refresh rate panels.
Bspec: 70151, 71477
Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
Reviewed-by: Mitul Golani <mitulkumar.ajitkumar.golani@intel.com>
---
drivers/gpu/drm/i915/display/intel_alpm.c | 15 +++++++++++++++
drivers/gpu/drm/i915/display/intel_alpm.h | 2 ++
2 files changed, 17 insertions(+)
diff --git a/drivers/gpu/drm/i915/display/intel_alpm.c b/drivers/gpu/drm/i915/display/intel_alpm.c
index ed7a7ed486b5..02de069b02d7 100644
--- a/drivers/gpu/drm/i915/display/intel_alpm.c
+++ b/drivers/gpu/drm/i915/display/intel_alpm.c
@@ -611,3 +611,18 @@ bool intel_alpm_get_error(struct intel_dp *intel_dp)
return false;
}
+
+int intel_alpm_compute_max_link_wake_latency(struct intel_crtc_state *crtc_state,
+ bool assume_all_enabled)
+{
+ int psr2_vblank_time = 0;
+ int auxless_wake_time = 0;
+
+ if (assume_all_enabled || crtc_state->has_sel_update)
+ psr2_vblank_time = io_buffer_wake_time(crtc_state);
+
+ if (assume_all_enabled || crtc_state->has_panel_replay)
+ auxless_wake_time = _lnl_compute_aux_less_wake_time(crtc_state);
+
+ return max(psr2_vblank_time, auxless_wake_time);
+}
diff --git a/drivers/gpu/drm/i915/display/intel_alpm.h b/drivers/gpu/drm/i915/display/intel_alpm.h
index a861c20b5d79..8f1db54eecf5 100644
--- a/drivers/gpu/drm/i915/display/intel_alpm.h
+++ b/drivers/gpu/drm/i915/display/intel_alpm.h
@@ -38,4 +38,6 @@ bool intel_alpm_is_alpm_aux_less(struct intel_dp *intel_dp,
const struct intel_crtc_state *crtc_state);
void intel_alpm_disable(struct intel_dp *intel_dp);
bool intel_alpm_get_error(struct intel_dp *intel_dp);
+int intel_alpm_compute_max_link_wake_latency(struct intel_crtc_state *crtc_state,
+ bool assume_all_enabled);
#endif
--
2.45.2
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH 08/14] drm/i915/vrr: Use vrr.sync_start for getting vtotal
2025-09-07 7:32 [PATCH 00/14] Optimize vrr.guardband and fix LRR Ankit Nautiyal
` (6 preceding siblings ...)
2025-09-07 7:32 ` [PATCH 07/14] drm/i915/alpm: Add function to compute max link-wake latency Ankit Nautiyal
@ 2025-09-07 7:32 ` Ankit Nautiyal
2025-09-07 7:32 ` [PATCH 09/14] drm/i915/display: Add guardband check for feature latencies Ankit Nautiyal
` (6 subsequent siblings)
14 siblings, 0 replies; 22+ messages in thread
From: Ankit Nautiyal @ 2025-09-07 7:32 UTC (permalink / raw)
To: intel-gfx, intel-xe; +Cc: ville.syrjala, Ankit Nautiyal, Mitul Golani
Currently, in intel_vrr_get_config() crtc_vtotal is computed from
vrr.vmin vtotal, since the VTOTAL.Vtotal bits are deprecated.
Since vmin is currently set to crtc_vtotal, this gives us the vtotal.
However, as we move to optimized guardband, vmin will be modified to set
to the minimum Vtotal for highest refresh rate supported.
Instead of depending on vmin, compute vtotal from crtc_vsync_start and
vrr.vsync_start. This works since vrr.vsync_start is measured from the
end of vblank, and crtc_vsync_start is measured from start of the
scanline. Together their sum is equal to the crtc_vtotal.
Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
Reviewed-by: Mitul Golani <mitulkumar.ajitkumar.golani@intel.com>
---
drivers/gpu/drm/i915/display/intel_vrr.c | 21 ++++++++++-----------
1 file changed, 10 insertions(+), 11 deletions(-)
diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c
index fd690de5b45b..855974174afd 100644
--- a/drivers/gpu/drm/i915/display/intel_vrr.c
+++ b/drivers/gpu/drm/i915/display/intel_vrr.c
@@ -735,17 +735,6 @@ void intel_vrr_get_config(struct intel_crtc_state *crtc_state)
TRANS_VRR_VMAX(display, cpu_transcoder)) + 1;
crtc_state->vrr.vmin = intel_de_read(display,
TRANS_VRR_VMIN(display, cpu_transcoder)) + 1;
-
- /*
- * For platforms that always use VRR Timing Generator, the VTOTAL.Vtotal
- * bits are not filled. Since for these platforms TRAN_VMIN is always
- * filled with crtc_vtotal, use TRAN_VRR_VMIN to get the vtotal for
- * adjusted_mode.
- */
- if (intel_vrr_always_use_vrr_tg(display))
- crtc_state->hw.adjusted_mode.crtc_vtotal =
- intel_vrr_vmin_vtotal(crtc_state);
-
if (HAS_AS_SDP(display)) {
trans_vrr_vsync =
intel_de_read(display,
@@ -755,6 +744,16 @@ void intel_vrr_get_config(struct intel_crtc_state *crtc_state)
crtc_state->vrr.vsync_end =
REG_FIELD_GET(VRR_VSYNC_END_MASK, trans_vrr_vsync);
}
+ /*
+ * For platforms that always use VRR Timing Generator, the VTOTAL.Vtotal
+ * 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.
+ */
+ 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;
}
vrr_enable = trans_vrr_ctl & VRR_CTL_VRR_ENABLE;
--
2.45.2
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH 09/14] drm/i915/display: Add guardband check for feature latencies
2025-09-07 7:32 [PATCH 00/14] Optimize vrr.guardband and fix LRR Ankit Nautiyal
` (7 preceding siblings ...)
2025-09-07 7:32 ` [PATCH 08/14] drm/i915/vrr: Use vrr.sync_start for getting vtotal Ankit Nautiyal
@ 2025-09-07 7:32 ` Ankit Nautiyal
2025-09-07 7:32 ` [PATCH 10/14] drm/i915/skl_watermark: Remove redundant latency checks from vblank validation Ankit Nautiyal
` (5 subsequent siblings)
14 siblings, 0 replies; 22+ messages in thread
From: Ankit Nautiyal @ 2025-09-07 7:32 UTC (permalink / raw)
To: intel-gfx, intel-xe; +Cc: ville.syrjala, Ankit Nautiyal, Mitul Golani
Add a check during atomic crtc check phase to ensure the programmed VRR
guardband is sufficient to cover latencies introduced by enabled features
such as DSC, PSR/PR, scalers, and DP SDPs.
Currently, the guardband is programmed to match the vblank length, so
existing checks in skl_is_vblank_too_short() are valid. However, upcoming
changes will optimize the guardband independently of vblank, making those
checks incorrect.
Introduce an explicit guardband check to prepare for future updates
that will remove checking against the vblank length and later program an
optimized guardband.
v2: Use new helper for PSR2/Panel Replay latency.
v3:
-Align the name of helper with intel_crtc_atomic_check and rename it to
intel_crtc_guardband_atomic_check(). (Jani)
-Simplify checks in the helper. (Mitul)
-Make a separate helper to compute wm0 prefill time. (Mitul)
v4: Drop redundant HAS_VRR() check. (Jani).
Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
Reviewed-by: Mitul Golani <mitulkumar.ajitkumar.golani@intel.com>
---
drivers/gpu/drm/i915/display/intel_display.c | 142 +++++++++++++++++++
drivers/gpu/drm/i915/display/skl_watermark.c | 2 +-
drivers/gpu/drm/i915/display/skl_watermark.h | 1 +
3 files changed, 144 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index c1a3a95c65f0..787bb6ebdc75 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -4227,6 +4227,142 @@ static int hsw_compute_linetime_wm(struct intel_atomic_state *state,
return 0;
}
+static int
+cdclk_prefill_adjustment(const struct intel_crtc_state *crtc_state)
+{
+ struct intel_display *display = to_intel_display(crtc_state);
+ struct intel_atomic_state *state =
+ to_intel_atomic_state(crtc_state->uapi.state);
+ const struct intel_cdclk_state *cdclk_state;
+
+ cdclk_state = intel_atomic_get_cdclk_state(state);
+ if (IS_ERR(cdclk_state)) {
+ drm_WARN_ON(display->drm, PTR_ERR(cdclk_state));
+ return 1;
+ }
+
+ return min(1, DIV_ROUND_UP(crtc_state->pixel_rate,
+ 2 * intel_cdclk_logical(cdclk_state)));
+}
+
+static int
+dsc_prefill_latency(const struct intel_crtc_state *crtc_state, int linetime)
+{
+ const struct intel_crtc_scaler_state *scaler_state = &crtc_state->scaler_state;
+ int chroma_downscaling_factor = skl_scaler_chroma_downscale_factor(crtc_state);
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+ int num_scaler_users = hweight32(scaler_state->scaler_users);
+ u64 hscale_k[ARRAY_SIZE(scaler_state->scalers)];
+ u64 vscale_k[ARRAY_SIZE(scaler_state->scalers)];
+ u32 dsc_prefill_latency = 0;
+
+ if (!crtc_state->dsc.compression_enable ||
+ !num_scaler_users ||
+ num_scaler_users > crtc->num_scalers)
+ return dsc_prefill_latency;
+
+ for (int i = 0; i < num_scaler_users; i++) {
+ hscale_k[i] = max(1000, mul_u32_u32(scaler_state->scalers[i].hscale, 1000) >> 16);
+ vscale_k[i] = max(1000, mul_u32_u32(scaler_state->scalers[i].vscale, 1000) >> 16);
+ }
+
+ dsc_prefill_latency =
+ intel_vrr_guardband_dsc_latency(num_scaler_users, hscale_k, vscale_k,
+ chroma_downscaling_factor,
+ cdclk_prefill_adjustment(crtc_state),
+ linetime);
+
+ return dsc_prefill_latency;
+}
+
+static int
+scaler_prefill_latency(const struct intel_crtc_state *crtc_state, int linetime)
+{
+ const struct intel_crtc_scaler_state *scaler_state = &crtc_state->scaler_state;
+ int chroma_downscaling_factor = skl_scaler_chroma_downscale_factor(crtc_state);
+ int num_scaler_users = hweight32(scaler_state->scaler_users);
+ u64 hscale_k = 0, vscale_k = 0;
+ int scaler_prefill_latency = 0;
+
+ if (!num_scaler_users)
+ return scaler_prefill_latency;
+
+ if (num_scaler_users > 1) {
+ hscale_k = max(1000, mul_u32_u32(scaler_state->scalers[0].hscale, 1000) >> 16);
+ vscale_k = max(1000, mul_u32_u32(scaler_state->scalers[0].vscale, 1000) >> 16);
+ }
+
+ scaler_prefill_latency =
+ intel_vrr_guardband_scaler_latency(num_scaler_users, hscale_k, vscale_k,
+ chroma_downscaling_factor,
+ cdclk_prefill_adjustment(crtc_state),
+ linetime);
+
+ return scaler_prefill_latency;
+}
+
+static int
+wm0_prefill_latency(int linetime_us, int max_wm0_lines)
+{
+ return 20 + linetime_us * max_wm0_lines;
+}
+
+static int intel_crtc_guardband_atomic_check(struct intel_crtc_state *crtc_state)
+{
+ struct intel_display *display = to_intel_display(crtc_state);
+ const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
+ int dsc_prefill_time = 0;
+ int scaler_prefill_time;
+ int wm0_prefill_time;
+ int pkgc_max_latency;
+ int psr2_pr_latency;
+ int min_guardband;
+ int guardband_us;
+ int sagv_latency;
+ int linetime_us;
+ int sdp_latency;
+ int pm_delay;
+
+ if (!crtc_state->vrr.enable && !intel_vrr_always_use_vrr_tg(display))
+ return 0;
+
+ if (!adjusted_mode->crtc_clock)
+ return 0;
+
+ linetime_us = DIV_ROUND_UP(adjusted_mode->crtc_htotal * 1000,
+ adjusted_mode->crtc_clock);
+
+ pkgc_max_latency = skl_watermark_max_latency(display, 1);
+ sagv_latency = display->sagv.block_time_us;
+
+ wm0_prefill_time = wm0_prefill_latency(linetime_us, skl_max_wm0_lines(crtc_state));
+
+ scaler_prefill_time = scaler_prefill_latency(crtc_state, linetime_us);
+
+ dsc_prefill_time = dsc_prefill_latency(crtc_state, linetime_us);
+
+ pm_delay = crtc_state->framestart_delay +
+ max(sagv_latency, pkgc_max_latency) +
+ wm0_prefill_time +
+ scaler_prefill_time +
+ dsc_prefill_time;
+
+ psr2_pr_latency = intel_alpm_compute_max_link_wake_latency(crtc_state, false);
+ sdp_latency = intel_dp_compute_sdp_latency(crtc_state, false);
+
+ guardband_us = max(sdp_latency, psr2_pr_latency);
+ guardband_us = max(guardband_us, pm_delay);
+ min_guardband = DIV_ROUND_UP(guardband_us, linetime_us);
+
+ if (crtc_state->vrr.guardband < min_guardband) {
+ drm_dbg_kms(display->drm, "vrr.guardband %d < min guardband %d\n",
+ crtc_state->vrr.guardband, min_guardband);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static int intel_crtc_atomic_check(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
@@ -4289,6 +4425,12 @@ static int intel_crtc_atomic_check(struct intel_atomic_state *state,
if (ret)
return ret;
+ if (intel_vrr_possible(crtc_state)) {
+ ret = intel_crtc_guardband_atomic_check(crtc_state);
+ if (ret)
+ return ret;
+ }
+
return 0;
}
diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c
index 1ff2b4d9a35e..83ac26004f05 100644
--- a/drivers/gpu/drm/i915/display/skl_watermark.c
+++ b/drivers/gpu/drm/i915/display/skl_watermark.c
@@ -2250,7 +2250,7 @@ skl_is_vblank_too_short(const struct intel_crtc_state *crtc_state,
adjusted_mode->crtc_vtotal - adjusted_mode->crtc_vblank_start;
}
-static int skl_max_wm0_lines(const struct intel_crtc_state *crtc_state)
+int skl_max_wm0_lines(const struct intel_crtc_state *crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
enum plane_id plane_id;
diff --git a/drivers/gpu/drm/i915/display/skl_watermark.h b/drivers/gpu/drm/i915/display/skl_watermark.h
index 62790816f030..8706c2010ebe 100644
--- a/drivers/gpu/drm/i915/display/skl_watermark.h
+++ b/drivers/gpu/drm/i915/display/skl_watermark.h
@@ -78,6 +78,7 @@ void intel_dbuf_mbus_post_ddb_update(struct intel_atomic_state *state);
void intel_program_dpkgc_latency(struct intel_atomic_state *state);
bool intel_dbuf_pmdemand_needs_update(struct intel_atomic_state *state);
+int skl_max_wm0_lines(const struct intel_crtc_state *crtc_state);
#endif /* __SKL_WATERMARK_H__ */
--
2.45.2
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH 10/14] drm/i915/skl_watermark: Remove redundant latency checks from vblank validation
2025-09-07 7:32 [PATCH 00/14] Optimize vrr.guardband and fix LRR Ankit Nautiyal
` (8 preceding siblings ...)
2025-09-07 7:32 ` [PATCH 09/14] drm/i915/display: Add guardband check for feature latencies Ankit Nautiyal
@ 2025-09-07 7:32 ` Ankit Nautiyal
2025-09-07 7:32 ` [PATCH 11/14] drm/i915/dsb: Align flipdone with delayed vblank using guardband wait Ankit Nautiyal
` (4 subsequent siblings)
14 siblings, 0 replies; 22+ messages in thread
From: Ankit Nautiyal @ 2025-09-07 7:32 UTC (permalink / raw)
To: intel-gfx, intel-xe; +Cc: ville.syrjala, Ankit Nautiyal, Mitul Golani
Drop DSC and scaler prefill latency checks from skl_is_vblank_too_short().
These are now covered by the guardband validation added during the atomic
CRTC check phase.
This cleanup prepares for future changes where the guardband will be
optimized independently of vblank length, making vblank-based checks
obsolete.
Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
Reviewed-by: Mitul Golani <mitulkumar.ajitkumar.golani@intel.com>
---
drivers/gpu/drm/i915/display/skl_watermark.c | 79 --------------------
1 file changed, 79 deletions(-)
diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c
index 83ac26004f05..07589096b143 100644
--- a/drivers/gpu/drm/i915/display/skl_watermark.c
+++ b/drivers/gpu/drm/i915/display/skl_watermark.c
@@ -28,7 +28,6 @@
#include "intel_flipq.h"
#include "intel_pcode.h"
#include "intel_plane.h"
-#include "intel_vrr.h"
#include "intel_wm.h"
#include "skl_universal_plane_regs.h"
#include "skl_scaler.h"
@@ -2159,93 +2158,15 @@ static int icl_build_plane_wm(struct intel_crtc_state *crtc_state,
return 0;
}
-static int
-cdclk_prefill_adjustment(const struct intel_crtc_state *crtc_state)
-{
- struct intel_display *display = to_intel_display(crtc_state);
- struct intel_atomic_state *state =
- to_intel_atomic_state(crtc_state->uapi.state);
- const struct intel_cdclk_state *cdclk_state;
-
- cdclk_state = intel_atomic_get_cdclk_state(state);
- if (IS_ERR(cdclk_state)) {
- drm_WARN_ON(display->drm, PTR_ERR(cdclk_state));
- return 1;
- }
-
- return min(1, DIV_ROUND_UP(crtc_state->pixel_rate,
- 2 * intel_cdclk_logical(cdclk_state)));
-}
-
-static int
-dsc_prefill_latency(const struct intel_crtc_state *crtc_state, int linetime)
-{
- const struct intel_crtc_scaler_state *scaler_state = &crtc_state->scaler_state;
- int chroma_downscaling_factor = skl_scaler_chroma_downscale_factor(crtc_state);
- struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
- int num_scaler_users = hweight32(scaler_state->scaler_users);
- u64 hscale_k[ARRAY_SIZE(scaler_state->scalers)];
- u64 vscale_k[ARRAY_SIZE(scaler_state->scalers)];
- u32 dsc_prefill_latency = 0;
-
- if (!crtc_state->dsc.compression_enable ||
- !num_scaler_users ||
- num_scaler_users > crtc->num_scalers)
- return dsc_prefill_latency;
-
- for (int i = 0; i < num_scaler_users; i++) {
- hscale_k[i] = max(1000, mul_u32_u32(scaler_state->scalers[i].hscale, 1000) >> 16);
- vscale_k[i] = max(1000, mul_u32_u32(scaler_state->scalers[i].vscale, 1000) >> 16);
- }
-
- dsc_prefill_latency =
- intel_vrr_guardband_dsc_latency(num_scaler_users, hscale_k, vscale_k,
- chroma_downscaling_factor,
- cdclk_prefill_adjustment(crtc_state),
- linetime);
-
- return dsc_prefill_latency;
-}
-
-static int
-scaler_prefill_latency(const struct intel_crtc_state *crtc_state, int linetime)
-{
- const struct intel_crtc_scaler_state *scaler_state = &crtc_state->scaler_state;
- int chroma_downscaling_factor = skl_scaler_chroma_downscale_factor(crtc_state);
- int num_scaler_users = hweight32(scaler_state->scaler_users);
- u64 hscale_k = 0, vscale_k = 0;
- int scaler_prefill_latency = 0;
-
- if (!num_scaler_users)
- return scaler_prefill_latency;
-
- if (num_scaler_users > 1) {
- hscale_k = max(1000, mul_u32_u32(scaler_state->scalers[0].hscale, 1000) >> 16);
- vscale_k = max(1000, mul_u32_u32(scaler_state->scalers[0].vscale, 1000) >> 16);
- }
-
- scaler_prefill_latency =
- intel_vrr_guardband_scaler_latency(num_scaler_users, hscale_k, vscale_k,
- chroma_downscaling_factor,
- cdclk_prefill_adjustment(crtc_state),
- linetime);
-
- return scaler_prefill_latency;
-}
-
static bool
skl_is_vblank_too_short(const struct intel_crtc_state *crtc_state,
int wm0_lines, int latency)
{
const struct drm_display_mode *adjusted_mode =
&crtc_state->hw.adjusted_mode;
- int linetime = DIV_ROUND_UP(1000 * adjusted_mode->htotal,
- adjusted_mode->clock);
return crtc_state->framestart_delay +
intel_usecs_to_scanlines(adjusted_mode, latency) +
- DIV_ROUND_UP(scaler_prefill_latency(crtc_state, linetime), linetime) +
- DIV_ROUND_UP(dsc_prefill_latency(crtc_state, linetime), linetime) +
wm0_lines >
adjusted_mode->crtc_vtotal - adjusted_mode->crtc_vblank_start;
}
--
2.45.2
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH 11/14] drm/i915/dsb: Align flipdone with delayed vblank using guardband wait
2025-09-07 7:32 [PATCH 00/14] Optimize vrr.guardband and fix LRR Ankit Nautiyal
` (9 preceding siblings ...)
2025-09-07 7:32 ` [PATCH 10/14] drm/i915/skl_watermark: Remove redundant latency checks from vblank validation Ankit Nautiyal
@ 2025-09-07 7:32 ` Ankit Nautiyal
2025-09-08 8:05 ` Shankar, Uma
2025-09-07 7:32 ` [PATCH 12/14] drm/i915/vrr: Use static guardband to support seamless LRR switching Ankit Nautiyal
` (3 subsequent siblings)
14 siblings, 1 reply; 22+ messages in thread
From: Ankit Nautiyal @ 2025-09-07 7:32 UTC (permalink / raw)
To: intel-gfx, intel-xe; +Cc: ville.syrjala, Ankit Nautiyal
Currently the guardband is same as vblank length and undelayed vblank
and the vblank and the flipdone with dsb interrupt are already aligned
for the fixed refresh rate case.
As we move towards a shorter optimized guardband we need to wait for the
delayed vblank before the DSB interrupt to align the flipdone event with
the delayed vblank.
Introduce a helper intel_dsb_wait_for_delayed_vblank() to wait for the
scanline range [delayed_vblank_start, vmin/vmax vtotal], depending on
whether fixed refresh rate mode or variable refresh rate mode is active,
before triggering the DSB interrupt.
Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
---
drivers/gpu/drm/i915/display/intel_display.c | 1 +
drivers/gpu/drm/i915/display/intel_dsb.c | 16 ++++++++++++++++
drivers/gpu/drm/i915/display/intel_dsb.h | 3 +++
3 files changed, 20 insertions(+)
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 787bb6ebdc75..fb072275b1c7 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -7447,6 +7447,7 @@ static void intel_atomic_dsb_finish(struct intel_atomic_state *state,
intel_vrr_send_push(new_crtc_state->dsb_commit, new_crtc_state);
intel_dsb_wait_vblank_delay(state, new_crtc_state->dsb_commit);
+ intel_dsb_wait_for_delayed_vblank(state, new_crtc_state->dsb_commit);
intel_vrr_check_push_sent(new_crtc_state->dsb_commit,
new_crtc_state);
intel_dsb_interrupt(new_crtc_state->dsb_commit);
diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c b/drivers/gpu/drm/i915/display/intel_dsb.c
index dee44d45b668..6b3a4d25a6c6 100644
--- a/drivers/gpu/drm/i915/display/intel_dsb.c
+++ b/drivers/gpu/drm/i915/display/intel_dsb.c
@@ -1026,3 +1026,19 @@ void intel_dsb_irq_handler(struct intel_display *display,
drm_err(display->drm, "[CRTC:%d:%s] DSB %d GOSUB programming error\n",
crtc->base.base.id, crtc->base.name, dsb_id);
}
+
+void intel_dsb_wait_for_delayed_vblank(struct intel_atomic_state *state,
+ struct intel_dsb *dsb)
+{
+ const struct intel_crtc_state *crtc_state;
+ struct intel_crtc *crtc = dsb->crtc;
+ int start, end;
+
+ crtc_state = intel_pre_commit_crtc_state(state, crtc);
+ start = intel_vrr_vmin_vblank_start(crtc_state);
+ end = crtc_state->vrr.enable ?
+ intel_vrr_vmax_vtotal(crtc_state) :
+ intel_vrr_vmin_vtotal(crtc_state);
+
+ intel_dsb_wait_scanline_in(state, dsb, start, end);
+}
diff --git a/drivers/gpu/drm/i915/display/intel_dsb.h b/drivers/gpu/drm/i915/display/intel_dsb.h
index c8f4499916eb..6eb810aad18f 100644
--- a/drivers/gpu/drm/i915/display/intel_dsb.h
+++ b/drivers/gpu/drm/i915/display/intel_dsb.h
@@ -74,4 +74,7 @@ void intel_dsb_wait(struct intel_dsb *dsb);
void intel_dsb_irq_handler(struct intel_display *display,
enum pipe pipe, enum intel_dsb_id dsb_id);
+void intel_dsb_wait_for_delayed_vblank(struct intel_atomic_state *state,
+ struct intel_dsb *dsb);
+
#endif
--
2.45.2
^ permalink raw reply related [flat|nested] 22+ messages in thread* RE: [PATCH 11/14] drm/i915/dsb: Align flipdone with delayed vblank using guardband wait
2025-09-07 7:32 ` [PATCH 11/14] drm/i915/dsb: Align flipdone with delayed vblank using guardband wait Ankit Nautiyal
@ 2025-09-08 8:05 ` Shankar, Uma
0 siblings, 0 replies; 22+ messages in thread
From: Shankar, Uma @ 2025-09-08 8:05 UTC (permalink / raw)
To: Nautiyal, Ankit K, intel-gfx@lists.freedesktop.org,
intel-xe@lists.freedesktop.org
Cc: ville.syrjala@linux.intel.com, Nautiyal, Ankit K
> -----Original Message-----
> From: Intel-xe <intel-xe-bounces@lists.freedesktop.org> On Behalf Of Ankit
> Nautiyal
> Sent: Sunday, September 7, 2025 1:03 PM
> To: intel-gfx@lists.freedesktop.org; intel-xe@lists.freedesktop.org
> Cc: ville.syrjala@linux.intel.com; Nautiyal, Ankit K <ankit.k.nautiyal@intel.com>
> Subject: [PATCH 11/14] drm/i915/dsb: Align flipdone with delayed vblank using
> guardband wait
>
> Currently the guardband is same as vblank length and undelayed vblank and the
> vblank and the flipdone with dsb interrupt are already aligned for the fixed refresh
> rate case.
>
> As we move towards a shorter optimized guardband we need to wait for the
> delayed vblank before the DSB interrupt to align the flipdone event with the
> delayed vblank.
>
> Introduce a helper intel_dsb_wait_for_delayed_vblank() to wait for the scanline
> range [delayed_vblank_start, vmin/vmax vtotal], depending on whether fixed
> refresh rate mode or variable refresh rate mode is active, before triggering the
> DSB interrupt.
>
> Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
> ---
> drivers/gpu/drm/i915/display/intel_display.c | 1 +
> drivers/gpu/drm/i915/display/intel_dsb.c | 16 ++++++++++++++++
> drivers/gpu/drm/i915/display/intel_dsb.h | 3 +++
> 3 files changed, 20 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c
> b/drivers/gpu/drm/i915/display/intel_display.c
> index 787bb6ebdc75..fb072275b1c7 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -7447,6 +7447,7 @@ static void intel_atomic_dsb_finish(struct
> intel_atomic_state *state,
>
> intel_vrr_send_push(new_crtc_state->dsb_commit,
> new_crtc_state);
> intel_dsb_wait_vblank_delay(state, new_crtc_state-
> >dsb_commit);
> + intel_dsb_wait_for_delayed_vblank(state, new_crtc_state-
> >dsb_commit);
> intel_vrr_check_push_sent(new_crtc_state->dsb_commit,
> new_crtc_state);
> intel_dsb_interrupt(new_crtc_state->dsb_commit);
> diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c
> b/drivers/gpu/drm/i915/display/intel_dsb.c
> index dee44d45b668..6b3a4d25a6c6 100644
> --- a/drivers/gpu/drm/i915/display/intel_dsb.c
> +++ b/drivers/gpu/drm/i915/display/intel_dsb.c
> @@ -1026,3 +1026,19 @@ void intel_dsb_irq_handler(struct intel_display
> *display,
> drm_err(display->drm, "[CRTC:%d:%s] DSB %d GOSUB
> programming error\n",
> crtc->base.base.id, crtc->base.name, dsb_id); }
> +
> +void intel_dsb_wait_for_delayed_vblank(struct intel_atomic_state *state,
> + struct intel_dsb *dsb)
> +{
> + const struct intel_crtc_state *crtc_state;
> + struct intel_crtc *crtc = dsb->crtc;
> + int start, end;
> +
> + crtc_state = intel_pre_commit_crtc_state(state, crtc);
> + start = intel_vrr_vmin_vblank_start(crtc_state);
> + end = crtc_state->vrr.enable ?
> + intel_vrr_vmax_vtotal(crtc_state) :
> + intel_vrr_vmin_vtotal(crtc_state);
Add comment explaining the reasoning more clearly here, why its different between VRR vs Fixed RR.
Also add a "Fixed Me" and fix it cleanly as separate patch with "intel_dsb_wait_vblank_delay".
With above addressed,
Reviewed-by: Uma Shankar <uma.shankar@intel.com>
> +
> + intel_dsb_wait_scanline_in(state, dsb, start, end); }
> diff --git a/drivers/gpu/drm/i915/display/intel_dsb.h
> b/drivers/gpu/drm/i915/display/intel_dsb.h
> index c8f4499916eb..6eb810aad18f 100644
> --- a/drivers/gpu/drm/i915/display/intel_dsb.h
> +++ b/drivers/gpu/drm/i915/display/intel_dsb.h
> @@ -74,4 +74,7 @@ void intel_dsb_wait(struct intel_dsb *dsb); void
> intel_dsb_irq_handler(struct intel_display *display,
> enum pipe pipe, enum intel_dsb_id dsb_id);
>
> +void intel_dsb_wait_for_delayed_vblank(struct intel_atomic_state *state,
> + struct intel_dsb *dsb);
> +
> #endif
> --
> 2.45.2
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH 12/14] drm/i915/vrr: Use static guardband to support seamless LRR switching
2025-09-07 7:32 [PATCH 00/14] Optimize vrr.guardband and fix LRR Ankit Nautiyal
` (10 preceding siblings ...)
2025-09-07 7:32 ` [PATCH 11/14] drm/i915/dsb: Align flipdone with delayed vblank using guardband wait Ankit Nautiyal
@ 2025-09-07 7:32 ` Ankit Nautiyal
2025-09-08 16:43 ` Ville Syrjälä
2025-09-07 7:32 ` [PATCH 13/14] drm/i915/panel: Refactor helper to get highest fixed mode Ankit Nautiyal
` (2 subsequent siblings)
14 siblings, 1 reply; 22+ messages in thread
From: Ankit Nautiyal @ 2025-09-07 7:32 UTC (permalink / raw)
To: intel-gfx, intel-xe; +Cc: ville.syrjala, Ankit Nautiyal, Mitul Golani
In the current VRR implementation, vrr.vmin and vrr.guardband are set such
that they do not need to change when switching from fixed refresh rate to
variable refresh rate. Specifically, vrr.guardband is always set to match
the vblank length. This approach works for most cases, but not for LRR,
where the guardband would need to change while the VRR timing generator is
still active.
With the VRR TG always active, live updates to guardband are unsafe and not
recommended. To ensure hardware safety, guardband was moved out of the
!fastset block, meaning any change now requires a full modeset.
This breaks seamless LRR switching, which was previously supported.
Since the problem arises from guardband being matched to the vblank length,
solution is to use a minimal, sufficient static value, instead. So we use a
static guardband defined during mode-set that fits within the smallest
expected vblank and remains unchanged in case of features like LRR where
vtotal changes. To compute this minimum guardband we take into account
latencies/delays due to different features as mentioned in the Bspec.
v2:
-Use helpers for dsc/scaler prefill latencies. (Mitul)
-Account for pkgc latency and take max of pkgc and sagv latencies.
v3: Use new helper for PSR2/Panel Replay latency.
v4: Avoid re-setting the Vmin/Flipline for optimized guardband.
Bspec: 70151
Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
Reviewed-by: Mitul Golani <mitulkumar.ajitkumar.golani@intel.com> (#v3)
---
drivers/gpu/drm/i915/display/intel_display.c | 2 +-
drivers/gpu/drm/i915/display/intel_vrr.c | 127 ++++++++++++++++++-
drivers/gpu/drm/i915/display/intel_vrr.h | 3 +-
3 files changed, 128 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index fb072275b1c7..3fa94675d5e1 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -4902,7 +4902,6 @@ intel_modeset_pipe_config_late(struct intel_atomic_state *state,
struct drm_connector *connector;
int i;
- intel_vrr_compute_config_late(crtc_state);
for_each_new_connector_in_state(&state->base, connector,
conn_state, i) {
@@ -4914,6 +4913,7 @@ intel_modeset_pipe_config_late(struct intel_atomic_state *state,
!encoder->compute_config_late)
continue;
+ intel_vrr_compute_config_late(crtc_state, conn_state);
ret = encoder->compute_config_late(encoder, crtc_state,
conn_state);
if (ret)
diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c
index 855974174afd..fff684eb2514 100644
--- a/drivers/gpu/drm/i915/display/intel_vrr.c
+++ b/drivers/gpu/drm/i915/display/intel_vrr.c
@@ -6,12 +6,15 @@
#include <drm/drm_print.h>
+#include "intel_alpm.h"
#include "intel_de.h"
#include "intel_display_regs.h"
#include "intel_display_types.h"
#include "intel_dp.h"
#include "intel_vrr.h"
#include "intel_vrr_regs.h"
+#include "skl_scaler.h"
+#include "skl_watermark.h"
#define FIXED_POINT_PRECISION 100
#define CMRR_PRECISION_TOLERANCE 10
@@ -413,15 +416,135 @@ intel_vrr_compute_config(struct intel_crtc_state *crtc_state,
}
}
-void intel_vrr_compute_config_late(struct intel_crtc_state *crtc_state)
+static
+int scaler_prefill_latency(struct intel_crtc_state *crtc_state, int linetime_us)
+{
+ int chroma_downscaling_factor = skl_scaler_chroma_downscale_factor(crtc_state);
+ u64 hscale_k, vscale_k;
+ int cdclk_adjustment;
+ int num_scaler_users;
+
+ /*
+ * Assuming:
+ * Both scaler enabled.
+ * scaler 1 downscaling factor as 2 x 2 (Horiz x Vert)
+ * scaler 2 downscaling factor as 2 x 1 (Horiz x Vert)
+ * Cdclk Adjustment : 1
+ */
+ num_scaler_users = 2;
+ hscale_k = 2 * 1000;
+ vscale_k = 2 * 1000;
+ cdclk_adjustment = 1;
+
+ return intel_vrr_guardband_scaler_latency(num_scaler_users, hscale_k, vscale_k,
+ chroma_downscaling_factor,
+ cdclk_adjustment,
+ linetime_us);
+}
+
+static
+int dsc_prefill_latency(struct intel_crtc_state *crtc_state, int linetime_us)
+{
+#define MAX_SCALERS 2
+ int chroma_downscaling_factor = skl_scaler_chroma_downscale_factor(crtc_state);
+ u64 hscale_k[MAX_SCALERS], vscale_k[MAX_SCALERS];
+ int cdclk_adjustment;
+ int num_scaler_users;
+
+ /*
+ * Assuming:
+ * Both scaler enabled.
+ * scaler 1 downscaling factor as 2 x 2 (Horiz x Vert)
+ * scaler 2 downscaling factor as 2 x 1 (Horiz x Vert)
+ * Cdclk Adjustment : 1
+ */
+ num_scaler_users = MAX_SCALERS;
+ hscale_k[0] = 2 * 1000;
+ vscale_k[0] = 2 * 1000;
+ hscale_k[1] = 2 * 1000;
+ vscale_k[1] = 1 * 1000;
+
+ cdclk_adjustment = 1;
+
+ return intel_vrr_guardband_dsc_latency(num_scaler_users, hscale_k, vscale_k,
+ chroma_downscaling_factor,
+ cdclk_adjustment,
+ linetime_us);
+}
+
+static
+int intel_vrr_compute_guardband(struct intel_crtc_state *crtc_state,
+ struct intel_connector *connector)
+{
+ const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
+ struct intel_display *display = to_intel_display(crtc_state);
+ int dsc_prefill_time = 0;
+ int psr2_pr_latency = 0;
+ int scaler_prefill_time;
+ int wm0_prefill_time;
+ int pkgc_max_latency;
+ int sagv_latency;
+ int sdp_latency = 0;
+ int guardband_us;
+ int linetime_us;
+ int guardband;
+ int pm_delay;
+
+ linetime_us = DIV_ROUND_UP(adjusted_mode->crtc_htotal * 1000,
+ adjusted_mode->crtc_clock);
+
+ pkgc_max_latency = skl_watermark_max_latency(display, 1);
+ sagv_latency = display->sagv.block_time_us;
+
+ /* Assuming max wm0 lines = 4 */
+ wm0_prefill_time = 4 * linetime_us + 20;
+
+ scaler_prefill_time = scaler_prefill_latency(crtc_state, linetime_us);
+
+ if (crtc_state->dsc.compression_enable)
+ dsc_prefill_time = dsc_prefill_latency(crtc_state, linetime_us);
+
+ pm_delay = crtc_state->framestart_delay +
+ max(sagv_latency, pkgc_max_latency) +
+ wm0_prefill_time +
+ scaler_prefill_time +
+ dsc_prefill_time;
+
+ switch (connector->base.connector_type) {
+ case DRM_MODE_CONNECTOR_eDP:
+ case DRM_MODE_CONNECTOR_DisplayPort:
+ psr2_pr_latency = intel_alpm_compute_max_link_wake_latency(crtc_state, true);
+ sdp_latency = intel_dp_compute_sdp_latency(crtc_state, true);
+ break;
+ default:
+ break;
+ }
+
+ guardband_us = max(sdp_latency, psr2_pr_latency);
+ guardband_us = max(guardband_us, pm_delay);
+
+ guardband = DIV_ROUND_UP(guardband_us, linetime_us);
+
+ /* guardband cannot be more than the Vmax vblank */
+ guardband = min(guardband, crtc_state->vrr.vmax - adjusted_mode->crtc_vblank_start);
+
+ return guardband;
+}
+
+void intel_vrr_compute_config_late(struct intel_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state)
{
struct intel_display *display = to_intel_display(crtc_state);
const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
+ struct intel_connector *connector =
+ to_intel_connector(conn_state->connector);
if (!intel_vrr_possible(crtc_state))
return;
- if (DISPLAY_VER(display) >= 13) {
+ if (intel_vrr_always_use_vrr_tg(display)) {
+ crtc_state->vrr.guardband = intel_vrr_compute_guardband(crtc_state, connector);
+ } else if (DISPLAY_VER(display) >= 13) {
crtc_state->vrr.guardband =
crtc_state->vrr.vmin - adjusted_mode->crtc_vblank_start;
} else {
diff --git a/drivers/gpu/drm/i915/display/intel_vrr.h b/drivers/gpu/drm/i915/display/intel_vrr.h
index 950041647e47..362638fd0d66 100644
--- a/drivers/gpu/drm/i915/display/intel_vrr.h
+++ b/drivers/gpu/drm/i915/display/intel_vrr.h
@@ -21,7 +21,8 @@ bool intel_vrr_possible(const struct intel_crtc_state *crtc_state);
void intel_vrr_check_modeset(struct intel_atomic_state *state);
void intel_vrr_compute_config(struct intel_crtc_state *crtc_state,
struct drm_connector_state *conn_state);
-void intel_vrr_compute_config_late(struct intel_crtc_state *crtc_state);
+void intel_vrr_compute_config_late(struct intel_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state);
void intel_vrr_set_transcoder_timings(const struct intel_crtc_state *crtc_state);
void intel_vrr_enable(const struct intel_crtc_state *crtc_state);
void intel_vrr_send_push(struct intel_dsb *dsb,
--
2.45.2
^ permalink raw reply related [flat|nested] 22+ messages in thread* Re: [PATCH 12/14] drm/i915/vrr: Use static guardband to support seamless LRR switching
2025-09-07 7:32 ` [PATCH 12/14] drm/i915/vrr: Use static guardband to support seamless LRR switching Ankit Nautiyal
@ 2025-09-08 16:43 ` Ville Syrjälä
2025-09-09 15:02 ` Nautiyal, Ankit K
0 siblings, 1 reply; 22+ messages in thread
From: Ville Syrjälä @ 2025-09-08 16:43 UTC (permalink / raw)
To: Ankit Nautiyal; +Cc: intel-gfx, intel-xe, Mitul Golani
On Sun, Sep 07, 2025 at 01:02:39PM +0530, Ankit Nautiyal wrote:
> In the current VRR implementation, vrr.vmin and vrr.guardband are set such
> that they do not need to change when switching from fixed refresh rate to
> variable refresh rate. Specifically, vrr.guardband is always set to match
> the vblank length. This approach works for most cases, but not for LRR,
> where the guardband would need to change while the VRR timing generator is
> still active.
>
> With the VRR TG always active, live updates to guardband are unsafe and not
> recommended. To ensure hardware safety, guardband was moved out of the
> !fastset block, meaning any change now requires a full modeset.
> This breaks seamless LRR switching, which was previously supported.
>
> Since the problem arises from guardband being matched to the vblank length,
> solution is to use a minimal, sufficient static value, instead. So we use a
> static guardband defined during mode-set that fits within the smallest
> expected vblank and remains unchanged in case of features like LRR where
> vtotal changes. To compute this minimum guardband we take into account
> latencies/delays due to different features as mentioned in the Bspec.
>
> v2:
> -Use helpers for dsc/scaler prefill latencies. (Mitul)
> -Account for pkgc latency and take max of pkgc and sagv latencies.
> v3: Use new helper for PSR2/Panel Replay latency.
> v4: Avoid re-setting the Vmin/Flipline for optimized guardband.
>
> Bspec: 70151
> Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
> Reviewed-by: Mitul Golani <mitulkumar.ajitkumar.golani@intel.com> (#v3)
> ---
> drivers/gpu/drm/i915/display/intel_display.c | 2 +-
> drivers/gpu/drm/i915/display/intel_vrr.c | 127 ++++++++++++++++++-
> drivers/gpu/drm/i915/display/intel_vrr.h | 3 +-
> 3 files changed, 128 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> index fb072275b1c7..3fa94675d5e1 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -4902,7 +4902,6 @@ intel_modeset_pipe_config_late(struct intel_atomic_state *state,
> struct drm_connector *connector;
> int i;
>
> - intel_vrr_compute_config_late(crtc_state);
>
> for_each_new_connector_in_state(&state->base, connector,
> conn_state, i) {
> @@ -4914,6 +4913,7 @@ intel_modeset_pipe_config_late(struct intel_atomic_state *state,
> !encoder->compute_config_late)
> continue;
>
> + intel_vrr_compute_config_late(crtc_state, conn_state);
> ret = encoder->compute_config_late(encoder, crtc_state,
> conn_state);
> if (ret)
> diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c
> index 855974174afd..fff684eb2514 100644
> --- a/drivers/gpu/drm/i915/display/intel_vrr.c
> +++ b/drivers/gpu/drm/i915/display/intel_vrr.c
> @@ -6,12 +6,15 @@
>
> #include <drm/drm_print.h>
>
> +#include "intel_alpm.h"
> #include "intel_de.h"
> #include "intel_display_regs.h"
> #include "intel_display_types.h"
> #include "intel_dp.h"
> #include "intel_vrr.h"
> #include "intel_vrr_regs.h"
> +#include "skl_scaler.h"
> +#include "skl_watermark.h"
>
> #define FIXED_POINT_PRECISION 100
> #define CMRR_PRECISION_TOLERANCE 10
> @@ -413,15 +416,135 @@ intel_vrr_compute_config(struct intel_crtc_state *crtc_state,
> }
> }
>
> -void intel_vrr_compute_config_late(struct intel_crtc_state *crtc_state)
> +static
> +int scaler_prefill_latency(struct intel_crtc_state *crtc_state, int linetime_us)
> +{
> + int chroma_downscaling_factor = skl_scaler_chroma_downscale_factor(crtc_state);
> + u64 hscale_k, vscale_k;
> + int cdclk_adjustment;
> + int num_scaler_users;
> +
> + /*
> + * Assuming:
> + * Both scaler enabled.
> + * scaler 1 downscaling factor as 2 x 2 (Horiz x Vert)
> + * scaler 2 downscaling factor as 2 x 1 (Horiz x Vert)
> + * Cdclk Adjustment : 1
> + */
> + num_scaler_users = 2;
> + hscale_k = 2 * 1000;
> + vscale_k = 2 * 1000;
> + cdclk_adjustment = 1;
> +
> + return intel_vrr_guardband_scaler_latency(num_scaler_users, hscale_k, vscale_k,
> + chroma_downscaling_factor,
> + cdclk_adjustment,
> + linetime_us);
> +}
> +
> +static
> +int dsc_prefill_latency(struct intel_crtc_state *crtc_state, int linetime_us)
> +{
> +#define MAX_SCALERS 2
> + int chroma_downscaling_factor = skl_scaler_chroma_downscale_factor(crtc_state);
> + u64 hscale_k[MAX_SCALERS], vscale_k[MAX_SCALERS];
> + int cdclk_adjustment;
> + int num_scaler_users;
> +
> + /*
> + * Assuming:
> + * Both scaler enabled.
> + * scaler 1 downscaling factor as 2 x 2 (Horiz x Vert)
> + * scaler 2 downscaling factor as 2 x 1 (Horiz x Vert)
> + * Cdclk Adjustment : 1
> + */
> + num_scaler_users = MAX_SCALERS;
> + hscale_k[0] = 2 * 1000;
> + vscale_k[0] = 2 * 1000;
> + hscale_k[1] = 2 * 1000;
> + vscale_k[1] = 1 * 1000;
> +
> + cdclk_adjustment = 1;
> +
> + return intel_vrr_guardband_dsc_latency(num_scaler_users, hscale_k, vscale_k,
> + chroma_downscaling_factor,
> + cdclk_adjustment,
> + linetime_us);
> +}
> +
> +static
> +int intel_vrr_compute_guardband(struct intel_crtc_state *crtc_state,
> + struct intel_connector *connector)
> +{
> + const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
> + struct intel_display *display = to_intel_display(crtc_state);
> + int dsc_prefill_time = 0;
> + int psr2_pr_latency = 0;
> + int scaler_prefill_time;
> + int wm0_prefill_time;
> + int pkgc_max_latency;
> + int sagv_latency;
> + int sdp_latency = 0;
> + int guardband_us;
> + int linetime_us;
> + int guardband;
> + int pm_delay;
> +
> + linetime_us = DIV_ROUND_UP(adjusted_mode->crtc_htotal * 1000,
> + adjusted_mode->crtc_clock);
> +
> + pkgc_max_latency = skl_watermark_max_latency(display, 1);
> + sagv_latency = display->sagv.block_time_us;
> +
> + /* Assuming max wm0 lines = 4 */
> + wm0_prefill_time = 4 * linetime_us + 20;
> +
> + scaler_prefill_time = scaler_prefill_latency(crtc_state, linetime_us);
> +
> + if (crtc_state->dsc.compression_enable)
> + dsc_prefill_time = dsc_prefill_latency(crtc_state, linetime_us);
> +
> + pm_delay = crtc_state->framestart_delay +
> + max(sagv_latency, pkgc_max_latency) +
> + wm0_prefill_time +
> + scaler_prefill_time +
> + dsc_prefill_time;
> +
> + switch (connector->base.connector_type) {
> + case DRM_MODE_CONNECTOR_eDP:
> + case DRM_MODE_CONNECTOR_DisplayPort:
> + psr2_pr_latency = intel_alpm_compute_max_link_wake_latency(crtc_state, true);
> + sdp_latency = intel_dp_compute_sdp_latency(crtc_state, true);
> + break;
> + default:
> + break;
> + }
> +
> + guardband_us = max(sdp_latency, psr2_pr_latency);
> + guardband_us = max(guardband_us, pm_delay);
> +
> + guardband = DIV_ROUND_UP(guardband_us, linetime_us);
> +
> + /* guardband cannot be more than the Vmax vblank */
> + guardband = min(guardband, crtc_state->vrr.vmax - adjusted_mode->crtc_vblank_start);
> +
> + return guardband;
> +}
> +
> +void intel_vrr_compute_config_late(struct intel_crtc_state *crtc_state,
> + struct drm_connector_state *conn_state)
> {
> struct intel_display *display = to_intel_display(crtc_state);
> const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
> + struct intel_connector *connector =
> + to_intel_connector(conn_state->connector);
>
> if (!intel_vrr_possible(crtc_state))
> return;
>
> - if (DISPLAY_VER(display) >= 13) {
> + if (intel_vrr_always_use_vrr_tg(display)) {
> + crtc_state->vrr.guardband = intel_vrr_compute_guardband(crtc_state, connector);
This all looks to be in the wrong place. It needs to be done as part of
intel_crtc_compute_vblank_delay() which then updates crtc_vblank_start
to reflect reality instead of leaving some incorrect junk in there.
Presumably that is why you also had to do that
intel_dsb_wait_for_delayed_vblank() hack.
> + } else if (DISPLAY_VER(display) >= 13) {
> crtc_state->vrr.guardband =
> crtc_state->vrr.vmin - adjusted_mode->crtc_vblank_start;
> } else {
> diff --git a/drivers/gpu/drm/i915/display/intel_vrr.h b/drivers/gpu/drm/i915/display/intel_vrr.h
> index 950041647e47..362638fd0d66 100644
> --- a/drivers/gpu/drm/i915/display/intel_vrr.h
> +++ b/drivers/gpu/drm/i915/display/intel_vrr.h
> @@ -21,7 +21,8 @@ bool intel_vrr_possible(const struct intel_crtc_state *crtc_state);
> void intel_vrr_check_modeset(struct intel_atomic_state *state);
> void intel_vrr_compute_config(struct intel_crtc_state *crtc_state,
> struct drm_connector_state *conn_state);
> -void intel_vrr_compute_config_late(struct intel_crtc_state *crtc_state);
> +void intel_vrr_compute_config_late(struct intel_crtc_state *crtc_state,
> + struct drm_connector_state *conn_state);
> void intel_vrr_set_transcoder_timings(const struct intel_crtc_state *crtc_state);
> void intel_vrr_enable(const struct intel_crtc_state *crtc_state);
> void intel_vrr_send_push(struct intel_dsb *dsb,
> --
> 2.45.2
--
Ville Syrjälä
Intel
^ permalink raw reply [flat|nested] 22+ messages in thread* Re: [PATCH 12/14] drm/i915/vrr: Use static guardband to support seamless LRR switching
2025-09-08 16:43 ` Ville Syrjälä
@ 2025-09-09 15:02 ` Nautiyal, Ankit K
2025-09-10 12:30 ` Ville Syrjälä
0 siblings, 1 reply; 22+ messages in thread
From: Nautiyal, Ankit K @ 2025-09-09 15:02 UTC (permalink / raw)
To: Ville Syrjälä; +Cc: intel-gfx, intel-xe, Mitul Golani
On 9/8/2025 10:13 PM, Ville Syrjälä wrote:
> On Sun, Sep 07, 2025 at 01:02:39PM +0530, Ankit Nautiyal wrote:
>> In the current VRR implementation, vrr.vmin and vrr.guardband are set such
>> that they do not need to change when switching from fixed refresh rate to
>> variable refresh rate. Specifically, vrr.guardband is always set to match
>> the vblank length. This approach works for most cases, but not for LRR,
>> where the guardband would need to change while the VRR timing generator is
>> still active.
>>
>> With the VRR TG always active, live updates to guardband are unsafe and not
>> recommended. To ensure hardware safety, guardband was moved out of the
>> !fastset block, meaning any change now requires a full modeset.
>> This breaks seamless LRR switching, which was previously supported.
>>
>> Since the problem arises from guardband being matched to the vblank length,
>> solution is to use a minimal, sufficient static value, instead. So we use a
>> static guardband defined during mode-set that fits within the smallest
>> expected vblank and remains unchanged in case of features like LRR where
>> vtotal changes. To compute this minimum guardband we take into account
>> latencies/delays due to different features as mentioned in the Bspec.
>>
>> v2:
>> -Use helpers for dsc/scaler prefill latencies. (Mitul)
>> -Account for pkgc latency and take max of pkgc and sagv latencies.
>> v3: Use new helper for PSR2/Panel Replay latency.
>> v4: Avoid re-setting the Vmin/Flipline for optimized guardband.
>>
>> Bspec: 70151
>> Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
>> Reviewed-by: Mitul Golani <mitulkumar.ajitkumar.golani@intel.com> (#v3)
>> ---
>> drivers/gpu/drm/i915/display/intel_display.c | 2 +-
>> drivers/gpu/drm/i915/display/intel_vrr.c | 127 ++++++++++++++++++-
>> drivers/gpu/drm/i915/display/intel_vrr.h | 3 +-
>> 3 files changed, 128 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
>> index fb072275b1c7..3fa94675d5e1 100644
>> --- a/drivers/gpu/drm/i915/display/intel_display.c
>> +++ b/drivers/gpu/drm/i915/display/intel_display.c
>> @@ -4902,7 +4902,6 @@ intel_modeset_pipe_config_late(struct intel_atomic_state *state,
>> struct drm_connector *connector;
>> int i;
>>
>> - intel_vrr_compute_config_late(crtc_state);
>>
>> for_each_new_connector_in_state(&state->base, connector,
>> conn_state, i) {
>> @@ -4914,6 +4913,7 @@ intel_modeset_pipe_config_late(struct intel_atomic_state *state,
>> !encoder->compute_config_late)
>> continue;
>>
>> + intel_vrr_compute_config_late(crtc_state, conn_state);
>> ret = encoder->compute_config_late(encoder, crtc_state,
>> conn_state);
>> if (ret)
>> diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c
>> index 855974174afd..fff684eb2514 100644
>> --- a/drivers/gpu/drm/i915/display/intel_vrr.c
>> +++ b/drivers/gpu/drm/i915/display/intel_vrr.c
>> @@ -6,12 +6,15 @@
>>
>> #include <drm/drm_print.h>
>>
>> +#include "intel_alpm.h"
>> #include "intel_de.h"
>> #include "intel_display_regs.h"
>> #include "intel_display_types.h"
>> #include "intel_dp.h"
>> #include "intel_vrr.h"
>> #include "intel_vrr_regs.h"
>> +#include "skl_scaler.h"
>> +#include "skl_watermark.h"
>>
>> #define FIXED_POINT_PRECISION 100
>> #define CMRR_PRECISION_TOLERANCE 10
>> @@ -413,15 +416,135 @@ intel_vrr_compute_config(struct intel_crtc_state *crtc_state,
>> }
>> }
>>
>> -void intel_vrr_compute_config_late(struct intel_crtc_state *crtc_state)
>> +static
>> +int scaler_prefill_latency(struct intel_crtc_state *crtc_state, int linetime_us)
>> +{
>> + int chroma_downscaling_factor = skl_scaler_chroma_downscale_factor(crtc_state);
>> + u64 hscale_k, vscale_k;
>> + int cdclk_adjustment;
>> + int num_scaler_users;
>> +
>> + /*
>> + * Assuming:
>> + * Both scaler enabled.
>> + * scaler 1 downscaling factor as 2 x 2 (Horiz x Vert)
>> + * scaler 2 downscaling factor as 2 x 1 (Horiz x Vert)
>> + * Cdclk Adjustment : 1
>> + */
>> + num_scaler_users = 2;
>> + hscale_k = 2 * 1000;
>> + vscale_k = 2 * 1000;
>> + cdclk_adjustment = 1;
>> +
>> + return intel_vrr_guardband_scaler_latency(num_scaler_users, hscale_k, vscale_k,
>> + chroma_downscaling_factor,
>> + cdclk_adjustment,
>> + linetime_us);
>> +}
>> +
>> +static
>> +int dsc_prefill_latency(struct intel_crtc_state *crtc_state, int linetime_us)
>> +{
>> +#define MAX_SCALERS 2
>> + int chroma_downscaling_factor = skl_scaler_chroma_downscale_factor(crtc_state);
>> + u64 hscale_k[MAX_SCALERS], vscale_k[MAX_SCALERS];
>> + int cdclk_adjustment;
>> + int num_scaler_users;
>> +
>> + /*
>> + * Assuming:
>> + * Both scaler enabled.
>> + * scaler 1 downscaling factor as 2 x 2 (Horiz x Vert)
>> + * scaler 2 downscaling factor as 2 x 1 (Horiz x Vert)
>> + * Cdclk Adjustment : 1
>> + */
>> + num_scaler_users = MAX_SCALERS;
>> + hscale_k[0] = 2 * 1000;
>> + vscale_k[0] = 2 * 1000;
>> + hscale_k[1] = 2 * 1000;
>> + vscale_k[1] = 1 * 1000;
>> +
>> + cdclk_adjustment = 1;
>> +
>> + return intel_vrr_guardband_dsc_latency(num_scaler_users, hscale_k, vscale_k,
>> + chroma_downscaling_factor,
>> + cdclk_adjustment,
>> + linetime_us);
>> +}
>> +
>> +static
>> +int intel_vrr_compute_guardband(struct intel_crtc_state *crtc_state,
>> + struct intel_connector *connector)
>> +{
>> + const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
>> + struct intel_display *display = to_intel_display(crtc_state);
>> + int dsc_prefill_time = 0;
>> + int psr2_pr_latency = 0;
>> + int scaler_prefill_time;
>> + int wm0_prefill_time;
>> + int pkgc_max_latency;
>> + int sagv_latency;
>> + int sdp_latency = 0;
>> + int guardband_us;
>> + int linetime_us;
>> + int guardband;
>> + int pm_delay;
>> +
>> + linetime_us = DIV_ROUND_UP(adjusted_mode->crtc_htotal * 1000,
>> + adjusted_mode->crtc_clock);
>> +
>> + pkgc_max_latency = skl_watermark_max_latency(display, 1);
>> + sagv_latency = display->sagv.block_time_us;
>> +
>> + /* Assuming max wm0 lines = 4 */
>> + wm0_prefill_time = 4 * linetime_us + 20;
>> +
>> + scaler_prefill_time = scaler_prefill_latency(crtc_state, linetime_us);
>> +
>> + if (crtc_state->dsc.compression_enable)
>> + dsc_prefill_time = dsc_prefill_latency(crtc_state, linetime_us);
>> +
>> + pm_delay = crtc_state->framestart_delay +
>> + max(sagv_latency, pkgc_max_latency) +
>> + wm0_prefill_time +
>> + scaler_prefill_time +
>> + dsc_prefill_time;
>> +
>> + switch (connector->base.connector_type) {
>> + case DRM_MODE_CONNECTOR_eDP:
>> + case DRM_MODE_CONNECTOR_DisplayPort:
>> + psr2_pr_latency = intel_alpm_compute_max_link_wake_latency(crtc_state, true);
>> + sdp_latency = intel_dp_compute_sdp_latency(crtc_state, true);
>> + break;
>> + default:
>> + break;
>> + }
>> +
>> + guardband_us = max(sdp_latency, psr2_pr_latency);
>> + guardband_us = max(guardband_us, pm_delay);
>> +
>> + guardband = DIV_ROUND_UP(guardband_us, linetime_us);
>> +
>> + /* guardband cannot be more than the Vmax vblank */
>> + guardband = min(guardband, crtc_state->vrr.vmax - adjusted_mode->crtc_vblank_start);
>> +
>> + return guardband;
>> +}
>> +
>> +void intel_vrr_compute_config_late(struct intel_crtc_state *crtc_state,
>> + struct drm_connector_state *conn_state)
>> {
>> struct intel_display *display = to_intel_display(crtc_state);
>> const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
>> + struct intel_connector *connector =
>> + to_intel_connector(conn_state->connector);
>>
>> if (!intel_vrr_possible(crtc_state))
>> return;
>>
>> - if (DISPLAY_VER(display) >= 13) {
>> + if (intel_vrr_always_use_vrr_tg(display)) {
>> + crtc_state->vrr.guardband = intel_vrr_compute_guardband(crtc_state, connector);
> This all looks to be in the wrong place. It needs to be done as part of
> intel_crtc_compute_vblank_delay() which then updates crtc_vblank_start
> to reflect reality instead of leaving some incorrect junk in there.
> Presumably that is why you also had to do that
> intel_dsb_wait_for_delayed_vblank() hack.
Hi Ville,
Thanks for for the comments.
Looks like intel_crtc_compute_vblank_delay() indeed is the place to add
the vblank_delay and get the crtc_vblank_start point to the delayed vblank.
But I think, there are couple of things need to take care with this change:
1) The SCL currently is derived from crtc_vblank_start - vdisplay, which
is ~1 with guradband = vblank length.
With modified crtc_vblank_start, this will become huge so perhaps we
need to set it to 1?
2) The intel_dsb_wait_vblank_delay() (which inturn uses
intel_vrr_real_vblank_delay() for vrr case) also computes a fixed delay
based on (crtc_vblank_start - vdisplay) lines
Instead of this should we not use intel_dsb_wait_scanline_in() to wait
only till scanline reaches in range [flipline decision boundary, vmax
decision boundary]?
Let me know what you think, I can send a follow-up patch with the
suggested changes.
Regards,
Ankit
>
>> + } else if (DISPLAY_VER(display) >= 13) {
>> crtc_state->vrr.guardband =
>> crtc_state->vrr.vmin - adjusted_mode->crtc_vblank_start;
>> } else {
>> diff --git a/drivers/gpu/drm/i915/display/intel_vrr.h b/drivers/gpu/drm/i915/display/intel_vrr.h
>> index 950041647e47..362638fd0d66 100644
>> --- a/drivers/gpu/drm/i915/display/intel_vrr.h
>> +++ b/drivers/gpu/drm/i915/display/intel_vrr.h
>> @@ -21,7 +21,8 @@ bool intel_vrr_possible(const struct intel_crtc_state *crtc_state);
>> void intel_vrr_check_modeset(struct intel_atomic_state *state);
>> void intel_vrr_compute_config(struct intel_crtc_state *crtc_state,
>> struct drm_connector_state *conn_state);
>> -void intel_vrr_compute_config_late(struct intel_crtc_state *crtc_state);
>> +void intel_vrr_compute_config_late(struct intel_crtc_state *crtc_state,
>> + struct drm_connector_state *conn_state);
>> void intel_vrr_set_transcoder_timings(const struct intel_crtc_state *crtc_state);
>> void intel_vrr_enable(const struct intel_crtc_state *crtc_state);
>> void intel_vrr_send_push(struct intel_dsb *dsb,
>> --
>> 2.45.2
^ permalink raw reply [flat|nested] 22+ messages in thread* Re: [PATCH 12/14] drm/i915/vrr: Use static guardband to support seamless LRR switching
2025-09-09 15:02 ` Nautiyal, Ankit K
@ 2025-09-10 12:30 ` Ville Syrjälä
2025-09-10 13:37 ` Nautiyal, Ankit K
0 siblings, 1 reply; 22+ messages in thread
From: Ville Syrjälä @ 2025-09-10 12:30 UTC (permalink / raw)
To: Nautiyal, Ankit K; +Cc: intel-gfx, intel-xe, Mitul Golani
On Tue, Sep 09, 2025 at 08:32:11PM +0530, Nautiyal, Ankit K wrote:
>
> On 9/8/2025 10:13 PM, Ville Syrjälä wrote:
> > On Sun, Sep 07, 2025 at 01:02:39PM +0530, Ankit Nautiyal wrote:
> >> In the current VRR implementation, vrr.vmin and vrr.guardband are set such
> >> that they do not need to change when switching from fixed refresh rate to
> >> variable refresh rate. Specifically, vrr.guardband is always set to match
> >> the vblank length. This approach works for most cases, but not for LRR,
> >> where the guardband would need to change while the VRR timing generator is
> >> still active.
> >>
> >> With the VRR TG always active, live updates to guardband are unsafe and not
> >> recommended. To ensure hardware safety, guardband was moved out of the
> >> !fastset block, meaning any change now requires a full modeset.
> >> This breaks seamless LRR switching, which was previously supported.
> >>
> >> Since the problem arises from guardband being matched to the vblank length,
> >> solution is to use a minimal, sufficient static value, instead. So we use a
> >> static guardband defined during mode-set that fits within the smallest
> >> expected vblank and remains unchanged in case of features like LRR where
> >> vtotal changes. To compute this minimum guardband we take into account
> >> latencies/delays due to different features as mentioned in the Bspec.
> >>
> >> v2:
> >> -Use helpers for dsc/scaler prefill latencies. (Mitul)
> >> -Account for pkgc latency and take max of pkgc and sagv latencies.
> >> v3: Use new helper for PSR2/Panel Replay latency.
> >> v4: Avoid re-setting the Vmin/Flipline for optimized guardband.
> >>
> >> Bspec: 70151
> >> Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
> >> Reviewed-by: Mitul Golani <mitulkumar.ajitkumar.golani@intel.com> (#v3)
> >> ---
> >> drivers/gpu/drm/i915/display/intel_display.c | 2 +-
> >> drivers/gpu/drm/i915/display/intel_vrr.c | 127 ++++++++++++++++++-
> >> drivers/gpu/drm/i915/display/intel_vrr.h | 3 +-
> >> 3 files changed, 128 insertions(+), 4 deletions(-)
> >>
> >> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> >> index fb072275b1c7..3fa94675d5e1 100644
> >> --- a/drivers/gpu/drm/i915/display/intel_display.c
> >> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> >> @@ -4902,7 +4902,6 @@ intel_modeset_pipe_config_late(struct intel_atomic_state *state,
> >> struct drm_connector *connector;
> >> int i;
> >>
> >> - intel_vrr_compute_config_late(crtc_state);
> >>
> >> for_each_new_connector_in_state(&state->base, connector,
> >> conn_state, i) {
> >> @@ -4914,6 +4913,7 @@ intel_modeset_pipe_config_late(struct intel_atomic_state *state,
> >> !encoder->compute_config_late)
> >> continue;
> >>
> >> + intel_vrr_compute_config_late(crtc_state, conn_state);
> >> ret = encoder->compute_config_late(encoder, crtc_state,
> >> conn_state);
> >> if (ret)
> >> diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c
> >> index 855974174afd..fff684eb2514 100644
> >> --- a/drivers/gpu/drm/i915/display/intel_vrr.c
> >> +++ b/drivers/gpu/drm/i915/display/intel_vrr.c
> >> @@ -6,12 +6,15 @@
> >>
> >> #include <drm/drm_print.h>
> >>
> >> +#include "intel_alpm.h"
> >> #include "intel_de.h"
> >> #include "intel_display_regs.h"
> >> #include "intel_display_types.h"
> >> #include "intel_dp.h"
> >> #include "intel_vrr.h"
> >> #include "intel_vrr_regs.h"
> >> +#include "skl_scaler.h"
> >> +#include "skl_watermark.h"
> >>
> >> #define FIXED_POINT_PRECISION 100
> >> #define CMRR_PRECISION_TOLERANCE 10
> >> @@ -413,15 +416,135 @@ intel_vrr_compute_config(struct intel_crtc_state *crtc_state,
> >> }
> >> }
> >>
> >> -void intel_vrr_compute_config_late(struct intel_crtc_state *crtc_state)
> >> +static
> >> +int scaler_prefill_latency(struct intel_crtc_state *crtc_state, int linetime_us)
> >> +{
> >> + int chroma_downscaling_factor = skl_scaler_chroma_downscale_factor(crtc_state);
> >> + u64 hscale_k, vscale_k;
> >> + int cdclk_adjustment;
> >> + int num_scaler_users;
> >> +
> >> + /*
> >> + * Assuming:
> >> + * Both scaler enabled.
> >> + * scaler 1 downscaling factor as 2 x 2 (Horiz x Vert)
> >> + * scaler 2 downscaling factor as 2 x 1 (Horiz x Vert)
> >> + * Cdclk Adjustment : 1
> >> + */
> >> + num_scaler_users = 2;
> >> + hscale_k = 2 * 1000;
> >> + vscale_k = 2 * 1000;
> >> + cdclk_adjustment = 1;
> >> +
> >> + return intel_vrr_guardband_scaler_latency(num_scaler_users, hscale_k, vscale_k,
> >> + chroma_downscaling_factor,
> >> + cdclk_adjustment,
> >> + linetime_us);
> >> +}
> >> +
> >> +static
> >> +int dsc_prefill_latency(struct intel_crtc_state *crtc_state, int linetime_us)
> >> +{
> >> +#define MAX_SCALERS 2
> >> + int chroma_downscaling_factor = skl_scaler_chroma_downscale_factor(crtc_state);
> >> + u64 hscale_k[MAX_SCALERS], vscale_k[MAX_SCALERS];
> >> + int cdclk_adjustment;
> >> + int num_scaler_users;
> >> +
> >> + /*
> >> + * Assuming:
> >> + * Both scaler enabled.
> >> + * scaler 1 downscaling factor as 2 x 2 (Horiz x Vert)
> >> + * scaler 2 downscaling factor as 2 x 1 (Horiz x Vert)
> >> + * Cdclk Adjustment : 1
> >> + */
> >> + num_scaler_users = MAX_SCALERS;
> >> + hscale_k[0] = 2 * 1000;
> >> + vscale_k[0] = 2 * 1000;
> >> + hscale_k[1] = 2 * 1000;
> >> + vscale_k[1] = 1 * 1000;
> >> +
> >> + cdclk_adjustment = 1;
> >> +
> >> + return intel_vrr_guardband_dsc_latency(num_scaler_users, hscale_k, vscale_k,
> >> + chroma_downscaling_factor,
> >> + cdclk_adjustment,
> >> + linetime_us);
> >> +}
> >> +
> >> +static
> >> +int intel_vrr_compute_guardband(struct intel_crtc_state *crtc_state,
> >> + struct intel_connector *connector)
> >> +{
> >> + const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
> >> + struct intel_display *display = to_intel_display(crtc_state);
> >> + int dsc_prefill_time = 0;
> >> + int psr2_pr_latency = 0;
> >> + int scaler_prefill_time;
> >> + int wm0_prefill_time;
> >> + int pkgc_max_latency;
> >> + int sagv_latency;
> >> + int sdp_latency = 0;
> >> + int guardband_us;
> >> + int linetime_us;
> >> + int guardband;
> >> + int pm_delay;
> >> +
> >> + linetime_us = DIV_ROUND_UP(adjusted_mode->crtc_htotal * 1000,
> >> + adjusted_mode->crtc_clock);
> >> +
> >> + pkgc_max_latency = skl_watermark_max_latency(display, 1);
> >> + sagv_latency = display->sagv.block_time_us;
> >> +
> >> + /* Assuming max wm0 lines = 4 */
> >> + wm0_prefill_time = 4 * linetime_us + 20;
> >> +
> >> + scaler_prefill_time = scaler_prefill_latency(crtc_state, linetime_us);
> >> +
> >> + if (crtc_state->dsc.compression_enable)
> >> + dsc_prefill_time = dsc_prefill_latency(crtc_state, linetime_us);
> >> +
> >> + pm_delay = crtc_state->framestart_delay +
> >> + max(sagv_latency, pkgc_max_latency) +
> >> + wm0_prefill_time +
> >> + scaler_prefill_time +
> >> + dsc_prefill_time;
> >> +
> >> + switch (connector->base.connector_type) {
> >> + case DRM_MODE_CONNECTOR_eDP:
> >> + case DRM_MODE_CONNECTOR_DisplayPort:
> >> + psr2_pr_latency = intel_alpm_compute_max_link_wake_latency(crtc_state, true);
> >> + sdp_latency = intel_dp_compute_sdp_latency(crtc_state, true);
> >> + break;
> >> + default:
> >> + break;
> >> + }
> >> +
> >> + guardband_us = max(sdp_latency, psr2_pr_latency);
> >> + guardband_us = max(guardband_us, pm_delay);
> >> +
> >> + guardband = DIV_ROUND_UP(guardband_us, linetime_us);
> >> +
> >> + /* guardband cannot be more than the Vmax vblank */
> >> + guardband = min(guardband, crtc_state->vrr.vmax - adjusted_mode->crtc_vblank_start);
> >> +
> >> + return guardband;
> >> +}
> >> +
> >> +void intel_vrr_compute_config_late(struct intel_crtc_state *crtc_state,
> >> + struct drm_connector_state *conn_state)
> >> {
> >> struct intel_display *display = to_intel_display(crtc_state);
> >> const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
> >> + struct intel_connector *connector =
> >> + to_intel_connector(conn_state->connector);
> >>
> >> if (!intel_vrr_possible(crtc_state))
> >> return;
> >>
> >> - if (DISPLAY_VER(display) >= 13) {
> >> + if (intel_vrr_always_use_vrr_tg(display)) {
> >> + crtc_state->vrr.guardband = intel_vrr_compute_guardband(crtc_state, connector);
> > This all looks to be in the wrong place. It needs to be done as part of
> > intel_crtc_compute_vblank_delay() which then updates crtc_vblank_start
> > to reflect reality instead of leaving some incorrect junk in there.
> > Presumably that is why you also had to do that
> > intel_dsb_wait_for_delayed_vblank() hack.
>
> Hi Ville,
>
> Thanks for for the comments.
>
> Looks like intel_crtc_compute_vblank_delay() indeed is the place to add
> the vblank_delay and get the crtc_vblank_start point to the delayed vblank.
>
> But I think, there are couple of things need to take care with this change:
> 1) The SCL currently is derived from crtc_vblank_start - vdisplay, which
> is ~1 with guradband = vblank length.
> With modified crtc_vblank_start, this will become huge so perhaps we
> need to set it to 1?
When using the legacy timing generator SCL is what defines the
position of the delayed vblank. So it should be exactly what it is.
I don't quite recall how this stuff works with the VRR timing
generator. I think it might have been that guardband more or less
defines the location of the delayed vblank, and SCL then effectively
defines the start of the safe window. So I think it should stay
exactly the way it is. IIRC there is some way on new platforms to
even move the SCL position into the vertical active, but I haven't
though through what that would actually do for us.
>
> 2) The intel_dsb_wait_vblank_delay() (which inturn uses
> intel_vrr_real_vblank_delay() for vrr case) also computes a fixed delay
> based on (crtc_vblank_start - vdisplay) lines
> Instead of this should we not use intel_dsb_wait_scanline_in() to wait
> only till scanline reaches in range [flipline decision boundary, vmax
> decision boundary]?
You can't use absolute line numbers with VRR since you don't know
when the vblank will be terminated. It has to be all relative.
>
> Let me know what you think, I can send a follow-up patch with the
> suggested changes.
>
> Regards,
> Ankit
>
>
> >
> >> + } else if (DISPLAY_VER(display) >= 13) {
> >> crtc_state->vrr.guardband =
> >> crtc_state->vrr.vmin - adjusted_mode->crtc_vblank_start;
> >> } else {
> >> diff --git a/drivers/gpu/drm/i915/display/intel_vrr.h b/drivers/gpu/drm/i915/display/intel_vrr.h
> >> index 950041647e47..362638fd0d66 100644
> >> --- a/drivers/gpu/drm/i915/display/intel_vrr.h
> >> +++ b/drivers/gpu/drm/i915/display/intel_vrr.h
> >> @@ -21,7 +21,8 @@ bool intel_vrr_possible(const struct intel_crtc_state *crtc_state);
> >> void intel_vrr_check_modeset(struct intel_atomic_state *state);
> >> void intel_vrr_compute_config(struct intel_crtc_state *crtc_state,
> >> struct drm_connector_state *conn_state);
> >> -void intel_vrr_compute_config_late(struct intel_crtc_state *crtc_state);
> >> +void intel_vrr_compute_config_late(struct intel_crtc_state *crtc_state,
> >> + struct drm_connector_state *conn_state);
> >> void intel_vrr_set_transcoder_timings(const struct intel_crtc_state *crtc_state);
> >> void intel_vrr_enable(const struct intel_crtc_state *crtc_state);
> >> void intel_vrr_send_push(struct intel_dsb *dsb,
> >> --
> >> 2.45.2
--
Ville Syrjälä
Intel
^ permalink raw reply [flat|nested] 22+ messages in thread* Re: [PATCH 12/14] drm/i915/vrr: Use static guardband to support seamless LRR switching
2025-09-10 12:30 ` Ville Syrjälä
@ 2025-09-10 13:37 ` Nautiyal, Ankit K
0 siblings, 0 replies; 22+ messages in thread
From: Nautiyal, Ankit K @ 2025-09-10 13:37 UTC (permalink / raw)
To: Ville Syrjälä; +Cc: intel-gfx, intel-xe, Mitul Golani
On 9/10/2025 6:00 PM, Ville Syrjälä wrote:
> On Tue, Sep 09, 2025 at 08:32:11PM +0530, Nautiyal, Ankit K wrote:
>> On 9/8/2025 10:13 PM, Ville Syrjälä wrote:
>>> On Sun, Sep 07, 2025 at 01:02:39PM +0530, Ankit Nautiyal wrote:
>>>> In the current VRR implementation, vrr.vmin and vrr.guardband are set such
>>>> that they do not need to change when switching from fixed refresh rate to
>>>> variable refresh rate. Specifically, vrr.guardband is always set to match
>>>> the vblank length. This approach works for most cases, but not for LRR,
>>>> where the guardband would need to change while the VRR timing generator is
>>>> still active.
>>>>
>>>> With the VRR TG always active, live updates to guardband are unsafe and not
>>>> recommended. To ensure hardware safety, guardband was moved out of the
>>>> !fastset block, meaning any change now requires a full modeset.
>>>> This breaks seamless LRR switching, which was previously supported.
>>>>
>>>> Since the problem arises from guardband being matched to the vblank length,
>>>> solution is to use a minimal, sufficient static value, instead. So we use a
>>>> static guardband defined during mode-set that fits within the smallest
>>>> expected vblank and remains unchanged in case of features like LRR where
>>>> vtotal changes. To compute this minimum guardband we take into account
>>>> latencies/delays due to different features as mentioned in the Bspec.
>>>>
>>>> v2:
>>>> -Use helpers for dsc/scaler prefill latencies. (Mitul)
>>>> -Account for pkgc latency and take max of pkgc and sagv latencies.
>>>> v3: Use new helper for PSR2/Panel Replay latency.
>>>> v4: Avoid re-setting the Vmin/Flipline for optimized guardband.
>>>>
>>>> Bspec: 70151
>>>> Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
>>>> Reviewed-by: Mitul Golani <mitulkumar.ajitkumar.golani@intel.com> (#v3)
>>>> ---
>>>> drivers/gpu/drm/i915/display/intel_display.c | 2 +-
>>>> drivers/gpu/drm/i915/display/intel_vrr.c | 127 ++++++++++++++++++-
>>>> drivers/gpu/drm/i915/display/intel_vrr.h | 3 +-
>>>> 3 files changed, 128 insertions(+), 4 deletions(-)
>>>>
>>>> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
>>>> index fb072275b1c7..3fa94675d5e1 100644
>>>> --- a/drivers/gpu/drm/i915/display/intel_display.c
>>>> +++ b/drivers/gpu/drm/i915/display/intel_display.c
>>>> @@ -4902,7 +4902,6 @@ intel_modeset_pipe_config_late(struct intel_atomic_state *state,
>>>> struct drm_connector *connector;
>>>> int i;
>>>>
>>>> - intel_vrr_compute_config_late(crtc_state);
>>>>
>>>> for_each_new_connector_in_state(&state->base, connector,
>>>> conn_state, i) {
>>>> @@ -4914,6 +4913,7 @@ intel_modeset_pipe_config_late(struct intel_atomic_state *state,
>>>> !encoder->compute_config_late)
>>>> continue;
>>>>
>>>> + intel_vrr_compute_config_late(crtc_state, conn_state);
>>>> ret = encoder->compute_config_late(encoder, crtc_state,
>>>> conn_state);
>>>> if (ret)
>>>> diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c
>>>> index 855974174afd..fff684eb2514 100644
>>>> --- a/drivers/gpu/drm/i915/display/intel_vrr.c
>>>> +++ b/drivers/gpu/drm/i915/display/intel_vrr.c
>>>> @@ -6,12 +6,15 @@
>>>>
>>>> #include <drm/drm_print.h>
>>>>
>>>> +#include "intel_alpm.h"
>>>> #include "intel_de.h"
>>>> #include "intel_display_regs.h"
>>>> #include "intel_display_types.h"
>>>> #include "intel_dp.h"
>>>> #include "intel_vrr.h"
>>>> #include "intel_vrr_regs.h"
>>>> +#include "skl_scaler.h"
>>>> +#include "skl_watermark.h"
>>>>
>>>> #define FIXED_POINT_PRECISION 100
>>>> #define CMRR_PRECISION_TOLERANCE 10
>>>> @@ -413,15 +416,135 @@ intel_vrr_compute_config(struct intel_crtc_state *crtc_state,
>>>> }
>>>> }
>>>>
>>>> -void intel_vrr_compute_config_late(struct intel_crtc_state *crtc_state)
>>>> +static
>>>> +int scaler_prefill_latency(struct intel_crtc_state *crtc_state, int linetime_us)
>>>> +{
>>>> + int chroma_downscaling_factor = skl_scaler_chroma_downscale_factor(crtc_state);
>>>> + u64 hscale_k, vscale_k;
>>>> + int cdclk_adjustment;
>>>> + int num_scaler_users;
>>>> +
>>>> + /*
>>>> + * Assuming:
>>>> + * Both scaler enabled.
>>>> + * scaler 1 downscaling factor as 2 x 2 (Horiz x Vert)
>>>> + * scaler 2 downscaling factor as 2 x 1 (Horiz x Vert)
>>>> + * Cdclk Adjustment : 1
>>>> + */
>>>> + num_scaler_users = 2;
>>>> + hscale_k = 2 * 1000;
>>>> + vscale_k = 2 * 1000;
>>>> + cdclk_adjustment = 1;
>>>> +
>>>> + return intel_vrr_guardband_scaler_latency(num_scaler_users, hscale_k, vscale_k,
>>>> + chroma_downscaling_factor,
>>>> + cdclk_adjustment,
>>>> + linetime_us);
>>>> +}
>>>> +
>>>> +static
>>>> +int dsc_prefill_latency(struct intel_crtc_state *crtc_state, int linetime_us)
>>>> +{
>>>> +#define MAX_SCALERS 2
>>>> + int chroma_downscaling_factor = skl_scaler_chroma_downscale_factor(crtc_state);
>>>> + u64 hscale_k[MAX_SCALERS], vscale_k[MAX_SCALERS];
>>>> + int cdclk_adjustment;
>>>> + int num_scaler_users;
>>>> +
>>>> + /*
>>>> + * Assuming:
>>>> + * Both scaler enabled.
>>>> + * scaler 1 downscaling factor as 2 x 2 (Horiz x Vert)
>>>> + * scaler 2 downscaling factor as 2 x 1 (Horiz x Vert)
>>>> + * Cdclk Adjustment : 1
>>>> + */
>>>> + num_scaler_users = MAX_SCALERS;
>>>> + hscale_k[0] = 2 * 1000;
>>>> + vscale_k[0] = 2 * 1000;
>>>> + hscale_k[1] = 2 * 1000;
>>>> + vscale_k[1] = 1 * 1000;
>>>> +
>>>> + cdclk_adjustment = 1;
>>>> +
>>>> + return intel_vrr_guardband_dsc_latency(num_scaler_users, hscale_k, vscale_k,
>>>> + chroma_downscaling_factor,
>>>> + cdclk_adjustment,
>>>> + linetime_us);
>>>> +}
>>>> +
>>>> +static
>>>> +int intel_vrr_compute_guardband(struct intel_crtc_state *crtc_state,
>>>> + struct intel_connector *connector)
>>>> +{
>>>> + const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
>>>> + struct intel_display *display = to_intel_display(crtc_state);
>>>> + int dsc_prefill_time = 0;
>>>> + int psr2_pr_latency = 0;
>>>> + int scaler_prefill_time;
>>>> + int wm0_prefill_time;
>>>> + int pkgc_max_latency;
>>>> + int sagv_latency;
>>>> + int sdp_latency = 0;
>>>> + int guardband_us;
>>>> + int linetime_us;
>>>> + int guardband;
>>>> + int pm_delay;
>>>> +
>>>> + linetime_us = DIV_ROUND_UP(adjusted_mode->crtc_htotal * 1000,
>>>> + adjusted_mode->crtc_clock);
>>>> +
>>>> + pkgc_max_latency = skl_watermark_max_latency(display, 1);
>>>> + sagv_latency = display->sagv.block_time_us;
>>>> +
>>>> + /* Assuming max wm0 lines = 4 */
>>>> + wm0_prefill_time = 4 * linetime_us + 20;
>>>> +
>>>> + scaler_prefill_time = scaler_prefill_latency(crtc_state, linetime_us);
>>>> +
>>>> + if (crtc_state->dsc.compression_enable)
>>>> + dsc_prefill_time = dsc_prefill_latency(crtc_state, linetime_us);
>>>> +
>>>> + pm_delay = crtc_state->framestart_delay +
>>>> + max(sagv_latency, pkgc_max_latency) +
>>>> + wm0_prefill_time +
>>>> + scaler_prefill_time +
>>>> + dsc_prefill_time;
>>>> +
>>>> + switch (connector->base.connector_type) {
>>>> + case DRM_MODE_CONNECTOR_eDP:
>>>> + case DRM_MODE_CONNECTOR_DisplayPort:
>>>> + psr2_pr_latency = intel_alpm_compute_max_link_wake_latency(crtc_state, true);
>>>> + sdp_latency = intel_dp_compute_sdp_latency(crtc_state, true);
>>>> + break;
>>>> + default:
>>>> + break;
>>>> + }
>>>> +
>>>> + guardband_us = max(sdp_latency, psr2_pr_latency);
>>>> + guardband_us = max(guardband_us, pm_delay);
>>>> +
>>>> + guardband = DIV_ROUND_UP(guardband_us, linetime_us);
>>>> +
>>>> + /* guardband cannot be more than the Vmax vblank */
>>>> + guardband = min(guardband, crtc_state->vrr.vmax - adjusted_mode->crtc_vblank_start);
>>>> +
>>>> + return guardband;
>>>> +}
>>>> +
>>>> +void intel_vrr_compute_config_late(struct intel_crtc_state *crtc_state,
>>>> + struct drm_connector_state *conn_state)
>>>> {
>>>> struct intel_display *display = to_intel_display(crtc_state);
>>>> const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
>>>> + struct intel_connector *connector =
>>>> + to_intel_connector(conn_state->connector);
>>>>
>>>> if (!intel_vrr_possible(crtc_state))
>>>> return;
>>>>
>>>> - if (DISPLAY_VER(display) >= 13) {
>>>> + if (intel_vrr_always_use_vrr_tg(display)) {
>>>> + crtc_state->vrr.guardband = intel_vrr_compute_guardband(crtc_state, connector);
>>> This all looks to be in the wrong place. It needs to be done as part of
>>> intel_crtc_compute_vblank_delay() which then updates crtc_vblank_start
>>> to reflect reality instead of leaving some incorrect junk in there.
>>> Presumably that is why you also had to do that
>>> intel_dsb_wait_for_delayed_vblank() hack.
>> Hi Ville,
>>
>> Thanks for for the comments.
>>
>> Looks like intel_crtc_compute_vblank_delay() indeed is the place to add
>> the vblank_delay and get the crtc_vblank_start point to the delayed vblank.
>>
>> But I think, there are couple of things need to take care with this change:
>> 1) The SCL currently is derived from crtc_vblank_start - vdisplay, which
>> is ~1 with guradband = vblank length.
>> With modified crtc_vblank_start, this will become huge so perhaps we
>> need to set it to 1?
> When using the legacy timing generator SCL is what defines the
> position of the delayed vblank. So it should be exactly what it is.
>
> I don't quite recall how this stuff works with the VRR timing
> generator. I think it might have been that guardband more or less
> defines the location of the delayed vblank, and SCL then effectively
> defines the start of the safe window. So I think it should stay
> exactly the way it is. IIRC there is some way on new platforms to
> even move the SCL position into the vertical active, but I haven't
> though through what that would actually do for us.
Hmm yes for VRR timing generator case, guardband defines the position
of the delayed vblank.
Currently, I see that in most cases the vblank delay (crtc_vblank_start
- crtc_vdisplay) evaluates to 0.
In few case its 1, I think based on intel_psr_min_vblank_delay().
This vblank delay is used to write in TRANS_SET_CONTEXT_LATENCY and to
compute the vblank_start during readback.
With this series, since we have a shorter guardband now, the
crtc_vblank_start is moved away by quite a bit.
Without modification this is resulting in TRANS_SET_CONTEXT_LATENCY to a
bigger value and we are getting DSB POLL errors as it waits for safe window.
So with the updated crtc_vblank_start, for platforms where VRR TG is
always on (and static guardband is used), I am now clamping the set
context latency value between (0, 1).
There are couple of more points like with updated crtc_vblank_start for
LRR, where it now changes since vtotal is changed.
Since guardband is static value the vblank_start moves due to change in
vtotal, and prevents from fastset.
I have made some changes and will be posting patches after some more
testing.
>
>> 2) The intel_dsb_wait_vblank_delay() (which inturn uses
>> intel_vrr_real_vblank_delay() for vrr case) also computes a fixed delay
>> based on (crtc_vblank_start - vdisplay) lines
>> Instead of this should we not use intel_dsb_wait_scanline_in() to wait
>> only till scanline reaches in range [flipline decision boundary, vmax
>> decision boundary]?
> You can't use absolute line numbers with VRR since you don't know
> when the vblank will be terminated. It has to be all relative.
Oh ok. Then I will leave it as it is then.
Thanks & Regards,
Ankit
>
>> Let me know what you think, I can send a follow-up patch with the
>> suggested changes.
>>
>> Regards,
>> Ankit
>>
>>
>>>> + } else if (DISPLAY_VER(display) >= 13) {
>>>> crtc_state->vrr.guardband =
>>>> crtc_state->vrr.vmin - adjusted_mode->crtc_vblank_start;
>>>> } else {
>>>> diff --git a/drivers/gpu/drm/i915/display/intel_vrr.h b/drivers/gpu/drm/i915/display/intel_vrr.h
>>>> index 950041647e47..362638fd0d66 100644
>>>> --- a/drivers/gpu/drm/i915/display/intel_vrr.h
>>>> +++ b/drivers/gpu/drm/i915/display/intel_vrr.h
>>>> @@ -21,7 +21,8 @@ bool intel_vrr_possible(const struct intel_crtc_state *crtc_state);
>>>> void intel_vrr_check_modeset(struct intel_atomic_state *state);
>>>> void intel_vrr_compute_config(struct intel_crtc_state *crtc_state,
>>>> struct drm_connector_state *conn_state);
>>>> -void intel_vrr_compute_config_late(struct intel_crtc_state *crtc_state);
>>>> +void intel_vrr_compute_config_late(struct intel_crtc_state *crtc_state,
>>>> + struct drm_connector_state *conn_state);
>>>> void intel_vrr_set_transcoder_timings(const struct intel_crtc_state *crtc_state);
>>>> void intel_vrr_enable(const struct intel_crtc_state *crtc_state);
>>>> void intel_vrr_send_push(struct intel_dsb *dsb,
>>>> --
>>>> 2.45.2
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH 13/14] drm/i915/panel: Refactor helper to get highest fixed mode
2025-09-07 7:32 [PATCH 00/14] Optimize vrr.guardband and fix LRR Ankit Nautiyal
` (11 preceding siblings ...)
2025-09-07 7:32 ` [PATCH 12/14] drm/i915/vrr: Use static guardband to support seamless LRR switching Ankit Nautiyal
@ 2025-09-07 7:32 ` Ankit Nautiyal
2025-09-07 7:32 ` [PATCH 14/14] drm/i915/vrr: Fix seamless_mn drrs for PTL Ankit Nautiyal
2025-09-07 10:03 ` ✓ i915.CI.BAT: success for Optimize vrr.guardband and fix LRR (rev9) Patchwork
14 siblings, 0 replies; 22+ messages in thread
From: Ankit Nautiyal @ 2025-09-07 7:32 UTC (permalink / raw)
To: intel-gfx, intel-xe; +Cc: ville.syrjala, Ankit Nautiyal, Mitul Golani
Refactor intel_panel_highest_mode() to return the fixed mode with the
highest pixel clock, removing the fallback to the adjusted mode. This makes
the function semantics clearer and better suited for future use cases where
fallback is not desirable.
Update the caller in intel_dp_mode_clock() to handle the NULL case
explicitly by falling back to the adjusted mode's crtc_clock. This also
addresses the existing FIXME comment about ambiguity between clock and
crtc_clock, by using mode->clock for fixed modes and mode->crtc_clock for
adjusted modes.
v2: Avoid introducing a new function and refactor existing one instead.
(Jani).
Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
Reviewed-by: Mitul Golani <mitulkumar.ajitkumar.golani@intel.com>
---
drivers/gpu/drm/i915/display/intel_dp.c | 14 +++++++++-----
drivers/gpu/drm/i915/display/intel_panel.c | 11 +++++------
drivers/gpu/drm/i915/display/intel_panel.h | 3 +--
3 files changed, 15 insertions(+), 13 deletions(-)
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index d5d30bdc6848..beab66ce0550 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1760,11 +1760,15 @@ static int intel_dp_mode_clock(const struct intel_crtc_state *crtc_state,
struct intel_connector *connector = to_intel_connector(conn_state->connector);
const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
- /* FIXME a bit of a mess wrt clock vs. crtc_clock */
- if (has_seamless_m_n(connector))
- return intel_panel_highest_mode(connector, adjusted_mode)->clock;
- else
- return adjusted_mode->crtc_clock;
+ if (has_seamless_m_n(connector)) {
+ const struct drm_display_mode *highest_mode;
+
+ highest_mode = intel_panel_highest_mode(connector);
+ if (highest_mode)
+ return highest_mode->clock;
+ }
+
+ return adjusted_mode->crtc_clock;
}
/* Optimize link config in order: max bpp, min clock, min lanes */
diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c
index 2a20aaaaac39..ac0f04073ecb 100644
--- a/drivers/gpu/drm/i915/display/intel_panel.c
+++ b/drivers/gpu/drm/i915/display/intel_panel.c
@@ -144,18 +144,17 @@ intel_panel_downclock_mode(struct intel_connector *connector,
}
const struct drm_display_mode *
-intel_panel_highest_mode(struct intel_connector *connector,
- const struct drm_display_mode *adjusted_mode)
+intel_panel_highest_mode(struct intel_connector *connector)
{
- const struct drm_display_mode *fixed_mode, *best_mode = adjusted_mode;
+ const struct drm_display_mode *fixed_mode, *highest_mode = NULL;
/* pick the fixed_mode that has the highest clock */
list_for_each_entry(fixed_mode, &connector->panel.fixed_modes, head) {
- if (fixed_mode->clock > best_mode->clock)
- best_mode = fixed_mode;
+ if (!highest_mode || fixed_mode->clock > highest_mode->clock)
+ highest_mode = fixed_mode;
}
- return best_mode;
+ return highest_mode;
}
int intel_panel_get_modes(struct intel_connector *connector)
diff --git a/drivers/gpu/drm/i915/display/intel_panel.h b/drivers/gpu/drm/i915/display/intel_panel.h
index 56a6412cf0fb..8a17600e46a3 100644
--- a/drivers/gpu/drm/i915/display/intel_panel.h
+++ b/drivers/gpu/drm/i915/display/intel_panel.h
@@ -37,8 +37,7 @@ const struct drm_display_mode *
intel_panel_downclock_mode(struct intel_connector *connector,
const struct drm_display_mode *adjusted_mode);
const struct drm_display_mode *
-intel_panel_highest_mode(struct intel_connector *connector,
- const struct drm_display_mode *adjusted_mode);
+intel_panel_highest_mode(struct intel_connector *connector);
int intel_panel_get_modes(struct intel_connector *connector);
enum drrs_type intel_panel_drrs_type(struct intel_connector *connector);
enum drm_mode_status
--
2.45.2
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH 14/14] drm/i915/vrr: Fix seamless_mn drrs for PTL
2025-09-07 7:32 [PATCH 00/14] Optimize vrr.guardband and fix LRR Ankit Nautiyal
` (12 preceding siblings ...)
2025-09-07 7:32 ` [PATCH 13/14] drm/i915/panel: Refactor helper to get highest fixed mode Ankit Nautiyal
@ 2025-09-07 7:32 ` Ankit Nautiyal
2025-09-07 10:03 ` ✓ i915.CI.BAT: success for Optimize vrr.guardband and fix LRR (rev9) Patchwork
14 siblings, 0 replies; 22+ messages in thread
From: Ankit Nautiyal @ 2025-09-07 7:32 UTC (permalink / raw)
To: intel-gfx, intel-xe; +Cc: ville.syrjala, Ankit Nautiyal, Mitul Golani
With VRR timing generator always on, the fixed refresh rate is achieved
by setting vrr.flipline and vrr.vmax as the vtotal for the desired mode.
This creates a problem for seamless_mn drrs feature, where user can
seamlessly set a lower mode on the supporting panels. With VRR timing
generator, the vrr.flipline and vrr.vmax are set to vtotal, but that
corresponds to the higher mode.
To fix this, re-compute the vrr timings when seamless_mn drrs is in
picture. At the same time make sure that the vrr.guardband is set as
per the highest mode for such panels, so that switching between higher
to lower mode, does not change the vrr.guardband.
v2: Add a new member `use_highest_mode` to vrr struct to help set the
vrr timings for highest mode for the seamless_mn drrs case.
v3:
-Modify existing function to compute fixed refresh rate timings instead
of adding a new function. (Mitul)
-Tweak computation for scaling the vtotal and use DIV_ROUND_UP_ULL.
-Improve documentation.
Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
Reviewed-by: Mitul Golani <mitulkumar.ajitkumar.golani@intel.com>
---
.../drm/i915/display/intel_display_types.h | 2 +
drivers/gpu/drm/i915/display/intel_dp.c | 2 +-
drivers/gpu/drm/i915/display/intel_dp.h | 1 +
drivers/gpu/drm/i915/display/intel_vrr.c | 90 ++++++++++++++++++-
4 files changed, 90 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index fd9d2527889b..e2b0d0a22ffd 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1319,6 +1319,8 @@ struct intel_crtc_state {
u8 pipeline_full;
u16 flipline, vmin, vmax, guardband;
u32 vsync_end, vsync_start;
+ /* Indicates VRR timing is scaled to highest mode for seamless M/N */
+ bool use_highest_mode;
} vrr;
/* Content Match Refresh Rate state */
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index beab66ce0550..97e9b1aee5ec 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1742,7 +1742,7 @@ static int intel_dp_max_bpp(struct intel_dp *intel_dp,
return bpp;
}
-static bool has_seamless_m_n(struct intel_connector *connector)
+bool has_seamless_m_n(struct intel_connector *connector)
{
struct intel_display *display = to_intel_display(connector);
diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h
index bfd1bd448672..932f5504399e 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.h
+++ b/drivers/gpu/drm/i915/display/intel_dp.h
@@ -216,5 +216,6 @@ int intel_dp_dsc_bpp_step_x16(const struct intel_connector *connector);
void intel_dp_dpcd_set_probe(struct intel_dp *intel_dp, bool force_on_external);
bool intel_dp_in_hdr_mode(const struct drm_connector_state *conn_state);
int intel_dp_compute_sdp_latency(struct intel_crtc_state *crtc_state, bool assume_all_enabled);
+bool has_seamless_m_n(struct intel_connector *connector);
#endif /* __INTEL_DP_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c
index fff684eb2514..880339f7c110 100644
--- a/drivers/gpu/drm/i915/display/intel_vrr.c
+++ b/drivers/gpu/drm/i915/display/intel_vrr.c
@@ -11,6 +11,7 @@
#include "intel_display_regs.h"
#include "intel_display_types.h"
#include "intel_dp.h"
+#include "intel_panel.h"
#include "intel_vrr.h"
#include "intel_vrr_regs.h"
#include "skl_scaler.h"
@@ -299,6 +300,16 @@ void intel_vrr_set_fixed_rr_timings(const struct intel_crtc_state *crtc_state)
if (!intel_vrr_possible(crtc_state))
return;
+ if (crtc_state->vrr.use_highest_mode) {
+ intel_de_write(display, TRANS_VRR_VMIN(display, cpu_transcoder),
+ crtc_state->vrr.vmin - 1);
+ intel_de_write(display, TRANS_VRR_VMAX(display, cpu_transcoder),
+ crtc_state->vrr.vmax - 1);
+ intel_de_write(display, TRANS_VRR_FLIPLINE(display, cpu_transcoder),
+ crtc_state->vrr.flipline - 1);
+ return;
+ }
+
intel_de_write(display, TRANS_VRR_VMIN(display, cpu_transcoder),
intel_vrr_fixed_rr_vmin(crtc_state) - 1);
intel_de_write(display, TRANS_VRR_VMAX(display, cpu_transcoder),
@@ -307,15 +318,69 @@ void intel_vrr_set_fixed_rr_timings(const struct intel_crtc_state *crtc_state)
intel_vrr_fixed_rr_flipline(crtc_state) - 1);
}
+static bool needs_seamless_m_n_timings(struct intel_crtc_state *crtc_state,
+ struct intel_connector *connector)
+{
+ if (!has_seamless_m_n(connector) || crtc_state->joiner_pipes)
+ return false;
+
+ return true;
+}
+
+static int intel_vrr_scale_vtotal_for_seamless_m_n(struct intel_crtc_state *crtc_state,
+ struct intel_connector *connector)
+{
+ const struct drm_display_mode *highest_mode = intel_panel_highest_mode(connector);
+ const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
+ int vtotal = adjusted_mode->crtc_vtotal;
+
+ /*
+ * For panels with seamless_m_n drrs, the user can seamlessly switch to
+ * a lower mode, which has a lower clock. This works with legacy timing
+ * generator, but not with the VRR timing generator.
+ *
+ * The VRR timing generator requires flipline and vmax to be equal for
+ * fixed refresh rate operation. The default fixed RR computation sets
+ * these to the current mode's vtotal. However, when switching to a
+ * lower clock mode, this would result in a higher refresh rate than
+ * desired.
+ *
+ * To simulate the lower refresh rate correctly, we scale the vtotal
+ * based on the ratio of the highest mode's clock to the current mode's
+ * clock.
+ *
+ * When switching to a higher clock mode, the current vtotal already
+ * results in the desired refresh rate, so no scaling is needed.
+ *
+ * So compute the scaled vtotal if required, and update vrr.vmin to
+ * the scaled value. Also, set vrr.use_highest_mode to indicate that
+ * VRR timings are based on the highest mode.
+ */
+ if (highest_mode && adjusted_mode->crtc_clock < highest_mode->clock) {
+ vtotal = DIV_ROUND_UP_ULL(vtotal * highest_mode->clock,
+ adjusted_mode->crtc_clock);
+ crtc_state->vrr.vmin = vtotal;
+ crtc_state->vrr.use_highest_mode = true;
+ }
+
+ return vtotal;
+}
+
static
-void intel_vrr_compute_fixed_rr_timings(struct intel_crtc_state *crtc_state)
+void intel_vrr_compute_fixed_rr_timings(struct intel_crtc_state *crtc_state,
+ struct intel_connector *connector)
{
+ int vtotal = crtc_state->hw.adjusted_mode.crtc_vtotal;
+
+ if (needs_seamless_m_n_timings(crtc_state, connector))
+ vtotal = intel_vrr_scale_vtotal_for_seamless_m_n(crtc_state, connector);
+
/*
* For fixed rr, vmin = vmax = flipline.
* vmin is already set to crtc_vtotal set vmax and flipline the same.
*/
- crtc_state->vrr.vmax = crtc_state->hw.adjusted_mode.crtc_vtotal;
- crtc_state->vrr.flipline = crtc_state->hw.adjusted_mode.crtc_vtotal;
+ crtc_state->vrr.vmax = vtotal;
+ crtc_state->vrr.flipline = vtotal;
}
static
@@ -397,7 +462,7 @@ intel_vrr_compute_config(struct intel_crtc_state *crtc_state,
else if (is_cmrr_frac_required(crtc_state) && is_edp)
intel_vrr_compute_cmrr_timings(crtc_state);
else
- intel_vrr_compute_fixed_rr_timings(crtc_state);
+ intel_vrr_compute_fixed_rr_timings(crtc_state, connector);
/*
* flipline determines the min vblank length the hardware will
@@ -478,6 +543,7 @@ int intel_vrr_compute_guardband(struct intel_crtc_state *crtc_state,
{
const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
struct intel_display *display = to_intel_display(crtc_state);
+ const struct drm_display_mode *highest_mode;
int dsc_prefill_time = 0;
int psr2_pr_latency = 0;
int scaler_prefill_time;
@@ -490,6 +556,22 @@ int intel_vrr_compute_guardband(struct intel_crtc_state *crtc_state,
int guardband;
int pm_delay;
+ /*
+ * For seamless m_n the clock is changed while other modeline
+ * parameters are same. In that case the linetime_us will change,
+ * causing the guardband to change, and the seamless switch to
+ * lower mode would not take place.
+ * To avoid this, take the highest mode where panel supports
+ * seamless drrs and make guardband equal to the vblank length
+ * for the highest mode.
+ */
+ highest_mode = intel_panel_highest_mode(connector);
+ if (needs_seamless_m_n_timings(crtc_state, connector) && highest_mode) {
+ guardband = highest_mode->vtotal - highest_mode->vdisplay;
+
+ return guardband;
+ }
+
linetime_us = DIV_ROUND_UP(adjusted_mode->crtc_htotal * 1000,
adjusted_mode->crtc_clock);
--
2.45.2
^ permalink raw reply related [flat|nested] 22+ messages in thread* ✓ i915.CI.BAT: success for Optimize vrr.guardband and fix LRR (rev9)
2025-09-07 7:32 [PATCH 00/14] Optimize vrr.guardband and fix LRR Ankit Nautiyal
` (13 preceding siblings ...)
2025-09-07 7:32 ` [PATCH 14/14] drm/i915/vrr: Fix seamless_mn drrs for PTL Ankit Nautiyal
@ 2025-09-07 10:03 ` Patchwork
14 siblings, 0 replies; 22+ messages in thread
From: Patchwork @ 2025-09-07 10:03 UTC (permalink / raw)
To: Ankit Nautiyal; +Cc: intel-gfx
[-- Attachment #1: Type: text/plain, Size: 2607 bytes --]
== Series Details ==
Series: Optimize vrr.guardband and fix LRR (rev9)
URL : https://patchwork.freedesktop.org/series/151245/
State : success
== Summary ==
CI Bug Log - changes from CI_DRM_17147 -> Patchwork_151245v9
====================================================
Summary
-------
**SUCCESS**
No regressions found.
External URL: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_151245v9/index.html
Participating hosts (43 -> 41)
------------------------------
Missing (2): bat-atsm-1 fi-snb-2520m
Known issues
------------
Here are the changes found in Patchwork_151245v9 that come from known issues:
### IGT changes ###
#### Issues hit ####
* igt@i915_selftest@live:
- bat-mtlp-8: [PASS][1] -> [DMESG-FAIL][2] ([i915#12061]) +1 other test dmesg-fail
[1]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17147/bat-mtlp-8/igt@i915_selftest@live.html
[2]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_151245v9/bat-mtlp-8/igt@i915_selftest@live.html
* igt@i915_selftest@live@workarounds:
- bat-dg2-11: [PASS][3] -> [DMESG-FAIL][4] ([i915#12061]) +1 other test dmesg-fail
[3]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17147/bat-dg2-11/igt@i915_selftest@live@workarounds.html
[4]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_151245v9/bat-dg2-11/igt@i915_selftest@live@workarounds.html
#### Possible fixes ####
* igt@i915_selftest@live@workarounds:
- bat-arls-5: [DMESG-FAIL][5] ([i915#12061]) -> [PASS][6] +1 other test pass
[5]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17147/bat-arls-5/igt@i915_selftest@live@workarounds.html
[6]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_151245v9/bat-arls-5/igt@i915_selftest@live@workarounds.html
- bat-dg2-14: [DMESG-FAIL][7] ([i915#12061]) -> [PASS][8] +1 other test pass
[7]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17147/bat-dg2-14/igt@i915_selftest@live@workarounds.html
[8]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_151245v9/bat-dg2-14/igt@i915_selftest@live@workarounds.html
[i915#12061]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/12061
Build changes
-------------
* Linux: CI_DRM_17147 -> Patchwork_151245v9
CI-20190529: 20190529
CI_DRM_17147: b58a0fdf32d1945f3a6d900fdc6763b7acdaf558 @ git://anongit.freedesktop.org/gfx-ci/linux
IGT_8524: 8524
Patchwork_151245v9: b58a0fdf32d1945f3a6d900fdc6763b7acdaf558 @ git://anongit.freedesktop.org/gfx-ci/linux
== Logs ==
For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_151245v9/index.html
[-- Attachment #2: Type: text/html, Size: 3492 bytes --]
^ permalink raw reply [flat|nested] 22+ messages in thread