On Mon, 08 Jun 2026, Vidya Srinivas <[email protected]> wrote:
> From: Vidya Srinivas <[email protected]>
>
> The existing icl_plane_min_cdclk() uses a simple pixel_rate/PPC
> calculation that does not account for the pipeline granularity
> adjustment when horizontal downscaling is active. The effective
> pixels-per-clock throughput is reduced due to integer pipeline
> granularity, requiring a higher CDCLK than the current one computes.
> This causes FIFO underruns on multi-pipe configurations near max CDCLK.
>
> Additionally, limit second scaler to 1:1
> (no horizontal or vertical downscaling) on DISPLAY_VER > 14
>
> Also apply CDCLK PLL disable/enable WA for DISPLAY_VER 30
>
> Signed-off-by: Vidya Srinivas <[email protected]>
> Signed-off-by: Charlton Lin <[email protected]>
If you're sending a patch from you, why is Charlton's Signed-off-by
here? Who is the author? Did you inted to add Co-developed-by: Charlton?
BR,
Jani.
> ---
> drivers/gpu/drm/i915/display/intel_cdclk.c | 3 +-
> drivers/gpu/drm/i915/display/skl_scaler.c | 4 +-
> .../drm/i915/display/skl_universal_plane.c | 58 +++++++++++++++++--
> 3 files changed, 57 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c
> b/drivers/gpu/drm/i915/display/intel_cdclk.c
> index 189ae2d3cfc9..f724227c3726 100644
> --- a/drivers/gpu/drm/i915/display/intel_cdclk.c
> +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c
> @@ -2149,7 +2149,8 @@ static bool
> cdclk_compute_crawl_and_squash_midpoint(struct intel_display *displa
>
> static bool pll_enable_wa_needed(struct intel_display *display)
> {
> - return (DISPLAY_VERx100(display) == 2000 ||
> + return (DISPLAY_VERx100(display) == 3000 ||
> + DISPLAY_VERx100(display) == 2000 ||
> DISPLAY_VERx100(display) == 1400 ||
> display->platform.dg2) &&
> display->cdclk.hw.vco > 0;
> diff --git a/drivers/gpu/drm/i915/display/skl_scaler.c
> b/drivers/gpu/drm/i915/display/skl_scaler.c
> index 7994b983d509..3673b52de4da 100644
> --- a/drivers/gpu/drm/i915/display/skl_scaler.c
> +++ b/drivers/gpu/drm/i915/display/skl_scaler.c
> @@ -382,8 +382,10 @@ calculate_max_scale(struct intel_crtc *crtc,
>
> if (scaler_id == 0)
> *max_vscale = 0x30000 - 1;
> - else
> + else {
> + *max_hscale = 0x10000;
> *max_vscale = 0x10000;
> + }
> } else if (DISPLAY_VER(display) >= 10 || !is_yuv_semiplanar) {
> *max_hscale = 0x30000 - 1;
> *max_vscale = 0x30000 - 1;
> diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c
> b/drivers/gpu/drm/i915/display/skl_universal_plane.c
> index ad4bfff6903d..c49f330c4878 100644
> --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c
> +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c
> @@ -264,12 +264,58 @@ 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);
> -
> - /* two pixels per clock */
> - return DIV_ROUND_UP(pixel_rate, 2);
> + const struct intel_plane_state *plane_state)
> +{
> + struct intel_display *display = to_intel_display(crtc_state);
> + unsigned int pixel_rate = intel_plane_pixel_rate(crtc_state,
> plane_state);
> +
> + if (DISPLAY_VER(display) >= 30) {
> + unsigned int src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
> + unsigned int dst_w = drm_rect_width(&plane_state->uapi.dst);
> + unsigned int src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
> + unsigned int dst_h = drm_rect_height(&plane_state->uapi.dst);
> + const unsigned int ppc = 2;
> +
> + /*
> + * "Resolution Support" PPC-granularity:
> + * Hscale_PPC = (src_w / dst_w) * PPC
> + * int_part = floor(Hscale_PPC)
> + * frac = Hscale_PPC - int_part
> + * adjusted_frac = frac > 0 ? 1/ROUNDUP(1/frac) : 0
> + * H_down = int_part/PPC + adjusted_frac
> + * min_cdclk = crtc_clock * H_down * V_down / PPC
> + */
> + if (dst_w && dst_h && src_w > dst_w) {
> + unsigned int hscale_ppc = src_w * ppc;
> + unsigned int int_part = hscale_ppc / dst_w;
> + unsigned int frac_num = hscale_ppc % dst_w;
> + unsigned int v_num = max(src_h, dst_h);
> + u64 num;
> +
> + if (frac_num) {
> + unsigned int recip_ceil = DIV_ROUND_UP(dst_w, frac_num);
> + /* H_down = (int_part * recip_ceil + ppc) / (ppc *
> recip_ceil) */
> + unsigned int h_num = int_part * recip_ceil + ppc;
> + unsigned int h_den = ppc * recip_ceil;
> +
> + num = mul_u32_u32(crtc_state->pixel_rate, h_num);
> + num *= v_num;
> + return DIV_ROUND_UP_ULL(num,
> + (u64)h_den * ppc * dst_h);
> + }
> +
> + /* frac == 0: H_down = int_part / ppc exactly */
> + num = mul_u32_u32(crtc_state->pixel_rate, int_part);
> + num *= v_num;
> + return DIV_ROUND_UP_ULL(num, (u64)ppc * ppc * dst_h);
> + }
> +
> + /* No horizontal downscale */
> + return DIV_ROUND_UP(pixel_rate, ppc);
> + }
> +
> + /* two pixels per clock */
> + return DIV_ROUND_UP(pixel_rate, 2);
> }
>
> static void
--
Jani Nikula, Intel