1// SPDX-License-Identifier: MIT
2/*
3 * Copyright © 2025 Intel Corporation
4 */
5
6#include <linux/debugfs.h>
7
8#include <drm/drm_print.h>
9
10#include "intel_cdclk.h"
11#include "intel_display_core.h"
12#include "intel_display_types.h"
13#include "intel_vblank.h"
14#include "intel_vdsc.h"
15#include "skl_prefill.h"
16#include "skl_scaler.h"
17#include "skl_watermark.h"
18
19static unsigned int prefill_usecs_to_lines(const struct intel_crtc_state *crtc_state,
20 unsigned int usecs)
21{
22 const struct drm_display_mode *pipe_mode = &crtc_state->hw.pipe_mode;
23
24 return DIV_ROUND_UP_ULL(mul_u32_u32(pipe_mode->crtc_clock, usecs << 16),
25 pipe_mode->crtc_htotal * 1000);
26}
27
28static void prefill_init(struct skl_prefill_ctx *ctx,
29 const struct intel_crtc_state *crtc_state)
30{
31 memset(ctx, 0, sizeof(*ctx));
32
33 ctx->prefill.fixed = crtc_state->framestart_delay << 16;
34
35 /* 20 usec for translation walks/etc. */
36 ctx->prefill.fixed += prefill_usecs_to_lines(crtc_state, usecs: 20);
37
38 ctx->prefill.dsc = intel_vdsc_prefill_lines(crtc_state);
39}
40
41static void prefill_init_nocdclk_worst(struct skl_prefill_ctx *ctx,
42 const struct intel_crtc_state *crtc_state)
43{
44 prefill_init(ctx, crtc_state);
45
46 ctx->prefill.wm0 = skl_wm0_prefill_lines_worst(crtc_state);
47 ctx->prefill.scaler_1st = skl_scaler_1st_prefill_lines_worst(crtc_state);
48 ctx->prefill.scaler_2nd = skl_scaler_2nd_prefill_lines_worst(crtc_state);
49
50 ctx->adj.scaler_1st = skl_scaler_1st_prefill_adjustment_worst(crtc_state);
51 ctx->adj.scaler_2nd = skl_scaler_2nd_prefill_adjustment_worst(crtc_state);
52}
53
54static void prefill_init_nocdclk(struct skl_prefill_ctx *ctx,
55 const struct intel_crtc_state *crtc_state)
56{
57 prefill_init(ctx, crtc_state);
58
59 ctx->prefill.wm0 = skl_wm0_prefill_lines(crtc_state);
60 ctx->prefill.scaler_1st = skl_scaler_1st_prefill_lines(crtc_state);
61 ctx->prefill.scaler_2nd = skl_scaler_2nd_prefill_lines(crtc_state);
62
63 ctx->adj.scaler_1st = skl_scaler_1st_prefill_adjustment(crtc_state);
64 ctx->adj.scaler_2nd = skl_scaler_2nd_prefill_adjustment(crtc_state);
65}
66
67static unsigned int prefill_adjust(unsigned int value, unsigned int factor)
68{
69 return DIV_ROUND_UP_ULL(mul_u32_u32(value, factor), 0x10000);
70}
71
72static unsigned int prefill_lines_nocdclk(const struct skl_prefill_ctx *ctx)
73{
74 unsigned int prefill = 0;
75
76 prefill += ctx->prefill.dsc;
77 prefill = prefill_adjust(value: prefill, factor: ctx->adj.scaler_2nd);
78
79 prefill += ctx->prefill.scaler_2nd;
80 prefill = prefill_adjust(value: prefill, factor: ctx->adj.scaler_1st);
81
82 prefill += ctx->prefill.scaler_1st;
83 prefill += ctx->prefill.wm0;
84
85 return prefill;
86}
87
88static unsigned int prefill_lines_cdclk(const struct skl_prefill_ctx *ctx)
89{
90 return prefill_adjust(value: prefill_lines_nocdclk(ctx), factor: ctx->adj.cdclk);
91}
92
93static unsigned int prefill_lines_full(const struct skl_prefill_ctx *ctx)
94{
95 return ctx->prefill.fixed + prefill_lines_cdclk(ctx);
96}
97
98void skl_prefill_init_worst(struct skl_prefill_ctx *ctx,
99 const struct intel_crtc_state *crtc_state)
100{
101 prefill_init_nocdclk_worst(ctx, crtc_state);
102
103 ctx->adj.cdclk = intel_cdclk_prefill_adjustment_worst(crtc_state);
104
105 ctx->prefill.full = prefill_lines_full(ctx);
106}
107
108void skl_prefill_init(struct skl_prefill_ctx *ctx,
109 const struct intel_crtc_state *crtc_state)
110{
111 prefill_init_nocdclk(ctx, crtc_state);
112
113 ctx->adj.cdclk = intel_cdclk_prefill_adjustment(crtc_state);
114
115 ctx->prefill.full = prefill_lines_full(ctx);
116}
117
118static unsigned int prefill_lines_with_latency(const struct skl_prefill_ctx *ctx,
119 const struct intel_crtc_state *crtc_state,
120 unsigned int latency_us)
121{
122 return ctx->prefill.full + prefill_usecs_to_lines(crtc_state, usecs: latency_us);
123}
124
125int skl_prefill_min_guardband(const struct skl_prefill_ctx *ctx,
126 const struct intel_crtc_state *crtc_state,
127 unsigned int latency_us)
128{
129 unsigned int prefill = prefill_lines_with_latency(ctx, crtc_state, latency_us);
130
131 return DIV_ROUND_UP(prefill, 0x10000);
132}
133
134static unsigned int prefill_guardband(const struct intel_crtc_state *crtc_state)
135{
136 return intel_crtc_vblank_length(crtc_state) << 16;
137}
138
139bool skl_prefill_vblank_too_short(const struct skl_prefill_ctx *ctx,
140 const struct intel_crtc_state *crtc_state,
141 unsigned int latency_us)
142{
143 unsigned int guardband = prefill_guardband(crtc_state);
144 unsigned int prefill = prefill_lines_with_latency(ctx, crtc_state, latency_us);
145
146 return guardband < prefill;
147}
148
149int skl_prefill_min_cdclk(const struct skl_prefill_ctx *ctx,
150 const struct intel_crtc_state *crtc_state)
151{
152 unsigned int prefill_unadjusted = prefill_lines_nocdclk(ctx);
153 unsigned int prefill_available = prefill_guardband(crtc_state) - ctx->prefill.fixed;
154
155 return intel_cdclk_min_cdclk_for_prefill(crtc_state, prefill_lines_unadjusted: prefill_unadjusted,
156 prefill_lines_available: prefill_available);
157}
158

source code of linux/drivers/gpu/drm/i915/display/skl_prefill.c