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 #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
26 #include "dc.h"
27 #include "core_types.h"
28 #include "dsc.h"
29 #include <drm/drm_dp_helper.h>
30
31 struct dc_dsc_policy {
32 bool use_min_slices_h;
33 int max_slices_h; // Maximum available if 0
34 int min_sice_height; // Must not be less than 8
35 int max_target_bpp;
36 int min_target_bpp; // Minimum target bits per pixel
37 };
38
39 const struct dc_dsc_policy dsc_policy = {
40 .use_min_slices_h = true, // DSC Policy: Use minimum number of slices that fits the pixel clock
41 .max_slices_h = 0, // DSC Policy: Use max available slices (in our case 4 for or 8, depending on the mode)
42 .min_sice_height = 108, // DSC Policy: Use slice height recommended by VESA DSC Spreadsheet user guide
43 .max_target_bpp = 16,
44 .min_target_bpp = 8,
45 };
46
47
48 /* This module's internal functions */
49
dsc_buff_block_size_from_dpcd(int dpcd_buff_block_size,int * buff_block_size)50 static bool dsc_buff_block_size_from_dpcd(int dpcd_buff_block_size, int *buff_block_size)
51 {
52
53 switch (dpcd_buff_block_size) {
54 case DP_DSC_RC_BUF_BLK_SIZE_1:
55 *buff_block_size = 1024;
56 break;
57 case DP_DSC_RC_BUF_BLK_SIZE_4:
58 *buff_block_size = 4 * 1024;
59 break;
60 case DP_DSC_RC_BUF_BLK_SIZE_16:
61 *buff_block_size = 16 * 1024;
62 break;
63 case DP_DSC_RC_BUF_BLK_SIZE_64:
64 *buff_block_size = 64 * 1024;
65 break;
66 default: {
67 dm_error("%s: DPCD DSC buffer size not recognized.\n", __func__);
68 return false;
69 }
70 }
71
72 return true;
73 }
74
75
dsc_line_buff_depth_from_dpcd(int dpcd_line_buff_bit_depth,int * line_buff_bit_depth)76 static bool dsc_line_buff_depth_from_dpcd(int dpcd_line_buff_bit_depth, int *line_buff_bit_depth)
77 {
78 if (0 <= dpcd_line_buff_bit_depth && dpcd_line_buff_bit_depth <= 7)
79 *line_buff_bit_depth = dpcd_line_buff_bit_depth + 9;
80 else if (dpcd_line_buff_bit_depth == 8)
81 *line_buff_bit_depth = 8;
82 else {
83 dm_error("%s: DPCD DSC buffer depth not recognized.\n", __func__);
84 return false;
85 }
86
87 return true;
88 }
89
90
dsc_throughput_from_dpcd(int dpcd_throughput,int * throughput)91 static bool dsc_throughput_from_dpcd(int dpcd_throughput, int *throughput)
92 {
93 switch (dpcd_throughput) {
94 case DP_DSC_THROUGHPUT_MODE_0_UPSUPPORTED:
95 *throughput = 0;
96 break;
97 case DP_DSC_THROUGHPUT_MODE_0_170:
98 *throughput = 170;
99 break;
100 case DP_DSC_THROUGHPUT_MODE_0_340:
101 *throughput = 340;
102 break;
103 case DP_DSC_THROUGHPUT_MODE_0_400:
104 *throughput = 400;
105 break;
106 case DP_DSC_THROUGHPUT_MODE_0_450:
107 *throughput = 450;
108 break;
109 case DP_DSC_THROUGHPUT_MODE_0_500:
110 *throughput = 500;
111 break;
112 case DP_DSC_THROUGHPUT_MODE_0_550:
113 *throughput = 550;
114 break;
115 case DP_DSC_THROUGHPUT_MODE_0_600:
116 *throughput = 600;
117 break;
118 case DP_DSC_THROUGHPUT_MODE_0_650:
119 *throughput = 650;
120 break;
121 case DP_DSC_THROUGHPUT_MODE_0_700:
122 *throughput = 700;
123 break;
124 case DP_DSC_THROUGHPUT_MODE_0_750:
125 *throughput = 750;
126 break;
127 case DP_DSC_THROUGHPUT_MODE_0_800:
128 *throughput = 800;
129 break;
130 case DP_DSC_THROUGHPUT_MODE_0_850:
131 *throughput = 850;
132 break;
133 case DP_DSC_THROUGHPUT_MODE_0_900:
134 *throughput = 900;
135 break;
136 case DP_DSC_THROUGHPUT_MODE_0_950:
137 *throughput = 950;
138 break;
139 case DP_DSC_THROUGHPUT_MODE_0_1000:
140 *throughput = 1000;
141 break;
142 default: {
143 dm_error("%s: DPCD DSC throughput mode not recognized.\n", __func__);
144 return false;
145 }
146 }
147
148 return true;
149 }
150
151
dsc_bpp_increment_div_from_dpcd(int bpp_increment_dpcd,uint32_t * bpp_increment_div)152 static bool dsc_bpp_increment_div_from_dpcd(int bpp_increment_dpcd, uint32_t *bpp_increment_div)
153 {
154
155 switch (bpp_increment_dpcd) {
156 case 0:
157 *bpp_increment_div = 16;
158 break;
159 case 1:
160 *bpp_increment_div = 8;
161 break;
162 case 2:
163 *bpp_increment_div = 4;
164 break;
165 case 3:
166 *bpp_increment_div = 2;
167 break;
168 case 4:
169 *bpp_increment_div = 1;
170 break;
171 default: {
172 dm_error("%s: DPCD DSC bits-per-pixel increment not recognized.\n", __func__);
173 return false;
174 }
175 }
176
177 return true;
178 }
179
get_dsc_enc_caps(const struct dc * dc,struct dsc_enc_caps * dsc_enc_caps,int pixel_clock_100Hz)180 static void get_dsc_enc_caps(
181 const struct dc *dc,
182 struct dsc_enc_caps *dsc_enc_caps,
183 int pixel_clock_100Hz)
184 {
185 // This is a static HW query, so we can use any DSC
186 struct display_stream_compressor *dsc = dc->res_pool->dscs[0];
187
188 memset(dsc_enc_caps, 0, sizeof(struct dsc_enc_caps));
189 if (dsc)
190 dsc->funcs->dsc_get_enc_caps(dsc_enc_caps, pixel_clock_100Hz);
191 }
192
193 /* Returns 'false' if no intersection was found for at least one capablity.
194 * It also implicitly validates some sink caps against invalid value of zero.
195 */
intersect_dsc_caps(const struct dsc_dec_dpcd_caps * dsc_sink_caps,const struct dsc_enc_caps * dsc_enc_caps,enum dc_pixel_encoding pixel_encoding,struct dsc_enc_caps * dsc_common_caps)196 static bool intersect_dsc_caps(
197 const struct dsc_dec_dpcd_caps *dsc_sink_caps,
198 const struct dsc_enc_caps *dsc_enc_caps,
199 enum dc_pixel_encoding pixel_encoding,
200 struct dsc_enc_caps *dsc_common_caps)
201 {
202 int32_t max_slices;
203 int32_t total_sink_throughput;
204
205 memset(dsc_common_caps, 0, sizeof(struct dsc_enc_caps));
206
207 dsc_common_caps->dsc_version = min(dsc_sink_caps->dsc_version, dsc_enc_caps->dsc_version);
208 if (!dsc_common_caps->dsc_version)
209 return false;
210
211 dsc_common_caps->slice_caps.bits.NUM_SLICES_1 = dsc_sink_caps->slice_caps1.bits.NUM_SLICES_1 && dsc_enc_caps->slice_caps.bits.NUM_SLICES_1;
212 dsc_common_caps->slice_caps.bits.NUM_SLICES_2 = dsc_sink_caps->slice_caps1.bits.NUM_SLICES_2 && dsc_enc_caps->slice_caps.bits.NUM_SLICES_2;
213 dsc_common_caps->slice_caps.bits.NUM_SLICES_4 = dsc_sink_caps->slice_caps1.bits.NUM_SLICES_4 && dsc_enc_caps->slice_caps.bits.NUM_SLICES_4;
214 dsc_common_caps->slice_caps.bits.NUM_SLICES_8 = dsc_sink_caps->slice_caps1.bits.NUM_SLICES_8 && dsc_enc_caps->slice_caps.bits.NUM_SLICES_8;
215 if (!dsc_common_caps->slice_caps.raw)
216 return false;
217
218 dsc_common_caps->lb_bit_depth = min(dsc_sink_caps->lb_bit_depth, dsc_enc_caps->lb_bit_depth);
219 if (!dsc_common_caps->lb_bit_depth)
220 return false;
221
222 dsc_common_caps->is_block_pred_supported = dsc_sink_caps->is_block_pred_supported && dsc_enc_caps->is_block_pred_supported;
223
224 dsc_common_caps->color_formats.raw = dsc_sink_caps->color_formats.raw & dsc_enc_caps->color_formats.raw;
225 if (!dsc_common_caps->color_formats.raw)
226 return false;
227
228 dsc_common_caps->color_depth.raw = dsc_sink_caps->color_depth.raw & dsc_enc_caps->color_depth.raw;
229 if (!dsc_common_caps->color_depth.raw)
230 return false;
231
232 max_slices = 0;
233 if (dsc_common_caps->slice_caps.bits.NUM_SLICES_1)
234 max_slices = 1;
235
236 if (dsc_common_caps->slice_caps.bits.NUM_SLICES_2)
237 max_slices = 2;
238
239 if (dsc_common_caps->slice_caps.bits.NUM_SLICES_4)
240 max_slices = 4;
241
242 total_sink_throughput = max_slices * dsc_sink_caps->throughput_mode_0_mps;
243 if (pixel_encoding == PIXEL_ENCODING_YCBCR422 || pixel_encoding == PIXEL_ENCODING_YCBCR420)
244 total_sink_throughput = max_slices * dsc_sink_caps->throughput_mode_1_mps;
245
246 dsc_common_caps->max_total_throughput_mps = min(total_sink_throughput, dsc_enc_caps->max_total_throughput_mps);
247
248 dsc_common_caps->max_slice_width = min(dsc_sink_caps->max_slice_width, dsc_enc_caps->max_slice_width);
249 if (!dsc_common_caps->max_slice_width)
250 return false;
251
252 dsc_common_caps->bpp_increment_div = min(dsc_sink_caps->bpp_increment_div, dsc_enc_caps->bpp_increment_div);
253
254 // TODO DSC: Remove this workaround for N422 and 420 once it's fixed, or move it to get_dsc_encoder_caps()
255 if (pixel_encoding == PIXEL_ENCODING_YCBCR422 || pixel_encoding == PIXEL_ENCODING_YCBCR420)
256 dsc_common_caps->bpp_increment_div = min(dsc_common_caps->bpp_increment_div, (uint32_t)8);
257
258 return true;
259 }
260
dsc_div_by_10_round_up(uint32_t value)261 static inline uint32_t dsc_div_by_10_round_up(uint32_t value)
262 {
263 return (value + 9) / 10;
264 }
265
calc_dsc_bpp_x16(uint32_t stream_bandwidth_kbps,uint32_t pix_clk_100hz,uint32_t bpp_increment_div)266 static inline uint32_t calc_dsc_bpp_x16(uint32_t stream_bandwidth_kbps, uint32_t pix_clk_100hz, uint32_t bpp_increment_div)
267 {
268 uint32_t dsc_target_bpp_x16;
269 float f_dsc_target_bpp;
270 float f_stream_bandwidth_100bps = stream_bandwidth_kbps * 10.0f;
271 uint32_t precision = bpp_increment_div; // bpp_increment_div is actually precision
272
273 f_dsc_target_bpp = f_stream_bandwidth_100bps / pix_clk_100hz;
274
275 // Round down to the nearest precision stop to bring it into DSC spec range
276 dsc_target_bpp_x16 = (uint32_t)(f_dsc_target_bpp * precision);
277 dsc_target_bpp_x16 = (dsc_target_bpp_x16 * 16) / precision;
278
279 return dsc_target_bpp_x16;
280 }
281
282 /* Get DSC bandwidth range based on [min_bpp, max_bpp] target bitrate range, and timing's pixel clock
283 * and uncompressed bandwidth.
284 */
get_dsc_bandwidth_range(const uint32_t min_bpp,const uint32_t max_bpp,const struct dsc_enc_caps * dsc_caps,const struct dc_crtc_timing * timing,struct dc_dsc_bw_range * range)285 static void get_dsc_bandwidth_range(
286 const uint32_t min_bpp,
287 const uint32_t max_bpp,
288 const struct dsc_enc_caps *dsc_caps,
289 const struct dc_crtc_timing *timing,
290 struct dc_dsc_bw_range *range)
291 {
292 /* native stream bandwidth */
293 range->stream_kbps = dc_bandwidth_in_kbps_from_timing(timing);
294
295 /* max dsc target bpp */
296 range->max_kbps = dsc_div_by_10_round_up(max_bpp * timing->pix_clk_100hz);
297 range->max_target_bpp_x16 = max_bpp * 16;
298 if (range->max_kbps > range->stream_kbps) {
299 /* max dsc target bpp is capped to native bandwidth */
300 range->max_kbps = range->stream_kbps;
301 range->max_target_bpp_x16 = calc_dsc_bpp_x16(range->stream_kbps, timing->pix_clk_100hz, dsc_caps->bpp_increment_div);
302 }
303
304 /* min dsc target bpp */
305 range->min_kbps = dsc_div_by_10_round_up(min_bpp * timing->pix_clk_100hz);
306 range->min_target_bpp_x16 = min_bpp * 16;
307 if (range->min_kbps > range->max_kbps) {
308 /* min dsc target bpp is capped to max dsc bandwidth*/
309 range->min_kbps = range->max_kbps;
310 range->min_target_bpp_x16 = range->max_target_bpp_x16;
311 }
312 }
313
314
315 /* Decides if DSC should be used and calculates target bpp if it should, applying DSC policy.
316 *
317 * Returns:
318 * - 'true' if DSC was required by policy and was successfully applied
319 * - 'false' if DSC was not necessary (e.g. if uncompressed stream fits 'target_bandwidth_kbps'),
320 * or if it couldn't be applied based on DSC policy.
321 */
decide_dsc_target_bpp_x16(const struct dc_dsc_policy * policy,const struct dsc_enc_caps * dsc_common_caps,const int target_bandwidth_kbps,const struct dc_crtc_timing * timing,int * target_bpp_x16)322 static bool decide_dsc_target_bpp_x16(
323 const struct dc_dsc_policy *policy,
324 const struct dsc_enc_caps *dsc_common_caps,
325 const int target_bandwidth_kbps,
326 const struct dc_crtc_timing *timing,
327 int *target_bpp_x16)
328 {
329 bool should_use_dsc = false;
330 struct dc_dsc_bw_range range;
331
332 memset(&range, 0, sizeof(range));
333
334 get_dsc_bandwidth_range(policy->min_target_bpp, policy->max_target_bpp,
335 dsc_common_caps, timing, &range);
336 if (target_bandwidth_kbps >= range.stream_kbps) {
337 /* enough bandwidth without dsc */
338 *target_bpp_x16 = 0;
339 should_use_dsc = false;
340 } else if (target_bandwidth_kbps >= range.max_kbps) {
341 /* use max target bpp allowed */
342 *target_bpp_x16 = range.max_target_bpp_x16;
343 should_use_dsc = true;
344 } else if (target_bandwidth_kbps >= range.min_kbps) {
345 /* use target bpp that can take entire target bandwidth */
346 *target_bpp_x16 = calc_dsc_bpp_x16(target_bandwidth_kbps, timing->pix_clk_100hz, dsc_common_caps->bpp_increment_div);
347 should_use_dsc = true;
348 } else {
349 /* not enough bandwidth to fulfill minimum requirement */
350 *target_bpp_x16 = 0;
351 should_use_dsc = false;
352 }
353
354 return should_use_dsc;
355 }
356
357 #define MIN_AVAILABLE_SLICES_SIZE 4
358
get_available_dsc_slices(union dsc_enc_slice_caps slice_caps,int * available_slices)359 static int get_available_dsc_slices(union dsc_enc_slice_caps slice_caps, int *available_slices)
360 {
361 int idx = 0;
362
363 memset(available_slices, -1, MIN_AVAILABLE_SLICES_SIZE);
364
365 if (slice_caps.bits.NUM_SLICES_1)
366 available_slices[idx++] = 1;
367
368 if (slice_caps.bits.NUM_SLICES_2)
369 available_slices[idx++] = 2;
370
371 if (slice_caps.bits.NUM_SLICES_4)
372 available_slices[idx++] = 4;
373
374 if (slice_caps.bits.NUM_SLICES_8)
375 available_slices[idx++] = 8;
376
377 return idx;
378 }
379
380
get_max_dsc_slices(union dsc_enc_slice_caps slice_caps)381 static int get_max_dsc_slices(union dsc_enc_slice_caps slice_caps)
382 {
383 int max_slices = 0;
384 int available_slices[MIN_AVAILABLE_SLICES_SIZE];
385 int end_idx = get_available_dsc_slices(slice_caps, &available_slices[0]);
386
387 if (end_idx > 0)
388 max_slices = available_slices[end_idx - 1];
389
390 return max_slices;
391 }
392
393
394 // Increment sice number in available sice numbers stops if possible, or just increment if not
inc_num_slices(union dsc_enc_slice_caps slice_caps,int num_slices)395 static int inc_num_slices(union dsc_enc_slice_caps slice_caps, int num_slices)
396 {
397 // Get next bigger num slices available in common caps
398 int available_slices[MIN_AVAILABLE_SLICES_SIZE];
399 int end_idx;
400 int i;
401 int new_num_slices = num_slices;
402
403 end_idx = get_available_dsc_slices(slice_caps, &available_slices[0]);
404 if (end_idx == 0) {
405 // No available slices found
406 new_num_slices++;
407 return new_num_slices;
408 }
409
410 // Numbers of slices found - get the next bigger number
411 for (i = 0; i < end_idx; i++) {
412 if (new_num_slices < available_slices[i]) {
413 new_num_slices = available_slices[i];
414 break;
415 }
416 }
417
418 if (new_num_slices == num_slices) // No biger number of slices found
419 new_num_slices++;
420
421 return new_num_slices;
422 }
423
424
425 // Decrement sice number in available sice numbers stops if possible, or just decrement if not. Stop at zero.
dec_num_slices(union dsc_enc_slice_caps slice_caps,int num_slices)426 static int dec_num_slices(union dsc_enc_slice_caps slice_caps, int num_slices)
427 {
428 // Get next bigger num slices available in common caps
429 int available_slices[MIN_AVAILABLE_SLICES_SIZE];
430 int end_idx;
431 int i;
432 int new_num_slices = num_slices;
433
434 end_idx = get_available_dsc_slices(slice_caps, &available_slices[0]);
435 if (end_idx == 0 && new_num_slices > 0) {
436 // No numbers of slices found
437 new_num_slices++;
438 return new_num_slices;
439 }
440
441 // Numbers of slices found - get the next smaller number
442 for (i = end_idx - 1; i >= 0; i--) {
443 if (new_num_slices > available_slices[i]) {
444 new_num_slices = available_slices[i];
445 break;
446 }
447 }
448
449 if (new_num_slices == num_slices) {
450 // No smaller number of slices found
451 new_num_slices--;
452 if (new_num_slices < 0)
453 new_num_slices = 0;
454 }
455
456 return new_num_slices;
457 }
458
459
460 // Choose next bigger number of slices if the requested number of slices is not available
fit_num_slices_up(union dsc_enc_slice_caps slice_caps,int num_slices)461 static int fit_num_slices_up(union dsc_enc_slice_caps slice_caps, int num_slices)
462 {
463 // Get next bigger num slices available in common caps
464 int available_slices[MIN_AVAILABLE_SLICES_SIZE];
465 int end_idx;
466 int i;
467 int new_num_slices = num_slices;
468
469 end_idx = get_available_dsc_slices(slice_caps, &available_slices[0]);
470 if (end_idx == 0) {
471 // No available slices found
472 new_num_slices++;
473 return new_num_slices;
474 }
475
476 // Numbers of slices found - get the equal or next bigger number
477 for (i = 0; i < end_idx; i++) {
478 if (new_num_slices <= available_slices[i]) {
479 new_num_slices = available_slices[i];
480 break;
481 }
482 }
483
484 return new_num_slices;
485 }
486
487
488 /* Attempts to set DSC configuration for the stream, applying DSC policy.
489 * Returns 'true' if successful or 'false' if not.
490 *
491 * Parameters:
492 *
493 * dsc_sink_caps - DSC sink decoder capabilities (from DPCD)
494 *
495 * dsc_enc_caps - DSC encoder capabilities
496 *
497 * target_bandwidth_kbps - Target bandwidth to fit the stream into.
498 * If 0, do not calculate target bpp.
499 *
500 * timing - The stream timing to fit into 'target_bandwidth_kbps' or apply
501 * maximum compression to, if 'target_badwidth == 0'
502 *
503 * dsc_cfg - DSC configuration to use if it was possible to come up with
504 * one for the given inputs.
505 * The target bitrate after DSC can be calculated by multiplying
506 * dsc_cfg.bits_per_pixel (in U6.4 format) by pixel rate, e.g.
507 *
508 * dsc_stream_bitrate_kbps = (int)ceil(timing->pix_clk_khz * dsc_cfg.bits_per_pixel / 16.0);
509 */
setup_dsc_config(const struct dsc_dec_dpcd_caps * dsc_sink_caps,const struct dsc_enc_caps * dsc_enc_caps,int target_bandwidth_kbps,const struct dc_crtc_timing * timing,struct dc_dsc_config * dsc_cfg)510 static bool setup_dsc_config(
511 const struct dsc_dec_dpcd_caps *dsc_sink_caps,
512 const struct dsc_enc_caps *dsc_enc_caps,
513 int target_bandwidth_kbps,
514 const struct dc_crtc_timing *timing,
515 struct dc_dsc_config *dsc_cfg)
516 {
517 struct dsc_enc_caps dsc_common_caps;
518 int max_slices_h;
519 int min_slices_h;
520 int num_slices_h;
521 int pic_width;
522 int slice_width;
523 int target_bpp;
524 int sink_per_slice_throughput_mps;
525 int branch_max_throughput_mps = 0;
526 bool is_dsc_possible = false;
527 int pic_height;
528 int slice_height;
529
530 memset(dsc_cfg, 0, sizeof(struct dc_dsc_config));
531
532 pic_width = timing->h_addressable + timing->h_border_left + timing->h_border_right;
533 pic_height = timing->v_addressable + timing->v_border_top + timing->v_border_bottom;
534
535 if (!dsc_sink_caps->is_dsc_supported)
536 goto done;
537
538 if (dsc_sink_caps->branch_max_line_width && dsc_sink_caps->branch_max_line_width < pic_width)
539 goto done;
540
541 // Intersect decoder with encoder DSC caps and validate DSC settings
542 is_dsc_possible = intersect_dsc_caps(dsc_sink_caps, dsc_enc_caps, timing->pixel_encoding, &dsc_common_caps);
543 if (!is_dsc_possible)
544 goto done;
545
546 if (target_bandwidth_kbps > 0) {
547 is_dsc_possible = decide_dsc_target_bpp_x16(&dsc_policy, &dsc_common_caps, target_bandwidth_kbps, timing, &target_bpp);
548 dsc_cfg->bits_per_pixel = target_bpp;
549 }
550 if (!is_dsc_possible)
551 goto done;
552
553 sink_per_slice_throughput_mps = 0;
554
555 // Validate available DSC settings against the mode timing
556
557 // Validate color format (and pick up the throughput values)
558 dsc_cfg->ycbcr422_simple = false;
559 switch (timing->pixel_encoding) {
560 case PIXEL_ENCODING_RGB:
561 is_dsc_possible = (bool)dsc_common_caps.color_formats.bits.RGB;
562 sink_per_slice_throughput_mps = dsc_sink_caps->throughput_mode_0_mps;
563 branch_max_throughput_mps = dsc_sink_caps->branch_overall_throughput_0_mps;
564 break;
565 case PIXEL_ENCODING_YCBCR444:
566 is_dsc_possible = (bool)dsc_common_caps.color_formats.bits.YCBCR_444;
567 sink_per_slice_throughput_mps = dsc_sink_caps->throughput_mode_0_mps;
568 branch_max_throughput_mps = dsc_sink_caps->branch_overall_throughput_0_mps;
569 break;
570 case PIXEL_ENCODING_YCBCR422:
571 is_dsc_possible = (bool)dsc_common_caps.color_formats.bits.YCBCR_NATIVE_422;
572 sink_per_slice_throughput_mps = dsc_sink_caps->throughput_mode_1_mps;
573 branch_max_throughput_mps = dsc_sink_caps->branch_overall_throughput_1_mps;
574 if (!is_dsc_possible) {
575 is_dsc_possible = (bool)dsc_common_caps.color_formats.bits.YCBCR_SIMPLE_422;
576 dsc_cfg->ycbcr422_simple = is_dsc_possible;
577 sink_per_slice_throughput_mps = dsc_sink_caps->throughput_mode_0_mps;
578 }
579 break;
580 case PIXEL_ENCODING_YCBCR420:
581 is_dsc_possible = (bool)dsc_common_caps.color_formats.bits.YCBCR_NATIVE_420;
582 sink_per_slice_throughput_mps = dsc_sink_caps->throughput_mode_1_mps;
583 branch_max_throughput_mps = dsc_sink_caps->branch_overall_throughput_1_mps;
584 break;
585 default:
586 is_dsc_possible = false;
587 }
588
589 // Validate branch's maximum throughput
590 if (branch_max_throughput_mps && dsc_div_by_10_round_up(timing->pix_clk_100hz) > branch_max_throughput_mps * 1000)
591 is_dsc_possible = false;
592
593 if (!is_dsc_possible)
594 goto done;
595
596 // Color depth
597 switch (timing->display_color_depth) {
598 case COLOR_DEPTH_888:
599 is_dsc_possible = (bool)dsc_common_caps.color_depth.bits.COLOR_DEPTH_8_BPC;
600 break;
601 case COLOR_DEPTH_101010:
602 is_dsc_possible = (bool)dsc_common_caps.color_depth.bits.COLOR_DEPTH_10_BPC;
603 break;
604 case COLOR_DEPTH_121212:
605 is_dsc_possible = (bool)dsc_common_caps.color_depth.bits.COLOR_DEPTH_12_BPC;
606 break;
607 default:
608 is_dsc_possible = false;
609 }
610
611 if (!is_dsc_possible)
612 goto done;
613
614 // Slice width (i.e. number of slices per line)
615 max_slices_h = get_max_dsc_slices(dsc_common_caps.slice_caps);
616
617 while (max_slices_h > 0) {
618 if (pic_width % max_slices_h == 0)
619 break;
620
621 max_slices_h = dec_num_slices(dsc_common_caps.slice_caps, max_slices_h);
622 }
623
624 is_dsc_possible = (dsc_common_caps.max_slice_width > 0);
625 if (!is_dsc_possible)
626 goto done;
627
628 min_slices_h = pic_width / dsc_common_caps.max_slice_width;
629 if (pic_width % dsc_common_caps.max_slice_width)
630 min_slices_h++;
631
632 min_slices_h = fit_num_slices_up(dsc_common_caps.slice_caps, min_slices_h);
633
634 while (min_slices_h <= max_slices_h) {
635 int pix_clk_per_slice_khz = dsc_div_by_10_round_up(timing->pix_clk_100hz) / min_slices_h;
636 if (pix_clk_per_slice_khz <= sink_per_slice_throughput_mps * 1000)
637 break;
638
639 min_slices_h = inc_num_slices(dsc_common_caps.slice_caps, min_slices_h);
640 }
641
642 if (pic_width % min_slices_h != 0)
643 min_slices_h = 0; // DSC TODO: Maybe try increasing the number of slices first?
644
645 is_dsc_possible = (min_slices_h <= max_slices_h);
646 if (!is_dsc_possible)
647 goto done;
648
649 if (dsc_policy.use_min_slices_h) {
650 if (min_slices_h > 0)
651 num_slices_h = min_slices_h;
652 else if (max_slices_h > 0) { // Fall back to max slices if min slices is not working out
653 if (dsc_policy.max_slices_h)
654 num_slices_h = min(dsc_policy.max_slices_h, max_slices_h);
655 else
656 num_slices_h = max_slices_h;
657 } else
658 is_dsc_possible = false;
659 } else {
660 if (max_slices_h > 0) {
661 if (dsc_policy.max_slices_h)
662 num_slices_h = min(dsc_policy.max_slices_h, max_slices_h);
663 else
664 num_slices_h = max_slices_h;
665 } else if (min_slices_h > 0) // Fall back to min slices if max slices is not possible
666 num_slices_h = min_slices_h;
667 else
668 is_dsc_possible = false;
669 }
670
671 if (!is_dsc_possible)
672 goto done;
673
674 dsc_cfg->num_slices_h = num_slices_h;
675 slice_width = pic_width / num_slices_h;
676
677 is_dsc_possible = slice_width <= dsc_common_caps.max_slice_width;
678 if (!is_dsc_possible)
679 goto done;
680
681 // Slice height (i.e. number of slices per column): start with policy and pick the first one that height is divisible by.
682 // For 4:2:0 make sure the slice height is divisible by 2 as well.
683 slice_height = min(dsc_policy.min_sice_height, pic_height);
684
685 while (slice_height < pic_height && (pic_height % slice_height != 0 ||
686 (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420 && slice_height % 2 != 0)))
687 slice_height++;
688
689 if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) // For the case when pic_height < dsc_policy.min_sice_height
690 is_dsc_possible = (slice_height % 2 == 0);
691
692 if (!is_dsc_possible)
693 goto done;
694
695 dsc_cfg->num_slices_v = pic_height/slice_height;
696
697 // Final decission: can we do DSC or not?
698 if (is_dsc_possible) {
699 // Fill out the rest of DSC settings
700 dsc_cfg->block_pred_enable = dsc_common_caps.is_block_pred_supported;
701 dsc_cfg->linebuf_depth = dsc_common_caps.lb_bit_depth;
702 dsc_cfg->version_minor = (dsc_common_caps.dsc_version & 0xf0) >> 4;
703 }
704
705 done:
706 if (!is_dsc_possible)
707 memset(dsc_cfg, 0, sizeof(struct dc_dsc_config));
708
709 return is_dsc_possible;
710 }
711
dc_dsc_parse_dsc_dpcd(const uint8_t * dpcd_dsc_basic_data,const uint8_t * dpcd_dsc_ext_data,struct dsc_dec_dpcd_caps * dsc_sink_caps)712 bool dc_dsc_parse_dsc_dpcd(const uint8_t *dpcd_dsc_basic_data, const uint8_t *dpcd_dsc_ext_data, struct dsc_dec_dpcd_caps *dsc_sink_caps)
713 {
714 if (!dpcd_dsc_basic_data)
715 return false;
716
717 dsc_sink_caps->is_dsc_supported = (dpcd_dsc_basic_data[DP_DSC_SUPPORT - DP_DSC_SUPPORT] & DP_DSC_DECOMPRESSION_IS_SUPPORTED) != 0;
718 if (!dsc_sink_caps->is_dsc_supported)
719 return false;
720
721 dsc_sink_caps->dsc_version = dpcd_dsc_basic_data[DP_DSC_REV - DP_DSC_SUPPORT];
722
723 {
724 int buff_block_size;
725 int buff_size;
726
727 if (!dsc_buff_block_size_from_dpcd(dpcd_dsc_basic_data[DP_DSC_RC_BUF_BLK_SIZE - DP_DSC_SUPPORT], &buff_block_size))
728 return false;
729
730 buff_size = dpcd_dsc_basic_data[DP_DSC_RC_BUF_SIZE - DP_DSC_SUPPORT] + 1;
731 dsc_sink_caps->rc_buffer_size = buff_size * buff_block_size;
732 }
733
734 dsc_sink_caps->slice_caps1.raw = dpcd_dsc_basic_data[DP_DSC_SLICE_CAP_1 - DP_DSC_SUPPORT];
735 if (!dsc_line_buff_depth_from_dpcd(dpcd_dsc_basic_data[DP_DSC_LINE_BUF_BIT_DEPTH - DP_DSC_SUPPORT], &dsc_sink_caps->lb_bit_depth))
736 return false;
737
738 dsc_sink_caps->is_block_pred_supported =
739 (dpcd_dsc_basic_data[DP_DSC_BLK_PREDICTION_SUPPORT - DP_DSC_SUPPORT] & DP_DSC_BLK_PREDICTION_IS_SUPPORTED) != 0;
740
741 dsc_sink_caps->edp_max_bits_per_pixel =
742 dpcd_dsc_basic_data[DP_DSC_MAX_BITS_PER_PIXEL_LOW - DP_DSC_SUPPORT] |
743 dpcd_dsc_basic_data[DP_DSC_MAX_BITS_PER_PIXEL_HI - DP_DSC_SUPPORT] << 8;
744
745 dsc_sink_caps->color_formats.raw = dpcd_dsc_basic_data[DP_DSC_DEC_COLOR_FORMAT_CAP - DP_DSC_SUPPORT];
746 dsc_sink_caps->color_depth.raw = dpcd_dsc_basic_data[DP_DSC_DEC_COLOR_DEPTH_CAP - DP_DSC_SUPPORT];
747
748 {
749 int dpcd_throughput = dpcd_dsc_basic_data[DP_DSC_PEAK_THROUGHPUT - DP_DSC_SUPPORT];
750
751 if (!dsc_throughput_from_dpcd(dpcd_throughput & DP_DSC_THROUGHPUT_MODE_0_MASK, &dsc_sink_caps->throughput_mode_0_mps))
752 return false;
753
754 dpcd_throughput = (dpcd_throughput & DP_DSC_THROUGHPUT_MODE_1_MASK) >> DP_DSC_THROUGHPUT_MODE_1_SHIFT;
755 if (!dsc_throughput_from_dpcd(dpcd_throughput, &dsc_sink_caps->throughput_mode_1_mps))
756 return false;
757 }
758
759 dsc_sink_caps->max_slice_width = dpcd_dsc_basic_data[DP_DSC_MAX_SLICE_WIDTH - DP_DSC_SUPPORT] * 320;
760 dsc_sink_caps->slice_caps2.raw = dpcd_dsc_basic_data[DP_DSC_SLICE_CAP_2 - DP_DSC_SUPPORT];
761
762 if (!dsc_bpp_increment_div_from_dpcd(dpcd_dsc_basic_data[DP_DSC_BITS_PER_PIXEL_INC - DP_DSC_SUPPORT], &dsc_sink_caps->bpp_increment_div))
763 return false;
764
765 /* Extended caps */
766 if (dpcd_dsc_ext_data == NULL) { // Extended DPCD DSC data can be null, e.g. because it doesn't apply to SST
767 dsc_sink_caps->branch_overall_throughput_0_mps = 0;
768 dsc_sink_caps->branch_overall_throughput_1_mps = 0;
769 dsc_sink_caps->branch_max_line_width = 0;
770 return true;
771 }
772
773 dsc_sink_caps->branch_overall_throughput_0_mps = dpcd_dsc_ext_data[DP_DSC_BRANCH_OVERALL_THROUGHPUT_0 - DP_DSC_BRANCH_OVERALL_THROUGHPUT_0];
774 if (dsc_sink_caps->branch_overall_throughput_0_mps == 0)
775 dsc_sink_caps->branch_overall_throughput_0_mps = 0;
776 else if (dsc_sink_caps->branch_overall_throughput_0_mps == 1)
777 dsc_sink_caps->branch_overall_throughput_0_mps = 680;
778 else {
779 dsc_sink_caps->branch_overall_throughput_0_mps *= 50;
780 dsc_sink_caps->branch_overall_throughput_0_mps += 600;
781 }
782
783 dsc_sink_caps->branch_overall_throughput_1_mps = dpcd_dsc_ext_data[DP_DSC_BRANCH_OVERALL_THROUGHPUT_1 - DP_DSC_BRANCH_OVERALL_THROUGHPUT_0];
784 if (dsc_sink_caps->branch_overall_throughput_1_mps == 0)
785 dsc_sink_caps->branch_overall_throughput_1_mps = 0;
786 else if (dsc_sink_caps->branch_overall_throughput_1_mps == 1)
787 dsc_sink_caps->branch_overall_throughput_1_mps = 680;
788 else {
789 dsc_sink_caps->branch_overall_throughput_1_mps *= 50;
790 dsc_sink_caps->branch_overall_throughput_1_mps += 600;
791 }
792
793 dsc_sink_caps->branch_max_line_width = dpcd_dsc_ext_data[DP_DSC_BRANCH_MAX_LINE_WIDTH - DP_DSC_BRANCH_OVERALL_THROUGHPUT_0] * 320;
794 ASSERT(dsc_sink_caps->branch_max_line_width == 0 || dsc_sink_caps->branch_max_line_width >= 5120);
795
796 return true;
797 }
798
799
800 /* If DSC is possbile, get DSC bandwidth range based on [min_bpp, max_bpp] target bitrate range and
801 * timing's pixel clock and uncompressed bandwidth.
802 * If DSC is not possible, leave '*range' untouched.
803 */
dc_dsc_compute_bandwidth_range(const struct dc * dc,const uint32_t min_bpp,const uint32_t max_bpp,const struct dsc_dec_dpcd_caps * dsc_sink_caps,const struct dc_crtc_timing * timing,struct dc_dsc_bw_range * range)804 bool dc_dsc_compute_bandwidth_range(
805 const struct dc *dc,
806 const uint32_t min_bpp,
807 const uint32_t max_bpp,
808 const struct dsc_dec_dpcd_caps *dsc_sink_caps,
809 const struct dc_crtc_timing *timing,
810 struct dc_dsc_bw_range *range)
811 {
812 bool is_dsc_possible = false;
813 struct dsc_enc_caps dsc_enc_caps;
814 struct dsc_enc_caps dsc_common_caps;
815 struct dc_dsc_config config;
816
817 get_dsc_enc_caps(dc, &dsc_enc_caps, timing->pix_clk_100hz);
818
819 is_dsc_possible = intersect_dsc_caps(dsc_sink_caps, &dsc_enc_caps,
820 timing->pixel_encoding, &dsc_common_caps);
821
822 if (is_dsc_possible)
823 is_dsc_possible = setup_dsc_config(dsc_sink_caps,
824 &dsc_enc_caps,
825 0,
826 timing, &config);
827
828 if (is_dsc_possible)
829 get_dsc_bandwidth_range(min_bpp, max_bpp, &dsc_common_caps, timing, range);
830
831 return is_dsc_possible;
832 }
833
dc_dsc_compute_config(const struct dc * dc,const struct dsc_dec_dpcd_caps * dsc_sink_caps,uint32_t target_bandwidth_kbps,const struct dc_crtc_timing * timing,struct dc_dsc_config * dsc_cfg)834 bool dc_dsc_compute_config(
835 const struct dc *dc,
836 const struct dsc_dec_dpcd_caps *dsc_sink_caps,
837 uint32_t target_bandwidth_kbps,
838 const struct dc_crtc_timing *timing,
839 struct dc_dsc_config *dsc_cfg)
840 {
841 bool is_dsc_possible = false;
842 struct dsc_enc_caps dsc_enc_caps;
843
844 get_dsc_enc_caps(dc, &dsc_enc_caps, timing->pix_clk_100hz);
845 is_dsc_possible = setup_dsc_config(dsc_sink_caps,
846 &dsc_enc_caps,
847 target_bandwidth_kbps,
848 timing, dsc_cfg);
849 return is_dsc_possible;
850 }
851 #endif /* CONFIG_DRM_AMD_DC_DSC_SUPPORT */
852