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

Reply via email to