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