Intel-XE Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Ville Syrjala <ville.syrjala@linux.intel.com>
To: intel-gfx@lists.freedesktop.org
Cc: intel-xe@lists.freedesktop.org
Subject: [RFC][PATCH 05/11] drm/i915/scaler: Add scaler prefill helpers
Date: Wed,  8 Oct 2025 21:25:52 +0300	[thread overview]
Message-ID: <20251008182559.20615-6-ville.syrjala@linux.intel.com> (raw)
In-Reply-To: <20251008182559.20615-1-ville.syrjala@linux.intel.com>

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Add helpers to compute the required prefill line count and
adjustment factors for the scalers.

The "1st" variants hand out numbers for the first scaler stage
in the pipeline (pipe scaler if no plane scalers are enabled,
or the max from all the plane scaler). The "2nd" variants deal
with second scaler stage (pipe scaler when plane scaling is also
enabled, otherwise there is no second stage).

The _worst() variants give out worst case estimates, meant for
guardband sizing. The other variants are meant for the actual
vblank/guardband length check vs. prefill+pkgc/sagv latency.

A few other helpers are added for the purpose of the WM0 prefill
worst case estimates (to be introduced later).

The returned numbers are in .16 binary fixed point.

TODO: pretty rough, should check the actual scaler max scaling
      factros instead of just assuming 3x everywhere

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/display/skl_scaler.c | 174 ++++++++++++++++++++++
 drivers/gpu/drm/i915/display/skl_scaler.h |  11 ++
 2 files changed, 185 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/skl_scaler.c b/drivers/gpu/drm/i915/display/skl_scaler.c
index c6cccf170ff1..6e90639494ca 100644
--- a/drivers/gpu/drm/i915/display/skl_scaler.c
+++ b/drivers/gpu/drm/i915/display/skl_scaler.c
@@ -968,3 +968,177 @@ void adl_scaler_ecc_unmask(const struct intel_crtc_state *crtc_state)
 			  1);
 	intel_de_write(display, XELPD_DISPLAY_ERR_FATAL_MASK, 0);
 }
