From: Ville Syrjala <ville.syrjala@linux.intel.com>
To: intel-gfx@lists.freedesktop.org
Cc: intel-xe@lists.freedesktop.org
Subject: [PATCH 4/4] drm/i915/cdclk: Deal with 2 PPC hscale issues when calculating min CDCLK
Date: Wed, 15 Jul 2026 15:09:26 +0300 [thread overview]
Message-ID: <20260715120926.10786-5-ville.syrjala@linux.intel.com> (raw)
In-Reply-To: <20260715120926.10786-1-ville.syrjala@linux.intel.com>
From: Ville Syrjälä <ville.syrjala@linux.intel.com>
Double the fractional part of the horizontal scale factor
for the purposes of min_cdck calculation. This bumps the min
CDCLK sufficiently to overcome some kind of 2 PPC granularity
issue. Without this CDCLK may end up being too low and we get
underruns with certail horizontal downscale factors.
The current Bspec formula calls for doubling only the
fractional part below 0.5, and rounding it to down to
a unit fraction. But that formula does not result in a
sufficient CDCLK bump in a lot of cases. Empirical evidence
supports doubling the entire fractional part, so let's just
do that while we wait for further analysis from the hardware
team.
Also note that the position of the scaler output window also
seems to matter. If the output is near the left edge of the
screen then lower CDCLK is sufficient, but moving the output
window further to the right causes underruns unless CDCLK is
also bumped. Some prefill happening during hblank already?
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
drivers/gpu/drm/i915/display/intel_display.c | 26 ++++++++-
drivers/gpu/drm/i915/display/intel_plane.c | 55 +++++++++++++++++++
drivers/gpu/drm/i915/display/intel_plane.h | 5 ++
.../drm/i915/display/skl_universal_plane.c | 6 +-
4 files changed, 88 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index df43be51b3ba..2c55a4818ad7 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -2234,6 +2234,29 @@ static u32 ilk_pipe_pixel_rate(const struct intel_crtc_state *crtc_state)
pixel_rate);
}
+static u32 ilk_pipe_pixel_rate_cdclk(const struct intel_crtc_state *crtc_state)
+{
+ struct intel_display *display = to_intel_display(crtc_state);
+ u32 pixel_rate = crtc_state->hw.pipe_mode.crtc_clock;
+ unsigned int ppc = HAS_2PPC(display) ? 2 : 1;
+ struct drm_rect src;
+
+ /*
+ * We only use IF-ID interlacing. If we ever use
+ * PF-ID we'll need to adjust the pixel_rate here.
+ */
+
+ if (!crtc_state->pch_pfit.enabled)
+ return pixel_rate;
+
+ drm_rect_init(&src, 0, 0,
+ drm_rect_width(&crtc_state->pipe_src) << 16,
+ drm_rect_height(&crtc_state->pipe_src) << 16);
+
+ return intel_adjusted_rate_cdclk(&src, &crtc_state->pch_pfit.dst,
+ pixel_rate, ppc);
+}
+
static void intel_mode_from_crtc_timings(struct drm_display_mode *mode,
const struct drm_display_mode *timings)
{
@@ -2267,7 +2290,8 @@ static void intel_crtc_compute_pixel_rate(struct intel_crtc_state *crtc_state)
} else {
crtc_state->pixel_rate =
ilk_pipe_pixel_rate(crtc_state);
- crtc_state->pixel_rate_cdclk = crtc_state->pixel_rate;
+ crtc_state->pixel_rate_cdclk =
+ ilk_pipe_pixel_rate_cdclk(crtc_state);
}
}
diff --git a/drivers/gpu/drm/i915/display/intel_plane.c b/drivers/gpu/drm/i915/display/intel_plane.c
index a440f92ff00c..47c3e0c157b6 100644
--- a/drivers/gpu/drm/i915/display/intel_plane.c
+++ b/drivers/gpu/drm/i915/display/intel_plane.c
@@ -264,6 +264,50 @@ unsigned int intel_adjusted_rate(const struct drm_rect *src,
dst_w * dst_h);
}
+static unsigned int hscale_cdclk(const struct drm_rect *src,
+ const struct drm_rect *dst,
+ unsigned int ppc)
+{
+ unsigned int hscale;
+
+ hscale = drm_rect_calc_hscale(src, dst, 0, INT_MAX);
+ hscale = max(hscale, 0x10000);
+
+ /*
+ * Double the fractional part due to some 2 PPC granularity issue
+ *
+ * FIXME: BSpec calls for doubling only the <0.5 fractional part,
+ * and rounding it down to a unit fraction. In practice that is
+ * not sufficient, and we need a more aggressive CDCLK bump in
+ * many cases. The updated formula was derived empirically.
+ * This may need to be updated once we have better undestading
+ * of what's happening in the hardware...
+ */
+ return (hscale & ~0xffff) + ppc * (hscale & 0xffff);
+}
+
+static unsigned int vscale_cdclk(const struct drm_rect *src,
+ const struct drm_rect *dst)
+{
+ unsigned int vscale;
+
+ vscale = drm_rect_calc_vscale(src, dst,0, INT_MAX);
+ vscale = max(vscale, 0x10000);
+
+ return vscale;
+}
+
+unsigned int intel_adjusted_rate_cdclk(const struct drm_rect *src,
+ const struct drm_rect *dst,
+ unsigned int rate,
+ unsigned int ppc)
+{
+ unsigned int hscale = hscale_cdclk(src, dst, ppc);
+ unsigned int vscale = vscale_cdclk(src, dst);
+
+ return DIV64_U64_ROUND_UP((u64) rate * hscale * vscale, 1ull << 32);
+}
+
unsigned int intel_plane_pixel_rate(const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state)
{
@@ -284,6 +328,17 @@ unsigned int intel_plane_pixel_rate(const struct intel_crtc_state *crtc_state,
crtc_state->pixel_rate);
}
+unsigned int intel_plane_pixel_rate_cdclk(const struct intel_crtc_state *crtc_state,
+ const struct intel_plane_state *plane_state)
+{
+ struct intel_display *display = to_intel_display(crtc_state);
+ unsigned int ppc = HAS_2PPC(display) ? 2 : 1;
+
+ return intel_adjusted_rate_cdclk(&plane_state->uapi.src,
+ &plane_state->uapi.dst,
+ crtc_state->pixel_rate_cdclk, ppc);
+}
+
unsigned int intel_plane_data_rate(const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state,
int color_plane)
diff --git a/drivers/gpu/drm/i915/display/intel_plane.h b/drivers/gpu/drm/i915/display/intel_plane.h
index 31a6229aea73..dba2be24aae2 100644
--- a/drivers/gpu/drm/i915/display/intel_plane.h
+++ b/drivers/gpu/drm/i915/display/intel_plane.h
@@ -29,8 +29,13 @@ bool intel_plane_can_async_flip(struct intel_plane *plane,
unsigned int intel_adjusted_rate(const struct drm_rect *src,
const struct drm_rect *dst,
unsigned int rate);
+unsigned int intel_adjusted_rate_cdclk(const struct drm_rect *src,
+ const struct drm_rect *dst,
+ unsigned int rate, unsigned int ppc);
unsigned int intel_plane_pixel_rate(const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state);
+unsigned int intel_plane_pixel_rate_cdclk(const struct intel_crtc_state *crtc_state,
+ const struct intel_plane_state *plane_state);
unsigned int intel_plane_data_rate(const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state,
diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c
index 164b7d61c9a3..b246fc48558b 100644
--- a/drivers/gpu/drm/i915/display/skl_universal_plane.c
+++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c
@@ -266,7 +266,7 @@ bool icl_is_hdr_plane(struct intel_display *display, enum plane_id plane_id)
static int icl_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state)
{
- unsigned int pixel_rate = intel_plane_pixel_rate(crtc_state, plane_state);
+ unsigned int pixel_rate = intel_plane_pixel_rate_cdclk(crtc_state, plane_state);
/* two pixels per clock */
return DIV_ROUND_UP(pixel_rate, 2);
@@ -290,7 +290,7 @@ glk_plane_ratio(const struct intel_plane_state *plane_state,
static int glk_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state)
{
- unsigned int pixel_rate = intel_plane_pixel_rate(crtc_state, plane_state);
+ unsigned int pixel_rate = intel_plane_pixel_rate_cdclk(crtc_state, plane_state);
unsigned int num, den;
glk_plane_ratio(plane_state, &num, &den);
@@ -317,7 +317,7 @@ skl_plane_ratio(const struct intel_plane_state *plane_state,
static int skl_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state)
{
- unsigned int pixel_rate = intel_plane_pixel_rate(crtc_state, plane_state);
+ unsigned int pixel_rate = intel_plane_pixel_rate_cdclk(crtc_state, plane_state);
unsigned int num, den;
skl_plane_ratio(plane_state, &num, &den);
--
2.54.0
next prev parent reply other threads:[~2026-07-15 12:09 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-15 12:09 [PATCH 0/4] drm/i915/cdclk: Workaround some kind of scaler 2PPC issue Ville Syrjala
2026-07-15 12:09 ` [PATCH 1/4] drm/i915/cdclk: Use intel_cdclk_ppc() in intel_modeset_readout_hw_state() Ville Syrjala
2026-07-16 3:59 ` Garg, Nemesa
2026-07-15 12:09 ` [PATCH 2/4] drm/i915/cdclk: Introduce HAS_2PPC() Ville Syrjala
2026-07-16 4:03 ` Garg, Nemesa
2026-07-15 12:09 ` [PATCH 3/4] drm/i915/cdclk: Introduce crtc_state->pixel_rate_cdclk Ville Syrjala
2026-07-16 4:00 ` Garg, Nemesa
2026-07-15 12:09 ` Ville Syrjala [this message]
2026-07-16 4:01 ` [PATCH 4/4] drm/i915/cdclk: Deal with 2 PPC hscale issues when calculating min CDCLK Garg, Nemesa
2026-07-16 10:58 ` Srinivas, Vidya
2026-07-15 13:28 ` ✗ CI.checkpatch: warning for drm/i915/cdclk: Workaround some kind of scaler 2PPC issue Patchwork
2026-07-15 13:29 ` ✓ CI.KUnit: success " Patchwork
2026-07-15 14:06 ` ✓ Xe.CI.BAT: " Patchwork
2026-07-15 15:53 ` ✗ 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=20260715120926.10786-5-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