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