1272 lines · c
1/*2 * Copyright 2019 Advanced Micro Devices, Inc.3 *4 * Permission is hereby granted, free of charge, to any person obtaining a5 * copy of this software and associated documentation files (the "Software"),6 * to deal in the Software without restriction, including without limitation7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,8 * and/or sell copies of the Software, and to permit persons to whom the9 * Software is furnished to do so, subject to the following conditions:10 *11 * The above copyright notice and this permission notice shall be included in12 * all copies or substantial portions of the Software.13 *14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR18 * 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 OR20 * OTHER DEALINGS IN THE SOFTWARE.21 *22 * Author: AMD23 */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 */36static uint32_t dsc_policy_max_target_bpp_limit = 16;37 38/* default DSC policy enables DSC only when needed */39static bool dsc_policy_enable_dsc_when_not_needed;40 41static bool dsc_policy_disable_dsc_stream_overhead;42 43static bool disable_128b_132b_stream_overhead;44 45#ifndef MAX46#define MAX(X, Y) ((X) > (Y) ? (X) : (Y))47#endif48#ifndef MIN49#define MIN(X, Y) ((X) < (Y) ? (X) : (Y))50#endif51 52/* Need to account for padding due to pixel-to-symbol packing53 * for uncompressed 128b/132b streams.54 */55static 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(kbps);68 bpp = dc_fixpt_div_int(bpp, 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_HActive72 */73 overhead_factor = dc_fixpt_from_int(timing->h_addressable);74 overhead_factor = dc_fixpt_mul(overhead_factor, bpp);75 overhead_factor = dc_fixpt_div_int(overhead_factor, 128);76 overhead_factor = dc_fixpt_div(77 dc_fixpt_from_int(dc_fixpt_ceil(overhead_factor)),78 overhead_factor);79 80 total_kbps = dc_fixpt_ceil(81 dc_fixpt_mul_int(overhead_factor, total_kbps));82 }83 84 return total_kbps;85}86 87uint32_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 timing->dsc_cfg.bits_per_pixel,97 timing->dsc_cfg.num_slices_h,98 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/* Forward Declerations */149static bool decide_dsc_bandwidth_range(150 const uint32_t min_bpp_x16,151 const uint32_t max_bpp_x16,152 const uint32_t num_slices_h,153 const struct dsc_enc_caps *dsc_caps,154 const struct dc_crtc_timing *timing,155 const enum dc_link_encoding_format link_encoding,156 struct dc_dsc_bw_range *range);157 158static uint32_t compute_bpp_x16_from_target_bandwidth(159 const uint32_t bandwidth_in_kbps,160 const struct dc_crtc_timing *timing,161 const uint32_t num_slices_h,162 const uint32_t bpp_increment_div,163 const bool is_dp);164 165static void get_dsc_enc_caps(166 const struct display_stream_compressor *dsc,167 struct dsc_enc_caps *dsc_enc_caps,168 int pixel_clock_100Hz);169 170static bool intersect_dsc_caps(171 const struct dsc_dec_dpcd_caps *dsc_sink_caps,172 const struct dsc_enc_caps *dsc_enc_caps,173 enum dc_pixel_encoding pixel_encoding,174 struct dsc_enc_caps *dsc_common_caps);175 176static bool setup_dsc_config(177 const struct dsc_dec_dpcd_caps *dsc_sink_caps,178 const struct dsc_enc_caps *dsc_enc_caps,179 int target_bandwidth_kbps,180 const struct dc_crtc_timing *timing,181 const struct dc_dsc_config_options *options,182 const enum dc_link_encoding_format link_encoding,183 struct dc_dsc_config *dsc_cfg);184 185static bool dsc_buff_block_size_from_dpcd(int dpcd_buff_block_size, int *buff_block_size)186{187 188 switch (dpcd_buff_block_size) {189 case DP_DSC_RC_BUF_BLK_SIZE_1:190 *buff_block_size = 1024;191 break;192 case DP_DSC_RC_BUF_BLK_SIZE_4:193 *buff_block_size = 4 * 1024;194 break;195 case DP_DSC_RC_BUF_BLK_SIZE_16:196 *buff_block_size = 16 * 1024;197 break;198 case DP_DSC_RC_BUF_BLK_SIZE_64:199 *buff_block_size = 64 * 1024;200 break;201 default: {202 dm_error("%s: DPCD DSC buffer size not recognized.\n", __func__);203 return false;204 }205 }206 207 return true;208}209 210 211static bool dsc_line_buff_depth_from_dpcd(int dpcd_line_buff_bit_depth, int *line_buff_bit_depth)212{213 if (0 <= dpcd_line_buff_bit_depth && dpcd_line_buff_bit_depth <= 7)214 *line_buff_bit_depth = dpcd_line_buff_bit_depth + 9;215 else if (dpcd_line_buff_bit_depth == 8)216 *line_buff_bit_depth = 8;217 else {218 dm_error("%s: DPCD DSC buffer depth not recognized.\n", __func__);219 return false;220 }221 222 return true;223}224 225 226static bool dsc_throughput_from_dpcd(int dpcd_throughput, int *throughput)227{228 switch (dpcd_throughput) {229 case DP_DSC_THROUGHPUT_MODE_0_UNSUPPORTED:230 *throughput = 0;231 break;232 case DP_DSC_THROUGHPUT_MODE_0_170:233 *throughput = 170;234 break;235 case DP_DSC_THROUGHPUT_MODE_0_340:236 *throughput = 340;237 break;238 case DP_DSC_THROUGHPUT_MODE_0_400:239 *throughput = 400;240 break;241 case DP_DSC_THROUGHPUT_MODE_0_450:242 *throughput = 450;243 break;244 case DP_DSC_THROUGHPUT_MODE_0_500:245 *throughput = 500;246 break;247 case DP_DSC_THROUGHPUT_MODE_0_550:248 *throughput = 550;249 break;250 case DP_DSC_THROUGHPUT_MODE_0_600:251 *throughput = 600;252 break;253 case DP_DSC_THROUGHPUT_MODE_0_650:254 *throughput = 650;255 break;256 case DP_DSC_THROUGHPUT_MODE_0_700:257 *throughput = 700;258 break;259 case DP_DSC_THROUGHPUT_MODE_0_750:260 *throughput = 750;261 break;262 case DP_DSC_THROUGHPUT_MODE_0_800:263 *throughput = 800;264 break;265 case DP_DSC_THROUGHPUT_MODE_0_850:266 *throughput = 850;267 break;268 case DP_DSC_THROUGHPUT_MODE_0_900:269 *throughput = 900;270 break;271 case DP_DSC_THROUGHPUT_MODE_0_950:272 *throughput = 950;273 break;274 case DP_DSC_THROUGHPUT_MODE_0_1000:275 *throughput = 1000;276 break;277 default: {278 dm_error("%s: DPCD DSC throughput mode not recognized.\n", __func__);279 return false;280 }281 }282 283 return true;284}285 286 287static bool dsc_bpp_increment_div_from_dpcd(uint8_t bpp_increment_dpcd, uint32_t *bpp_increment_div)288{289 // Mask bpp increment dpcd field to avoid reading other fields290 bpp_increment_dpcd &= 0x7;291 292 switch (bpp_increment_dpcd) {293 case 0:294 *bpp_increment_div = 16;295 break;296 case 1:297 *bpp_increment_div = 8;298 break;299 case 2:300 *bpp_increment_div = 4;301 break;302 case 3:303 *bpp_increment_div = 2;304 break;305 case 4:306 *bpp_increment_div = 1;307 break;308 default: {309 dm_error("%s: DPCD DSC bits-per-pixel increment not recognized.\n", __func__);310 return false;311 }312 }313 314 return true;315}316 317 318 319bool dc_dsc_parse_dsc_dpcd(const struct dc *dc,320 const uint8_t *dpcd_dsc_basic_data,321 const uint8_t *dpcd_dsc_branch_decoder_caps,322 struct dsc_dec_dpcd_caps *dsc_sink_caps)323{324 if (!dpcd_dsc_basic_data)325 return false;326 327 dsc_sink_caps->is_dsc_supported =328 (dpcd_dsc_basic_data[DP_DSC_SUPPORT - DP_DSC_SUPPORT] & DP_DSC_DECOMPRESSION_IS_SUPPORTED) != 0;329 if (!dsc_sink_caps->is_dsc_supported)330 return false;331 332 dsc_sink_caps->dsc_version = dpcd_dsc_basic_data[DP_DSC_REV - DP_DSC_SUPPORT];333 334 {335 int buff_block_size;336 int buff_size;337 338 if (!dsc_buff_block_size_from_dpcd(339 dpcd_dsc_basic_data[DP_DSC_RC_BUF_BLK_SIZE - DP_DSC_SUPPORT] & 0x03,340 &buff_block_size))341 return false;342 343 buff_size = dpcd_dsc_basic_data[DP_DSC_RC_BUF_SIZE - DP_DSC_SUPPORT] + 1;344 dsc_sink_caps->rc_buffer_size = buff_size * buff_block_size;345 }346 347 dsc_sink_caps->slice_caps1.raw = dpcd_dsc_basic_data[DP_DSC_SLICE_CAP_1 - DP_DSC_SUPPORT];348 if (!dsc_line_buff_depth_from_dpcd(dpcd_dsc_basic_data[DP_DSC_LINE_BUF_BIT_DEPTH - DP_DSC_SUPPORT],349 &dsc_sink_caps->lb_bit_depth))350 return false;351 352 dsc_sink_caps->is_block_pred_supported =353 (dpcd_dsc_basic_data[DP_DSC_BLK_PREDICTION_SUPPORT - DP_DSC_SUPPORT] &354 DP_DSC_BLK_PREDICTION_IS_SUPPORTED) != 0;355 356 dsc_sink_caps->edp_max_bits_per_pixel =357 dpcd_dsc_basic_data[DP_DSC_MAX_BITS_PER_PIXEL_LOW - DP_DSC_SUPPORT] |358 dpcd_dsc_basic_data[DP_DSC_MAX_BITS_PER_PIXEL_HI - DP_DSC_SUPPORT] << 8;359 360 dsc_sink_caps->color_formats.raw = dpcd_dsc_basic_data[DP_DSC_DEC_COLOR_FORMAT_CAP - DP_DSC_SUPPORT];361 dsc_sink_caps->color_depth.raw = dpcd_dsc_basic_data[DP_DSC_DEC_COLOR_DEPTH_CAP - DP_DSC_SUPPORT];362 363 {364 int dpcd_throughput = dpcd_dsc_basic_data[DP_DSC_PEAK_THROUGHPUT - DP_DSC_SUPPORT];365 int dsc_throughput_granular_delta;366 367 dsc_throughput_granular_delta = dpcd_dsc_basic_data[DP_DSC_RC_BUF_BLK_SIZE - DP_DSC_SUPPORT] >> 3;368 dsc_throughput_granular_delta *= 2;369 370 if (!dsc_throughput_from_dpcd(dpcd_throughput & DP_DSC_THROUGHPUT_MODE_0_MASK,371 &dsc_sink_caps->throughput_mode_0_mps))372 return false;373 dsc_sink_caps->throughput_mode_0_mps += dsc_throughput_granular_delta;374 375 dpcd_throughput = (dpcd_throughput & DP_DSC_THROUGHPUT_MODE_1_MASK) >> DP_DSC_THROUGHPUT_MODE_1_SHIFT;376 if (!dsc_throughput_from_dpcd(dpcd_throughput, &dsc_sink_caps->throughput_mode_1_mps))377 return false;378 }379 380 dsc_sink_caps->max_slice_width = dpcd_dsc_basic_data[DP_DSC_MAX_SLICE_WIDTH - DP_DSC_SUPPORT] * 320;381 dsc_sink_caps->slice_caps2.raw = dpcd_dsc_basic_data[DP_DSC_SLICE_CAP_2 - DP_DSC_SUPPORT];382 383 if (!dsc_bpp_increment_div_from_dpcd(dpcd_dsc_basic_data[DP_DSC_BITS_PER_PIXEL_INC - DP_DSC_SUPPORT],384 &dsc_sink_caps->bpp_increment_div))385 return false;386 387 if (dc->debug.dsc_bpp_increment_div) {388 /* dsc_bpp_increment_div should onl be 1, 2, 4, 8 or 16, but rather than rejecting invalid values,389 * we'll accept all and get it into range. This also makes the above check against 0 redundant,390 * but that one stresses out the override will be only used if it's not 0.391 */392 if (dc->debug.dsc_bpp_increment_div >= 1)393 dsc_sink_caps->bpp_increment_div = 1;394 if (dc->debug.dsc_bpp_increment_div >= 2)395 dsc_sink_caps->bpp_increment_div = 2;396 if (dc->debug.dsc_bpp_increment_div >= 4)397 dsc_sink_caps->bpp_increment_div = 4;398 if (dc->debug.dsc_bpp_increment_div >= 8)399 dsc_sink_caps->bpp_increment_div = 8;400 if (dc->debug.dsc_bpp_increment_div >= 16)401 dsc_sink_caps->bpp_increment_div = 16;402 }403 404 /* Extended caps */405 if (dpcd_dsc_branch_decoder_caps == NULL) { // branch decoder DPCD DSC data can be null for non branch device406 dsc_sink_caps->branch_overall_throughput_0_mps = 0;407 dsc_sink_caps->branch_overall_throughput_1_mps = 0;408 dsc_sink_caps->branch_max_line_width = 0;409 return true;410 }411 412 dsc_sink_caps->branch_overall_throughput_0_mps =413 dpcd_dsc_branch_decoder_caps[DP_DSC_BRANCH_OVERALL_THROUGHPUT_0 - DP_DSC_BRANCH_OVERALL_THROUGHPUT_0];414 if (dsc_sink_caps->branch_overall_throughput_0_mps == 0)415 dsc_sink_caps->branch_overall_throughput_0_mps = 0;416 else if (dsc_sink_caps->branch_overall_throughput_0_mps == 1)417 dsc_sink_caps->branch_overall_throughput_0_mps = 680;418 else {419 dsc_sink_caps->branch_overall_throughput_0_mps *= 50;420 dsc_sink_caps->branch_overall_throughput_0_mps += 600;421 }422 423 dsc_sink_caps->branch_overall_throughput_1_mps =424 dpcd_dsc_branch_decoder_caps[DP_DSC_BRANCH_OVERALL_THROUGHPUT_1 - DP_DSC_BRANCH_OVERALL_THROUGHPUT_0];425 if (dsc_sink_caps->branch_overall_throughput_1_mps == 0)426 dsc_sink_caps->branch_overall_throughput_1_mps = 0;427 else if (dsc_sink_caps->branch_overall_throughput_1_mps == 1)428 dsc_sink_caps->branch_overall_throughput_1_mps = 680;429 else {430 dsc_sink_caps->branch_overall_throughput_1_mps *= 50;431 dsc_sink_caps->branch_overall_throughput_1_mps += 600;432 }433 434 dsc_sink_caps->branch_max_line_width =435 dpcd_dsc_branch_decoder_caps[DP_DSC_BRANCH_MAX_LINE_WIDTH - DP_DSC_BRANCH_OVERALL_THROUGHPUT_0] * 320;436 ASSERT(dsc_sink_caps->branch_max_line_width == 0 || dsc_sink_caps->branch_max_line_width >= 5120);437 438 dsc_sink_caps->is_dp = true;439 return true;440}441 442 443/* If DSC is possbile, get DSC bandwidth range based on [min_bpp, max_bpp] target bitrate range and444 * timing's pixel clock and uncompressed bandwidth.445 * If DSC is not possible, leave '*range' untouched.446 */447bool dc_dsc_compute_bandwidth_range(448 const struct display_stream_compressor *dsc,449 uint32_t dsc_min_slice_height_override,450 uint32_t min_bpp_x16,451 uint32_t max_bpp_x16,452 const struct dsc_dec_dpcd_caps *dsc_sink_caps,453 const struct dc_crtc_timing *timing,454 const enum dc_link_encoding_format link_encoding,455 struct dc_dsc_bw_range *range)456{457 bool is_dsc_possible = false;458 struct dsc_enc_caps dsc_enc_caps;459 struct dsc_enc_caps dsc_common_caps;460 struct dc_dsc_config config = {0};461 struct dc_dsc_config_options options = {0};462 463 options.dsc_min_slice_height_override = dsc_min_slice_height_override;464 options.max_target_bpp_limit_override_x16 = max_bpp_x16;465 options.slice_height_granularity = 1;466 467 get_dsc_enc_caps(dsc, &dsc_enc_caps, timing->pix_clk_100hz);468 469 is_dsc_possible = intersect_dsc_caps(dsc_sink_caps, &dsc_enc_caps,470 timing->pixel_encoding, &dsc_common_caps);471 472 if (is_dsc_possible)473 is_dsc_possible = setup_dsc_config(dsc_sink_caps, &dsc_enc_caps, 0, timing,474 &options, link_encoding, &config);475 476 if (is_dsc_possible)477 is_dsc_possible = decide_dsc_bandwidth_range(min_bpp_x16, max_bpp_x16,478 config.num_slices_h, &dsc_common_caps, timing, link_encoding, range);479 480 return is_dsc_possible;481}482 483static void get_dsc_enc_caps(484 const struct display_stream_compressor *dsc,485 struct dsc_enc_caps *dsc_enc_caps,486 int pixel_clock_100Hz)487{488 // This is a static HW query, so we can use any DSC489 490 memset(dsc_enc_caps, 0, sizeof(struct dsc_enc_caps));491 if (dsc) {492 if (!dsc->ctx->dc->debug.disable_dsc)493 dsc->funcs->dsc_get_enc_caps(dsc_enc_caps, pixel_clock_100Hz);494 if (dsc->ctx->dc->debug.native422_support)495 dsc_enc_caps->color_formats.bits.YCBCR_NATIVE_422 = 1;496 }497}498 499/* Returns 'false' if no intersection was found for at least one capability.500 * It also implicitly validates some sink caps against invalid value of zero.501 */502static bool intersect_dsc_caps(503 const struct dsc_dec_dpcd_caps *dsc_sink_caps,504 const struct dsc_enc_caps *dsc_enc_caps,505 enum dc_pixel_encoding pixel_encoding,506 struct dsc_enc_caps *dsc_common_caps)507{508 int32_t max_slices;509 int32_t total_sink_throughput;510 511 memset(dsc_common_caps, 0, sizeof(struct dsc_enc_caps));512 513 dsc_common_caps->dsc_version = min(dsc_sink_caps->dsc_version, dsc_enc_caps->dsc_version);514 if (!dsc_common_caps->dsc_version)515 return false;516 517 dsc_common_caps->slice_caps.bits.NUM_SLICES_1 =518 dsc_sink_caps->slice_caps1.bits.NUM_SLICES_1 && dsc_enc_caps->slice_caps.bits.NUM_SLICES_1;519 dsc_common_caps->slice_caps.bits.NUM_SLICES_2 =520 dsc_sink_caps->slice_caps1.bits.NUM_SLICES_2 && dsc_enc_caps->slice_caps.bits.NUM_SLICES_2;521 dsc_common_caps->slice_caps.bits.NUM_SLICES_4 =522 dsc_sink_caps->slice_caps1.bits.NUM_SLICES_4 && dsc_enc_caps->slice_caps.bits.NUM_SLICES_4;523 dsc_common_caps->slice_caps.bits.NUM_SLICES_8 =524 dsc_sink_caps->slice_caps1.bits.NUM_SLICES_8 && dsc_enc_caps->slice_caps.bits.NUM_SLICES_8;525 dsc_common_caps->slice_caps.bits.NUM_SLICES_12 =526 dsc_sink_caps->slice_caps1.bits.NUM_SLICES_12 && dsc_enc_caps->slice_caps.bits.NUM_SLICES_12;527 dsc_common_caps->slice_caps.bits.NUM_SLICES_16 =528 dsc_sink_caps->slice_caps2.bits.NUM_SLICES_16 && dsc_enc_caps->slice_caps.bits.NUM_SLICES_16;529 530 if (!dsc_common_caps->slice_caps.raw)531 return false;532 533 dsc_common_caps->lb_bit_depth = min(dsc_sink_caps->lb_bit_depth, dsc_enc_caps->lb_bit_depth);534 if (!dsc_common_caps->lb_bit_depth)535 return false;536 537 dsc_common_caps->is_block_pred_supported =538 dsc_sink_caps->is_block_pred_supported && dsc_enc_caps->is_block_pred_supported;539 540 dsc_common_caps->color_formats.raw = dsc_sink_caps->color_formats.raw & dsc_enc_caps->color_formats.raw;541 if (!dsc_common_caps->color_formats.raw)542 return false;543 544 dsc_common_caps->color_depth.raw = dsc_sink_caps->color_depth.raw & dsc_enc_caps->color_depth.raw;545 if (!dsc_common_caps->color_depth.raw)546 return false;547 548 max_slices = 0;549 if (dsc_common_caps->slice_caps.bits.NUM_SLICES_1)550 max_slices = 1;551 552 if (dsc_common_caps->slice_caps.bits.NUM_SLICES_2)553 max_slices = 2;554 555 if (dsc_common_caps->slice_caps.bits.NUM_SLICES_4)556 max_slices = 4;557 558 total_sink_throughput = max_slices * dsc_sink_caps->throughput_mode_0_mps;559 if (pixel_encoding == PIXEL_ENCODING_YCBCR422 || pixel_encoding == PIXEL_ENCODING_YCBCR420)560 total_sink_throughput = max_slices * dsc_sink_caps->throughput_mode_1_mps;561 562 dsc_common_caps->max_total_throughput_mps = min(total_sink_throughput, dsc_enc_caps->max_total_throughput_mps);563 564 dsc_common_caps->max_slice_width = min(dsc_sink_caps->max_slice_width, dsc_enc_caps->max_slice_width);565 if (!dsc_common_caps->max_slice_width)566 return false;567 568 dsc_common_caps->bpp_increment_div = min(dsc_sink_caps->bpp_increment_div, dsc_enc_caps->bpp_increment_div);569 570 // TODO DSC: Remove this workaround for N422 and 420 once it's fixed, or move it to get_dsc_encoder_caps()571 if (pixel_encoding == PIXEL_ENCODING_YCBCR422 || pixel_encoding == PIXEL_ENCODING_YCBCR420)572 dsc_common_caps->bpp_increment_div = min(dsc_common_caps->bpp_increment_div, (uint32_t)8);573 574 dsc_common_caps->edp_sink_max_bits_per_pixel = dsc_sink_caps->edp_max_bits_per_pixel;575 dsc_common_caps->is_dp = dsc_sink_caps->is_dp;576 return true;577}578 579static inline uint32_t dsc_div_by_10_round_up(uint32_t value)580{581 return (value + 9) / 10;582}583 584static uint32_t compute_bpp_x16_from_target_bandwidth(585 const uint32_t bandwidth_in_kbps,586 const struct dc_crtc_timing *timing,587 const uint32_t num_slices_h,588 const uint32_t bpp_increment_div,589 const bool is_dp)590{591 uint32_t overhead_in_kbps;592 struct fixed31_32 effective_bandwidth_in_kbps;593 struct fixed31_32 bpp_x16;594 595 overhead_in_kbps = dc_dsc_stream_bandwidth_overhead_in_kbps(596 timing, num_slices_h, is_dp);597 effective_bandwidth_in_kbps = dc_fixpt_from_int(bandwidth_in_kbps);598 effective_bandwidth_in_kbps = dc_fixpt_sub_int(effective_bandwidth_in_kbps,599 overhead_in_kbps);600 bpp_x16 = dc_fixpt_mul_int(effective_bandwidth_in_kbps, 10);601 bpp_x16 = dc_fixpt_div_int(bpp_x16, timing->pix_clk_100hz);602 bpp_x16 = dc_fixpt_from_int(dc_fixpt_floor(dc_fixpt_mul_int(bpp_x16, bpp_increment_div)));603 bpp_x16 = dc_fixpt_div_int(bpp_x16, bpp_increment_div);604 bpp_x16 = dc_fixpt_mul_int(bpp_x16, 16);605 return dc_fixpt_floor(bpp_x16);606}607 608/* Decide DSC bandwidth range based on signal, timing, specs specific and input min and max609 * requirements.610 * The range output includes decided min/max target bpp, the respective bandwidth requirements611 * and native timing bandwidth requirement when DSC is not used.612 */613static bool decide_dsc_bandwidth_range(614 const uint32_t min_bpp_x16,615 const uint32_t max_bpp_x16,616 const uint32_t num_slices_h,617 const struct dsc_enc_caps *dsc_caps,618 const struct dc_crtc_timing *timing,619 const enum dc_link_encoding_format link_encoding,620 struct dc_dsc_bw_range *range)621{622 uint32_t preferred_bpp_x16 = timing->dsc_fixed_bits_per_pixel_x16;623 624 memset(range, 0, sizeof(*range));625 626 /* apply signal, timing, specs and explicitly specified DSC range requirements */627 if (preferred_bpp_x16) {628 if (preferred_bpp_x16 <= max_bpp_x16 &&629 preferred_bpp_x16 >= min_bpp_x16) {630 range->max_target_bpp_x16 = preferred_bpp_x16;631 range->min_target_bpp_x16 = preferred_bpp_x16;632 }633 }634 /* TODO - make this value generic to all signal types */635 else if (dsc_caps->edp_sink_max_bits_per_pixel) {636 /* apply max bpp limitation from edp sink */637 range->max_target_bpp_x16 = MIN(dsc_caps->edp_sink_max_bits_per_pixel,638 max_bpp_x16);639 range->min_target_bpp_x16 = min_bpp_x16;640 }641 else {642 range->max_target_bpp_x16 = max_bpp_x16;643 range->min_target_bpp_x16 = min_bpp_x16;644 }645 646 /* populate output structure */647 if (range->max_target_bpp_x16 >= range->min_target_bpp_x16 && range->min_target_bpp_x16 > 0) {648 /* native stream bandwidth */649 range->stream_kbps = dc_bandwidth_in_kbps_from_timing(timing, link_encoding);650 651 /* max dsc target bpp */652 range->max_kbps = dc_dsc_stream_bandwidth_in_kbps(timing,653 range->max_target_bpp_x16, num_slices_h, dsc_caps->is_dp);654 655 /* min dsc target bpp */656 range->min_kbps = dc_dsc_stream_bandwidth_in_kbps(timing,657 range->min_target_bpp_x16, num_slices_h, dsc_caps->is_dp);658 }659 660 return range->max_kbps >= range->min_kbps && range->min_kbps > 0;661}662 663/* Decides if DSC should be used and calculates target bpp if it should, applying DSC policy.664 *665 * Returns:666 * - 'true' if target bpp is decided667 * - 'false' if target bpp cannot be decided (e.g. cannot fit even with min DSC bpp),668 */669static bool decide_dsc_target_bpp_x16(670 const struct dc_dsc_policy *policy,671 const struct dc_dsc_config_options *options,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(policy->min_target_bpp * 16, policy->max_target_bpp * 16,684 num_slices_h, dsc_common_caps, timing, link_encoding, &range)) {685 if (target_bandwidth_kbps >= range.stream_kbps) {686 if (policy->enable_dsc_when_not_needed || options->force_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 target_bandwidth_kbps, timing, num_slices_h,696 dsc_common_caps->bpp_increment_div,697 dsc_common_caps->is_dp);698 }699 }700 701 return *target_bpp_x16 != 0;702}703 704#define MIN_AVAILABLE_SLICES_SIZE 6705 706static 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 732static 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[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 not746static int inc_num_slices(union dsc_enc_slice_caps slice_caps, int num_slices)747{748 // Get next bigger num slices available in common caps749 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[0]);755 if (end_idx == 0) {756 // No available slices found757 new_num_slices++;758 return new_num_slices;759 }760 761 // Numbers of slices found - get the next bigger number762 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 found770 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.777static int dec_num_slices(union dsc_enc_slice_caps slice_caps, int num_slices)778{779 // Get next bigger num slices available in common caps780 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[0]);786 if (end_idx == 0 && new_num_slices > 0) {787 // No numbers of slices found788 new_num_slices++;789 return new_num_slices;790 }791 792 // Numbers of slices found - get the next smaller number793 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 found802 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 available812static 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 caps815 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[0]);821 if (end_idx == 0) {822 // No available slices found823 new_num_slices++;824 return new_num_slices;825 }826 827 // Numbers of slices found - get the equal or next bigger number828 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 capabilities847 *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 apply852 * maximum compression to, if 'target_badwidth == 0'853 *854 * dsc_cfg - DSC configuration to use if it was possible to come up with855 * one for the given inputs.856 * The target bitrate after DSC can be calculated by multiplying857 * 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 */861static 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 = 0;872 int min_slices_h = 0;873 int num_slices_h = 0;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, options->max_target_bpp_limit_override_x16, &policy, link_encoding);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 settings897 is_dsc_possible = intersect_dsc_caps(dsc_sink_caps, dsc_enc_caps, timing->pixel_encoding, &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 timing904 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 throughput938 if (branch_max_throughput_mps && dsc_div_by_10_round_up(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 depth945 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(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(dsc_common_caps.slice_caps, 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(dsc_common_caps.slice_caps, 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(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(dsc_common_caps.slice_caps, 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 out1005 if (policy.max_slices_h)1006 num_slices_h = min(policy.max_slices_h, max_slices_h);1007 else1008 num_slices_h = max_slices_h;1009 } else1010 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 else1016 num_slices_h = max_slices_h;1017 } else if (min_slices_h > 0) // Fall back to min slices if max slices is not possible1018 num_slices_h = min_slices_h;1019 else1020 is_dsc_possible = false;1021 }1022 // When we force ODM, num dsc h slices must be divisible by num odm h slices1023 switch (options->dsc_force_odm_hslice_override) {1024 case 0:1025 case 1:1026 break;1027 case 2:1028 if (num_slices_h < 2)1029 num_slices_h = fit_num_slices_up(dsc_common_caps.slice_caps, 2);1030 break;1031 case 3:1032 if (dsc_common_caps.slice_caps.bits.NUM_SLICES_12)1033 num_slices_h = 12;1034 else1035 num_slices_h = 0;1036 break;1037 case 4:1038 if (num_slices_h < 4)1039 num_slices_h = fit_num_slices_up(dsc_common_caps.slice_caps, 4);1040 break;1041 default:1042 break;1043 }1044 if (num_slices_h == 0)1045 is_dsc_possible = false;1046 if (!is_dsc_possible)1047 goto done;1048 1049 dsc_cfg->num_slices_h = num_slices_h;1050 slice_width = pic_width / num_slices_h;1051 1052 is_dsc_possible = slice_width <= dsc_common_caps.max_slice_width;1053 if (!is_dsc_possible)1054 goto done;1055 1056 // Slice height (i.e. number of slices per column): start with policy and pick the first one that height is divisible by.1057 // For 4:2:0 make sure the slice height is divisible by 2 as well.1058 if (options->dsc_min_slice_height_override == 0)1059 slice_height = min(policy.min_slice_height, pic_height);1060 else1061 slice_height = min((int)(options->dsc_min_slice_height_override), pic_height);1062 1063 while (slice_height < pic_height && (pic_height % slice_height != 0 ||1064 slice_height % options->slice_height_granularity != 0 ||1065 (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420 && slice_height % 2 != 0)))1066 slice_height++;1067 1068 if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) // For the case when pic_height < dsc_policy.min_sice_height1069 is_dsc_possible = (slice_height % 2 == 0);1070 1071 if (!is_dsc_possible)1072 goto done;1073 1074 if (slice_height > 0) {1075 dsc_cfg->num_slices_v = pic_height / slice_height;1076 } else {1077 is_dsc_possible = false;1078 goto done;1079 }1080 1081 if (target_bandwidth_kbps > 0) {1082 is_dsc_possible = decide_dsc_target_bpp_x16(1083 &policy,1084 options,1085 &dsc_common_caps,1086 target_bandwidth_kbps,1087 timing,1088 num_slices_h,1089 link_encoding,1090 &target_bpp);1091 dsc_cfg->bits_per_pixel = target_bpp;1092 }1093 if (!is_dsc_possible)1094 goto done;1095 1096 // Final decission: can we do DSC or not?1097 if (is_dsc_possible) {1098 // Fill out the rest of DSC settings1099 dsc_cfg->block_pred_enable = dsc_common_caps.is_block_pred_supported;1100 dsc_cfg->linebuf_depth = dsc_common_caps.lb_bit_depth;1101 dsc_cfg->version_minor = (dsc_common_caps.dsc_version & 0xf0) >> 4;1102 dsc_cfg->is_dp = dsc_sink_caps->is_dp;1103 }1104 1105done:1106 if (!is_dsc_possible)1107 memset(dsc_cfg, 0, sizeof(struct dc_dsc_config));1108 1109 return is_dsc_possible;1110}1111 1112bool dc_dsc_compute_config(1113 const struct display_stream_compressor *dsc,1114 const struct dsc_dec_dpcd_caps *dsc_sink_caps,1115 const struct dc_dsc_config_options *options,1116 uint32_t target_bandwidth_kbps,1117 const struct dc_crtc_timing *timing,1118 const enum dc_link_encoding_format link_encoding,1119 struct dc_dsc_config *dsc_cfg)1120{1121 bool is_dsc_possible = false;1122 struct dsc_enc_caps dsc_enc_caps;1123 1124 get_dsc_enc_caps(dsc, &dsc_enc_caps, timing->pix_clk_100hz);1125 is_dsc_possible = setup_dsc_config(dsc_sink_caps,1126 &dsc_enc_caps,1127 target_bandwidth_kbps,1128 timing, options, link_encoding, dsc_cfg);1129 return is_dsc_possible;1130}1131 1132uint32_t dc_dsc_stream_bandwidth_in_kbps(const struct dc_crtc_timing *timing,1133 uint32_t bpp_x16, uint32_t num_slices_h, bool is_dp)1134{1135 uint32_t overhead_in_kbps;1136 struct fixed31_32 bpp;1137 struct fixed31_32 actual_bandwidth_in_kbps;1138 1139 overhead_in_kbps = dc_dsc_stream_bandwidth_overhead_in_kbps(1140 timing, num_slices_h, is_dp);1141 bpp = dc_fixpt_from_fraction(bpp_x16, 16);1142 actual_bandwidth_in_kbps = dc_fixpt_from_fraction(timing->pix_clk_100hz, 10);1143 actual_bandwidth_in_kbps = dc_fixpt_mul(actual_bandwidth_in_kbps, bpp);1144 actual_bandwidth_in_kbps = dc_fixpt_add_int(actual_bandwidth_in_kbps, overhead_in_kbps);1145 return dc_fixpt_ceil(actual_bandwidth_in_kbps);1146}1147 1148uint32_t dc_dsc_stream_bandwidth_overhead_in_kbps(1149 const struct dc_crtc_timing *timing,1150 const int num_slices_h,1151 const bool is_dp)1152{1153 struct fixed31_32 max_dsc_overhead;1154 struct fixed31_32 refresh_rate;1155 1156 if (dsc_policy_disable_dsc_stream_overhead || !is_dp)1157 return 0;1158 1159 /* use target bpp that can take entire target bandwidth */1160 refresh_rate = dc_fixpt_from_int(timing->pix_clk_100hz);1161 refresh_rate = dc_fixpt_div_int(refresh_rate, timing->h_total);1162 refresh_rate = dc_fixpt_div_int(refresh_rate, timing->v_total);1163 refresh_rate = dc_fixpt_mul_int(refresh_rate, 100);1164 1165 max_dsc_overhead = dc_fixpt_from_int(num_slices_h);1166 max_dsc_overhead = dc_fixpt_mul_int(max_dsc_overhead, timing->v_total);1167 max_dsc_overhead = dc_fixpt_mul_int(max_dsc_overhead, 256);1168 max_dsc_overhead = dc_fixpt_div_int(max_dsc_overhead, 1000);1169 max_dsc_overhead = dc_fixpt_mul(max_dsc_overhead, refresh_rate);1170 1171 return dc_fixpt_ceil(max_dsc_overhead);1172}1173 1174void dc_dsc_get_policy_for_timing(const struct dc_crtc_timing *timing,1175 uint32_t max_target_bpp_limit_override_x16,1176 struct dc_dsc_policy *policy,1177 const enum dc_link_encoding_format link_encoding)1178{1179 uint32_t bpc = 0;1180 1181 policy->min_target_bpp = 0;1182 policy->max_target_bpp = 0;1183 1184 /* DSC Policy: Use minimum number of slices that fits the pixel clock */1185 policy->use_min_slices_h = true;1186 1187 /* DSC Policy: Use max available slices1188 * (in our case 4 for or 8, depending on the mode)1189 */1190 policy->max_slices_h = 0;1191 1192 /* DSC Policy: Use slice height recommended1193 * by VESA DSC Spreadsheet user guide1194 */1195 policy->min_slice_height = 108;1196 1197 /* DSC Policy: follow DP specs with an internal upper limit to 16 bpp1198 * for better interoperability1199 */1200 switch (timing->display_color_depth) {1201 case COLOR_DEPTH_888:1202 bpc = 8;1203 break;1204 case COLOR_DEPTH_101010:1205 bpc = 10;1206 break;1207 case COLOR_DEPTH_121212:1208 bpc = 12;1209 break;1210 default:1211 return;1212 }1213 switch (timing->pixel_encoding) {1214 case PIXEL_ENCODING_RGB:1215 case PIXEL_ENCODING_YCBCR444:1216 case PIXEL_ENCODING_YCBCR422: /* assume no YCbCr422 native support */1217 /* DP specs limits to 8 */1218 policy->min_target_bpp = 8;1219 /* DP specs limits to 3 x bpc */1220 policy->max_target_bpp = 3 * bpc;1221 break;1222 case PIXEL_ENCODING_YCBCR420:1223 /* DP specs limits to 6 */1224 policy->min_target_bpp = 6;1225 /* DP specs limits to 1.5 x bpc assume bpc is an even number */1226 policy->max_target_bpp = bpc * 3 / 2;1227 break;1228 default:1229 return;1230 }1231 1232 /* internal upper limit, default 16 bpp */1233 if (policy->max_target_bpp > dsc_policy_max_target_bpp_limit)1234 policy->max_target_bpp = dsc_policy_max_target_bpp_limit;1235 1236 /* apply override */1237 if (max_target_bpp_limit_override_x16 && policy->max_target_bpp > max_target_bpp_limit_override_x16 / 16)1238 policy->max_target_bpp = max_target_bpp_limit_override_x16 / 16;1239 1240 /* enable DSC when not needed, default false */1241 policy->enable_dsc_when_not_needed = dsc_policy_enable_dsc_when_not_needed;1242}1243 1244void dc_dsc_policy_set_max_target_bpp_limit(uint32_t limit)1245{1246 dsc_policy_max_target_bpp_limit = limit;1247}1248 1249void dc_dsc_policy_set_enable_dsc_when_not_needed(bool enable)1250{1251 dsc_policy_enable_dsc_when_not_needed = enable;1252}1253 1254void dc_dsc_policy_set_disable_dsc_stream_overhead(bool disable)1255{1256 dsc_policy_disable_dsc_stream_overhead = disable;1257}1258 1259void dc_set_disable_128b_132b_stream_overhead(bool disable)1260{1261 disable_128b_132b_stream_overhead = disable;1262}1263 1264void dc_dsc_get_default_config_option(const struct dc *dc, struct dc_dsc_config_options *options)1265{1266 options->dsc_min_slice_height_override = dc->debug.dsc_min_slice_height_override;1267 options->dsc_force_odm_hslice_override = dc->debug.force_odm_combine;1268 options->max_target_bpp_limit_override_x16 = 0;1269 options->slice_height_granularity = 1;1270 options->force_dsc_when_not_needed = false;1271}1272