intel-gfx.lists.freedesktop.org archive mirror
 help / color / mirror / Atom feed
From: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
To: intel-gfx@lists.freedesktop.org, intel-xe@lists.freedesktop.org
Cc: ville.syrjala@linux.intel.com,
	Ankit Nautiyal <ankit.k.nautiyal@intel.com>,
	Mitul Golani <mitulkumar.ajitkumar.golani@intel.com>
Subject: [PATCH 08/12] drm/i915/display: Add guardband check for feature latencies
Date: Mon, 25 Aug 2025 18:05:44 +0530	[thread overview]
Message-ID: <20250825123548.3022474-9-ankit.k.nautiyal@intel.com> (raw)
In-Reply-To: <20250825123548.3022474-1-ankit.k.nautiyal@intel.com>

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> (#v3)
---
 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 bb926e9d2bea..9ce526e6c285 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


  parent reply	other threads:[~2025-08-25 12:49 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-08-25 12:35 [PATCH 00/12] Optimize vrr.guardband and fix LRR Ankit Nautiyal
2025-08-25 12:35 ` [PATCH 01/12] drm/i915/skl_watermark: Fix the scaling factor for chroma subsampling Ankit Nautiyal
2025-08-25 12:35 ` [PATCH 02/12] drm/i915/skl_watermark: Pass linetime as argument to latency helpers Ankit Nautiyal
2025-08-25 12:35 ` [PATCH 03/12] drm/i915/skl_scaler: Introduce helper for chroma downscale factor Ankit Nautiyal
2025-08-25 12:35 ` [PATCH 04/12] drm/i915/display: Extract helpers to set dsc/scaler prefill latencies Ankit Nautiyal
2025-08-25 12:35 ` [PATCH 05/12] drm/i915/dp: Add SDP latency computation helper Ankit Nautiyal
2025-08-25 12:35 ` [PATCH 06/12] drm/i915/alpm: Add function to compute max link-wake latency Ankit Nautiyal
2025-08-25 12:35 ` [PATCH 07/12] drm/i915/vrr: Use vrr.sync_start for getting vtotal Ankit Nautiyal
2025-08-25 12:35 ` Ankit Nautiyal [this message]
2025-08-25 12:35 ` [PATCH 09/12] drm/i915/skl_watermark: Remove redundant latency checks from vblank validation Ankit Nautiyal
2025-08-25 12:35 ` [PATCH 10/12] drm/i915/vrr: Use static guardband to support seamless LRR switching Ankit Nautiyal
2025-08-25 12:35 ` [PATCH 11/12] drm/i915/panel: Refactor helper to get highest fixed mode Ankit Nautiyal
2025-08-25 12:35 ` [PATCH 12/12] drm/i915/vrr: Fix seamless_mn drrs for PTL Ankit Nautiyal
2025-08-25 14:31 ` ✓ i915.CI.BAT: success for Optimize vrr.guardband and fix LRR (rev7) Patchwork
2025-08-25 16:45 ` ✓ i915.CI.Full: " Patchwork
  -- strict thread matches above, loose matches on Subject: below --
2025-08-20  8:04 [PATCH 00/12] Optimize vrr.guardband and fix LRR Ankit Nautiyal
2025-08-20  8:04 ` [PATCH 08/12] drm/i915/display: Add guardband check for feature latencies Ankit Nautiyal
2025-08-22 11:31   ` Jani Nikula
2025-08-24  4:22     ` Nautiyal, Ankit K
2025-08-18  7:31 [PATCH 00/12] Optimize vrr.guardband and fix LRR Ankit Nautiyal
2025-08-18  7:31 ` [PATCH 08/12] drm/i915/display: Add guardband check for feature latencies Ankit Nautiyal
2025-08-18 11:16   ` Golani, Mitulkumar Ajitkumar
2025-08-07 11:15 [PATCH 00/12] Optimize vrr.guardband and fix LRR Ankit Nautiyal
2025-08-07 11:15 ` [PATCH 08/12] drm/i915/display: Add guardband check for feature latencies Ankit Nautiyal
2025-08-11  9:11   ` Golani, Mitulkumar Ajitkumar
2025-08-18  6:01     ` Nautiyal, Ankit K
2025-08-11  9:59   ` Golani, Mitulkumar Ajitkumar
2025-08-18  6:00     ` Nautiyal, Ankit K
2025-08-11 15:14   ` Jani Nikula
2025-08-18  6:02     ` Nautiyal, Ankit K

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250825123548.3022474-9-ankit.k.nautiyal@intel.com \
    --to=ankit.k.nautiyal@intel.com \
    --cc=intel-gfx@lists.freedesktop.org \
    --cc=intel-xe@lists.freedesktop.org \
    --cc=mitulkumar.ajitkumar.golani@intel.com \
    --cc=ville.syrjala@linux.intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).