+
+static unsigned int skl_scaler_scale(const struct intel_crtc_state *crtc_state, int i)
+{
+	const struct intel_crtc_scaler_state *scaler_state =
+		&crtc_state->scaler_state;
+
+	drm_dbg_kms(to_intel_display(crtc_state)->drm, "scaler %d %x %x\n",
+		    i, scaler_state->scalers[i].hscale,
+		    scaler_state->scalers[i].vscale);
+
+	return DIV_ROUND_UP_ULL(mul_u32_u32(scaler_state->scalers[i].hscale,
+					    scaler_state->scalers[i].vscale),
+				0x10000);
+}
+
+static unsigned int skl_scaler_downscale(const struct intel_crtc_state *crtc_state, int i)
+{
+	return max(0x10000, skl_scaler_scale(crtc_state, i));
+}
+
+static unsigned int skl_plane_scaler_downscale(const struct intel_crtc_state *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;
+	unsigned int scale = 0x10000;
+	int i;
+
+	for (i = 0; i < crtc->num_scalers; i++) {
+		/* ignore pfit */
+		if (i == scaler_state->scaler_id)
+			continue;
+
+		if (!scaler_state->scalers[i].in_use)
+			continue;
+
+		scale = max(scale, skl_scaler_downscale(crtc_state, i));
+	}
+
+	return scale;
+}
+
+static unsigned int skl_pipe_scaler_downscale(const struct intel_crtc_state *crtc_state)
+{
+	const struct intel_crtc_scaler_state *scaler_state =
+		&crtc_state->scaler_state;
+
+	if (!crtc_state->pch_pfit.enabled)
+		return 0x10000;
+
+	return skl_scaler_downscale(crtc_state, scaler_state->scaler_id);
+}
+
+unsigned int skl_scaler_1st_prefill_adjustment(const struct intel_crtc_state *crtc_state)
+{
+	const struct intel_crtc_scaler_state *scaler_state =
+		&crtc_state->scaler_state;
+	int num_scalers = hweight32(scaler_state->scaler_users);
+
+	if (num_scalers < 1)
+		return 0x10000;
+
+	if (num_scalers == 1 && crtc_state->pch_pfit.enabled)
+		return skl_pipe_scaler_downscale(crtc_state);
+	else
+		return skl_plane_scaler_downscale(crtc_state);
+}
+
+unsigned int skl_scaler_2nd_prefill_adjustment(const struct intel_crtc_state *crtc_state)
+{
+	const struct intel_crtc_scaler_state *scaler_state =
+		&crtc_state->scaler_state;
+	int num_scalers = hweight32(scaler_state->scaler_users);
+
+	if (num_scalers < 2)
+		return 0x10000;
+
+	return skl_pipe_scaler_downscale(crtc_state);
+}
+
+unsigned int skl_scaler_1st_prefill_lines(const struct intel_crtc_state *crtc_state)
+{
+	const struct intel_crtc_scaler_state *scaler_state =
+		&crtc_state->scaler_state;
+	int num_scalers = hweight32(scaler_state->scaler_users);
+
+	if (num_scalers > 0)
+		return 4 << 16;
+
+	return 0;
+}
+
+unsigned int skl_scaler_2nd_prefill_lines(const struct intel_crtc_state *crtc_state)
+{
+	const struct intel_crtc_scaler_state *scaler_state =
+		&crtc_state->scaler_state;
+	int num_scalers = hweight32(scaler_state->scaler_users);
+
+	if (num_scalers > 1 && crtc_state->pch_pfit.enabled)
+		return 4 << 16;
+
+	return 0;
+}
+
+static unsigned int _skl_scaler_max_scale(const struct intel_crtc_state *crtc_state,
+					  unsigned int max_scale)
+{
+	struct intel_display *display = to_intel_display(crtc_state);
+
+	/*
+	 * Downscaling requires increasing cdclk, so max scale
+	 * factor is limited to the max_dotclock/dotclock ratio.
+	 */
+	drm_dbg_kms(display->drm, "max %d, dotclock %d\n",
+		    display->cdclk.max_dotclk_freq, crtc_state->hw.pipe_mode.crtc_clock);
+
+	/* FIXME find out the max downscale factors properly */
+	return min(max_scale, DIV_ROUND_UP_ULL((u64)display->cdclk.max_dotclk_freq << 16,
+					       crtc_state->hw.pipe_mode.crtc_clock));
+}
+
+static unsigned int skl_scaler_max_scale(const struct intel_crtc_state *crtc_state)
+{
+	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+	unsigned int max_scale;
+
+	if (crtc->num_scalers < 1)
+		return 0x10000;
+
+	/* FIXME find out the max downscale factors properly */
+	max_scale = 9 << 16;
+
+	return _skl_scaler_max_scale(crtc_state, max_scale);
+}
+
+unsigned int skl_scaler_1st_prefill_adjustment_worst(const struct intel_crtc_state *crtc_state)
+{
+	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+
+	if (crtc->num_scalers > 0)
+		return skl_scaler_max_scale(crtc_state);
+	else
+		return 0x10000;
+}
+
+unsigned int skl_scaler_2nd_prefill_adjustment_worst(const struct intel_crtc_state *crtc_state)
+{
+	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+
+	if (crtc->num_scalers > 1)
+		return skl_scaler_max_scale(crtc_state);
+	else
+		return 0x10000;
+}
+
+unsigned int skl_scaler_1st_prefill_lines_worst(const struct intel_crtc_state *crtc_state)
+{
+	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+
+	if (crtc->num_scalers > 0)
+		return 4 << 16;
+	else
+		return 0;
+}
+
+unsigned int skl_scaler_2nd_prefill_lines_worst(const struct intel_crtc_state *crtc_state)
+{
+	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+
+	if (crtc->num_scalers > 1)
+		return 4 << 16;
+	else
+		return 0;
+}
diff --git a/drivers/gpu/drm/i915/display/skl_scaler.h b/drivers/gpu/drm/i915/display/skl_scaler.h
index 12a19016c5f6..6fab40d2b4ee 100644
--- a/drivers/gpu/drm/i915/display/skl_scaler.h
+++ b/drivers/gpu/drm/i915/display/skl_scaler.h
@@ -45,4 +45,15 @@ 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);
+
+unsigned int skl_scaler_1st_prefill_adjustment_worst(const struct intel_crtc_state *crtc_state);
+unsigned int skl_scaler_2nd_prefill_adjustment_worst(const struct intel_crtc_state *crtc_state);
+unsigned int skl_scaler_1st_prefill_lines_worst(const struct intel_crtc_state *crtc_state);
+unsigned int skl_scaler_2nd_prefill_lines_worst(const struct intel_crtc_state *crtc_state);
+
+unsigned int skl_scaler_1st_prefill_adjustment(const struct intel_crtc_state *crtc_state);
+unsigned int skl_scaler_2nd_prefill_adjustment(const struct intel_crtc_state *crtc_state);
+unsigned int skl_scaler_1st_prefill_lines(const struct intel_crtc_state *crtc_state);
+unsigned int skl_scaler_2nd_prefill_lines(const struct intel_crtc_state *crtc_state);
+
 #endif
