> -----Original Message----- > From: Intel-gfx <[email protected]> On Behalf Of Ville > Syrjala > Sent: Wednesday, October 8, 2025 11:56 PM > To: [email protected] > Cc: [email protected] > Subject: [RFC][PATCH 05/11] drm/i915/scaler: Add scaler prefill helpers > > From: Ville Syrjälä <[email protected]> > > 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
Nit: Typo in factors Looks Good to me. Reviewed-by: Uma Shankar <[email protected]> > Signed-off-by: Ville Syrjälä <[email protected]> > --- > 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
