xref: /linux/drivers/gpu/drm/i915/display/skl_prefill.c (revision 815e260a18a3af4dab59025ee99a7156c0e8b5e0)
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 
19 static 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 
28 static 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, 20);
37 
38 	ctx->prefill.dsc = intel_vdsc_prefill_lines(crtc_state);
39 }
40 
41 static 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 
54 static 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 
67 static 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 
72 static 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(prefill, ctx->adj.scaler_2nd);
78 
79 	prefill += ctx->prefill.scaler_2nd;
80 	prefill = prefill_adjust(prefill, ctx->adj.scaler_1st);
81 
82 	prefill += ctx->prefill.scaler_1st;
83 	prefill += ctx->prefill.wm0;
84 
85 	return prefill;
86 }
87 
88 static unsigned int prefill_lines_cdclk(const struct skl_prefill_ctx *ctx)
89 {
90 	return prefill_adjust(prefill_lines_nocdclk(ctx), ctx->adj.cdclk);
91 }
92 
93 static unsigned int prefill_lines_full(const struct skl_prefill_ctx *ctx)
94 {
95 	return ctx->prefill.fixed + prefill_lines_cdclk(ctx);
96 }
97 
98 void 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 
108 void 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 
118 static 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, latency_us);
123 }
124 
125 int 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 
134 static unsigned int prefill_guardband(const struct intel_crtc_state *crtc_state)
135 {
136 	return intel_crtc_vblank_length(crtc_state) << 16;
137 }
138 
139 bool 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 
149 int 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_unadjusted,
156 						 prefill_available);
157 }
158