On Mon, Oct 13, 2025 at 06:42:09PM +0000, Shankar, Uma wrote:
> 
> 
> > -----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.

Yeah, though SDP (and PSR) are separate from the pre-fill. So
they should be handled by the higher level guardband calculation
code, not by intel_prefill.

> 
> 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
> 

-- 
Ville Syrjälä
Intel

Reply via email to