> -----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 08/11] drm/i915/prefill: Introduce intel_prefill.c > > From: Ville Syrjälä <[email protected]> > > Add a new helper thingy to deal with the pipe prefill latency. > > We get three potentially useful thigns out of this: > - intel_prefill_vblank_too_short() used for checking the > actual vblank/guardband length > - intel_prefill_min_guardband() to calculate a suitable guardband > size based on some worst case scaling/etc. estimates > - intel_prefill_min_cdclk() used to calculate a minimum cdclk > freqency required for very small vblank lengths (in case the > otherwise compute minimum cdclk doesn't result in fast enough > prefill). > > The internal arithmetic is done terms of scanlines using .16 binary fixed > point > represantion.
Nit: Typo in representation. Only thing maybe left is the SDP related latency, which also can be planned for worst case. Looks Good to me. Reviewed-by: Uma Shankar <[email protected]> > > Signed-off-by: Ville Syrjälä <[email protected]> > --- > drivers/gpu/drm/i915/Makefile | 1 + > drivers/gpu/drm/i915/display/intel_prefill.c | 167 +++++++++++++++++++ > drivers/gpu/drm/i915/display/intel_prefill.h | 48 ++++++ > drivers/gpu/drm/xe/Makefile | 1 + > 4 files changed, 217 insertions(+) > create mode 100644 drivers/gpu/drm/i915/display/intel_prefill.c > create mode 100644 drivers/gpu/drm/i915/display/intel_prefill.h > > diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile > index > 78a45a6681df..088a6c6cd138 100644 > --- a/drivers/gpu/drm/i915/Makefile > +++ b/drivers/gpu/drm/i915/Makefile > @@ -351,6 +351,7 @@ i915-y += \ > display/intel_panel.o \ > display/intel_pfit.o \ > display/intel_pps.o \ > + display/intel_prefill.o \ > display/intel_qp_tables.o \ > display/intel_sdvo.o \ > display/intel_snps_hdmi_pll.o \ > diff --git a/drivers/gpu/drm/i915/display/intel_prefill.c > b/drivers/gpu/drm/i915/display/intel_prefill.c > new file mode 100644 > index 000000000000..8b9c14e5c505 > --- /dev/null > +++ b/drivers/gpu/drm/i915/display/intel_prefill.c > @@ -0,0 +1,167 @@ > +// SPDX-License-Identifier: MIT > +/* > + * Copyright © 2025 Intel Corporation > + */ > + > +#include <linux/debugfs.h> > + > +#include <drm/drm_print.h> > + > +#include "intel_cdclk.h" > +#include "intel_display_core.h" > +#include "intel_display_types.h" > +#include "intel_prefill.h" > +#include "intel_vdsc.h" > +#include "skl_scaler.h" > +#include "skl_watermark.h" > + > +static unsigned int prefill_usecs_to_lines(const struct > +intel_crtc_state *crtc_state, unsigned int usecs) { > + const struct drm_display_mode *pipe_mode = &crtc_state- > >hw.pipe_mode; > + > + return DIV_ROUND_UP_ULL(mul_u32_u32(pipe_mode->crtc_clock, > usecs << 16), > + pipe_mode->crtc_htotal * 1000); > +} > + > +static void _intel_prefill_init(struct intel_prefill_ctx *ctx, > + const struct intel_crtc_state *crtc_state) { > + ctx->prefill.fixed = crtc_state->framestart_delay; > + > + /* 20 usec for translation walks/etc. */ > + ctx->prefill.fixed += prefill_usecs_to_lines(crtc_state, 20); > + > + ctx->prefill.dsc = intel_vdsc_prefill_lines(crtc_state); > + > + ctx->prefill.full = 0; > +} > + > +static void intel_prefill_init_nocdclk_worst(struct intel_prefill_ctx *ctx, > + const struct intel_crtc_state > *crtc_state) { > + _intel_prefill_init(ctx, crtc_state); > + > + ctx->prefill.wm0 = skl_wm0_prefill_lines_worst(crtc_state); > + ctx->prefill.scaler_1st = > skl_scaler_1st_prefill_lines_worst(crtc_state); > + ctx->prefill.scaler_2nd = > +skl_scaler_2nd_prefill_lines_worst(crtc_state); > + > + ctx->adj.scaler_1st = > skl_scaler_1st_prefill_adjustment_worst(crtc_state); > + ctx->adj.scaler_2nd = > +skl_scaler_2nd_prefill_adjustment_worst(crtc_state); > +} > + > +static void intel_prefill_init_nocdclk(struct intel_prefill_ctx *ctx, > + const struct intel_crtc_state > *crtc_state) { > + _intel_prefill_init(ctx, crtc_state); > + > + ctx->prefill.wm0 = skl_wm0_prefill_lines(crtc_state); > + ctx->prefill.scaler_1st = skl_scaler_1st_prefill_lines(crtc_state); > + ctx->prefill.scaler_2nd = skl_scaler_2nd_prefill_lines(crtc_state); > + > + ctx->adj.scaler_1st = skl_scaler_1st_prefill_adjustment(crtc_state); > + ctx->adj.scaler_2nd = skl_scaler_2nd_prefill_adjustment(crtc_state); > +} > + > +static unsigned int prefill_adjust(unsigned int value, unsigned int > +factor) { > + return DIV_ROUND_UP_ULL(mul_u32_u32(value, factor), 0x10000); } > + > +static unsigned int prefill_lines_nocdclk(const struct > +intel_prefill_ctx *ctx) { > + unsigned int prefill = 0; > + > + prefill += ctx->prefill.dsc; > + prefill = prefill_adjust(prefill, ctx->adj.scaler_2nd); > + > + prefill += ctx->prefill.scaler_2nd; > + prefill = prefill_adjust(prefill, ctx->adj.scaler_1st); > + > + prefill += ctx->prefill.scaler_1st; > + prefill += ctx->prefill.wm0; > + > + return prefill; > +} > + > +static unsigned int prefill_lines_cdclk(const struct intel_prefill_ctx > +*ctx) { > + return prefill_adjust(prefill_lines_nocdclk(ctx), ctx->adj.cdclk); } > + > +static unsigned int prefill_lines_full(const struct intel_prefill_ctx > +*ctx) { > + return ctx->prefill.fixed + prefill_lines_cdclk(ctx); } > + > +void intel_prefill_init_worst(struct intel_prefill_ctx *ctx, > + const struct intel_crtc_state *crtc_state) { > + intel_prefill_init_nocdclk_worst(ctx, crtc_state); > + > + ctx->adj.cdclk = intel_cdclk_prefill_adjustment_worst(crtc_state); > + > + ctx->prefill.full = prefill_lines_full(ctx); } > + > +void intel_prefill_init(struct intel_prefill_ctx *ctx, > + const struct intel_crtc_state *crtc_state, > + const struct intel_cdclk_state *cdclk_state) { > + intel_prefill_init_nocdclk(ctx, crtc_state); > + > + ctx->adj.cdclk = intel_cdclk_prefill_adjustment(crtc_state, > +cdclk_state); > + > + ctx->prefill.full = prefill_lines_full(ctx); } > + > +static unsigned int prefill_lines_with_latency(const struct > intel_prefill_ctx *ctx, > + const struct intel_crtc_state > *crtc_state, > + unsigned int latency_us) > +{ > + return ctx->prefill.full + prefill_usecs_to_lines(crtc_state, > +latency_us); } > + > +int intel_prefill_min_guardband(const struct intel_prefill_ctx *ctx, > + const struct intel_crtc_state *crtc_state, > + unsigned int latency_us) > +{ > + unsigned int prefill = prefill_lines_with_latency(ctx, crtc_state, > +latency_us); > + > + return DIV_ROUND_UP(prefill, 0x10000); } > + > +static int intel_guardband(const struct intel_crtc_state *crtc_state) { > + const struct drm_display_mode *pipe_mode = &crtc_state- > >hw.pipe_mode; > + > + if (crtc_state->vrr.enable) > + return crtc_state->vrr.guardband; > + else > + return pipe_mode->crtc_vblank_end - pipe_mode- > >crtc_vblank_start; } > + > +static int intel_prefill_guardband(const struct intel_crtc_state > +*crtc_state) { > + return intel_guardband(crtc_state) << 16; } > + > +bool intel_prefill_vblank_too_short(const struct intel_prefill_ctx *ctx, > + const struct intel_crtc_state *crtc_state, > + unsigned int latency_us) > +{ > + unsigned int guardband = intel_prefill_guardband(crtc_state); > + unsigned int prefill = prefill_lines_with_latency(ctx, crtc_state, > +latency_us); > + > + return guardband < prefill; > +} > + > +int intel_prefill_min_cdclk(const struct intel_prefill_ctx *ctx, > + const struct intel_crtc_state *crtc_state) { > + unsigned int prefill_unadjusted = prefill_lines_nocdclk(ctx); > + unsigned int prefill_available = intel_prefill_guardband(crtc_state) - > + ctx->prefill.fixed; > + > + return intel_cdclk_min_cdclk_for_prefill(crtc_state, prefill_unadjusted, > + prefill_available); > +} > diff --git a/drivers/gpu/drm/i915/display/intel_prefill.h > b/drivers/gpu/drm/i915/display/intel_prefill.h > new file mode 100644 > index 000000000000..0f07660261dc > --- /dev/null > +++ b/drivers/gpu/drm/i915/display/intel_prefill.h > @@ -0,0 +1,48 @@ > +/* SPDX-License-Identifier: MIT */ > +/* > + * Copyright © 2025 Intel Corporation > + */ > + > +#ifndef __INTEL_PREFILL_H__ > +#define __INTEL_PREFILL_H__ > + > +#include <linux/types.h> > + > +struct intel_cdclk_state; > +struct intel_crtc_state; > + > +struct intel_prefill_ctx { > + /* .16 scanlines */ > + struct { > + unsigned int fixed; > + unsigned int wm0; > + unsigned int scaler_1st; > + unsigned int scaler_2nd; > + unsigned int dsc; > + unsigned int full; > + } prefill; > + > + /* .16 adjustment factors */ > + struct { > + unsigned int cdclk; > + unsigned int scaler_1st; > + unsigned int scaler_2nd; > + } adj; > +}; > + > +void intel_prefill_init_worst(struct intel_prefill_ctx *ctx, > + const struct intel_crtc_state *crtc_state); void > +intel_prefill_init(struct intel_prefill_ctx *ctx, > + const struct intel_crtc_state *crtc_state, > + const struct intel_cdclk_state *cdclk_state); > + > +bool intel_prefill_vblank_too_short(const struct intel_prefill_ctx *ctx, > + const struct intel_crtc_state *crtc_state, > + unsigned int latency_us); > +int intel_prefill_min_guardband(const struct intel_prefill_ctx *ctx, > + const struct intel_crtc_state *crtc_state, > + unsigned int latency_us); > +int intel_prefill_min_cdclk(const struct intel_prefill_ctx *ctx, > + const struct intel_crtc_state *crtc_state); > + > +#endif /* __INTEL_PREFILL_H__ */ > diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile index > 84321fad3265..1be020cc417d 100644 > --- a/drivers/gpu/drm/xe/Makefile > +++ b/drivers/gpu/drm/xe/Makefile > @@ -300,6 +300,7 @@ xe-$(CONFIG_DRM_XE_DISPLAY) += \ > i915-display/intel_pmdemand.o \ > i915-display/intel_pch.o \ > i915-display/intel_pps.o \ > + i915-display/intel_prefill.o \ > i915-display/intel_psr.o \ > i915-display/intel_qp_tables.o \ > i915-display/intel_quirks.o \ > -- > 2.49.1
