1 | /* |
2 | * Copyright 2019 Advanced Micro Devices, Inc. |
3 | * |
4 | * Permission is hereby granted, free of charge, to any person obtaining a |
5 | * copy of this software and associated documentation files (the "Software"), |
6 | * to deal in the Software without restriction, including without limitation |
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
8 | * and/or sell copies of the Software, and to permit persons to whom the |
9 | * Software is furnished to do so, subject to the following conditions: |
10 | * |
11 | * The above copyright notice and this permission notice shall be included in |
12 | * all copies or substantial portions of the Software. |
13 | * |
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR |
18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
20 | * OTHER DEALINGS IN THE SOFTWARE. |
21 | * |
22 | * Author: AMD |
23 | */ |
24 | |
25 | #include <drm/display/drm_dp_helper.h> |
26 | #include <drm/display/drm_dsc_helper.h> |
27 | #include "dc_hw_types.h" |
28 | #include "dsc.h" |
29 | #include "dc.h" |
30 | #include "rc_calc.h" |
31 | #include "fixed31_32.h" |
32 | |
33 | /* This module's internal functions */ |
34 | |
35 | /* default DSC policy target bitrate limit is 16bpp */ |
36 | static uint32_t dsc_policy_max_target_bpp_limit = 16; |
37 | |
38 | /* default DSC policy enables DSC only when needed */ |
39 | static bool dsc_policy_enable_dsc_when_not_needed; |
40 | |
41 | static bool dsc_policy_disable_dsc_stream_overhead; |
42 | |
43 | static bool disable_128b_132b_stream_overhead; |
44 | |
45 | #ifndef MAX |
46 | #define MAX(X, Y) ((X) > (Y) ? (X) : (Y)) |
47 | #endif |
48 | #ifndef MIN |
49 | #define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) |
50 | #endif |
51 | |
52 | /* Need to account for padding due to pixel-to-symbol packing |
53 | * for uncompressed 128b/132b streams. |
54 | */ |
55 | static uint32_t apply_128b_132b_stream_overhead( |
56 | const struct dc_crtc_timing *timing, const uint32_t kbps) |
57 | { |
58 | uint32_t total_kbps = kbps; |
59 | |
60 | if (disable_128b_132b_stream_overhead) |
61 | return kbps; |
62 | |
63 | if (!timing->flags.DSC) { |
64 | struct fixed31_32 bpp; |
65 | struct fixed31_32 overhead_factor; |
66 | |
67 | bpp = dc_fixpt_from_int(arg: kbps); |
68 | bpp = dc_fixpt_div_int(arg1: bpp, arg2: timing->pix_clk_100hz / 10); |
69 | |
70 | /* Symbols_per_HActive = HActive * bpp / (4 lanes * 32-bit symbol size) |
71 | * Overhead_factor = ceil(Symbols_per_HActive) / Symbols_per_HActive |
72 | */ |
73 | overhead_factor = dc_fixpt_from_int(arg: timing->h_addressable); |
74 | overhead_factor = dc_fixpt_mul(arg1: overhead_factor, arg2: bpp); |
75 | overhead_factor = dc_fixpt_div_int(arg1: overhead_factor, arg2: 128); |
76 | overhead_factor = dc_fixpt_div( |
77 | arg1: dc_fixpt_from_int(arg: dc_fixpt_ceil(arg: overhead_factor)), |
78 | arg2: overhead_factor); |
79 | |
80 | total_kbps = dc_fixpt_ceil( |
81 | arg: dc_fixpt_mul_int(arg1: overhead_factor, arg2: total_kbps)); |
82 | } |
83 | |
84 | return total_kbps; |
85 | } |
86 | |
87 | uint32_t dc_bandwidth_in_kbps_from_timing( |
88 | const struct dc_crtc_timing *timing, |
89 | const enum dc_link_encoding_format link_encoding) |
90 | { |
91 | uint32_t bits_per_channel = 0; |
92 | uint32_t kbps; |
93 | |
94 | if (timing->flags.DSC) |
95 | return dc_dsc_stream_bandwidth_in_kbps(timing, |
96 | bpp_x16: timing->dsc_cfg.bits_per_pixel, |
97 | num_slices_h: timing->dsc_cfg.num_slices_h, |
98 | is_dp: timing->dsc_cfg.is_dp); |
99 | |
100 | switch (timing->display_color_depth) { |
101 | case COLOR_DEPTH_666: |
102 | bits_per_channel = 6; |
103 | break; |
104 | case COLOR_DEPTH_888: |
105 | bits_per_channel = 8; |
106 | break; |
107 | case COLOR_DEPTH_101010: |
108 | bits_per_channel = 10; |
109 | break; |
110 | case COLOR_DEPTH_121212: |
111 | bits_per_channel = 12; |
112 | break; |
113 | case COLOR_DEPTH_141414: |
114 | bits_per_channel = 14; |
115 | break; |
116 | case COLOR_DEPTH_161616: |
117 | bits_per_channel = 16; |
118 | break; |
119 | default: |
120 | ASSERT(bits_per_channel != 0); |
121 | bits_per_channel = 8; |
122 | break; |
123 | } |
124 | |
125 | kbps = timing->pix_clk_100hz / 10; |
126 | kbps *= bits_per_channel; |
127 | |
128 | if (timing->flags.Y_ONLY != 1) { |
129 | /*Only YOnly make reduce bandwidth by 1/3 compares to RGB*/ |
130 | kbps *= 3; |
131 | if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) |
132 | kbps /= 2; |
133 | else if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) |
134 | kbps = kbps * 2 / 3; |
135 | } |
136 | |
137 | if (link_encoding == DC_LINK_ENCODING_DP_128b_132b) |
138 | kbps = apply_128b_132b_stream_overhead(timing, kbps); |
139 | |
140 | return kbps; |
141 | } |
142 | |
143 | |
144 | /* Forward Declerations */ |
145 | static bool decide_dsc_bandwidth_range( |
146 | const uint32_t min_bpp_x16, |
147 | const uint32_t max_bpp_x16, |
148 | const uint32_t num_slices_h, |
149 | const struct dsc_enc_caps *dsc_caps, |
150 | const struct dc_crtc_timing *timing, |
151 | const enum dc_link_encoding_format link_encoding, |
152 | struct dc_dsc_bw_range *range); |
153 | |
154 | static uint32_t compute_bpp_x16_from_target_bandwidth( |
155 | const uint32_t bandwidth_in_kbps, |
156 | const struct dc_crtc_timing *timing, |
157 | const uint32_t num_slices_h, |
158 | const uint32_t bpp_increment_div, |
159 | const bool is_dp); |
160 | |
161 | static void get_dsc_enc_caps( |
162 | const struct display_stream_compressor *dsc, |
163 | struct dsc_enc_caps *dsc_enc_caps, |
164 | int pixel_clock_100Hz); |
165 | |
166 | static bool intersect_dsc_caps( |
167 | const struct dsc_dec_dpcd_caps *dsc_sink_caps, |
168 | const struct dsc_enc_caps *dsc_enc_caps, |
169 | enum dc_pixel_encoding pixel_encoding, |
170 | struct dsc_enc_caps *dsc_common_caps); |
171 | |
172 | static bool setup_dsc_config( |
173 | const struct dsc_dec_dpcd_caps *dsc_sink_caps, |
174 | const struct dsc_enc_caps *dsc_enc_caps, |
175 | int target_bandwidth_kbps, |
176 | const struct dc_crtc_timing *timing, |
177 | const struct dc_dsc_config_options *options, |
178 | const enum dc_link_encoding_format link_encoding, |
179 | struct dc_dsc_config *dsc_cfg); |
180 | |
181 | static bool dsc_buff_block_size_from_dpcd(int dpcd_buff_block_size, int *buff_block_size) |
182 | { |
183 | |
184 | switch (dpcd_buff_block_size) { |
185 | case DP_DSC_RC_BUF_BLK_SIZE_1: |
186 | *buff_block_size = 1024; |
187 | break; |
188 | case DP_DSC_RC_BUF_BLK_SIZE_4: |
189 | *buff_block_size = 4 * 1024; |
190 | break; |
191 | case DP_DSC_RC_BUF_BLK_SIZE_16: |
192 | *buff_block_size = 16 * 1024; |
193 | break; |
194 | case DP_DSC_RC_BUF_BLK_SIZE_64: |
195 | *buff_block_size = 64 * 1024; |
196 | break; |
197 | default: { |
198 | dm_error("%s: DPCD DSC buffer size not recognized.\n" , __func__); |
199 | return false; |
200 | } |
201 | } |
202 | |
203 | return true; |
204 | } |
205 | |
206 | |
207 | static bool dsc_line_buff_depth_from_dpcd(int dpcd_line_buff_bit_depth, int *line_buff_bit_depth) |
208 | { |
209 | if (0 <= dpcd_line_buff_bit_depth && dpcd_line_buff_bit_depth <= 7) |
210 | *line_buff_bit_depth = dpcd_line_buff_bit_depth + 9; |
211 | else if (dpcd_line_buff_bit_depth == 8) |
212 | *line_buff_bit_depth = 8; |
213 | else { |
214 | dm_error("%s: DPCD DSC buffer depth not recognized.\n" , __func__); |
215 | return false; |
216 | } |
217 | |
218 | return true; |
219 | } |
220 | |
221 | |
222 | static bool dsc_throughput_from_dpcd(int dpcd_throughput, int *throughput) |
223 | { |
224 | switch (dpcd_throughput) { |
225 | case DP_DSC_THROUGHPUT_MODE_0_UNSUPPORTED: |
226 | *throughput = 0; |
227 | break; |
228 | case DP_DSC_THROUGHPUT_MODE_0_170: |
229 | *throughput = 170; |
230 | break; |
231 | case DP_DSC_THROUGHPUT_MODE_0_340: |
232 | *throughput = 340; |
233 | break; |
234 | case DP_DSC_THROUGHPUT_MODE_0_400: |
235 | *throughput = 400; |
236 | break; |
237 | case DP_DSC_THROUGHPUT_MODE_0_450: |
238 | *throughput = 450; |
239 | break; |
240 | case DP_DSC_THROUGHPUT_MODE_0_500: |
241 | *throughput = 500; |
242 | break; |
243 | case DP_DSC_THROUGHPUT_MODE_0_550: |
244 | *throughput = 550; |
245 | break; |
246 | case DP_DSC_THROUGHPUT_MODE_0_600: |
247 | *throughput = 600; |
248 | break; |
249 | case DP_DSC_THROUGHPUT_MODE_0_650: |
250 | *throughput = 650; |
251 | break; |
252 | case DP_DSC_THROUGHPUT_MODE_0_700: |
253 | *throughput = 700; |
254 | break; |
255 | case DP_DSC_THROUGHPUT_MODE_0_750: |
256 | *throughput = 750; |
257 | break; |
258 | case DP_DSC_THROUGHPUT_MODE_0_800: |
259 | *throughput = 800; |
260 | break; |
261 | case DP_DSC_THROUGHPUT_MODE_0_850: |
262 | *throughput = 850; |
263 | break; |
264 | case DP_DSC_THROUGHPUT_MODE_0_900: |
265 | *throughput = 900; |
266 | break; |
267 | case DP_DSC_THROUGHPUT_MODE_0_950: |
268 | *throughput = 950; |
269 | break; |
270 | case DP_DSC_THROUGHPUT_MODE_0_1000: |
271 | *throughput = 1000; |
272 | break; |
273 | default: { |
274 | dm_error("%s: DPCD DSC throughput mode not recognized.\n" , __func__); |
275 | return false; |
276 | } |
277 | } |
278 | |
279 | return true; |
280 | } |
281 | |
282 | |
283 | static bool dsc_bpp_increment_div_from_dpcd(uint8_t bpp_increment_dpcd, uint32_t *bpp_increment_div) |
284 | { |
285 | // Mask bpp increment dpcd field to avoid reading other fields |
286 | bpp_increment_dpcd &= 0x7; |
287 | |
288 | switch (bpp_increment_dpcd) { |
289 | case 0: |
290 | *bpp_increment_div = 16; |
291 | break; |
292 | case 1: |
293 | *bpp_increment_div = 8; |
294 | break; |
295 | case 2: |
296 | *bpp_increment_div = 4; |
297 | break; |
298 | case 3: |
299 | *bpp_increment_div = 2; |
300 | break; |
301 | case 4: |
302 | *bpp_increment_div = 1; |
303 | break; |
304 | default: { |
305 | dm_error("%s: DPCD DSC bits-per-pixel increment not recognized.\n" , __func__); |
306 | return false; |
307 | } |
308 | } |
309 | |
310 | return true; |
311 | } |
312 | |
313 | |
314 | |
315 | bool dc_dsc_parse_dsc_dpcd(const struct dc *dc, |
316 | const uint8_t *dpcd_dsc_basic_data, |
317 | const uint8_t *dpcd_dsc_branch_decoder_caps, |
318 | struct dsc_dec_dpcd_caps *dsc_sink_caps) |
319 | { |
320 | if (!dpcd_dsc_basic_data) |
321 | return false; |
322 | |
323 | dsc_sink_caps->is_dsc_supported = |
324 | (dpcd_dsc_basic_data[DP_DSC_SUPPORT - DP_DSC_SUPPORT] & DP_DSC_DECOMPRESSION_IS_SUPPORTED) != 0; |
325 | if (!dsc_sink_caps->is_dsc_supported) |
326 | return false; |
327 | |
328 | dsc_sink_caps->dsc_version = dpcd_dsc_basic_data[DP_DSC_REV - DP_DSC_SUPPORT]; |
329 | |
330 | { |
331 | int buff_block_size; |
332 | int buff_size; |
333 | |
334 | if (!dsc_buff_block_size_from_dpcd(dpcd_buff_block_size: dpcd_dsc_basic_data[DP_DSC_RC_BUF_BLK_SIZE - DP_DSC_SUPPORT], |
335 | buff_block_size: &buff_block_size)) |
336 | return false; |
337 | |
338 | buff_size = dpcd_dsc_basic_data[DP_DSC_RC_BUF_SIZE - DP_DSC_SUPPORT] + 1; |
339 | dsc_sink_caps->rc_buffer_size = buff_size * buff_block_size; |
340 | } |
341 | |
342 | dsc_sink_caps->slice_caps1.raw = dpcd_dsc_basic_data[DP_DSC_SLICE_CAP_1 - DP_DSC_SUPPORT]; |
343 | if (!dsc_line_buff_depth_from_dpcd(dpcd_line_buff_bit_depth: dpcd_dsc_basic_data[DP_DSC_LINE_BUF_BIT_DEPTH - DP_DSC_SUPPORT], |
344 | line_buff_bit_depth: &dsc_sink_caps->lb_bit_depth)) |
345 | return false; |
346 | |
347 | dsc_sink_caps->is_block_pred_supported = |
348 | (dpcd_dsc_basic_data[DP_DSC_BLK_PREDICTION_SUPPORT - DP_DSC_SUPPORT] & |
349 | DP_DSC_BLK_PREDICTION_IS_SUPPORTED) != 0; |
350 | |
351 | dsc_sink_caps->edp_max_bits_per_pixel = |
352 | dpcd_dsc_basic_data[DP_DSC_MAX_BITS_PER_PIXEL_LOW - DP_DSC_SUPPORT] | |
353 | dpcd_dsc_basic_data[DP_DSC_MAX_BITS_PER_PIXEL_HI - DP_DSC_SUPPORT] << 8; |
354 | |
355 | dsc_sink_caps->color_formats.raw = dpcd_dsc_basic_data[DP_DSC_DEC_COLOR_FORMAT_CAP - DP_DSC_SUPPORT]; |
356 | dsc_sink_caps->color_depth.raw = dpcd_dsc_basic_data[DP_DSC_DEC_COLOR_DEPTH_CAP - DP_DSC_SUPPORT]; |
357 | |
358 | { |
359 | int dpcd_throughput = dpcd_dsc_basic_data[DP_DSC_PEAK_THROUGHPUT - DP_DSC_SUPPORT]; |
360 | |
361 | if (!dsc_throughput_from_dpcd(dpcd_throughput: dpcd_throughput & DP_DSC_THROUGHPUT_MODE_0_MASK, |
362 | throughput: &dsc_sink_caps->throughput_mode_0_mps)) |
363 | return false; |
364 | |
365 | dpcd_throughput = (dpcd_throughput & DP_DSC_THROUGHPUT_MODE_1_MASK) >> DP_DSC_THROUGHPUT_MODE_1_SHIFT; |
366 | if (!dsc_throughput_from_dpcd(dpcd_throughput, throughput: &dsc_sink_caps->throughput_mode_1_mps)) |
367 | return false; |
368 | } |
369 | |
370 | dsc_sink_caps->max_slice_width = dpcd_dsc_basic_data[DP_DSC_MAX_SLICE_WIDTH - DP_DSC_SUPPORT] * 320; |
371 | dsc_sink_caps->slice_caps2.raw = dpcd_dsc_basic_data[DP_DSC_SLICE_CAP_2 - DP_DSC_SUPPORT]; |
372 | |
373 | if (!dsc_bpp_increment_div_from_dpcd(bpp_increment_dpcd: dpcd_dsc_basic_data[DP_DSC_BITS_PER_PIXEL_INC - DP_DSC_SUPPORT], |
374 | bpp_increment_div: &dsc_sink_caps->bpp_increment_div)) |
375 | return false; |
376 | |
377 | if (dc->debug.dsc_bpp_increment_div) { |
378 | /* dsc_bpp_increment_div should onl be 1, 2, 4, 8 or 16, but rather than rejecting invalid values, |
379 | * we'll accept all and get it into range. This also makes the above check against 0 redundant, |
380 | * but that one stresses out the override will be only used if it's not 0. |
381 | */ |
382 | if (dc->debug.dsc_bpp_increment_div >= 1) |
383 | dsc_sink_caps->bpp_increment_div = 1; |
384 | if (dc->debug.dsc_bpp_increment_div >= 2) |
385 | dsc_sink_caps->bpp_increment_div = 2; |
386 | if (dc->debug.dsc_bpp_increment_div >= 4) |
387 | dsc_sink_caps->bpp_increment_div = 4; |
388 | if (dc->debug.dsc_bpp_increment_div >= 8) |
389 | dsc_sink_caps->bpp_increment_div = 8; |
390 | if (dc->debug.dsc_bpp_increment_div >= 16) |
391 | dsc_sink_caps->bpp_increment_div = 16; |
392 | } |
393 | |
394 | /* Extended caps */ |
395 | if (dpcd_dsc_branch_decoder_caps == NULL) { // branch decoder DPCD DSC data can be null for non branch device |
396 | dsc_sink_caps->branch_overall_throughput_0_mps = 0; |
397 | dsc_sink_caps->branch_overall_throughput_1_mps = 0; |
398 | dsc_sink_caps->branch_max_line_width = 0; |
399 | return true; |
400 | } |
401 | |
402 | dsc_sink_caps->branch_overall_throughput_0_mps = |
403 | dpcd_dsc_branch_decoder_caps[DP_DSC_BRANCH_OVERALL_THROUGHPUT_0 - DP_DSC_BRANCH_OVERALL_THROUGHPUT_0]; |
404 | if (dsc_sink_caps->branch_overall_throughput_0_mps == 0) |
405 | dsc_sink_caps->branch_overall_throughput_0_mps = 0; |
406 | else if (dsc_sink_caps->branch_overall_throughput_0_mps == 1) |
407 | dsc_sink_caps->branch_overall_throughput_0_mps = 680; |
408 | else { |
409 | dsc_sink_caps->branch_overall_throughput_0_mps *= 50; |
410 | dsc_sink_caps->branch_overall_throughput_0_mps += 600; |
411 | } |
412 | |
413 | dsc_sink_caps->branch_overall_throughput_1_mps = |
414 | dpcd_dsc_branch_decoder_caps[DP_DSC_BRANCH_OVERALL_THROUGHPUT_1 - DP_DSC_BRANCH_OVERALL_THROUGHPUT_0]; |
415 | if (dsc_sink_caps->branch_overall_throughput_1_mps == 0) |
416 | dsc_sink_caps->branch_overall_throughput_1_mps = 0; |
417 | else if (dsc_sink_caps->branch_overall_throughput_1_mps == 1) |
418 | dsc_sink_caps->branch_overall_throughput_1_mps = 680; |
419 | else { |
420 | dsc_sink_caps->branch_overall_throughput_1_mps *= 50; |
421 | dsc_sink_caps->branch_overall_throughput_1_mps += 600; |
422 | } |
423 | |
424 | dsc_sink_caps->branch_max_line_width = |
425 | dpcd_dsc_branch_decoder_caps[DP_DSC_BRANCH_MAX_LINE_WIDTH - DP_DSC_BRANCH_OVERALL_THROUGHPUT_0] * 320; |
426 | ASSERT(dsc_sink_caps->branch_max_line_width == 0 || dsc_sink_caps->branch_max_line_width >= 5120); |
427 | |
428 | dsc_sink_caps->is_dp = true; |
429 | return true; |
430 | } |
431 | |
432 | |
433 | /* If DSC is possbile, get DSC bandwidth range based on [min_bpp, max_bpp] target bitrate range and |
434 | * timing's pixel clock and uncompressed bandwidth. |
435 | * If DSC is not possible, leave '*range' untouched. |
436 | */ |
437 | bool dc_dsc_compute_bandwidth_range( |
438 | const struct display_stream_compressor *dsc, |
439 | uint32_t dsc_min_slice_height_override, |
440 | uint32_t min_bpp_x16, |
441 | uint32_t max_bpp_x16, |
442 | const struct dsc_dec_dpcd_caps *dsc_sink_caps, |
443 | const struct dc_crtc_timing *timing, |
444 | const enum dc_link_encoding_format link_encoding, |
445 | struct dc_dsc_bw_range *range) |
446 | { |
447 | bool is_dsc_possible = false; |
448 | struct dsc_enc_caps dsc_enc_caps; |
449 | struct dsc_enc_caps dsc_common_caps; |
450 | struct dc_dsc_config config; |
451 | struct dc_dsc_config_options options = {0}; |
452 | |
453 | options.dsc_min_slice_height_override = dsc_min_slice_height_override; |
454 | options.max_target_bpp_limit_override_x16 = max_bpp_x16; |
455 | options.slice_height_granularity = 1; |
456 | |
457 | get_dsc_enc_caps(dsc, dsc_enc_caps: &dsc_enc_caps, pixel_clock_100Hz: timing->pix_clk_100hz); |
458 | |
459 | is_dsc_possible = intersect_dsc_caps(dsc_sink_caps, dsc_enc_caps: &dsc_enc_caps, |
460 | pixel_encoding: timing->pixel_encoding, dsc_common_caps: &dsc_common_caps); |
461 | |
462 | if (is_dsc_possible) |
463 | is_dsc_possible = setup_dsc_config(dsc_sink_caps, dsc_enc_caps: &dsc_enc_caps, target_bandwidth_kbps: 0, timing, |
464 | options: &options, link_encoding, dsc_cfg: &config); |
465 | |
466 | if (is_dsc_possible) |
467 | is_dsc_possible = decide_dsc_bandwidth_range(min_bpp_x16, max_bpp_x16, |
468 | num_slices_h: config.num_slices_h, dsc_caps: &dsc_common_caps, timing, link_encoding, range); |
469 | |
470 | return is_dsc_possible; |
471 | } |
472 | |
473 | static void get_dsc_enc_caps( |
474 | const struct display_stream_compressor *dsc, |
475 | struct dsc_enc_caps *dsc_enc_caps, |
476 | int pixel_clock_100Hz) |
477 | { |
478 | // This is a static HW query, so we can use any DSC |
479 | |
480 | memset(dsc_enc_caps, 0, sizeof(struct dsc_enc_caps)); |
481 | if (dsc) { |
482 | if (!dsc->ctx->dc->debug.disable_dsc) |
483 | dsc->funcs->dsc_get_enc_caps(dsc_enc_caps, pixel_clock_100Hz); |
484 | if (dsc->ctx->dc->debug.native422_support) |
485 | dsc_enc_caps->color_formats.bits.YCBCR_NATIVE_422 = 1; |
486 | } |
487 | } |
488 | |
489 | /* Returns 'false' if no intersection was found for at least one capability. |
490 | * It also implicitly validates some sink caps against invalid value of zero. |
491 | */ |
492 | static bool intersect_dsc_caps( |
493 | const struct dsc_dec_dpcd_caps *dsc_sink_caps, |
494 | const struct dsc_enc_caps *dsc_enc_caps, |
495 | enum dc_pixel_encoding pixel_encoding, |
496 | struct dsc_enc_caps *dsc_common_caps) |
497 | { |
498 | int32_t max_slices; |
499 | int32_t total_sink_throughput; |
500 | |
501 | memset(dsc_common_caps, 0, sizeof(struct dsc_enc_caps)); |
502 | |
503 | dsc_common_caps->dsc_version = min(dsc_sink_caps->dsc_version, dsc_enc_caps->dsc_version); |
504 | if (!dsc_common_caps->dsc_version) |
505 | return false; |
506 | |
507 | dsc_common_caps->slice_caps.bits.NUM_SLICES_1 = |
508 | dsc_sink_caps->slice_caps1.bits.NUM_SLICES_1 && dsc_enc_caps->slice_caps.bits.NUM_SLICES_1; |
509 | dsc_common_caps->slice_caps.bits.NUM_SLICES_2 = |
510 | dsc_sink_caps->slice_caps1.bits.NUM_SLICES_2 && dsc_enc_caps->slice_caps.bits.NUM_SLICES_2; |
511 | dsc_common_caps->slice_caps.bits.NUM_SLICES_4 = |
512 | dsc_sink_caps->slice_caps1.bits.NUM_SLICES_4 && dsc_enc_caps->slice_caps.bits.NUM_SLICES_4; |
513 | dsc_common_caps->slice_caps.bits.NUM_SLICES_8 = |
514 | dsc_sink_caps->slice_caps1.bits.NUM_SLICES_8 && dsc_enc_caps->slice_caps.bits.NUM_SLICES_8; |
515 | if (!dsc_common_caps->slice_caps.raw) |
516 | return false; |
517 | |
518 | dsc_common_caps->lb_bit_depth = min(dsc_sink_caps->lb_bit_depth, dsc_enc_caps->lb_bit_depth); |
519 | if (!dsc_common_caps->lb_bit_depth) |
520 | return false; |
521 | |
522 | dsc_common_caps->is_block_pred_supported = |
523 | dsc_sink_caps->is_block_pred_supported && dsc_enc_caps->is_block_pred_supported; |
524 | |
525 | dsc_common_caps->color_formats.raw = dsc_sink_caps->color_formats.raw & dsc_enc_caps->color_formats.raw; |
526 | if (!dsc_common_caps->color_formats.raw) |
527 | return false; |
528 | |
529 | dsc_common_caps->color_depth.raw = dsc_sink_caps->color_depth.raw & dsc_enc_caps->color_depth.raw; |
530 | if (!dsc_common_caps->color_depth.raw) |
531 | return false; |
532 | |
533 | max_slices = 0; |
534 | if (dsc_common_caps->slice_caps.bits.NUM_SLICES_1) |
535 | max_slices = 1; |
536 | |
537 | if (dsc_common_caps->slice_caps.bits.NUM_SLICES_2) |
538 | max_slices = 2; |
539 | |
540 | if (dsc_common_caps->slice_caps.bits.NUM_SLICES_4) |
541 | max_slices = 4; |
542 | |
543 | total_sink_throughput = max_slices * dsc_sink_caps->throughput_mode_0_mps; |
544 | if (pixel_encoding == PIXEL_ENCODING_YCBCR422 || pixel_encoding == PIXEL_ENCODING_YCBCR420) |
545 | total_sink_throughput = max_slices * dsc_sink_caps->throughput_mode_1_mps; |
546 | |
547 | dsc_common_caps->max_total_throughput_mps = min(total_sink_throughput, dsc_enc_caps->max_total_throughput_mps); |
548 | |
549 | dsc_common_caps->max_slice_width = min(dsc_sink_caps->max_slice_width, dsc_enc_caps->max_slice_width); |
550 | if (!dsc_common_caps->max_slice_width) |
551 | return false; |
552 | |
553 | dsc_common_caps->bpp_increment_div = min(dsc_sink_caps->bpp_increment_div, dsc_enc_caps->bpp_increment_div); |
554 | |
555 | // TODO DSC: Remove this workaround for N422 and 420 once it's fixed, or move it to get_dsc_encoder_caps() |
556 | if (pixel_encoding == PIXEL_ENCODING_YCBCR422 || pixel_encoding == PIXEL_ENCODING_YCBCR420) |
557 | dsc_common_caps->bpp_increment_div = min(dsc_common_caps->bpp_increment_div, (uint32_t)8); |
558 | |
559 | dsc_common_caps->edp_sink_max_bits_per_pixel = dsc_sink_caps->edp_max_bits_per_pixel; |
560 | dsc_common_caps->is_dp = dsc_sink_caps->is_dp; |
561 | return true; |
562 | } |
563 | |
564 | static inline uint32_t dsc_div_by_10_round_up(uint32_t value) |
565 | { |
566 | return (value + 9) / 10; |
567 | } |
568 | |
569 | static uint32_t compute_bpp_x16_from_target_bandwidth( |
570 | const uint32_t bandwidth_in_kbps, |
571 | const struct dc_crtc_timing *timing, |
572 | const uint32_t num_slices_h, |
573 | const uint32_t bpp_increment_div, |
574 | const bool is_dp) |
575 | { |
576 | uint32_t overhead_in_kbps; |
577 | struct fixed31_32 effective_bandwidth_in_kbps; |
578 | struct fixed31_32 bpp_x16; |
579 | |
580 | overhead_in_kbps = dc_dsc_stream_bandwidth_overhead_in_kbps( |
581 | timing, num_slices_h, is_dp); |
582 | effective_bandwidth_in_kbps = dc_fixpt_from_int(arg: bandwidth_in_kbps); |
583 | effective_bandwidth_in_kbps = dc_fixpt_sub_int(arg1: effective_bandwidth_in_kbps, |
584 | arg2: overhead_in_kbps); |
585 | bpp_x16 = dc_fixpt_mul_int(arg1: effective_bandwidth_in_kbps, arg2: 10); |
586 | bpp_x16 = dc_fixpt_div_int(arg1: bpp_x16, arg2: timing->pix_clk_100hz); |
587 | bpp_x16 = dc_fixpt_from_int(arg: dc_fixpt_floor(arg: dc_fixpt_mul_int(arg1: bpp_x16, arg2: bpp_increment_div))); |
588 | bpp_x16 = dc_fixpt_div_int(arg1: bpp_x16, arg2: bpp_increment_div); |
589 | bpp_x16 = dc_fixpt_mul_int(arg1: bpp_x16, arg2: 16); |
590 | return dc_fixpt_floor(arg: bpp_x16); |
591 | } |
592 | |
593 | /* Decide DSC bandwidth range based on signal, timing, specs specific and input min and max |
594 | * requirements. |
595 | * The range output includes decided min/max target bpp, the respective bandwidth requirements |
596 | * and native timing bandwidth requirement when DSC is not used. |
597 | */ |
598 | static bool decide_dsc_bandwidth_range( |
599 | const uint32_t min_bpp_x16, |
600 | const uint32_t max_bpp_x16, |
601 | const uint32_t num_slices_h, |
602 | const struct dsc_enc_caps *dsc_caps, |
603 | const struct dc_crtc_timing *timing, |
604 | const enum dc_link_encoding_format link_encoding, |
605 | struct dc_dsc_bw_range *range) |
606 | { |
607 | uint32_t preferred_bpp_x16 = timing->dsc_fixed_bits_per_pixel_x16; |
608 | |
609 | memset(range, 0, sizeof(*range)); |
610 | |
611 | /* apply signal, timing, specs and explicitly specified DSC range requirements */ |
612 | if (preferred_bpp_x16) { |
613 | if (preferred_bpp_x16 <= max_bpp_x16 && |
614 | preferred_bpp_x16 >= min_bpp_x16) { |
615 | range->max_target_bpp_x16 = preferred_bpp_x16; |
616 | range->min_target_bpp_x16 = preferred_bpp_x16; |
617 | } |
618 | } |
619 | /* TODO - make this value generic to all signal types */ |
620 | else if (dsc_caps->edp_sink_max_bits_per_pixel) { |
621 | /* apply max bpp limitation from edp sink */ |
622 | range->max_target_bpp_x16 = MIN(dsc_caps->edp_sink_max_bits_per_pixel, |
623 | max_bpp_x16); |
624 | range->min_target_bpp_x16 = min_bpp_x16; |
625 | } |
626 | else { |
627 | range->max_target_bpp_x16 = max_bpp_x16; |
628 | range->min_target_bpp_x16 = min_bpp_x16; |
629 | } |
630 | |
631 | /* populate output structure */ |
632 | if (range->max_target_bpp_x16 >= range->min_target_bpp_x16 && range->min_target_bpp_x16 > 0) { |
633 | /* native stream bandwidth */ |
634 | range->stream_kbps = dc_bandwidth_in_kbps_from_timing(timing, link_encoding); |
635 | |
636 | /* max dsc target bpp */ |
637 | range->max_kbps = dc_dsc_stream_bandwidth_in_kbps(timing, |
638 | bpp_x16: range->max_target_bpp_x16, num_slices_h, is_dp: dsc_caps->is_dp); |
639 | |
640 | /* min dsc target bpp */ |
641 | range->min_kbps = dc_dsc_stream_bandwidth_in_kbps(timing, |
642 | bpp_x16: range->min_target_bpp_x16, num_slices_h, is_dp: dsc_caps->is_dp); |
643 | } |
644 | |
645 | return range->max_kbps >= range->min_kbps && range->min_kbps > 0; |
646 | } |
647 | |
648 | /* Decides if DSC should be used and calculates target bpp if it should, applying DSC policy. |
649 | * |
650 | * Returns: |
651 | * - 'true' if target bpp is decided |
652 | * - 'false' if target bpp cannot be decided (e.g. cannot fit even with min DSC bpp), |
653 | */ |
654 | static bool decide_dsc_target_bpp_x16( |
655 | const struct dc_dsc_policy *policy, |
656 | const struct dsc_enc_caps *dsc_common_caps, |
657 | const int target_bandwidth_kbps, |
658 | const struct dc_crtc_timing *timing, |
659 | const int num_slices_h, |
660 | const enum dc_link_encoding_format link_encoding, |
661 | int *target_bpp_x16) |
662 | { |
663 | struct dc_dsc_bw_range range; |
664 | |
665 | *target_bpp_x16 = 0; |
666 | |
667 | if (decide_dsc_bandwidth_range(min_bpp_x16: policy->min_target_bpp * 16, max_bpp_x16: policy->max_target_bpp * 16, |
668 | num_slices_h, dsc_caps: dsc_common_caps, timing, link_encoding, range: &range)) { |
669 | if (target_bandwidth_kbps >= range.stream_kbps) { |
670 | if (policy->enable_dsc_when_not_needed) |
671 | /* enable max bpp even dsc is not needed */ |
672 | *target_bpp_x16 = range.max_target_bpp_x16; |
673 | } else if (target_bandwidth_kbps >= range.max_kbps) { |
674 | /* use max target bpp allowed */ |
675 | *target_bpp_x16 = range.max_target_bpp_x16; |
676 | } else if (target_bandwidth_kbps >= range.min_kbps) { |
677 | /* use target bpp that can take entire target bandwidth */ |
678 | *target_bpp_x16 = compute_bpp_x16_from_target_bandwidth( |
679 | bandwidth_in_kbps: target_bandwidth_kbps, timing, num_slices_h, |
680 | bpp_increment_div: dsc_common_caps->bpp_increment_div, |
681 | is_dp: dsc_common_caps->is_dp); |
682 | } |
683 | } |
684 | |
685 | return *target_bpp_x16 != 0; |
686 | } |
687 | |
688 | #define MIN_AVAILABLE_SLICES_SIZE 6 |
689 | |
690 | static int get_available_dsc_slices(union dsc_enc_slice_caps slice_caps, int *available_slices) |
691 | { |
692 | int idx = 0; |
693 | |
694 | if (slice_caps.bits.NUM_SLICES_1) |
695 | available_slices[idx++] = 1; |
696 | |
697 | if (slice_caps.bits.NUM_SLICES_2) |
698 | available_slices[idx++] = 2; |
699 | |
700 | if (slice_caps.bits.NUM_SLICES_4) |
701 | available_slices[idx++] = 4; |
702 | |
703 | if (slice_caps.bits.NUM_SLICES_8) |
704 | available_slices[idx++] = 8; |
705 | |
706 | return idx; |
707 | } |
708 | |
709 | |
710 | static int get_max_dsc_slices(union dsc_enc_slice_caps slice_caps) |
711 | { |
712 | int max_slices = 0; |
713 | int available_slices[MIN_AVAILABLE_SLICES_SIZE]; |
714 | int end_idx = get_available_dsc_slices(slice_caps, available_slices: &available_slices[0]); |
715 | |
716 | if (end_idx > 0) |
717 | max_slices = available_slices[end_idx - 1]; |
718 | |
719 | return max_slices; |
720 | } |
721 | |
722 | |
723 | // Increment slice number in available slice numbers stops if possible, or just increment if not |
724 | static int inc_num_slices(union dsc_enc_slice_caps slice_caps, int num_slices) |
725 | { |
726 | // Get next bigger num slices available in common caps |
727 | int available_slices[MIN_AVAILABLE_SLICES_SIZE]; |
728 | int end_idx; |
729 | int i; |
730 | int new_num_slices = num_slices; |
731 | |
732 | end_idx = get_available_dsc_slices(slice_caps, available_slices: &available_slices[0]); |
733 | if (end_idx == 0) { |
734 | // No available slices found |
735 | new_num_slices++; |
736 | return new_num_slices; |
737 | } |
738 | |
739 | // Numbers of slices found - get the next bigger number |
740 | for (i = 0; i < end_idx; i++) { |
741 | if (new_num_slices < available_slices[i]) { |
742 | new_num_slices = available_slices[i]; |
743 | break; |
744 | } |
745 | } |
746 | |
747 | if (new_num_slices == num_slices) // No bigger number of slices found |
748 | new_num_slices++; |
749 | |
750 | return new_num_slices; |
751 | } |
752 | |
753 | |
754 | // Decrement slice number in available slice numbers stops if possible, or just decrement if not. Stop at zero. |
755 | static int dec_num_slices(union dsc_enc_slice_caps slice_caps, int num_slices) |
756 | { |
757 | // Get next bigger num slices available in common caps |
758 | int available_slices[MIN_AVAILABLE_SLICES_SIZE]; |
759 | int end_idx; |
760 | int i; |
761 | int new_num_slices = num_slices; |
762 | |
763 | end_idx = get_available_dsc_slices(slice_caps, available_slices: &available_slices[0]); |
764 | if (end_idx == 0 && new_num_slices > 0) { |
765 | // No numbers of slices found |
766 | new_num_slices++; |
767 | return new_num_slices; |
768 | } |
769 | |
770 | // Numbers of slices found - get the next smaller number |
771 | for (i = end_idx - 1; i >= 0; i--) { |
772 | if (new_num_slices > available_slices[i]) { |
773 | new_num_slices = available_slices[i]; |
774 | break; |
775 | } |
776 | } |
777 | |
778 | if (new_num_slices == num_slices) { |
779 | // No smaller number of slices found |
780 | new_num_slices--; |
781 | if (new_num_slices < 0) |
782 | new_num_slices = 0; |
783 | } |
784 | |
785 | return new_num_slices; |
786 | } |
787 | |
788 | |
789 | // Choose next bigger number of slices if the requested number of slices is not available |
790 | static int fit_num_slices_up(union dsc_enc_slice_caps slice_caps, int num_slices) |
791 | { |
792 | // Get next bigger num slices available in common caps |
793 | int available_slices[MIN_AVAILABLE_SLICES_SIZE]; |
794 | int end_idx; |
795 | int i; |
796 | int new_num_slices = num_slices; |
797 | |
798 | end_idx = get_available_dsc_slices(slice_caps, available_slices: &available_slices[0]); |
799 | if (end_idx == 0) { |
800 | // No available slices found |
801 | new_num_slices++; |
802 | return new_num_slices; |
803 | } |
804 | |
805 | // Numbers of slices found - get the equal or next bigger number |
806 | for (i = 0; i < end_idx; i++) { |
807 | if (new_num_slices <= available_slices[i]) { |
808 | new_num_slices = available_slices[i]; |
809 | break; |
810 | } |
811 | } |
812 | |
813 | return new_num_slices; |
814 | } |
815 | |
816 | |
817 | /* Attempts to set DSC configuration for the stream, applying DSC policy. |
818 | * Returns 'true' if successful or 'false' if not. |
819 | * |
820 | * Parameters: |
821 | * |
822 | * dsc_sink_caps - DSC sink decoder capabilities (from DPCD) |
823 | * |
824 | * dsc_enc_caps - DSC encoder capabilities |
825 | * |
826 | * target_bandwidth_kbps - Target bandwidth to fit the stream into. |
827 | * If 0, do not calculate target bpp. |
828 | * |
829 | * timing - The stream timing to fit into 'target_bandwidth_kbps' or apply |
830 | * maximum compression to, if 'target_badwidth == 0' |
831 | * |
832 | * dsc_cfg - DSC configuration to use if it was possible to come up with |
833 | * one for the given inputs. |
834 | * The target bitrate after DSC can be calculated by multiplying |
835 | * dsc_cfg.bits_per_pixel (in U6.4 format) by pixel rate, e.g. |
836 | * |
837 | * dsc_stream_bitrate_kbps = (int)ceil(timing->pix_clk_khz * dsc_cfg.bits_per_pixel / 16.0); |
838 | */ |
839 | static bool setup_dsc_config( |
840 | const struct dsc_dec_dpcd_caps *dsc_sink_caps, |
841 | const struct dsc_enc_caps *dsc_enc_caps, |
842 | int target_bandwidth_kbps, |
843 | const struct dc_crtc_timing *timing, |
844 | const struct dc_dsc_config_options *options, |
845 | const enum dc_link_encoding_format link_encoding, |
846 | struct dc_dsc_config *dsc_cfg) |
847 | { |
848 | struct dsc_enc_caps dsc_common_caps; |
849 | int max_slices_h; |
850 | int min_slices_h; |
851 | int num_slices_h; |
852 | int pic_width; |
853 | int slice_width; |
854 | int target_bpp; |
855 | int sink_per_slice_throughput_mps; |
856 | int branch_max_throughput_mps = 0; |
857 | bool is_dsc_possible = false; |
858 | int pic_height; |
859 | int slice_height; |
860 | struct dc_dsc_policy policy; |
861 | |
862 | memset(dsc_cfg, 0, sizeof(struct dc_dsc_config)); |
863 | |
864 | dc_dsc_get_policy_for_timing(timing, max_target_bpp_limit_override_x16: options->max_target_bpp_limit_override_x16, policy: &policy); |
865 | pic_width = timing->h_addressable + timing->h_border_left + timing->h_border_right; |
866 | pic_height = timing->v_addressable + timing->v_border_top + timing->v_border_bottom; |
867 | |
868 | if (!dsc_sink_caps->is_dsc_supported) |
869 | goto done; |
870 | |
871 | if (dsc_sink_caps->branch_max_line_width && dsc_sink_caps->branch_max_line_width < pic_width) |
872 | goto done; |
873 | |
874 | // Intersect decoder with encoder DSC caps and validate DSC settings |
875 | is_dsc_possible = intersect_dsc_caps(dsc_sink_caps, dsc_enc_caps, pixel_encoding: timing->pixel_encoding, dsc_common_caps: &dsc_common_caps); |
876 | if (!is_dsc_possible) |
877 | goto done; |
878 | |
879 | sink_per_slice_throughput_mps = 0; |
880 | |
881 | // Validate available DSC settings against the mode timing |
882 | |
883 | // Validate color format (and pick up the throughput values) |
884 | dsc_cfg->ycbcr422_simple = false; |
885 | switch (timing->pixel_encoding) { |
886 | case PIXEL_ENCODING_RGB: |
887 | is_dsc_possible = (bool)dsc_common_caps.color_formats.bits.RGB; |
888 | sink_per_slice_throughput_mps = dsc_sink_caps->throughput_mode_0_mps; |
889 | branch_max_throughput_mps = dsc_sink_caps->branch_overall_throughput_0_mps; |
890 | break; |
891 | case PIXEL_ENCODING_YCBCR444: |
892 | is_dsc_possible = (bool)dsc_common_caps.color_formats.bits.YCBCR_444; |
893 | sink_per_slice_throughput_mps = dsc_sink_caps->throughput_mode_0_mps; |
894 | branch_max_throughput_mps = dsc_sink_caps->branch_overall_throughput_0_mps; |
895 | break; |
896 | case PIXEL_ENCODING_YCBCR422: |
897 | is_dsc_possible = (bool)dsc_common_caps.color_formats.bits.YCBCR_NATIVE_422; |
898 | sink_per_slice_throughput_mps = dsc_sink_caps->throughput_mode_1_mps; |
899 | branch_max_throughput_mps = dsc_sink_caps->branch_overall_throughput_1_mps; |
900 | if (!is_dsc_possible) { |
901 | is_dsc_possible = (bool)dsc_common_caps.color_formats.bits.YCBCR_SIMPLE_422; |
902 | dsc_cfg->ycbcr422_simple = is_dsc_possible; |
903 | sink_per_slice_throughput_mps = dsc_sink_caps->throughput_mode_0_mps; |
904 | } |
905 | break; |
906 | case PIXEL_ENCODING_YCBCR420: |
907 | is_dsc_possible = (bool)dsc_common_caps.color_formats.bits.YCBCR_NATIVE_420; |
908 | sink_per_slice_throughput_mps = dsc_sink_caps->throughput_mode_1_mps; |
909 | branch_max_throughput_mps = dsc_sink_caps->branch_overall_throughput_1_mps; |
910 | break; |
911 | default: |
912 | is_dsc_possible = false; |
913 | } |
914 | |
915 | // Validate branch's maximum throughput |
916 | if (branch_max_throughput_mps && dsc_div_by_10_round_up(value: timing->pix_clk_100hz) > branch_max_throughput_mps * 1000) |
917 | is_dsc_possible = false; |
918 | |
919 | if (!is_dsc_possible) |
920 | goto done; |
921 | |
922 | // Color depth |
923 | switch (timing->display_color_depth) { |
924 | case COLOR_DEPTH_888: |
925 | is_dsc_possible = (bool)dsc_common_caps.color_depth.bits.COLOR_DEPTH_8_BPC; |
926 | break; |
927 | case COLOR_DEPTH_101010: |
928 | is_dsc_possible = (bool)dsc_common_caps.color_depth.bits.COLOR_DEPTH_10_BPC; |
929 | break; |
930 | case COLOR_DEPTH_121212: |
931 | is_dsc_possible = (bool)dsc_common_caps.color_depth.bits.COLOR_DEPTH_12_BPC; |
932 | break; |
933 | default: |
934 | is_dsc_possible = false; |
935 | } |
936 | |
937 | if (!is_dsc_possible) |
938 | goto done; |
939 | |
940 | // Slice width (i.e. number of slices per line) |
941 | max_slices_h = get_max_dsc_slices(slice_caps: dsc_common_caps.slice_caps); |
942 | |
943 | while (max_slices_h > 0) { |
944 | if (pic_width % max_slices_h == 0) |
945 | break; |
946 | |
947 | max_slices_h = dec_num_slices(slice_caps: dsc_common_caps.slice_caps, num_slices: max_slices_h); |
948 | } |
949 | |
950 | is_dsc_possible = (dsc_common_caps.max_slice_width > 0); |
951 | if (!is_dsc_possible) |
952 | goto done; |
953 | |
954 | min_slices_h = pic_width / dsc_common_caps.max_slice_width; |
955 | if (pic_width % dsc_common_caps.max_slice_width) |
956 | min_slices_h++; |
957 | |
958 | min_slices_h = fit_num_slices_up(slice_caps: dsc_common_caps.slice_caps, num_slices: min_slices_h); |
959 | |
960 | while (min_slices_h <= max_slices_h) { |
961 | int pix_clk_per_slice_khz = dsc_div_by_10_round_up(value: timing->pix_clk_100hz) / min_slices_h; |
962 | if (pix_clk_per_slice_khz <= sink_per_slice_throughput_mps * 1000) |
963 | break; |
964 | |
965 | min_slices_h = inc_num_slices(slice_caps: dsc_common_caps.slice_caps, num_slices: min_slices_h); |
966 | } |
967 | |
968 | is_dsc_possible = (min_slices_h <= max_slices_h); |
969 | |
970 | if (pic_width % min_slices_h != 0) |
971 | min_slices_h = 0; // DSC TODO: Maybe try increasing the number of slices first? |
972 | |
973 | if (min_slices_h == 0 && max_slices_h == 0) |
974 | is_dsc_possible = false; |
975 | |
976 | if (!is_dsc_possible) |
977 | goto done; |
978 | |
979 | if (policy.use_min_slices_h) { |
980 | if (min_slices_h > 0) |
981 | num_slices_h = min_slices_h; |
982 | else if (max_slices_h > 0) { // Fall back to max slices if min slices is not working out |
983 | if (policy.max_slices_h) |
984 | num_slices_h = min(policy.max_slices_h, max_slices_h); |
985 | else |
986 | num_slices_h = max_slices_h; |
987 | } else |
988 | is_dsc_possible = false; |
989 | } else { |
990 | if (max_slices_h > 0) { |
991 | if (policy.max_slices_h) |
992 | num_slices_h = min(policy.max_slices_h, max_slices_h); |
993 | else |
994 | num_slices_h = max_slices_h; |
995 | } else if (min_slices_h > 0) // Fall back to min slices if max slices is not possible |
996 | num_slices_h = min_slices_h; |
997 | else |
998 | is_dsc_possible = false; |
999 | } |
1000 | // When we force 2:1 ODM, we can't have 1 slice to divide amongst 2 separate DSC instances |
1001 | // need to enforce at minimum 2 horizontal slices |
1002 | if (options->dsc_force_odm_hslice_override) { |
1003 | num_slices_h = fit_num_slices_up(slice_caps: dsc_common_caps.slice_caps, num_slices: 2); |
1004 | if (num_slices_h == 0) |
1005 | is_dsc_possible = false; |
1006 | } |
1007 | |
1008 | if (!is_dsc_possible) |
1009 | goto done; |
1010 | |
1011 | dsc_cfg->num_slices_h = num_slices_h; |
1012 | slice_width = pic_width / num_slices_h; |
1013 | |
1014 | is_dsc_possible = slice_width <= dsc_common_caps.max_slice_width; |
1015 | if (!is_dsc_possible) |
1016 | goto done; |
1017 | |
1018 | // Slice height (i.e. number of slices per column): start with policy and pick the first one that height is divisible by. |
1019 | // For 4:2:0 make sure the slice height is divisible by 2 as well. |
1020 | if (options->dsc_min_slice_height_override == 0) |
1021 | slice_height = min(policy.min_slice_height, pic_height); |
1022 | else |
1023 | slice_height = min((int)(options->dsc_min_slice_height_override), pic_height); |
1024 | |
1025 | while (slice_height < pic_height && (pic_height % slice_height != 0 || |
1026 | slice_height % options->slice_height_granularity != 0 || |
1027 | (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420 && slice_height % 2 != 0))) |
1028 | slice_height++; |
1029 | |
1030 | if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) // For the case when pic_height < dsc_policy.min_sice_height |
1031 | is_dsc_possible = (slice_height % 2 == 0); |
1032 | |
1033 | if (!is_dsc_possible) |
1034 | goto done; |
1035 | |
1036 | dsc_cfg->num_slices_v = pic_height/slice_height; |
1037 | |
1038 | if (target_bandwidth_kbps > 0) { |
1039 | is_dsc_possible = decide_dsc_target_bpp_x16( |
1040 | policy: &policy, |
1041 | dsc_common_caps: &dsc_common_caps, |
1042 | target_bandwidth_kbps, |
1043 | timing, |
1044 | num_slices_h, |
1045 | link_encoding, |
1046 | target_bpp_x16: &target_bpp); |
1047 | dsc_cfg->bits_per_pixel = target_bpp; |
1048 | } |
1049 | if (!is_dsc_possible) |
1050 | goto done; |
1051 | |
1052 | // Final decission: can we do DSC or not? |
1053 | if (is_dsc_possible) { |
1054 | // Fill out the rest of DSC settings |
1055 | dsc_cfg->block_pred_enable = dsc_common_caps.is_block_pred_supported; |
1056 | dsc_cfg->linebuf_depth = dsc_common_caps.lb_bit_depth; |
1057 | dsc_cfg->version_minor = (dsc_common_caps.dsc_version & 0xf0) >> 4; |
1058 | dsc_cfg->is_dp = dsc_sink_caps->is_dp; |
1059 | } |
1060 | |
1061 | done: |
1062 | if (!is_dsc_possible) |
1063 | memset(dsc_cfg, 0, sizeof(struct dc_dsc_config)); |
1064 | |
1065 | return is_dsc_possible; |
1066 | } |
1067 | |
1068 | bool dc_dsc_compute_config( |
1069 | const struct display_stream_compressor *dsc, |
1070 | const struct dsc_dec_dpcd_caps *dsc_sink_caps, |
1071 | const struct dc_dsc_config_options *options, |
1072 | uint32_t target_bandwidth_kbps, |
1073 | const struct dc_crtc_timing *timing, |
1074 | const enum dc_link_encoding_format link_encoding, |
1075 | struct dc_dsc_config *dsc_cfg) |
1076 | { |
1077 | bool is_dsc_possible = false; |
1078 | struct dsc_enc_caps dsc_enc_caps; |
1079 | |
1080 | get_dsc_enc_caps(dsc, dsc_enc_caps: &dsc_enc_caps, pixel_clock_100Hz: timing->pix_clk_100hz); |
1081 | is_dsc_possible = setup_dsc_config(dsc_sink_caps, |
1082 | dsc_enc_caps: &dsc_enc_caps, |
1083 | target_bandwidth_kbps, |
1084 | timing, options, link_encoding, dsc_cfg); |
1085 | return is_dsc_possible; |
1086 | } |
1087 | |
1088 | uint32_t dc_dsc_stream_bandwidth_in_kbps(const struct dc_crtc_timing *timing, |
1089 | uint32_t bpp_x16, uint32_t num_slices_h, bool is_dp) |
1090 | { |
1091 | uint32_t overhead_in_kbps; |
1092 | struct fixed31_32 bpp; |
1093 | struct fixed31_32 actual_bandwidth_in_kbps; |
1094 | |
1095 | overhead_in_kbps = dc_dsc_stream_bandwidth_overhead_in_kbps( |
1096 | timing, num_slices_h, is_dp); |
1097 | bpp = dc_fixpt_from_fraction(numerator: bpp_x16, denominator: 16); |
1098 | actual_bandwidth_in_kbps = dc_fixpt_from_fraction(numerator: timing->pix_clk_100hz, denominator: 10); |
1099 | actual_bandwidth_in_kbps = dc_fixpt_mul(arg1: actual_bandwidth_in_kbps, arg2: bpp); |
1100 | actual_bandwidth_in_kbps = dc_fixpt_add_int(arg1: actual_bandwidth_in_kbps, arg2: overhead_in_kbps); |
1101 | return dc_fixpt_ceil(arg: actual_bandwidth_in_kbps); |
1102 | } |
1103 | |
1104 | uint32_t dc_dsc_stream_bandwidth_overhead_in_kbps( |
1105 | const struct dc_crtc_timing *timing, |
1106 | const int num_slices_h, |
1107 | const bool is_dp) |
1108 | { |
1109 | struct fixed31_32 max_dsc_overhead; |
1110 | struct fixed31_32 refresh_rate; |
1111 | |
1112 | if (dsc_policy_disable_dsc_stream_overhead || !is_dp) |
1113 | return 0; |
1114 | |
1115 | /* use target bpp that can take entire target bandwidth */ |
1116 | refresh_rate = dc_fixpt_from_int(arg: timing->pix_clk_100hz); |
1117 | refresh_rate = dc_fixpt_div_int(arg1: refresh_rate, arg2: timing->h_total); |
1118 | refresh_rate = dc_fixpt_div_int(arg1: refresh_rate, arg2: timing->v_total); |
1119 | refresh_rate = dc_fixpt_mul_int(arg1: refresh_rate, arg2: 100); |
1120 | |
1121 | max_dsc_overhead = dc_fixpt_from_int(arg: num_slices_h); |
1122 | max_dsc_overhead = dc_fixpt_mul_int(arg1: max_dsc_overhead, arg2: timing->v_total); |
1123 | max_dsc_overhead = dc_fixpt_mul_int(arg1: max_dsc_overhead, arg2: 256); |
1124 | max_dsc_overhead = dc_fixpt_div_int(arg1: max_dsc_overhead, arg2: 1000); |
1125 | max_dsc_overhead = dc_fixpt_mul(arg1: max_dsc_overhead, arg2: refresh_rate); |
1126 | |
1127 | return dc_fixpt_ceil(arg: max_dsc_overhead); |
1128 | } |
1129 | |
1130 | void dc_dsc_get_policy_for_timing(const struct dc_crtc_timing *timing, |
1131 | uint32_t max_target_bpp_limit_override_x16, |
1132 | struct dc_dsc_policy *policy) |
1133 | { |
1134 | uint32_t bpc = 0; |
1135 | |
1136 | policy->min_target_bpp = 0; |
1137 | policy->max_target_bpp = 0; |
1138 | |
1139 | /* DSC Policy: Use minimum number of slices that fits the pixel clock */ |
1140 | policy->use_min_slices_h = true; |
1141 | |
1142 | /* DSC Policy: Use max available slices |
1143 | * (in our case 4 for or 8, depending on the mode) |
1144 | */ |
1145 | policy->max_slices_h = 0; |
1146 | |
1147 | /* DSC Policy: Use slice height recommended |
1148 | * by VESA DSC Spreadsheet user guide |
1149 | */ |
1150 | policy->min_slice_height = 108; |
1151 | |
1152 | /* DSC Policy: follow DP specs with an internal upper limit to 16 bpp |
1153 | * for better interoperability |
1154 | */ |
1155 | switch (timing->display_color_depth) { |
1156 | case COLOR_DEPTH_888: |
1157 | bpc = 8; |
1158 | break; |
1159 | case COLOR_DEPTH_101010: |
1160 | bpc = 10; |
1161 | break; |
1162 | case COLOR_DEPTH_121212: |
1163 | bpc = 12; |
1164 | break; |
1165 | default: |
1166 | return; |
1167 | } |
1168 | switch (timing->pixel_encoding) { |
1169 | case PIXEL_ENCODING_RGB: |
1170 | case PIXEL_ENCODING_YCBCR444: |
1171 | case PIXEL_ENCODING_YCBCR422: /* assume no YCbCr422 native support */ |
1172 | /* DP specs limits to 8 */ |
1173 | policy->min_target_bpp = 8; |
1174 | /* DP specs limits to 3 x bpc */ |
1175 | policy->max_target_bpp = 3 * bpc; |
1176 | break; |
1177 | case PIXEL_ENCODING_YCBCR420: |
1178 | /* DP specs limits to 6 */ |
1179 | policy->min_target_bpp = 6; |
1180 | /* DP specs limits to 1.5 x bpc assume bpc is an even number */ |
1181 | policy->max_target_bpp = bpc * 3 / 2; |
1182 | break; |
1183 | default: |
1184 | return; |
1185 | } |
1186 | |
1187 | /* internal upper limit, default 16 bpp */ |
1188 | if (policy->max_target_bpp > dsc_policy_max_target_bpp_limit) |
1189 | policy->max_target_bpp = dsc_policy_max_target_bpp_limit; |
1190 | |
1191 | /* apply override */ |
1192 | if (max_target_bpp_limit_override_x16 && policy->max_target_bpp > max_target_bpp_limit_override_x16 / 16) |
1193 | policy->max_target_bpp = max_target_bpp_limit_override_x16 / 16; |
1194 | |
1195 | /* enable DSC when not needed, default false */ |
1196 | if (dsc_policy_enable_dsc_when_not_needed) |
1197 | policy->enable_dsc_when_not_needed = dsc_policy_enable_dsc_when_not_needed; |
1198 | else |
1199 | policy->enable_dsc_when_not_needed = false; |
1200 | } |
1201 | |
1202 | void dc_dsc_policy_set_max_target_bpp_limit(uint32_t limit) |
1203 | { |
1204 | dsc_policy_max_target_bpp_limit = limit; |
1205 | } |
1206 | |
1207 | void dc_dsc_policy_set_enable_dsc_when_not_needed(bool enable) |
1208 | { |
1209 | dsc_policy_enable_dsc_when_not_needed = enable; |
1210 | } |
1211 | |
1212 | void dc_dsc_policy_set_disable_dsc_stream_overhead(bool disable) |
1213 | { |
1214 | dsc_policy_disable_dsc_stream_overhead = disable; |
1215 | } |
1216 | |
1217 | void dc_set_disable_128b_132b_stream_overhead(bool disable) |
1218 | { |
1219 | disable_128b_132b_stream_overhead = disable; |
1220 | } |
1221 | |
1222 | void dc_dsc_get_default_config_option(const struct dc *dc, struct dc_dsc_config_options *options) |
1223 | { |
1224 | options->dsc_min_slice_height_override = dc->debug.dsc_min_slice_height_override; |
1225 | options->dsc_force_odm_hslice_override = dc->debug.force_odm_combine; |
1226 | options->max_target_bpp_limit_override_x16 = 0; |
1227 | options->slice_height_granularity = 1; |
1228 | } |
1229 | |