xref: /linux/drivers/gpu/drm/amd/display/dc/dml/dml1_frl_cap_chk.c (revision 9611c0ce215a66770ccbe5c126bf57ba8c31bcad)
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright 2023 Advanced Micro Devices, Inc.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
19  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21  * OTHER DEALINGS IN THE SOFTWARE.
22  *
23  * Authors: AMD
24  *
25  */
26 
27 #include "dml_logger.h"
28 #include "dml1_frl_cap_chk.h"
29 #include "dml_inline_defs.h"
30 
31 static const double __maybe_unused EPSILON			= 0.01;
32 static const double __maybe_unused DBL_EPSILON			= 2.2204460492503131e-16;
33 static const double __maybe_unused OVERHEAD_M			= 0.003;  /* %   */
34 static const double __maybe_unused TOLERANCE_PIXEL_CLOCK	= 0.005;  /* %   */
35 static const double __maybe_unused DML_TOLERANCE_AUDIO_CLOCK	= 1000;   /* ppm */
36 
37 #define frl_dump_var(fmt, var) {}
38 #define frl_print(fmt, ...) {}
39 
40 const struct frl_primary_format prim_format_444[] = {
41 /* VIC/Rate/Lanes/HCactive/HCBlank */
42 	{64,  3, 3, 960,  360}, /* 1920x1080 @ 100 */
43 	{77,  3, 3, 960,  360}, /* 1920x1080 @ 100 */
44 	{63,  3, 3, 960,  140}, /* 1920x1080 @ 120 */
45 	{78,  3, 3, 960,  140}, /* 1920x1080 @ 120 */
46 	{93,  3, 3, 1920, 828}, /* 3840x2160 @ 24 */
47 	{103, 3, 3, 1920, 828}, /* 3840x2160 @ 24 */
48 	{94,  3, 3, 1920, 720}, /* 3840x2160 @ 25 */
49 	{104, 3, 3, 1920, 720}, /* 3840x2160 @ 25 */
50 	{95,  3, 3, 1920, 280}, /* 3840x2160 @ 30 */
51 	{105, 3, 3, 1920, 280}, /* 3840x2160 @ 30 */
52 	{114, 3, 3, 1920, 828}, /* 3840x2160 @ 48 */
53 	{116, 3, 3, 1920, 828}, /* 3840x2160 @ 48 */
54 	{96,  3, 3, 1920, 720}, /* 3840x2160 @ 50 */
55 	{106, 3, 3, 1920, 720}, /* 3840x2160 @ 50 */
56 	{97,  3, 3, 1920, 280}, /* 3840x2160 @ 60 */
57 	{107, 3, 3, 1920, 280}, /* 3840x2160 @ 60 */
58 	{117, 6, 3, 1920, 720}, /* 3840x2160 @ 100 */
59 	{119, 6, 3, 1920, 720}, /* 3840x2160 @ 100 */
60 	{118, 6, 3, 1920, 280}, /* 3840x2160 @ 120 */
61 	{120, 6, 3, 1920, 280}, /* 3840x2160 @ 120 */
62 	{98,  3, 3, 2048, 700}, /* 4096x2160 @ 24 */
63 	{99,  3, 3, 2048, 592}, /* 4096x2160 @ 25 */
64 	{100, 3, 3, 2048, 152}, /* 4096x2160 @ 30 */
65 	{115, 3, 3, 2048, 700}, /* 4096x2160 @ 48 */
66 	{101, 3, 3, 2048, 592}, /* 4096x2160 @ 50 */
67 	{102, 3, 3, 2048, 152}, /* 4096x2160 @ 60 */
68 	{218, 6, 3, 2048, 592}, /* 4096x2160 @ 100 */
69 	{219, 6, 3, 2048, 152}, /* 4096x2160 @ 120 */
70 	{121, 3, 3, 2560, 1188}, /* 5120x2160 @ 24 */
71 	{122, 3, 3, 2560, 1040}, /* 5120x2160 @ 25 */
72 	{123, 3, 3, 2560, 440}, /* 5120x2160 @ 30 */
73 	{124, 3, 3, 2560, 256}, /* 5120x2160 @ 48 */
74 	{125, 3, 3, 2560, 484}, /* 5120x2160 @ 50 */
75 	{126, 3, 3, 2307, 144}, /* 5120x2160 @ 60 */
76 	{127, 6, 3, 2560, 484}, /* 5120x2160 @ 100 */
77 	{193, 6, 3, 2334, 104}, /* 5120x2160 @ 120 */
78 	{194, 6, 3, 3840, 1660}, /* 7680x2160 @ 24 */
79 	{202, 6, 3, 3840, 1660}, /* 7680x2160 @ 24 */
80 	{195, 6, 3, 3840, 1560}, /* 7680x2160 @ 25 */
81 	{203, 6, 3, 3840, 1560}, /* 7680x2160 @ 25 */
82 	{196, 6, 3, 3840, 660}, /* 7680x2160 @ 30 */
83 	{204, 6, 3, 3840, 660}, /* 7680x2160 @ 30 */
84 	{197, 6, 4, 3142, 1292}, /* 7680x2160 @ 48 */
85 	{205, 6, 4, 3142, 1292}, /* 7680x2160 @ 48 */
86 	{198, 6, 4, 3142, 1180}, /* 7680x2160 @ 50 */
87 	{206, 6, 4, 3142, 1180}, /* 7680x2160 @ 50 */
88 	{199, 6, 4, 3182, 140}, /* 7680x2160 @ 60 */
89 	{207, 6, 4, 3182, 140}, /* 7680x2160 @ 60 */
90 	{200, 10, 4, 2680, 784}, /* 7680x2160 @ 100 */
91 	{208, 10, 4, 2680, 784}, /* 7680x2160 @ 100 */
92 	{201, 10, 4, 2600, 100}, /* 7680x2160 @ 120 */
93 	{209, 10, 4, 2600, 100}, /* 7680x2160 @ 120 */
94 	{210, 6, 3, 4854, 912}, /* 10240x4320 @ 24 */
95 	{211, 6, 3, 4827, 1536}, /* 10240x4320 @ 25 */
96 	{212, 6, 3, 4720, 128}, /* 10240x4320 @ 30 */
97 	{213, 8, 4, 4347, 756}, /* 10240x4320 @ 48 */
98 	{214, 8, 4, 4320, 1376}, /* 10240x4320 @ 50 */
99 	{215, 8, 4, 4187, 124}, /* 10240x4320 @ 60 */
100 };
101 
102 const struct frl_primary_format prim_format_422[] = {
103 /* VIC/Rate/Lanes/HCactive/HCBlank */
104 	{64,  3, 3, 960,  360}, /* 1920x1080 @ 100 */
105 	{77,  3, 3, 960,  360}, /* 1920x1080 @ 100 */
106 	{63,  3, 3, 960,  140}, /* 1920x1080 @ 120 */
107 	{78,  3, 3, 960,  140}, /* 1920x1080 @ 120 */
108 	{93,  3, 3, 1920, 828}, /* 3840x2160 @ 24 */
109 	{103, 3, 3, 1920, 828}, /* 3840x2160 @ 24 */
110 	{94,  3, 3, 1920, 720}, /* 3840x2160 @ 25 */
111 	{104, 3, 3, 1920, 720}, /* 3840x2160 @ 25 */
112 	{95,  3, 3, 1920, 280}, /* 3840x2160 @ 30 */
113 	{105, 3, 3, 1920, 280}, /* 3840x2160 @ 30 */
114 	{114, 3, 3, 1920, 828}, /* 3840x2160 @ 48 */
115 	{116, 3, 3, 1920, 828}, /* 3840x2160 @ 48 */
116 	{96,  3, 3, 1920, 720}, /* 3840x2160 @ 50 */
117 	{106, 3, 3, 1920, 720}, /* 3840x2160 @ 50 */
118 	{97,  3, 3, 1920, 280}, /* 3840x2160 @ 60 */
119 	{107, 3, 3, 1920, 280}, /* 3840x2160 @ 60 */
120 	{117, 3, 3, 1370, 104}, /* 3840x2160 @ 100 */
121 	{119, 3, 3, 1370, 104}, /* 3840x2160 @ 100 */
122 	{118, 3, 3, 1130, 104}, /* 3840x2160 @ 120 */
123 	{120, 3, 3, 1130, 104}, /* 3840x2160 @ 120 */
124 	{98,  3, 3, 2048, 700}, /* 4096x2160 @ 24 */
125 	{99,  3, 3, 2048, 592}, /* 4096x2160 @ 25 */
126 	{100, 3, 3, 2048, 152}, /* 4096x2160 @ 30 */
127 	{115, 3, 3, 2048, 700}, /* 4096x2160 @ 48 */
128 	{101, 3, 3, 2048, 592}, /* 4096x2160 @ 50 */
129 	{102, 3, 3, 2048, 152}, /* 4096x2160 @ 60 */
130 	{218, 6, 3, 2048, 592}, /* 4096x2160 @ 100 */
131 	{219, 6, 3, 2048, 152}, /* 4096x2160 @ 120 */
132 	{121, 3, 3, 2560, 1188}, /* 5120x2160 @ 24 */
133 	{122, 3, 3, 2560, 1040}, /* 5120x2160 @ 25 */
134 	{123, 3, 3, 2560, 440}, /* 5120x2160 @ 30 */
135 	{124, 3, 3, 2560, 256}, /* 5120x2160 @ 48 */
136 	{125, 3, 3, 2560, 484}, /* 5120x2160 @ 50 */
137 	{126, 3, 3, 2307, 144}, /* 5120x2160 @ 60 */
138 	{127, 6, 3, 2560, 484}, /* 5120x2160 @ 100 */
139 	{193, 6, 3, 2334, 104}, /* 5120x2160 @ 120 */
140 	{194, 3, 3, 2460, 816}, /* 7680x2160 @ 24 */
141 	{202, 3, 3, 2460, 816}, /* 7680x2160 @ 24 */
142 	{195, 3, 3, 2460, 732}, /* 7680x2160 @ 25 */
143 	{203, 3, 3, 2460, 732}, /* 7680x2160 @ 25 */
144 	{196, 3, 3, 2360, 144}, /* 7680x2160 @ 30 */
145 	{204, 3, 3, 2360, 144}, /* 7680x2160 @ 30 */
146 	{197, 6, 3, 2460, 816}, /* 7680x2160 @ 48 */
147 	{205, 6, 3, 2460, 816}, /* 7680x2160 @ 48 */
148 	{198, 6, 3, 2460, 732}, /* 7680x2160 @ 50 */
149 	{206, 6, 3, 2460, 732}, /* 7680x2160 @ 50 */
150 	{199, 6, 3, 2380, 116}, /* 7680x2160 @ 60 */
151 	{207, 6, 3, 2380, 116}, /* 7680x2160 @ 60 */
152 	{200, 10, 4, 2680, 784}, /* 7680x2160 @ 100 */
153 	{208, 10, 4, 2680, 784}, /* 7680x2160 @ 100 */
154 	{201, 10, 4, 2600, 100}, /* 7680x2160 @ 120 */
155 	{209, 10, 4, 2600, 100}, /* 7680x2160 @ 120 */
156 	{210, 6, 3, 4854, 912}, /* 10240x4320 @ 24 */
157 	{211, 6, 3, 4827, 1536}, /* 10240x4320 @ 25 */
158 	{212, 6, 3, 4720, 128}, /* 10240x4320 @ 30 */
159 	{213, 6, 4, 3360, 420}, /* 10240x4320 @ 48 */
160 	{214, 6, 4, 3334, 892}, /* 10240x4320 @ 50 */
161 	{215, 6, 4, 3120, 124}, /* 10240x4320 @ 60 */
162 	{216, 12, 4, 3334, 764}, /* 10240x4320 @ 100 */
163 	{217, 12, 4, 3120, 124}, /* 10240x4320 @ 120 */
164 };
165 
166 const struct frl_primary_format prim_format_420[] = {
167 /* VIC/Rate/Lanes/HCactive/HCBlank */
168 	{114, 3, 3, 1920, 828}, /* 3840x2160 @ 48 */
169 	{116, 3, 3, 1920, 828}, /* 3840x2160 @ 48 */
170 	{96,  3, 3, 1920, 720}, /* 3840x2160 @ 50 */
171 	{106, 3, 3, 1920, 720}, /* 3840x2160 @ 50 */
172 	{97,  3, 3, 1920, 280}, /* 3840x2160 @ 60 */
173 	{107, 3, 3, 1920, 280}, /* 3840x2160 @ 60 */
174 	{117, 3, 3, 1370, 104}, /* 3840x2160 @ 100 */
175 	{119, 3, 3, 1370, 104}, /* 3840x2160 @ 100 */
176 	{118, 3, 3, 1130, 104}, /* 3840x2160 @ 120 */
177 	{120, 3, 3, 1130, 104}, /* 3840x2160 @ 120 */
178 	{115, 3, 3, 2048, 700}, /* 4096x2160 @ 48 */
179 	{101, 3, 3, 2048, 592}, /* 4096x2160 @ 50 */
180 	{102, 3, 3, 2048, 152}, /* 4096x2160 @ 60 */
181 	{218, 3, 3, 1376, 96}, /* 4096x2160 @ 100 */
182 	{219, 3, 3, 1131, 84}, /* 4096x2160 @ 120 */
183 	{124, 3, 3, 2560, 256}, /* 5120x2160 @ 48 */
184 	{125, 3, 3, 2560, 484}, /* 5120x2160 @ 50 */
185 	{126, 3, 3, 2307, 144}, /* 5120x2160 @ 60 */
186 	{127, 6, 3, 2560, 484}, /* 5120x2160 @ 100 */
187 	{193, 6, 3, 2334, 104}, /* 5120x2160 @ 120 */
188 	{194, 3, 3, 2460, 816}, /* 7680x2160 @ 24 */
189 	{202, 3, 3, 2460, 816}, /* 7680x2160 @ 24 */
190 	{195, 3, 3, 2460, 732}, /* 7680x2160 @ 25 */
191 	{203, 3, 3, 2460, 732}, /* 7680x2160 @ 25 */
192 	{196, 3, 3, 2360, 144}, /* 7680x2160 @ 30 */
193 	{204, 3, 3, 2360, 144}, /* 7680x2160 @ 30 */
194 	{197, 6, 3, 2460, 816}, /* 7680x2160 @ 48 */
195 	{205, 6, 3, 2460, 816}, /* 7680x2160 @ 48 */
196 	{198, 6, 3, 2460, 732}, /* 7680x2160 @ 50 */
197 	{206, 6, 3, 2460, 732}, /* 7680x2160 @ 50 */
198 	{199, 6, 3, 2380, 116}, /* 7680x2160 @ 60 */
199 	{207, 6, 3, 2380, 116}, /* 7680x2160 @ 60 */
200 	{200, 8, 4, 2240, 480}, /* 7680x2160 @ 100 */
201 	{208, 8, 4, 2240, 480}, /* 7680x2160 @ 100 */
202 	{201, 8, 4, 2062, 108}, /* 7680x2160 @ 120 */
203 	{209, 8, 4, 2062, 108}, /* 7680x2160 @ 120 */
204 	{210, 3, 3, 2614, 172}, /* 10240x4320 @ 24 */
205 	{211, 3, 3, 2614, 500}, /* 10240x4320 @ 25 */
206 	{212, 6, 3, 4720, 128}, /* 10240x4320 @ 30 */
207 	{213, 6, 3, 2614, 172}, /* 10240x4320 @ 48 */
208 	{214, 6, 4, 3334, 892}, /* 10240x4320 @ 50 */
209 	{215, 6, 4, 3120, 124}, /* 10240x4320 @ 60 */
210 	{216, 10, 4, 2854, 520}, /* 10240x4320 @ 100 */
211 	{217, 10, 4, 2587, 120}, /* 10240x4320 @ 120 */
212 };
213 
214 enum frl_cap_chk_result dml1_frl_cap_chk_common(struct frl_cap_chk_intermediates *inter,
215 						struct frl_cap_chk_params *params)
216 {
217 	double audio_bw_reserve = (params->compressed ? 192000.0 : 0.0);
218 
219 	dc_assert_fp_enabled();
220 
221 #ifdef DEBUG_FRL_CAP_CHK
222 	{
223 		printf("frl_cap_chk inputs:\n");
224 		printf("-------------------\n");
225 		frl_dump_var("%i",  params->lanes);
226 		frl_dump_var("%le", params->f_pixel_clock_nominal);
227 		frl_dump_var("%le", params->r_bit_nominal);
228 		frl_dump_var("%i",  params->audio_packet_type);
229 		frl_dump_var("%le", params->f_audio);
230 		frl_dump_var("%i",  params->h_active);
231 		frl_dump_var("%i",  params->h_blank);
232 		frl_dump_var("%i",  params->bpc);
233 		frl_dump_var("%i",  params->pixel_encoding);
234 		frl_dump_var("%i",  params->compressed);
235 		frl_dump_var("%i",  params->slices);
236 		frl_dump_var("%i",  params->slice_width);
237 		frl_dump_var("%le", params->bpp_target);
238 		frl_dump_var("%i",  params->layout);
239 		frl_dump_var("%i",  params->acat);
240 		printf("frl_cap_chk outputs:\n");
241 		printf("---------------------\n");
242 	}
243 #endif
244 
245 	inter->c_frl_sb          = 4 * C_FRL_CB + params->lanes;
246 	inter->overhead_sb       = (double)params->lanes / inter->c_frl_sb;
247 	inter->overhead_rs       = 8.0 * 4.0 / inter->c_frl_sb;
248 	inter->overhead_map      = 2.5 / inter->c_frl_sb;
249 	inter->overhead_min      = inter->overhead_sb + inter->overhead_rs + inter->overhead_map;
250 	inter->overhead_max      = inter->overhead_min + OVERHEAD_M;
251 	inter->f_pixel_clock_max = params->f_pixel_clock_nominal * (1.0 + TOLERANCE_PIXEL_CLOCK);
252 	inter->t_line            = (params->h_active + params->h_blank) / inter->f_pixel_clock_max;
253 	inter->r_bit_min         = params->r_bit_nominal * (1.0 - TOLERANCE_FRL_BIT / 1000000.0);
254 	inter->r_frl_char_min    = inter->r_bit_min / 18.0;
255 	inter->c_frl_line        = dml_floor(inter->t_line * inter->r_frl_char_min * params->lanes, 1);
256 
257 #ifdef DEBUG_FRL_CAP_CHK
258 	{
259 		frl_dump_var("%i",  inter->c_frl_sb);
260 		frl_dump_var("%le", inter->overhead_sb);
261 		frl_dump_var("%le", inter->overhead_rs);
262 		frl_dump_var("%le", inter->overhead_map);
263 		frl_dump_var("%le", inter->overhead_min);
264 		frl_dump_var("%le", inter->overhead_max);
265 		frl_dump_var("%le", inter->f_pixel_clock_max);
266 		frl_dump_var("%le", inter->t_line);
267 		frl_dump_var("%le", inter->r_bit_min);
268 		frl_dump_var("%le", inter->r_frl_char_min);
269 		frl_dump_var("%le", inter->c_frl_line);
270 	}
271 #endif
272 
273 	switch (params->audio_packet_type) {
274 	case 0x02:
275 		if (params->layout == 0)
276 			inter->ap = 0.25;
277 		else if (params->layout == 1)
278 			inter->ap = 1.0;
279 		break;
280 	case 0x08:
281 		inter->ap = 0.25;
282 		break;
283 	case 0x09:
284 		inter->ap = 1.0;
285 		break;
286 	case 0x07:
287 	case 0x0e:
288 	case 0x0f:
289 	case 0x0b:
290 	case 0x0c:
291 		/* Unsupported audio format */
292 		return FRL_CAP_CHK_ERROR_UNSUPPORTED_AUDIO;
293 	default:
294 		inter->ap = 0.0;
295 	}
296 
297 	inter->r_ap                   = (dml_max(audio_bw_reserve, params->f_audio * inter->ap) + 2 * ACR_RATE_MAX) * (1 + DML_TOLERANCE_AUDIO_CLOCK / 1000000.0);
298 	inter->avg_audio_packets_line = inter->r_ap * inter->t_line;
299 	inter->audio_packets_line     = (int)dml_ceil(inter->avg_audio_packets_line, 1);
300 	inter->blank_audio_min        = 32 + 32 * inter->audio_packets_line; // h_blank_audio_min or hc_blank_audio_min
301 
302 	params->borrow_params.audio_packets_line = inter->audio_packets_line;
303 
304 #ifdef DEBUG_FRL_CAP_CHK
305 	{
306 		frl_dump_var("%le", inter->ap);
307 		frl_dump_var("%le", inter->r_ap);
308 		frl_dump_var("%le", inter->avg_audio_packets_line);
309 		frl_dump_var("%i",  inter->audio_packets_line);
310 		frl_dump_var("%i",  inter->blank_audio_min);
311 	}
312 #endif
313 
314 	return FRL_CAP_CHK_OK;
315 }
316 
317 enum frl_cap_chk_result dml1_frl_cap_chk_uncompressed(struct frl_cap_chk_params *params,
318 						      struct frl_cap_chk_intermediates *inter)
319 {
320 	enum frl_cap_chk_result res;
321 	int      k_420;
322 	double   k_cd;
323 	int      c_frl_free;
324 	int      c_frl_rc_margin;
325 	int      c_frl_rc_savings;
326 	int      bpp;
327 	double   bytes_line;
328 	int      tb_active;
329 	int      tb_blank;
330 	double   f_tb_average;
331 	double   t_active_ref;
332 	double   t_blank_ref;
333 	double   t_active_min;
334 	double   t_blank_min;
335 	double   t_borrowed;
336 	double   tb_borrowed;
337 	int      c_frl_actual_payload;
338 	double   utilization;
339 	double   margin;
340 
341 	dc_assert_fp_enabled();
342 
343 	res = dml1_frl_cap_chk_common(inter, params);
344 	if (res != FRL_CAP_CHK_OK)
345 		return res;
346 
347 	k_420            = params->pixel_encoding == HDMI_FRL_PIXEL_ENCODING_420 ? 2 : 1;
348 	k_cd             = params->pixel_encoding == HDMI_FRL_PIXEL_ENCODING_422 ? 1.0 : params->bpc / 8.0;
349 	c_frl_free       = (int)dml_max(params->h_blank * k_cd / k_420 - 32 * (1 + inter->audio_packets_line) - 7, 0);
350 	c_frl_rc_margin  = 4;
351 	c_frl_rc_savings = (int)dml_floor(dml_max(((7.0 / 8.0) * c_frl_free) - c_frl_rc_margin, 0.0), 1);
352 	bpp              = (int)(24 * k_cd / k_420);
353 	bytes_line       = bpp * params->h_active / 8.0;
354 	tb_active        = (int)dml_ceil(bytes_line / 3, 1);
355 	tb_blank         = (int)dml_ceil(params->h_blank * k_cd / k_420, 1);
356 
357 #ifdef DEBUG_FRL_CAP_CHK
358 	{
359 		frl_dump_var("%i", k_420);
360 		frl_dump_var("%le", k_cd);
361 		frl_dump_var("%i", c_frl_free);
362 		frl_dump_var("%i", c_frl_rc_margin);
363 		frl_dump_var("%i", c_frl_rc_savings);
364 		frl_dump_var("%i", bpp);
365 		frl_dump_var("%le", bytes_line);
366 		frl_dump_var("%i", tb_active);
367 		frl_dump_var("%i", tb_blank);
368 	}
369 #endif
370 
371 	if (!(inter->blank_audio_min <= tb_blank)) {
372 		frl_dump_var("%i", inter->blank_audio_min);
373 		frl_dump_var("%i", tb_blank);
374 		return FRL_CAP_CHK_ERROR_AUDIO_BW;
375 	}
376 
377 	f_tb_average = (inter->f_pixel_clock_max / (params->h_active + params->h_blank)) * (tb_active + tb_blank);
378 	t_active_ref = inter->t_line * ((double)params->h_active / (params->h_active + params->h_blank));
379 	t_blank_ref  = inter->t_line * ((double)params->h_blank / (params->h_active + params->h_blank));
380 	t_active_min = (3.0 / 2.0) * tb_active / (params->lanes * inter->r_frl_char_min * (1.0 - inter->overhead_max));
381 	t_blank_min  = tb_blank / (params->lanes * inter->r_frl_char_min * (1.0 - inter->overhead_max));
382 
383 #ifdef DEBUG_FRL_CAP_CHK
384 	{
385 		frl_dump_var("%le", f_tb_average);
386 		frl_dump_var("%le", t_active_ref);
387 		frl_dump_var("%le", t_blank_ref);
388 		frl_dump_var("%le", t_active_min);
389 		frl_dump_var("%le", t_blank_min);
390 	}
391 #endif
392 
393 	if (t_active_ref >= t_active_min && t_blank_ref >= t_blank_min) {
394 		t_borrowed = 0;
395 		params->borrow_params.borrow_mode = FRL_BORROW_MODE_NONE;
396 	} else if ((t_active_ref < t_active_min) && (t_blank_ref >= t_blank_min)) {
397 		t_borrowed = t_active_min - t_active_ref;
398 		params->borrow_params.borrow_mode = FRL_BORROW_MODE_FROM_BLANK;
399 	} else {
400 		return FRL_CAP_CHK_ERROR_BORROW;
401 	}
402 
403 	tb_borrowed = dml_ceil(t_borrowed * f_tb_average, 1);
404 
405 #ifdef DEBUG_FRL_CAP_CHK
406 	{
407 		frl_dump_var("%le", tb_borrowed);
408 		frl_dump_var("%i", params->borrow_params.borrow_mode);
409 	}
410 #endif
411 
412 	if (!(tb_borrowed <= TB_BORROWED_MAX))
413 		return FRL_CAP_CHK_ERROR_MAX_BORROW;
414 
415 	c_frl_actual_payload = (int)(dml_ceil((3.0 / 2.0) * tb_active, 1) + tb_blank - c_frl_rc_savings);
416 	utilization          = c_frl_actual_payload / inter->c_frl_line;
417 	margin               = 1.0 - (utilization + inter->overhead_max);
418 
419 #ifdef DEBUG_FRL_CAP_CHK
420 	{
421 		frl_dump_var("%i",  c_frl_actual_payload);
422 		frl_dump_var("%le", utilization);
423 		frl_dump_var("%le", margin);
424 	}
425 #endif
426 
427 	if (margin < 0 && dcn_bw_fabs(margin) > EPSILON)
428 		return FRL_CAP_CHK_ERROR_MARGIN;
429 
430 	return FRL_CAP_CHK_OK;
431 }
432 
433 #if defined (CONFIG_DRM_AMD_DC_FP)
434 enum frl_cap_chk_result dml1_frl_cap_chk_compressed(struct frl_cap_chk_params *params,
435 						    struct frl_cap_chk_intermediates *inter)
436 {
437 	enum frl_cap_chk_result res;
438 	int      c_frl_available;
439 #if defined(DEBUG_FRL_CAP_CHK)
440 	int      c_frl_active_available;
441 	int      c_frl_blank_available;
442 #endif
443 	int      bytes_target = 0;
444 	int      hc_active_target;
445 	int      hc_blank_target_est1;
446 	int      hc_blank_target_est2;
447 	int      hc_blank_target = 0;
448 	int      c_frl_actual_target_payload;
449 	double   utilization_targeted;
450 	double   margin_target;
451 	double   f_tb_average;
452 	double   t_active_ref;
453 	double   t_blank_ref;
454 	double   t_active_target;
455 	double   t_blank_target;
456 	double   tb_borrowed;
457 #ifdef DEBUG_FRL_CAP_CHK
458 	double   tb_delta;
459 	double   tb_delta_limit;
460 	int      tb_worst;
461 #endif
462 	int table_size_444 = ARRAY_SIZE(prim_format_444);
463 	int table_size_422 = ARRAY_SIZE(prim_format_422);
464 	int table_size_420 = ARRAY_SIZE(prim_format_420);
465 	int i;
466 	bool hc_active_blank_predefined = false;
467 
468 	dc_assert_fp_enabled();
469 
470 	res = dml1_frl_cap_chk_common(inter, params);
471 
472 	if (res != FRL_CAP_CHK_OK)
473 		return res;
474 
475 	c_frl_available        = (int)dml_floor((1 - inter->overhead_max) * inter->c_frl_line, 1);
476 #if defined(DEBUG_FRL_CAP_CHK)
477 	c_frl_active_available = dml_floor(c_frl_available * ((double)params->h_active / (params->h_active + params->h_blank)), 1);
478 	c_frl_blank_available  = dml_floor(c_frl_available * ((double)params->h_blank / (params->h_active + params->h_blank)), 1);
479 #endif
480 	bytes_target           = (int)(params->slices * dml_ceil(params->bpp_target * params->slice_width / 8.0, 1));
481 
482 	if (!params->bypass_hc_target_calc)
483 			hc_active_target = (int)dml_ceil(bytes_target / 3.0, 1);
484 	else
485 		hc_active_target = params->borrow_params.hc_active_target;
486 
487 	if (!params->allow_all_bpp && params->vic != 0) {
488 		if (params->pixel_encoding == HDMI_FRL_PIXEL_ENCODING_444) {
489 			for (i = 0; i < table_size_444 ; i++) {
490 				if (prim_format_444[i].vic == params->vic) {
491 					params->borrow_params.hc_active_target = prim_format_444[i].hc_active;
492 					params->borrow_params.hc_blank_target  = prim_format_444[i].hc_blank;
493 					hc_active_blank_predefined = true;
494 					break;
495 				}
496 			}
497 		} else if (params->pixel_encoding == HDMI_FRL_PIXEL_ENCODING_422) {
498 			for (i = 0; i < table_size_422 ; i++) {
499 				if (prim_format_422[i].vic == params->vic) {
500 					params->borrow_params.hc_active_target = prim_format_422[i].hc_active;
501 					params->borrow_params.hc_blank_target  = prim_format_422[i].hc_blank;
502 					hc_active_blank_predefined = true;
503 					break;
504 				}
505 			}
506 		} else if (params->pixel_encoding == HDMI_FRL_PIXEL_ENCODING_420) {
507 			for (i = 0; i < table_size_420 ; i++) {
508 				if (prim_format_420[i].vic == params->vic) {
509 					params->borrow_params.hc_active_target = prim_format_420[i].hc_active;
510 					params->borrow_params.hc_blank_target  = prim_format_420[i].hc_blank;
511 					hc_active_blank_predefined = true;
512 					break;
513 				}
514 			}
515 		}
516 
517 		if (hc_active_blank_predefined) {
518 			hc_active_target = params->borrow_params.hc_active_target;
519 			hc_blank_target = params->borrow_params.hc_blank_target;
520 		}
521 	}
522 
523 	hc_blank_target_est1 = (int)dml_ceil(hc_active_target * ((double)params->h_blank / params->h_active), 1);
524 	hc_blank_target_est2 = (int)dml_max(hc_blank_target_est1, inter->blank_audio_min);
525 
526 	if (!hc_active_blank_predefined) {
527 		if (!params->bypass_hc_target_calc) {
528 			hc_blank_target = (int)(4 * dml_floor(dml_min(hc_blank_target_est2, c_frl_available - 3.0 / 2.0 * hc_active_target) / 4.0, 1));
529 
530 			params->borrow_params.hc_active_target = hc_active_target;
531 			params->borrow_params.hc_blank_target  = hc_blank_target;
532 		} else {
533 			hc_blank_target  = params->borrow_params.hc_blank_target;
534 		}
535 	}
536 
537 #ifdef DEBUG_FRL_CAP_CHK
538 	{
539 		frl_dump_var("%i", c_frl_available);
540 		frl_dump_var("%i", c_frl_active_available);
541 		frl_dump_var("%i", c_frl_blank_available);
542 		frl_dump_var("%i", bytes_target);
543 		frl_dump_var("%i", hc_active_target);
544 		frl_dump_var("%i", hc_blank_target_est1);
545 		frl_dump_var("%i", hc_blank_target_est2);
546 		frl_dump_var("%i", hc_blank_target);
547 	}
548 #endif
549 
550 	if (!(inter->blank_audio_min <= hc_blank_target)) {
551 		frl_dump_var("%i", inter->blank_audio_min);
552 		frl_dump_var("%i", hc_blank_target);
553 		return FRL_CAP_CHK_ERROR_AUDIO_BW;
554 	}
555 
556 	f_tb_average    = inter->f_pixel_clock_max / (params->h_active + params->h_blank) * (hc_active_target + hc_blank_target);
557 	t_active_ref    = inter->t_line * ((double)params->h_active / (params->h_active + params->h_blank));
558 	t_blank_ref     = inter->t_line - t_active_ref; // * ((double) params->h_blank / (params->h_active + params->h_blank));
559 	t_active_target = dml_max((hc_active_target / f_tb_average),
560 				  (3.0 / 2.0 * hc_active_target) /
561 				  (params->lanes * inter->r_frl_char_min * (1.0 - inter->overhead_max)));
562 	t_blank_target  = inter->t_line - t_active_target;
563 
564 	tb_borrowed     = t_active_target * f_tb_average - hc_active_target;
565 #ifdef DEBUG_FRL_CAP_CHK
566 	tb_delta        = dcn_bw_fabs(t_active_target - t_active_ref) * (hc_active_target + hc_blank_target_est1) / inter->t_line;
567 
568 	{
569 		frl_dump_var("%le", f_tb_average);
570 		frl_dump_var("%le", t_active_ref);
571 		frl_dump_var("%le", t_blank_ref);
572 		frl_dump_var("%le", t_active_target);
573 		frl_dump_var("%le", t_blank_target);
574 		frl_dump_var("%le", tb_delta);
575 	}
576 #endif
577 
578 	if (t_blank_target - t_blank_ref > DBL_EPSILON) {
579 #ifdef DEBUG_FRL_CAP_CHK
580 		tb_delta_limit = (t_active_ref - hc_active_target / f_tb_average) * (hc_active_target + hc_blank_target_est1) / inter->t_line;
581 #endif
582 		params->borrow_params.borrow_mode = FRL_BORROW_MODE_FROM_ACTIVE;
583 	} else if (t_active_target - t_active_ref > DBL_EPSILON) {
584 #ifdef DEBUG_FRL_CAP_CHK
585 		tb_delta_limit = tb_delta;
586 #endif
587 		params->borrow_params.borrow_mode = FRL_BORROW_MODE_FROM_BLANK;
588 	} else {
589 #ifdef DEBUG_FRL_CAP_CHK
590 		tb_delta_limit = 0;
591 #endif
592 		params->borrow_params.borrow_mode = FRL_BORROW_MODE_NONE;
593 	}
594 
595 #ifdef DEBUG_FRL_CAP_CHK
596 	tb_worst = dml_ceil(dml_max(tb_borrowed, tb_delta_limit), 1);
597 
598 	{
599 		frl_dump_var("%le", tb_delta_limit);
600 		frl_dump_var("%le", tb_borrowed);
601 		frl_dump_var("%i", params->borrow_params.borrow_mode);
602 		frl_dump_var("%i", tb_worst);
603 	}
604 #endif
605 
606 	if (!(tb_borrowed <= TB_BORROWED_MAX))
607 		return FRL_CAP_CHK_ERROR_MAX_BORROW;
608 
609 	c_frl_actual_target_payload = (int)(dml_ceil(3.0 / 2.0 * hc_active_target, 1) + hc_blank_target);
610 	utilization_targeted        = c_frl_actual_target_payload / inter->c_frl_line;
611 	margin_target               = 1.0 - (utilization_targeted + inter->overhead_max);
612 
613 #ifdef DEBUG_FRL_CAP_CHK
614 	{
615 		frl_dump_var("%i",  c_frl_actual_target_payload);
616 		frl_dump_var("%le", utilization_targeted);
617 		frl_dump_var("%le", margin_target);
618 	}
619 #endif
620 
621 	// oversubscribed bandwidth relative to margin
622 	if (margin_target < 0 && dcn_bw_fabs(margin_target) > EPSILON)
623 		return FRL_CAP_CHK_ERROR_MARGIN;
624 
625 	return FRL_CAP_CHK_OK;
626 }
627 #endif
628 
629 enum frl_cap_chk_result dml1_frl_cap_chk(struct frl_cap_chk_params *params)
630 {
631 	struct frl_cap_chk_intermediates inter;
632 
633 #if defined (CONFIG_DRM_AMD_DC_FP)
634 	if (params->compressed)
635 		return dml1_frl_cap_chk_compressed(params, &inter);
636 #endif
637 
638 	return dml1_frl_cap_chk_inter(params, &inter);
639 }
640 
641 enum frl_cap_chk_result dml1_frl_cap_chk_inter(struct frl_cap_chk_params *params,
642 					       struct frl_cap_chk_intermediates *inter)
643 {
644 	return dml1_frl_cap_chk_uncompressed(params, inter);
645 }
646 
647 static double calculate_compressed_active_time(uint32_t h_active,
648 	const uint32_t h_blank,
649 	const int hc_active,
650 	const int hc_blank,
651 	const uint32_t frl_num_lanes,
652 	const double pix_clk,
653 	const int frl_link_rate)
654 {
655 	double f_tb_average;
656 	double r_bit_nominal;
657 	double r_bit_min;
658 	double r_frl_char_min;
659 	double t_active_est_1;
660 	double t_active_est_2;
661 	double t_active_target;
662 	int c_frl_sb = 510;
663 	int frl_bit_tolerance = 300;
664 	double overhead_m = 0.003;
665 	double overhead_sb;
666 	double overhead_rs;
667 	double overhead_map;
668 	double overhead_min;
669 	double overhead_max;
670 
671 	switch (frl_link_rate) {
672 	case FRL_LINK_RATE_3GBPS:
673 		r_bit_nominal = 3.0e9;
674 		break;
675 	case FRL_LINK_RATE_6GBPS:
676 	case FRL_LINK_RATE_6GBPS_4LANE:
677 		r_bit_nominal = 6.0e9;
678 		break;
679 	case FRL_LINK_RATE_8GBPS:
680 		r_bit_nominal = 8.0e9;
681 		break;
682 	case FRL_LINK_RATE_10GBPS:
683 	default:
684 		r_bit_nominal = 10.0e9;
685 		break;
686 	case FRL_LINK_RATE_12GBPS:
687 		r_bit_nominal = 12.0e9;
688 		break;
689 	}
690 
691 	f_tb_average = pix_clk / (h_active + h_blank)
692 					* (hc_active + hc_blank);
693 
694 	c_frl_sb = 4 * c_frl_sb + frl_num_lanes;
695 	overhead_sb = (double)frl_num_lanes / c_frl_sb;
696 	overhead_rs = 8.0 * 4.0 / c_frl_sb;
697 	overhead_map = 2.5 / c_frl_sb;
698 	overhead_min = overhead_sb + overhead_rs + overhead_map;
699 	overhead_max = overhead_min + overhead_m;
700 
701 	r_bit_min = r_bit_nominal * (1.0 - frl_bit_tolerance / 1000000.0);
702 	r_frl_char_min = r_bit_min / 18.0;
703 	t_active_est_1 = hc_active / f_tb_average;
704 	t_active_est_2 = (3.0 / 2.0 * hc_active) /
705 				  (frl_num_lanes * r_frl_char_min * (1.0 - overhead_max));
706 
707 	if (t_active_est_1 > t_active_est_2) {
708 		t_active_target = t_active_est_1;
709 	} else {
710 		t_active_target = t_active_est_2;
711 	}
712 
713 	return t_active_target;
714 }
715 
716 void frl_modified_pix_clock_for_dsc_padding(const int hc_active_target,
717 	const int hc_blank_target,
718 	const uint8_t frl_num_lanes,
719 	const uint32_t pix_clk_100hz,
720 	const int frl_link_rate,
721 	const uint32_t h_addressable,
722 	const uint32_t h_border_left,
723 	const uint32_t h_border_right,
724 	const uint32_t h_total,
725 	const uint32_t h_addressable_otg,
726 	uint32_t *pix_clk_100hz_otg,
727 	uint32_t *h_total_otg)
728 {
729 	double pix_clk;
730 	int h_active;
731 	int h_blank;
732 	double t_active_target;
733 	double hw_pix_clk;
734 	double h_total_otg_temp;
735 
736 	pix_clk = (double)pix_clk_100hz * 100;
737 
738 	h_active = h_addressable + h_border_left + h_border_right;
739 	h_blank = h_total - h_active;
740 
741 	t_active_target = calculate_compressed_active_time(h_active, h_blank, hc_active_target, hc_blank_target, frl_num_lanes, pix_clk, frl_link_rate);
742 
743 	h_total_otg_temp = ((double)h_addressable_otg * (double)h_total) / ((double)pix_clk_100hz * 100.0 * t_active_target);
744 	/* Htotal must be a multiple of 4, also take the ceiling */
745 	*h_total_otg = (uint32_t)dml_ceil(h_total_otg_temp, 4.0);
746 
747 	hw_pix_clk = (double)(pix_clk_100hz * 100.0 * (double)*h_total_otg) / (double)h_total;
748 	*pix_clk_100hz_otg = (uint32_t)(hw_pix_clk / 100.0);
749 }
750 
751 int frl_modify_borrow_mode_for_dsc_padding(const uint32_t pix_clk_100hz,
752 	const uint32_t h_active,
753 	const uint32_t h_active_padded,
754 	const uint32_t h_blank,
755 	const uint32_t h_blank_padded,
756 	const int hc_active,
757 	const int hc_blank,
758 	const uint8_t frl_num_lanes,
759 	const int frl_link_rate)
760 {
761 	double f_pixel_clock_max;
762 	double t_line;
763 	double t_active;
764 	double t_blank;
765 	double t_active_target;
766 	double t_blank_target;
767 	double pix_clk_tolerance = 0.005;
768 
769 	enum frl_borrow_mode borrow_mode;
770 
771 	f_pixel_clock_max = (double)pix_clk_100hz * (1.0 + pix_clk_tolerance);
772 	t_line = (double)(h_active + h_blank) / f_pixel_clock_max;
773 
774 	t_active_target = calculate_compressed_active_time(h_active, h_blank, hc_active, hc_blank, frl_num_lanes, f_pixel_clock_max, frl_link_rate);
775 
776 	t_active = t_line * ((double)h_active_padded / (h_active_padded + h_blank_padded));
777 	t_blank = t_line - t_active;
778 
779 	t_blank_target = t_line - t_active_target;
780 
781 	if (t_blank_target - t_blank > DBL_EPSILON) {
782 		borrow_mode = FRL_BORROW_MODE_FROM_ACTIVE;
783 	} else if (t_active_target - t_active > DBL_EPSILON) {
784 		borrow_mode = FRL_BORROW_MODE_FROM_BLANK;
785 	} else {
786 		borrow_mode = FRL_BORROW_MODE_NONE;
787 	}
788 
789 	return borrow_mode;
790 }
791