-- 
2.49.1


  parent reply	other threads:[~2025-10-08 18:26 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-10-08 18:25 [RFC][PATCH 00/11] drm/i915/prefill: Introduce helpers for prefill latency calculations Ville Syrjala
2025-10-08 18:25 ` [RFC][PATCH 01/11] drm/i915: Reject modes with linetime > 64 usec Ville Syrjala
2025-10-13 15:15   ` Shankar, Uma
2025-10-08 18:25 ` [RFC][PATCH 02/11] drm/i915/cdclk: Add prefill helpers for CDCLK Ville Syrjala
2025-10-13 16:11   ` Shankar, Uma
2025-10-08 18:25 ` [RFC][PATCH 03/11] drm/i915/cdclk: Add intel_cdclk_min_cdclk_for_prefill() Ville Syrjala
2025-10-13 16:25   ` Shankar, Uma
2025-10-08 18:25 ` [RFC][PATCH 04/11] drm/i915/dsc: Add prefill helper for DSC Ville Syrjala
2025-10-13 16:26   ` Shankar, Uma
2025-10-08 18:25 ` Ville Syrjala [this message]
2025-10-13 17:56   ` [RFC][PATCH 05/11] drm/i915/scaler: Add scaler prefill helpers Shankar, Uma
2025-10-08 18:25 ` [RFC][PATCH 06/11] drm/i195/wm: Add WM0 " Ville Syrjala
2025-10-13 18:30   ` Shankar, Uma
2025-10-13 21:49     ` Ville Syrjälä
2025-10-08 18:25 ` [RFC][PATCH 07/11] drm/i915: Introduce intel_compute_global_watermarks_late() Ville Syrjala
2025-10-13 18:36   ` Shankar, Uma
2025-10-13 20:35     ` Ville Syrjälä
2025-10-08 18:25 ` [RFC][PATCH 08/11] drm/i915/prefill: Introduce intel_prefill.c Ville Syrjala
2025-10-13 18:42   ` Shankar, Uma
2025-10-13 21:37     ` Ville Syrjälä
2025-10-08 18:25 ` [RFC][PATCH 09/11] drm/i915/wm: Use intel_prefill Ville Syrjala
2025-10-13 18:43   ` Shankar, Uma
2025-10-08 18:25 ` [RFC][PATCH 10/11] drm/i915/prefill: Print the prefill details Ville Syrjala
2025-10-13 18:45   ` Shankar, Uma
2025-10-08 18:25 ` [RFC][PATCH 11/11] drm/i915/prefill: Also print out the worst case estimates Ville Syrjala
2025-10-13 18:47   ` Shankar, Uma
2025-10-08 19:10 ` ✗ CI.checkpatch: warning for drm/i915/prefill: Introduce helpers for prefill latency calculations Patchwork
2025-10-08 19:11 ` ✓ CI.KUnit: success " Patchwork
2025-10-08 19:26 ` ✗ CI.checksparse: warning " Patchwork
2025-10-08 19:58 ` ✓ Xe.CI.BAT: success " Patchwork
2025-10-08 23:13 ` ✗ Xe.CI.Full: failure " Patchwork

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=20251008182559.20615-6-ville.syrjala@linux.intel.com \
    --to=ville.syrjala@linux.intel.com \
    --cc=intel-gfx@lists.freedesktop.org \
    --cc=intel-xe@lists.freedesktop.org \
    /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