| 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 | #include "clk_mgr.h" |
| 34 | #include "resource.h" |
| 35 | |
| 36 | #define DC_LOGGER \ |
| 37 | dsc->ctx->logger |
| 38 | |
| 39 | /* This module's internal functions */ |
| 40 | |
| 41 | /* default DSC policy target bitrate limit is 16bpp */ |
| 42 | static uint32_t dsc_policy_max_target_bpp_limit = 16; |
| 43 | |
| 44 | /* default DSC policy enables DSC only when needed */ |
| 45 | static bool dsc_policy_enable_dsc_when_not_needed; |
| 46 | |
| 47 | static bool dsc_policy_disable_dsc_stream_overhead; |
| 48 | |
| 49 | static bool disable_128b_132b_stream_overhead; |
| 50 | |
| 51 | #ifndef MAX |
| 52 | #define MAX(X, Y) ((X) > (Y) ? (X) : (Y)) |
| 53 | #endif |
| 54 | #ifndef MIN |
| 55 | #define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) |
| 56 | #endif |
| 57 | |
| 58 | /* Need to account for padding due to pixel-to-symbol packing |
| 59 | * for uncompressed 128b/132b streams. |
| 60 | */ |
| 61 | static uint32_t apply_128b_132b_stream_overhead( |
| 62 | const struct dc_crtc_timing *timing, const uint32_t kbps) |
| 63 | { |
| 64 | uint32_t total_kbps = kbps; |
| 65 | |
| 66 | if (disable_128b_132b_stream_overhead) |
| 67 | return kbps; |
| 68 | |
| 69 | if (!timing->flags.DSC) { |
| 70 | struct fixed31_32 bpp; |
| 71 | struct fixed31_32 overhead_factor; |
| 72 | |
| 73 | bpp = dc_fixpt_from_int(arg: kbps); |
| 74 | bpp = dc_fixpt_div_int(arg1: bpp, arg2: timing->pix_clk_100hz / 10); |
| 75 | |
| 76 | /* Symbols_per_HActive = HActive * bpp / (4 lanes * 32-bit symbol size) |
| 77 | * Overhead_factor = ceil(Symbols_per_HActive) / Symbols_per_HActive |
| 78 | */ |
| 79 | overhead_factor = dc_fixpt_from_int(arg: timing->h_addressable); |
| 80 | overhead_factor = dc_fixpt_mul(arg1: overhead_factor, arg2: bpp); |
| 81 | overhead_factor = dc_fixpt_div_int(arg1: overhead_factor, arg2: 128); |
| 82 | overhead_factor = dc_fixpt_div( |
| 83 | arg1: dc_fixpt_from_int(arg: dc_fixpt_ceil(arg: overhead_factor)), |
| 84 | arg2: overhead_factor); |
| 85 | |
| 86 | total_kbps = dc_fixpt_ceil( |
| 87 | arg: dc_fixpt_mul_int(arg1: overhead_factor, arg2: total_kbps)); |
| 88 | } |
| 89 | |
| 90 | return total_kbps; |
| 91 | } |
| 92 | |
| 93 | uint32_t dc_bandwidth_in_kbps_from_timing( |
| 94 | const struct dc_crtc_timing *timing, |
| 95 | const enum dc_link_encoding_format link_encoding) |
| 96 | { |
| 97 | uint32_t bits_per_channel = 0; |
| 98 | uint32_t kbps; |
| 99 | |
| 100 | if (timing->flags.DSC) |
| 101 | return dc_dsc_stream_bandwidth_in_kbps(timing, |
| 102 | bpp_x16: timing->dsc_cfg.bits_per_pixel, |
| 103 | num_slices_h: timing->dsc_cfg.num_slices_h, |
| 104 | is_dp: timing->dsc_cfg.is_dp); |
| 105 | |
| 106 | switch (timing->display_color_depth) { |
| 107 | case COLOR_DEPTH_666: |
| 108 | bits_per_channel = 6; |
| 109 | break; |
| 110 | case COLOR_DEPTH_888: |
| 111 | bits_per_channel = 8; |
| 112 | break; |
| 113 | case COLOR_DEPTH_101010: |
| 114 | bits_per_channel = 10; |
| 115 | break; |
| 116 | case COLOR_DEPTH_121212: |
| 117 | bits_per_channel = 12; |
| 118 | break; |
| 119 | case COLOR_DEPTH_141414: |
| 120 | bits_per_channel = 14; |
| 121 | break; |
| 122 | case COLOR_DEPTH_161616: |
| 123 | bits_per_channel = 16; |
| 124 | break; |
| 125 | default: |
| 126 | ASSERT(bits_per_channel != 0); |
| 127 | bits_per_channel = 8; |
| 128 | break; |
| 129 | } |
| 130 | |
| 131 | kbps = timing->pix_clk_100hz / 10; |
| 132 | kbps *= bits_per_channel; |
| 133 | |
| 134 | if (timing->flags.Y_ONLY != 1) { |
| 135 | /*Only YOnly make reduce bandwidth by 1/3 compares to RGB*/ |
| 136 | kbps *= 3; |
| 137 | if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) |
| 138 | kbps /= 2; |
| 139 | else if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) |
| 140 | kbps = kbps * 2 / 3; |
| 141 | } |
| 142 | |
| 143 | if (link_encoding == DC_LINK_ENCODING_DP_128b_132b) |
| 144 | kbps = apply_128b_132b_stream_overhead(timing, kbps); |
| 145 | |
| 146 | if (link_encoding == DC_LINK_ENCODING_HDMI_FRL && |
| 147 | timing->vic == 0 && timing->hdmi_vic == 0 && |
| 148 | timing->frl_uncompressed_video_bandwidth_in_kbps != 0) |
| 149 | kbps = timing->frl_uncompressed_video_bandwidth_in_kbps; |
| 150 | |
| 151 | return kbps; |
| 152 | } |
| 153 | |
| 154 | /* Forward Declerations */ |
| 155 | static unsigned int get_min_dsc_slice_count_for_odm( |
| 156 | const struct display_stream_compressor *dsc, |
| 157 | const struct dsc_enc_caps *dsc_enc_caps, |
| 158 | const struct dc_crtc_timing *timing); |
| 159 | |
| 160 | static bool decide_dsc_bandwidth_range( |
| 161 | const uint32_t min_bpp_x16, |
| 162 | const uint32_t max_bpp_x16, |
| 163 | const uint32_t num_slices_h, |
| 164 | const struct dsc_enc_caps *dsc_caps, |
| 165 | const struct dc_crtc_timing *timing, |
| 166 | const enum dc_link_encoding_format link_encoding, |
| 167 | struct dc_dsc_bw_range *range); |
| 168 | |
| 169 | static uint32_t compute_bpp_x16_from_target_bandwidth( |
| 170 | const uint32_t bandwidth_in_kbps, |
| 171 | const struct dc_crtc_timing *timing, |
| 172 | const uint32_t num_slices_h, |
| 173 | const uint32_t bpp_increment_div, |
| 174 | const bool is_dp); |
| 175 | |
| 176 | static void get_dsc_enc_caps( |
| 177 | const struct display_stream_compressor *dsc, |
| 178 | struct dsc_enc_caps *dsc_enc_caps, |
| 179 | int pixel_clock_100Hz); |
| 180 | |
| 181 | static bool intersect_dsc_caps( |
| 182 | const struct dsc_dec_dpcd_caps *dsc_sink_caps, |
| 183 | const struct dsc_enc_caps *dsc_enc_caps, |
| 184 | enum dc_pixel_encoding pixel_encoding, |
| 185 | struct dsc_enc_caps *dsc_common_caps); |
| 186 | |
| 187 | static bool setup_dsc_config( |
| 188 | const struct dsc_dec_dpcd_caps *dsc_sink_caps, |
| 189 | const struct dsc_enc_caps *dsc_enc_caps, |
| 190 | int target_bandwidth_kbps, |
| 191 | const struct dc_crtc_timing *timing, |
| 192 | const struct dc_dsc_config_options *options, |
| 193 | const enum dc_link_encoding_format link_encoding, |
| 194 | int min_slice_count, |
| 195 | struct dc_dsc_config *dsc_cfg); |
| 196 | |
| 197 | static bool dsc_buff_block_size_from_dpcd(int dpcd_buff_block_size, int *buff_block_size) |
| 198 | { |
| 199 | |
| 200 | switch (dpcd_buff_block_size) { |
| 201 | case DP_DSC_RC_BUF_BLK_SIZE_1: |
| 202 | *buff_block_size = 1024; |
| 203 | break; |
| 204 | case DP_DSC_RC_BUF_BLK_SIZE_4: |
| 205 | *buff_block_size = 4 * 1024; |
| 206 | break; |
| 207 | case DP_DSC_RC_BUF_BLK_SIZE_16: |
| 208 | *buff_block_size = 16 * 1024; |
| 209 | break; |
| 210 | case DP_DSC_RC_BUF_BLK_SIZE_64: |
| 211 | *buff_block_size = 64 * 1024; |
| 212 | break; |
| 213 | default: { |
| 214 | dm_error("%s: DPCD DSC buffer size not recognized.\n" , __func__); |
| 215 | return false; |
| 216 | } |
| 217 | } |
| 218 | |
| 219 | return true; |
| 220 | } |
| 221 | |
| 222 | |
| 223 | static bool dsc_line_buff_depth_from_dpcd(int dpcd_line_buff_bit_depth, int *line_buff_bit_depth) |
| 224 | { |
| 225 | if (0 <= dpcd_line_buff_bit_depth && dpcd_line_buff_bit_depth <= 7) |
| 226 | *line_buff_bit_depth = dpcd_line_buff_bit_depth + 9; |
| 227 | else if (dpcd_line_buff_bit_depth == 8) |
| 228 | *line_buff_bit_depth = 8; |
| 229 | else { |
| 230 | dm_error("%s: DPCD DSC buffer depth not recognized.\n" , __func__); |
| 231 | return false; |
| 232 | } |
| 233 | |
| 234 | return true; |
| 235 | } |
| 236 | |
| 237 | |
| 238 | static bool dsc_throughput_from_dpcd(int dpcd_throughput, int *throughput) |
| 239 | { |
| 240 | switch (dpcd_throughput) { |
| 241 | case DP_DSC_THROUGHPUT_MODE_0_UNSUPPORTED: |
| 242 | *throughput = 0; |
| 243 | break; |
| 244 | case DP_DSC_THROUGHPUT_MODE_0_170: |
| 245 | *throughput = 170; |
| 246 | break; |
| 247 | case DP_DSC_THROUGHPUT_MODE_0_340: |
| 248 | *throughput = 340; |
| 249 | break; |
| 250 | case DP_DSC_THROUGHPUT_MODE_0_400: |
| 251 | *throughput = 400; |
| 252 | break; |
| 253 | case DP_DSC_THROUGHPUT_MODE_0_450: |
| 254 | *throughput = 450; |
| 255 | break; |
| 256 | case DP_DSC_THROUGHPUT_MODE_0_500: |
| 257 | *throughput = 500; |
| 258 | break; |
| 259 | case DP_DSC_THROUGHPUT_MODE_0_550: |
| 260 | *throughput = 550; |
| 261 | break; |
| 262 | case DP_DSC_THROUGHPUT_MODE_0_600: |
| 263 | *throughput = 600; |
| 264 | break; |
| 265 | case DP_DSC_THROUGHPUT_MODE_0_650: |
| 266 | *throughput = 650; |
| 267 | break; |
| 268 | case DP_DSC_THROUGHPUT_MODE_0_700: |
| 269 | *throughput = 700; |
| 270 | break; |
| 271 | case DP_DSC_THROUGHPUT_MODE_0_750: |
| 272 | *throughput = 750; |
| 273 | break; |
| 274 | case DP_DSC_THROUGHPUT_MODE_0_800: |
| 275 | *throughput = 800; |
| 276 | break; |
| 277 | case DP_DSC_THROUGHPUT_MODE_0_850: |
| 278 | *throughput = 850; |
| 279 | break; |
| 280 | case DP_DSC_THROUGHPUT_MODE_0_900: |
| 281 | *throughput = 900; |
| 282 | break; |
| 283 | case DP_DSC_THROUGHPUT_MODE_0_950: |
| 284 | *throughput = 950; |
| 285 | break; |
| 286 | case DP_DSC_THROUGHPUT_MODE_0_1000: |
| 287 | *throughput = 1000; |
| 288 | break; |
| 289 | default: { |
| 290 | dm_error("%s: DPCD DSC throughput mode not recognized.\n" , __func__); |
| 291 | return false; |
| 292 | } |
| 293 | } |
| 294 | |
| 295 | return true; |
| 296 | } |
| 297 | |
| 298 | |
| 299 | static bool dsc_bpp_increment_div_from_dpcd(uint8_t bpp_increment_dpcd, uint32_t *bpp_increment_div) |
| 300 | { |
| 301 | // Mask bpp increment dpcd field to avoid reading other fields |
| 302 | bpp_increment_dpcd &= 0x7; |
| 303 | |
| 304 | switch (bpp_increment_dpcd) { |
| 305 | case 0: |
| 306 | *bpp_increment_div = 16; |
| 307 | break; |
| 308 | case 1: |
| 309 | *bpp_increment_div = 8; |
| 310 | break; |
| 311 | case 2: |
| 312 | *bpp_increment_div = 4; |
| 313 | break; |
| 314 | case 3: |
| 315 | *bpp_increment_div = 2; |
| 316 | break; |
| 317 | case 4: |
| 318 | *bpp_increment_div = 1; |
| 319 | break; |
| 320 | default: { |
| 321 | dm_error("%s: DPCD DSC bits-per-pixel increment not recognized.\n" , __func__); |
| 322 | return false; |
| 323 | } |
| 324 | } |
| 325 | |
| 326 | return true; |
| 327 | } |
| 328 | |
| 329 | |
| 330 | |
| 331 | bool dc_dsc_parse_dsc_dpcd(const struct dc *dc, |
| 332 | const uint8_t *dpcd_dsc_basic_data, |
| 333 | const uint8_t *dpcd_dsc_branch_decoder_caps, |
| 334 | struct dsc_dec_dpcd_caps *dsc_sink_caps) |
| 335 | { |
| 336 | if (!dpcd_dsc_basic_data) |
| 337 | return false; |
| 338 | |
| 339 | dsc_sink_caps->is_dsc_supported = |
| 340 | (dpcd_dsc_basic_data[DP_DSC_SUPPORT - DP_DSC_SUPPORT] & DP_DSC_DECOMPRESSION_IS_SUPPORTED) != 0; |
| 341 | if (!dsc_sink_caps->is_dsc_supported) |
| 342 | return false; |
| 343 | |
| 344 | dsc_sink_caps->dsc_version = dpcd_dsc_basic_data[DP_DSC_REV - DP_DSC_SUPPORT]; |
| 345 | |
| 346 | { |
| 347 | int buff_block_size; |
| 348 | int buff_size; |
| 349 | |
| 350 | if (!dsc_buff_block_size_from_dpcd( |
| 351 | dpcd_buff_block_size: dpcd_dsc_basic_data[DP_DSC_RC_BUF_BLK_SIZE - DP_DSC_SUPPORT] & 0x03, |
| 352 | buff_block_size: &buff_block_size)) |
| 353 | return false; |
| 354 | |
| 355 | buff_size = dpcd_dsc_basic_data[DP_DSC_RC_BUF_SIZE - DP_DSC_SUPPORT] + 1; |
| 356 | dsc_sink_caps->rc_buffer_size = buff_size * buff_block_size; |
| 357 | } |
| 358 | |
| 359 | dsc_sink_caps->slice_caps1.raw = dpcd_dsc_basic_data[DP_DSC_SLICE_CAP_1 - DP_DSC_SUPPORT]; |
| 360 | if (!dsc_line_buff_depth_from_dpcd(dpcd_line_buff_bit_depth: dpcd_dsc_basic_data[DP_DSC_LINE_BUF_BIT_DEPTH - DP_DSC_SUPPORT], |
| 361 | line_buff_bit_depth: &dsc_sink_caps->lb_bit_depth)) |
| 362 | return false; |
| 363 | |
| 364 | dsc_sink_caps->is_block_pred_supported = |
| 365 | (dpcd_dsc_basic_data[DP_DSC_BLK_PREDICTION_SUPPORT - DP_DSC_SUPPORT] & |
| 366 | DP_DSC_BLK_PREDICTION_IS_SUPPORTED) != 0; |
| 367 | |
| 368 | dsc_sink_caps->edp_max_bits_per_pixel = |
| 369 | dpcd_dsc_basic_data[DP_DSC_MAX_BITS_PER_PIXEL_LOW - DP_DSC_SUPPORT] | |
| 370 | dpcd_dsc_basic_data[DP_DSC_MAX_BITS_PER_PIXEL_HI - DP_DSC_SUPPORT] << 8; |
| 371 | |
| 372 | dsc_sink_caps->color_formats.raw = dpcd_dsc_basic_data[DP_DSC_DEC_COLOR_FORMAT_CAP - DP_DSC_SUPPORT]; |
| 373 | dsc_sink_caps->color_depth.raw = dpcd_dsc_basic_data[DP_DSC_DEC_COLOR_DEPTH_CAP - DP_DSC_SUPPORT]; |
| 374 | |
| 375 | { |
| 376 | int dpcd_throughput = dpcd_dsc_basic_data[DP_DSC_PEAK_THROUGHPUT - DP_DSC_SUPPORT]; |
| 377 | int dsc_throughput_granular_delta; |
| 378 | |
| 379 | dsc_throughput_granular_delta = dpcd_dsc_basic_data[DP_DSC_RC_BUF_BLK_SIZE - DP_DSC_SUPPORT] >> 3; |
| 380 | dsc_throughput_granular_delta *= 2; |
| 381 | |
| 382 | if (!dsc_throughput_from_dpcd(dpcd_throughput: dpcd_throughput & DP_DSC_THROUGHPUT_MODE_0_MASK, |
| 383 | throughput: &dsc_sink_caps->throughput_mode_0_mps)) |
| 384 | return false; |
| 385 | dsc_sink_caps->throughput_mode_0_mps += dsc_throughput_granular_delta; |
| 386 | |
| 387 | dpcd_throughput = (dpcd_throughput & DP_DSC_THROUGHPUT_MODE_1_MASK) >> DP_DSC_THROUGHPUT_MODE_1_SHIFT; |
| 388 | if (!dsc_throughput_from_dpcd(dpcd_throughput, throughput: &dsc_sink_caps->throughput_mode_1_mps)) |
| 389 | return false; |
| 390 | } |
| 391 | |
| 392 | dsc_sink_caps->max_slice_width = dpcd_dsc_basic_data[DP_DSC_MAX_SLICE_WIDTH - DP_DSC_SUPPORT] * 320; |
| 393 | dsc_sink_caps->slice_caps2.raw = dpcd_dsc_basic_data[DP_DSC_SLICE_CAP_2 - DP_DSC_SUPPORT]; |
| 394 | |
| 395 | if (!dsc_bpp_increment_div_from_dpcd(bpp_increment_dpcd: dpcd_dsc_basic_data[DP_DSC_BITS_PER_PIXEL_INC - DP_DSC_SUPPORT], |
| 396 | bpp_increment_div: &dsc_sink_caps->bpp_increment_div)) |
| 397 | return false; |
| 398 | |
| 399 | if (dc->debug.dsc_bpp_increment_div) { |
| 400 | /* dsc_bpp_increment_div should onl be 1, 2, 4, 8 or 16, but rather than rejecting invalid values, |
| 401 | * we'll accept all and get it into range. This also makes the above check against 0 redundant, |
| 402 | * but that one stresses out the override will be only used if it's not 0. |
| 403 | */ |
| 404 | if (dc->debug.dsc_bpp_increment_div >= 1) |
| 405 | dsc_sink_caps->bpp_increment_div = 1; |
| 406 | if (dc->debug.dsc_bpp_increment_div >= 2) |
| 407 | dsc_sink_caps->bpp_increment_div = 2; |
| 408 | if (dc->debug.dsc_bpp_increment_div >= 4) |
| 409 | dsc_sink_caps->bpp_increment_div = 4; |
| 410 | if (dc->debug.dsc_bpp_increment_div >= 8) |
| 411 | dsc_sink_caps->bpp_increment_div = 8; |
| 412 | if (dc->debug.dsc_bpp_increment_div >= 16) |
| 413 | dsc_sink_caps->bpp_increment_div = 16; |
| 414 | } |
| 415 | |
| 416 | /* Extended caps */ |
| 417 | if (dpcd_dsc_branch_decoder_caps == NULL) { // branch decoder DPCD DSC data can be null for non branch device |
| 418 | dsc_sink_caps->branch_overall_throughput_0_mps = 0; |
| 419 | dsc_sink_caps->branch_overall_throughput_1_mps = 0; |
| 420 | dsc_sink_caps->branch_max_line_width = 0; |
| 421 | return true; |
| 422 | } |
| 423 | |
| 424 | dsc_sink_caps->branch_overall_throughput_0_mps = |
| 425 | dpcd_dsc_branch_decoder_caps[DP_DSC_BRANCH_OVERALL_THROUGHPUT_0 - DP_DSC_BRANCH_OVERALL_THROUGHPUT_0]; |
| 426 | if (dsc_sink_caps->branch_overall_throughput_0_mps == 0) |
| 427 | dsc_sink_caps->branch_overall_throughput_0_mps = 0; |
| 428 | else if (dsc_sink_caps->branch_overall_throughput_0_mps == 1) |
| 429 | dsc_sink_caps->branch_overall_throughput_0_mps = 680; |
| 430 | else { |
| 431 | dsc_sink_caps->branch_overall_throughput_0_mps *= 50; |
| 432 | dsc_sink_caps->branch_overall_throughput_0_mps += 600; |
| 433 | } |
| 434 | |
| 435 | dsc_sink_caps->branch_overall_throughput_1_mps = |
| 436 | dpcd_dsc_branch_decoder_caps[DP_DSC_BRANCH_OVERALL_THROUGHPUT_1 - DP_DSC_BRANCH_OVERALL_THROUGHPUT_0]; |
| 437 | if (dsc_sink_caps->branch_overall_throughput_1_mps == 0) |
| 438 | dsc_sink_caps->branch_overall_throughput_1_mps = 0; |
| 439 | else if (dsc_sink_caps->branch_overall_throughput_1_mps == 1) |
| 440 | dsc_sink_caps->branch_overall_throughput_1_mps = 680; |
| 441 | else { |
| 442 | dsc_sink_caps->branch_overall_throughput_1_mps *= 50; |
| 443 | dsc_sink_caps->branch_overall_throughput_1_mps += 600; |
| 444 | } |
| 445 | |
| 446 | dsc_sink_caps->branch_max_line_width = |
| 447 | dpcd_dsc_branch_decoder_caps[DP_DSC_BRANCH_MAX_LINE_WIDTH - DP_DSC_BRANCH_OVERALL_THROUGHPUT_0] * 320; |
| 448 | ASSERT(dsc_sink_caps->branch_max_line_width == 0 || dsc_sink_caps->branch_max_line_width >= 5120); |
| 449 | |
| 450 | dsc_sink_caps->is_dp = true; |
| 451 | return true; |
| 452 | } |
| 453 | |
| 454 | /* If DSC is possbile, get DSC bandwidth range based on [min_bpp, max_bpp] target bitrate range and |
| 455 | * timing's pixel clock and uncompressed bandwidth. |
| 456 | * If DSC is not possible, leave '*range' untouched. |
| 457 | */ |
| 458 | bool dc_dsc_compute_bandwidth_range( |
| 459 | const struct display_stream_compressor *dsc, |
| 460 | uint32_t dsc_min_slice_height_override, |
| 461 | uint32_t min_bpp_x16, |
| 462 | uint32_t max_bpp_x16, |
| 463 | const struct dsc_dec_dpcd_caps *dsc_sink_caps, |
| 464 | const struct dc_crtc_timing *timing, |
| 465 | const enum dc_link_encoding_format link_encoding, |
| 466 | struct dc_dsc_bw_range *range) |
| 467 | { |
| 468 | bool is_dsc_possible = false; |
| 469 | unsigned int min_dsc_slice_count; |
| 470 | struct dsc_enc_caps dsc_enc_caps; |
| 471 | struct dsc_enc_caps dsc_common_caps; |
| 472 | struct dc_dsc_config config = {0}; |
| 473 | struct dc_dsc_config_options options = {0}; |
| 474 | |
| 475 | options.dsc_min_slice_height_override = dsc_min_slice_height_override; |
| 476 | options.max_target_bpp_limit_override_x16 = max_bpp_x16; |
| 477 | options.slice_height_granularity = 1; |
| 478 | |
| 479 | get_dsc_enc_caps(dsc, dsc_enc_caps: &dsc_enc_caps, pixel_clock_100Hz: timing->pix_clk_100hz); |
| 480 | |
| 481 | min_dsc_slice_count = get_min_dsc_slice_count_for_odm(dsc, dsc_enc_caps: &dsc_enc_caps, timing); |
| 482 | |
| 483 | is_dsc_possible = intersect_dsc_caps(dsc_sink_caps, dsc_enc_caps: &dsc_enc_caps, |
| 484 | pixel_encoding: timing->pixel_encoding, dsc_common_caps: &dsc_common_caps); |
| 485 | |
| 486 | if (is_dsc_possible) |
| 487 | is_dsc_possible = setup_dsc_config(dsc_sink_caps, dsc_enc_caps: &dsc_enc_caps, target_bandwidth_kbps: 0, timing, |
| 488 | options: &options, link_encoding, min_slice_count: min_dsc_slice_count, dsc_cfg: &config); |
| 489 | |
| 490 | if (is_dsc_possible) |
| 491 | is_dsc_possible = decide_dsc_bandwidth_range(min_bpp_x16, max_bpp_x16, |
| 492 | num_slices_h: config.num_slices_h, dsc_caps: &dsc_common_caps, timing, link_encoding, range); |
| 493 | |
| 494 | return is_dsc_possible; |
| 495 | } |
| 496 | |
| 497 | void dc_dsc_dump_encoder_caps(const struct display_stream_compressor *dsc, |
| 498 | const struct dc_crtc_timing *timing) |
| 499 | { |
| 500 | struct dsc_enc_caps dsc_enc_caps; |
| 501 | |
| 502 | get_dsc_enc_caps(dsc, dsc_enc_caps: &dsc_enc_caps, pixel_clock_100Hz: timing->pix_clk_100hz); |
| 503 | |
| 504 | DC_LOG_DSC("dsc encoder caps:" ); |
| 505 | DC_LOG_DSC("\tdsc_version 0x%x" , dsc_enc_caps.dsc_version); |
| 506 | DC_LOG_DSC("\tslice_caps 0x%x" , dsc_enc_caps.slice_caps.raw); |
| 507 | DC_LOG_DSC("\tlb_bit_depth %d" , dsc_enc_caps.lb_bit_depth); |
| 508 | DC_LOG_DSC("\tis_block_pred_supported %d" , dsc_enc_caps.is_block_pred_supported); |
| 509 | DC_LOG_DSC("\tcolor_formats 0x%x" , dsc_enc_caps.color_formats.raw); |
| 510 | DC_LOG_DSC("\tcolor_depth 0x%x" , dsc_enc_caps.color_depth.raw); |
| 511 | DC_LOG_DSC("\tmax_total_throughput_mps %d" , dsc_enc_caps.max_total_throughput_mps); |
| 512 | DC_LOG_DSC("\tmax_slice_width %d" , dsc_enc_caps.max_slice_width); |
| 513 | DC_LOG_DSC("\tbpp_increment_div %d" , dsc_enc_caps.bpp_increment_div); |
| 514 | } |
| 515 | |
| 516 | void dc_dsc_dump_decoder_caps(const struct display_stream_compressor *dsc, |
| 517 | const struct dsc_dec_dpcd_caps *dsc_sink_caps) |
| 518 | { |
| 519 | DC_LOG_DSC("dsc decoder caps:" ); |
| 520 | DC_LOG_DSC("\tis_dsc_supported %d" , dsc_sink_caps->is_dsc_supported); |
| 521 | DC_LOG_DSC("\tdsc_version 0x%x" , dsc_sink_caps->dsc_version); |
| 522 | DC_LOG_DSC("\trc_buffer_size %d" , dsc_sink_caps->rc_buffer_size); |
| 523 | DC_LOG_DSC("\tslice_caps1 0x%x" , dsc_sink_caps->slice_caps1.raw); |
| 524 | DC_LOG_DSC("\tslice_caps2 0x%x" , dsc_sink_caps->slice_caps2.raw); |
| 525 | DC_LOG_DSC("\tlb_bit_depth %d" , dsc_sink_caps->lb_bit_depth); |
| 526 | DC_LOG_DSC("\tis_block_pred_supported %d" , dsc_sink_caps->is_block_pred_supported); |
| 527 | DC_LOG_DSC("\tedp_max_bits_per_pixel %d" , dsc_sink_caps->edp_max_bits_per_pixel); |
| 528 | DC_LOG_DSC("\tcolor_formats 0x%x" , dsc_sink_caps->color_formats.raw); |
| 529 | DC_LOG_DSC("\tthroughput_mode_0_mps %d" , dsc_sink_caps->throughput_mode_0_mps); |
| 530 | DC_LOG_DSC("\tthroughput_mode_1_mps %d" , dsc_sink_caps->throughput_mode_1_mps); |
| 531 | DC_LOG_DSC("\tmax_slice_width %d" , dsc_sink_caps->max_slice_width); |
| 532 | DC_LOG_DSC("\tbpp_increment_div %d" , dsc_sink_caps->bpp_increment_div); |
| 533 | DC_LOG_DSC("\tbranch_overall_throughput_0_mps %d" , dsc_sink_caps->branch_overall_throughput_0_mps); |
| 534 | DC_LOG_DSC("\tbranch_overall_throughput_1_mps %d" , dsc_sink_caps->branch_overall_throughput_1_mps); |
| 535 | DC_LOG_DSC("\tbranch_max_line_width %d" , dsc_sink_caps->branch_max_line_width); |
| 536 | DC_LOG_DSC("\tis_dp %d" , dsc_sink_caps->is_dp); |
| 537 | } |
| 538 | |
| 539 | |
| 540 | static void build_dsc_enc_combined_slice_caps( |
| 541 | const struct dsc_enc_caps *single_dsc_enc_caps, |
| 542 | struct dsc_enc_caps *dsc_enc_caps, |
| 543 | unsigned int max_odm_combine_factor) |
| 544 | { |
| 545 | /* 1-16 slice configurations, single DSC */ |
| 546 | dsc_enc_caps->slice_caps.raw |= single_dsc_enc_caps->slice_caps.raw; |
| 547 | |
| 548 | /* 2x DSC's */ |
| 549 | if (max_odm_combine_factor >= 2) { |
| 550 | /* 1 + 1 */ |
| 551 | dsc_enc_caps->slice_caps.bits.NUM_SLICES_2 |= single_dsc_enc_caps->slice_caps.bits.NUM_SLICES_1; |
| 552 | |
| 553 | /* 2 + 2 */ |
| 554 | dsc_enc_caps->slice_caps.bits.NUM_SLICES_4 |= single_dsc_enc_caps->slice_caps.bits.NUM_SLICES_2; |
| 555 | |
| 556 | /* 4 + 4 */ |
| 557 | dsc_enc_caps->slice_caps.bits.NUM_SLICES_8 |= single_dsc_enc_caps->slice_caps.bits.NUM_SLICES_4; |
| 558 | |
| 559 | /* 8 + 8 */ |
| 560 | dsc_enc_caps->slice_caps.bits.NUM_SLICES_16 |= single_dsc_enc_caps->slice_caps.bits.NUM_SLICES_8; |
| 561 | } |
| 562 | |
| 563 | /* 3x DSC's */ |
| 564 | if (max_odm_combine_factor >= 3) { |
| 565 | /* 4 + 4 + 4 */ |
| 566 | dsc_enc_caps->slice_caps.bits.NUM_SLICES_12 |= single_dsc_enc_caps->slice_caps.bits.NUM_SLICES_4; |
| 567 | } |
| 568 | |
| 569 | /* 4x DSC's */ |
| 570 | if (max_odm_combine_factor >= 4) { |
| 571 | /* 1 + 1 + 1 + 1 */ |
| 572 | dsc_enc_caps->slice_caps.bits.NUM_SLICES_4 |= single_dsc_enc_caps->slice_caps.bits.NUM_SLICES_1; |
| 573 | |
| 574 | /* 2 + 2 + 2 + 2 */ |
| 575 | dsc_enc_caps->slice_caps.bits.NUM_SLICES_8 |= single_dsc_enc_caps->slice_caps.bits.NUM_SLICES_2; |
| 576 | |
| 577 | /* 3 + 3 + 3 + 3 */ |
| 578 | dsc_enc_caps->slice_caps.bits.NUM_SLICES_12 |= single_dsc_enc_caps->slice_caps.bits.NUM_SLICES_3; |
| 579 | |
| 580 | /* 4 + 4 + 4 + 4 */ |
| 581 | dsc_enc_caps->slice_caps.bits.NUM_SLICES_16 |= single_dsc_enc_caps->slice_caps.bits.NUM_SLICES_4; |
| 582 | } |
| 583 | } |
| 584 | |
| 585 | static void build_dsc_enc_caps( |
| 586 | const struct display_stream_compressor *dsc, |
| 587 | struct dsc_enc_caps *dsc_enc_caps) |
| 588 | { |
| 589 | unsigned int max_dscclk_khz; |
| 590 | unsigned int num_dsc; |
| 591 | unsigned int max_odm_combine_factor; |
| 592 | struct dsc_enc_caps single_dsc_enc_caps; |
| 593 | |
| 594 | struct dc *dc; |
| 595 | |
| 596 | if (!dsc || !dsc->ctx || !dsc->ctx->dc || !dsc->funcs->dsc_get_single_enc_caps) |
| 597 | return; |
| 598 | |
| 599 | dc = dsc->ctx->dc; |
| 600 | |
| 601 | if (!dc->clk_mgr || !dc->clk_mgr->funcs->get_max_clock_khz || !dc->res_pool || dc->debug.disable_dsc) |
| 602 | return; |
| 603 | |
| 604 | /* get max DSCCLK from clk_mgr */ |
| 605 | max_dscclk_khz = dc->clk_mgr->funcs->get_max_clock_khz(dc->clk_mgr, CLK_TYPE_DSCCLK); |
| 606 | |
| 607 | dsc->funcs->dsc_get_single_enc_caps(&single_dsc_enc_caps, max_dscclk_khz); |
| 608 | |
| 609 | /* global capabilities */ |
| 610 | dsc_enc_caps->dsc_version = single_dsc_enc_caps.dsc_version; |
| 611 | dsc_enc_caps->lb_bit_depth = single_dsc_enc_caps.lb_bit_depth; |
| 612 | dsc_enc_caps->is_block_pred_supported = single_dsc_enc_caps.is_block_pred_supported; |
| 613 | dsc_enc_caps->max_slice_width = single_dsc_enc_caps.max_slice_width; |
| 614 | dsc_enc_caps->bpp_increment_div = single_dsc_enc_caps.bpp_increment_div; |
| 615 | dsc_enc_caps->color_formats.raw = single_dsc_enc_caps.color_formats.raw; |
| 616 | dsc_enc_caps->color_depth.raw = single_dsc_enc_caps.color_depth.raw; |
| 617 | |
| 618 | /* expand per DSC capabilities to global */ |
| 619 | max_odm_combine_factor = dc->caps.max_odm_combine_factor; |
| 620 | num_dsc = dc->res_pool->res_cap->num_dsc; |
| 621 | max_odm_combine_factor = min(max_odm_combine_factor, num_dsc); |
| 622 | dsc_enc_caps->max_total_throughput_mps = |
| 623 | single_dsc_enc_caps.max_total_throughput_mps * |
| 624 | max_odm_combine_factor; |
| 625 | |
| 626 | /* check slice counts possible for with ODM combine */ |
| 627 | build_dsc_enc_combined_slice_caps(single_dsc_enc_caps: &single_dsc_enc_caps, dsc_enc_caps, max_odm_combine_factor); |
| 628 | } |
| 629 | |
| 630 | static inline uint32_t dsc_div_by_10_round_up(uint32_t value) |
| 631 | { |
| 632 | return (value + 9) / 10; |
| 633 | } |
| 634 | |
| 635 | static unsigned int get_min_dsc_slice_count_for_odm( |
| 636 | const struct display_stream_compressor *dsc, |
| 637 | const struct dsc_enc_caps *dsc_enc_caps, |
| 638 | const struct dc_crtc_timing *timing) |
| 639 | { |
| 640 | unsigned int max_dispclk_khz; |
| 641 | |
| 642 | /* get max pixel rate and combine caps */ |
| 643 | max_dispclk_khz = dsc_enc_caps->max_total_throughput_mps * 1000; |
| 644 | if (dsc && dsc->ctx->dc) { |
| 645 | if (dsc->ctx->dc->clk_mgr && |
| 646 | dsc->ctx->dc->clk_mgr->funcs->get_max_clock_khz) { |
| 647 | /* dispclk is available */ |
| 648 | max_dispclk_khz = dsc->ctx->dc->clk_mgr->funcs->get_max_clock_khz(dsc->ctx->dc->clk_mgr, CLK_TYPE_DISPCLK); |
| 649 | } |
| 650 | } |
| 651 | |
| 652 | /* validate parameters */ |
| 653 | if (max_dispclk_khz == 0 || dsc_enc_caps->max_slice_width == 0) |
| 654 | return 1; |
| 655 | |
| 656 | /* consider minimum odm slices required due to |
| 657 | * 1) display pipe throughput (dispclk) |
| 658 | * 2) max image width per slice |
| 659 | */ |
| 660 | return dc_fixpt_ceil(arg: dc_fixpt_max( |
| 661 | arg1: dc_fixpt_div_int(arg1: dc_fixpt_from_int(arg: dsc_div_by_10_round_up(value: timing->pix_clk_100hz)), |
| 662 | arg2: max_dispclk_khz), // throughput |
| 663 | arg2: dc_fixpt_div_int(arg1: dc_fixpt_from_int(arg: timing->h_addressable + timing->h_border_left + timing->h_border_right), |
| 664 | arg2: dsc_enc_caps->max_slice_width))); // slice width |
| 665 | } |
| 666 | |
| 667 | static void get_dsc_enc_caps( |
| 668 | const struct display_stream_compressor *dsc, |
| 669 | struct dsc_enc_caps *dsc_enc_caps, |
| 670 | int pixel_clock_100Hz) |
| 671 | { |
| 672 | memset(dsc_enc_caps, 0, sizeof(struct dsc_enc_caps)); |
| 673 | |
| 674 | if (!dsc || !dsc->ctx || !dsc->ctx->dc || dsc->ctx->dc->debug.disable_dsc) |
| 675 | return; |
| 676 | |
| 677 | /* check if reported cap global or only for a single DCN DSC enc */ |
| 678 | if (dsc->funcs->dsc_get_enc_caps) { |
| 679 | dsc->funcs->dsc_get_enc_caps(dsc_enc_caps, pixel_clock_100Hz); |
| 680 | } else { |
| 681 | build_dsc_enc_caps(dsc, dsc_enc_caps); |
| 682 | } |
| 683 | |
| 684 | if (dsc->ctx->dc->debug.native422_support) |
| 685 | dsc_enc_caps->color_formats.bits.YCBCR_NATIVE_422 = 1; |
| 686 | } |
| 687 | |
| 688 | /* Returns 'false' if no intersection was found for at least one capability. |
| 689 | * It also implicitly validates some sink caps against invalid value of zero. |
| 690 | */ |
| 691 | static bool intersect_dsc_caps( |
| 692 | const struct dsc_dec_dpcd_caps *dsc_sink_caps, |
| 693 | const struct dsc_enc_caps *dsc_enc_caps, |
| 694 | enum dc_pixel_encoding pixel_encoding, |
| 695 | struct dsc_enc_caps *dsc_common_caps) |
| 696 | { |
| 697 | int32_t max_slices; |
| 698 | int32_t total_sink_throughput; |
| 699 | |
| 700 | memset(dsc_common_caps, 0, sizeof(struct dsc_enc_caps)); |
| 701 | |
| 702 | dsc_common_caps->dsc_version = min(dsc_sink_caps->dsc_version, dsc_enc_caps->dsc_version); |
| 703 | if (!dsc_common_caps->dsc_version) |
| 704 | return false; |
| 705 | |
| 706 | dsc_common_caps->slice_caps.bits.NUM_SLICES_1 = |
| 707 | dsc_sink_caps->slice_caps1.bits.NUM_SLICES_1 && dsc_enc_caps->slice_caps.bits.NUM_SLICES_1; |
| 708 | dsc_common_caps->slice_caps.bits.NUM_SLICES_2 = |
| 709 | dsc_sink_caps->slice_caps1.bits.NUM_SLICES_2 && dsc_enc_caps->slice_caps.bits.NUM_SLICES_2; |
| 710 | dsc_common_caps->slice_caps.bits.NUM_SLICES_4 = |
| 711 | dsc_sink_caps->slice_caps1.bits.NUM_SLICES_4 && dsc_enc_caps->slice_caps.bits.NUM_SLICES_4; |
| 712 | dsc_common_caps->slice_caps.bits.NUM_SLICES_8 = |
| 713 | dsc_sink_caps->slice_caps1.bits.NUM_SLICES_8 && dsc_enc_caps->slice_caps.bits.NUM_SLICES_8; |
| 714 | dsc_common_caps->slice_caps.bits.NUM_SLICES_12 = |
| 715 | dsc_sink_caps->slice_caps1.bits.NUM_SLICES_12 && dsc_enc_caps->slice_caps.bits.NUM_SLICES_12; |
| 716 | dsc_common_caps->slice_caps.bits.NUM_SLICES_16 = |
| 717 | dsc_sink_caps->slice_caps2.bits.NUM_SLICES_16 && dsc_enc_caps->slice_caps.bits.NUM_SLICES_16; |
| 718 | |
| 719 | if (!dsc_common_caps->slice_caps.raw) |
| 720 | return false; |
| 721 | |
| 722 | dsc_common_caps->lb_bit_depth = min(dsc_sink_caps->lb_bit_depth, dsc_enc_caps->lb_bit_depth); |
| 723 | if (!dsc_common_caps->lb_bit_depth) |
| 724 | return false; |
| 725 | |
| 726 | dsc_common_caps->is_block_pred_supported = |
| 727 | dsc_sink_caps->is_block_pred_supported && dsc_enc_caps->is_block_pred_supported; |
| 728 | |
| 729 | dsc_common_caps->color_formats.raw = dsc_sink_caps->color_formats.raw & dsc_enc_caps->color_formats.raw; |
| 730 | if (!dsc_common_caps->color_formats.raw) |
| 731 | return false; |
| 732 | |
| 733 | dsc_common_caps->color_depth.raw = dsc_sink_caps->color_depth.raw & dsc_enc_caps->color_depth.raw; |
| 734 | if (!dsc_common_caps->color_depth.raw) |
| 735 | return false; |
| 736 | |
| 737 | max_slices = 0; |
| 738 | if (dsc_common_caps->slice_caps.bits.NUM_SLICES_1) |
| 739 | max_slices = 1; |
| 740 | |
| 741 | if (dsc_common_caps->slice_caps.bits.NUM_SLICES_2) |
| 742 | max_slices = 2; |
| 743 | |
| 744 | if (dsc_common_caps->slice_caps.bits.NUM_SLICES_4) |
| 745 | max_slices = 4; |
| 746 | |
| 747 | total_sink_throughput = max_slices * dsc_sink_caps->throughput_mode_0_mps; |
| 748 | if (pixel_encoding == PIXEL_ENCODING_YCBCR422 || pixel_encoding == PIXEL_ENCODING_YCBCR420) |
| 749 | total_sink_throughput = max_slices * dsc_sink_caps->throughput_mode_1_mps; |
| 750 | |
| 751 | dsc_common_caps->max_total_throughput_mps = min(total_sink_throughput, dsc_enc_caps->max_total_throughput_mps); |
| 752 | |
| 753 | dsc_common_caps->max_slice_width = min(dsc_sink_caps->max_slice_width, dsc_enc_caps->max_slice_width); |
| 754 | if (!dsc_common_caps->max_slice_width) |
| 755 | return false; |
| 756 | |
| 757 | dsc_common_caps->bpp_increment_div = min(dsc_sink_caps->bpp_increment_div, dsc_enc_caps->bpp_increment_div); |
| 758 | |
| 759 | // TODO DSC: Remove this workaround for N422 and 420 once it's fixed, or move it to get_dsc_encoder_caps() |
| 760 | if (pixel_encoding == PIXEL_ENCODING_YCBCR422 || pixel_encoding == PIXEL_ENCODING_YCBCR420) |
| 761 | dsc_common_caps->bpp_increment_div = min(dsc_common_caps->bpp_increment_div, (uint32_t)8); |
| 762 | |
| 763 | dsc_common_caps->edp_sink_max_bits_per_pixel = dsc_sink_caps->edp_max_bits_per_pixel; |
| 764 | dsc_common_caps->is_dp = dsc_sink_caps->is_dp; |
| 765 | return true; |
| 766 | } |
| 767 | |
| 768 | static uint32_t compute_bpp_x16_from_target_bandwidth( |
| 769 | const uint32_t bandwidth_in_kbps, |
| 770 | const struct dc_crtc_timing *timing, |
| 771 | const uint32_t num_slices_h, |
| 772 | const uint32_t bpp_increment_div, |
| 773 | const bool is_dp) |
| 774 | { |
| 775 | uint32_t overhead_in_kbps; |
| 776 | struct fixed31_32 effective_bandwidth_in_kbps; |
| 777 | struct fixed31_32 bpp_x16; |
| 778 | |
| 779 | overhead_in_kbps = dc_dsc_stream_bandwidth_overhead_in_kbps( |
| 780 | timing, num_slices_h, is_dp); |
| 781 | effective_bandwidth_in_kbps = dc_fixpt_from_int(arg: bandwidth_in_kbps); |
| 782 | effective_bandwidth_in_kbps = dc_fixpt_sub_int(arg1: effective_bandwidth_in_kbps, |
| 783 | arg2: overhead_in_kbps); |
| 784 | bpp_x16 = dc_fixpt_mul_int(arg1: effective_bandwidth_in_kbps, arg2: 10); |
| 785 | bpp_x16 = dc_fixpt_div_int(arg1: bpp_x16, arg2: timing->pix_clk_100hz); |
| 786 | bpp_x16 = dc_fixpt_from_int(arg: dc_fixpt_floor(arg: dc_fixpt_mul_int(arg1: bpp_x16, arg2: bpp_increment_div))); |
| 787 | bpp_x16 = dc_fixpt_div_int(arg1: bpp_x16, arg2: bpp_increment_div); |
| 788 | bpp_x16 = dc_fixpt_mul_int(arg1: bpp_x16, arg2: 16); |
| 789 | return dc_fixpt_floor(arg: bpp_x16); |
| 790 | } |
| 791 | |
| 792 | /* Decide DSC bandwidth range based on signal, timing, specs specific and input min and max |
| 793 | * requirements. |
| 794 | * The range output includes decided min/max target bpp, the respective bandwidth requirements |
| 795 | * and native timing bandwidth requirement when DSC is not used. |
| 796 | */ |
| 797 | static bool decide_dsc_bandwidth_range( |
| 798 | const uint32_t min_bpp_x16, |
| 799 | const uint32_t max_bpp_x16, |
| 800 | const uint32_t num_slices_h, |
| 801 | const struct dsc_enc_caps *dsc_caps, |
| 802 | const struct dc_crtc_timing *timing, |
| 803 | const enum dc_link_encoding_format link_encoding, |
| 804 | struct dc_dsc_bw_range *range) |
| 805 | { |
| 806 | uint32_t preferred_bpp_x16 = timing->dsc_fixed_bits_per_pixel_x16; |
| 807 | |
| 808 | memset(range, 0, sizeof(*range)); |
| 809 | |
| 810 | /* apply signal, timing, specs and explicitly specified DSC range requirements */ |
| 811 | if (preferred_bpp_x16) { |
| 812 | if (preferred_bpp_x16 <= max_bpp_x16 && |
| 813 | preferred_bpp_x16 >= min_bpp_x16) { |
| 814 | range->max_target_bpp_x16 = preferred_bpp_x16; |
| 815 | range->min_target_bpp_x16 = preferred_bpp_x16; |
| 816 | } |
| 817 | } |
| 818 | /* TODO - make this value generic to all signal types */ |
| 819 | else if (dsc_caps->edp_sink_max_bits_per_pixel) { |
| 820 | /* apply max bpp limitation from edp sink */ |
| 821 | range->max_target_bpp_x16 = MIN(dsc_caps->edp_sink_max_bits_per_pixel, |
| 822 | max_bpp_x16); |
| 823 | range->min_target_bpp_x16 = min_bpp_x16; |
| 824 | } |
| 825 | else { |
| 826 | range->max_target_bpp_x16 = max_bpp_x16; |
| 827 | range->min_target_bpp_x16 = min_bpp_x16; |
| 828 | } |
| 829 | |
| 830 | /* populate output structure */ |
| 831 | if (range->max_target_bpp_x16 >= range->min_target_bpp_x16 && range->min_target_bpp_x16 > 0) { |
| 832 | /* native stream bandwidth */ |
| 833 | range->stream_kbps = dc_bandwidth_in_kbps_from_timing(timing, link_encoding); |
| 834 | |
| 835 | /* max dsc target bpp */ |
| 836 | range->max_kbps = dc_dsc_stream_bandwidth_in_kbps(timing, |
| 837 | bpp_x16: range->max_target_bpp_x16, num_slices_h, is_dp: dsc_caps->is_dp); |
| 838 | |
| 839 | /* min dsc target bpp */ |
| 840 | range->min_kbps = dc_dsc_stream_bandwidth_in_kbps(timing, |
| 841 | bpp_x16: range->min_target_bpp_x16, num_slices_h, is_dp: dsc_caps->is_dp); |
| 842 | } |
| 843 | |
| 844 | return range->max_kbps >= range->min_kbps && range->min_kbps > 0; |
| 845 | } |
| 846 | |
| 847 | /* Decides if DSC should be used and calculates target bpp if it should, applying DSC policy. |
| 848 | * |
| 849 | * Returns: |
| 850 | * - 'true' if target bpp is decided |
| 851 | * - 'false' if target bpp cannot be decided (e.g. cannot fit even with min DSC bpp), |
| 852 | */ |
| 853 | static bool decide_dsc_target_bpp_x16( |
| 854 | const struct dc_dsc_policy *policy, |
| 855 | const struct dc_dsc_config_options *options, |
| 856 | const struct dsc_enc_caps *dsc_common_caps, |
| 857 | const int target_bandwidth_kbps, |
| 858 | const struct dc_crtc_timing *timing, |
| 859 | const int num_slices_h, |
| 860 | const enum dc_link_encoding_format link_encoding, |
| 861 | int *target_bpp_x16) |
| 862 | { |
| 863 | struct dc_dsc_bw_range range; |
| 864 | |
| 865 | *target_bpp_x16 = 0; |
| 866 | |
| 867 | if (decide_dsc_bandwidth_range(min_bpp_x16: policy->min_target_bpp * 16, max_bpp_x16: policy->max_target_bpp * 16, |
| 868 | num_slices_h, dsc_caps: dsc_common_caps, timing, link_encoding, range: &range)) { |
| 869 | if (target_bandwidth_kbps >= range.stream_kbps) { |
| 870 | if (policy->enable_dsc_when_not_needed || options->force_dsc_when_not_needed) |
| 871 | /* enable max bpp even dsc is not needed */ |
| 872 | *target_bpp_x16 = range.max_target_bpp_x16; |
| 873 | } else if (target_bandwidth_kbps >= range.max_kbps) { |
| 874 | /* use max target bpp allowed */ |
| 875 | *target_bpp_x16 = range.max_target_bpp_x16; |
| 876 | } else if (target_bandwidth_kbps >= range.min_kbps) { |
| 877 | /* use target bpp that can take entire target bandwidth */ |
| 878 | *target_bpp_x16 = compute_bpp_x16_from_target_bandwidth( |
| 879 | bandwidth_in_kbps: target_bandwidth_kbps, timing, num_slices_h, |
| 880 | bpp_increment_div: dsc_common_caps->bpp_increment_div, |
| 881 | is_dp: dsc_common_caps->is_dp); |
| 882 | } |
| 883 | } |
| 884 | |
| 885 | return *target_bpp_x16 != 0; |
| 886 | } |
| 887 | |
| 888 | #define MIN_AVAILABLE_SLICES_SIZE 6 |
| 889 | |
| 890 | static int get_available_dsc_slices(union dsc_enc_slice_caps slice_caps, int *available_slices) |
| 891 | { |
| 892 | int idx = 0; |
| 893 | |
| 894 | if (slice_caps.bits.NUM_SLICES_1) |
| 895 | available_slices[idx++] = 1; |
| 896 | |
| 897 | if (slice_caps.bits.NUM_SLICES_2) |
| 898 | available_slices[idx++] = 2; |
| 899 | |
| 900 | if (slice_caps.bits.NUM_SLICES_4) |
| 901 | available_slices[idx++] = 4; |
| 902 | |
| 903 | if (slice_caps.bits.NUM_SLICES_8) |
| 904 | available_slices[idx++] = 8; |
| 905 | |
| 906 | if (slice_caps.bits.NUM_SLICES_12) |
| 907 | available_slices[idx++] = 12; |
| 908 | |
| 909 | if (slice_caps.bits.NUM_SLICES_16) |
| 910 | available_slices[idx++] = 16; |
| 911 | |
| 912 | return idx; |
| 913 | } |
| 914 | |
| 915 | |
| 916 | static int get_max_dsc_slices(union dsc_enc_slice_caps slice_caps) |
| 917 | { |
| 918 | int max_slices = 0; |
| 919 | int available_slices[MIN_AVAILABLE_SLICES_SIZE]; |
| 920 | int end_idx = get_available_dsc_slices(slice_caps, available_slices: &available_slices[0]); |
| 921 | |
| 922 | if (end_idx > 0) |
| 923 | max_slices = available_slices[end_idx - 1]; |
| 924 | |
| 925 | return max_slices; |
| 926 | } |
| 927 | |
| 928 | |
| 929 | // Increment slice number in available slice numbers stops if possible, or just increment if not |
| 930 | static int inc_num_slices(union dsc_enc_slice_caps slice_caps, int num_slices) |
| 931 | { |
| 932 | // Get next bigger num slices available in common caps |
| 933 | int available_slices[MIN_AVAILABLE_SLICES_SIZE]; |
| 934 | int end_idx; |
| 935 | int i; |
| 936 | int new_num_slices = num_slices; |
| 937 | |
| 938 | end_idx = get_available_dsc_slices(slice_caps, available_slices: &available_slices[0]); |
| 939 | if (end_idx == 0) { |
| 940 | // No available slices found |
| 941 | new_num_slices++; |
| 942 | return new_num_slices; |
| 943 | } |
| 944 | |
| 945 | // Numbers of slices found - get the next bigger number |
| 946 | for (i = 0; i < end_idx; i++) { |
| 947 | if (new_num_slices < available_slices[i]) { |
| 948 | new_num_slices = available_slices[i]; |
| 949 | break; |
| 950 | } |
| 951 | } |
| 952 | |
| 953 | if (new_num_slices == num_slices) // No bigger number of slices found |
| 954 | new_num_slices++; |
| 955 | |
| 956 | return new_num_slices; |
| 957 | } |
| 958 | |
| 959 | |
| 960 | // Decrement slice number in available slice numbers stops if possible, or just decrement if not. Stop at zero. |
| 961 | static int dec_num_slices(union dsc_enc_slice_caps slice_caps, int num_slices) |
| 962 | { |
| 963 | // Get next bigger num slices available in common caps |
| 964 | int available_slices[MIN_AVAILABLE_SLICES_SIZE]; |
| 965 | int end_idx; |
| 966 | int i; |
| 967 | int new_num_slices = num_slices; |
| 968 | |
| 969 | end_idx = get_available_dsc_slices(slice_caps, available_slices: &available_slices[0]); |
| 970 | if (end_idx == 0 && new_num_slices > 0) { |
| 971 | // No numbers of slices found |
| 972 | new_num_slices++; |
| 973 | return new_num_slices; |
| 974 | } |
| 975 | |
| 976 | // Numbers of slices found - get the next smaller number |
| 977 | for (i = end_idx - 1; i >= 0; i--) { |
| 978 | if (new_num_slices > available_slices[i]) { |
| 979 | new_num_slices = available_slices[i]; |
| 980 | break; |
| 981 | } |
| 982 | } |
| 983 | |
| 984 | if (new_num_slices == num_slices) { |
| 985 | // No smaller number of slices found |
| 986 | new_num_slices--; |
| 987 | if (new_num_slices < 0) |
| 988 | new_num_slices = 0; |
| 989 | } |
| 990 | |
| 991 | return new_num_slices; |
| 992 | } |
| 993 | |
| 994 | |
| 995 | // Choose next bigger number of slices if the requested number of slices is not available |
| 996 | static int fit_num_slices_up(union dsc_enc_slice_caps slice_caps, int num_slices) |
| 997 | { |
| 998 | // Get next bigger num slices available in common caps |
| 999 | int available_slices[MIN_AVAILABLE_SLICES_SIZE]; |
| 1000 | int end_idx; |
| 1001 | int i; |
| 1002 | int new_num_slices = num_slices; |
| 1003 | |
| 1004 | end_idx = get_available_dsc_slices(slice_caps, available_slices: &available_slices[0]); |
| 1005 | if (end_idx == 0) { |
| 1006 | // No available slices found |
| 1007 | new_num_slices++; |
| 1008 | return new_num_slices; |
| 1009 | } |
| 1010 | |
| 1011 | // Numbers of slices found - get the equal or next bigger number |
| 1012 | for (i = 0; i < end_idx; i++) { |
| 1013 | if (new_num_slices <= available_slices[i]) { |
| 1014 | new_num_slices = available_slices[i]; |
| 1015 | break; |
| 1016 | } |
| 1017 | } |
| 1018 | |
| 1019 | return new_num_slices; |
| 1020 | } |
| 1021 | |
| 1022 | |
| 1023 | /* Attempts to set DSC configuration for the stream, applying DSC policy. |
| 1024 | * Returns 'true' if successful or 'false' if not. |
| 1025 | * |
| 1026 | * Parameters: |
| 1027 | * |
| 1028 | * dsc_sink_caps - DSC sink decoder capabilities (from DPCD) |
| 1029 | * |
| 1030 | * dsc_enc_caps - DSC encoder capabilities |
| 1031 | * |
| 1032 | * target_bandwidth_kbps - Target bandwidth to fit the stream into. |
| 1033 | * If 0, do not calculate target bpp. |
| 1034 | * |
| 1035 | * timing - The stream timing to fit into 'target_bandwidth_kbps' or apply |
| 1036 | * maximum compression to, if 'target_badwidth == 0' |
| 1037 | * |
| 1038 | * dsc_cfg - DSC configuration to use if it was possible to come up with |
| 1039 | * one for the given inputs. |
| 1040 | * The target bitrate after DSC can be calculated by multiplying |
| 1041 | * dsc_cfg.bits_per_pixel (in U6.4 format) by pixel rate, e.g. |
| 1042 | * |
| 1043 | * dsc_stream_bitrate_kbps = (int)ceil(timing->pix_clk_khz * dsc_cfg.bits_per_pixel / 16.0); |
| 1044 | */ |
| 1045 | static bool setup_dsc_config( |
| 1046 | const struct dsc_dec_dpcd_caps *dsc_sink_caps, |
| 1047 | const struct dsc_enc_caps *dsc_enc_caps, |
| 1048 | int target_bandwidth_kbps, |
| 1049 | const struct dc_crtc_timing *timing, |
| 1050 | const struct dc_dsc_config_options *options, |
| 1051 | const enum dc_link_encoding_format link_encoding, |
| 1052 | int min_slices_h, |
| 1053 | struct dc_dsc_config *dsc_cfg) |
| 1054 | { |
| 1055 | struct dsc_enc_caps dsc_common_caps; |
| 1056 | int max_slices_h = 0; |
| 1057 | int num_slices_h = 0; |
| 1058 | int pic_width; |
| 1059 | int slice_width; |
| 1060 | int target_bpp; |
| 1061 | int sink_per_slice_throughput_mps; |
| 1062 | int branch_max_throughput_mps = 0; |
| 1063 | bool is_dsc_possible = false; |
| 1064 | int pic_height; |
| 1065 | int slice_height; |
| 1066 | struct dc_dsc_policy policy; |
| 1067 | |
| 1068 | memset(dsc_cfg, 0, sizeof(struct dc_dsc_config)); |
| 1069 | |
| 1070 | dc_dsc_get_policy_for_timing(timing, max_target_bpp_limit_override_x16: options->max_target_bpp_limit_override_x16, policy: &policy, link_encoding); |
| 1071 | pic_width = timing->h_addressable + timing->h_border_left + timing->h_border_right; |
| 1072 | pic_height = timing->v_addressable + timing->v_border_top + timing->v_border_bottom; |
| 1073 | |
| 1074 | if (!dsc_sink_caps->is_dsc_supported) |
| 1075 | goto done; |
| 1076 | |
| 1077 | if (dsc_sink_caps->branch_max_line_width && dsc_sink_caps->branch_max_line_width < pic_width) |
| 1078 | goto done; |
| 1079 | |
| 1080 | // Intersect decoder with encoder DSC caps and validate DSC settings |
| 1081 | is_dsc_possible = intersect_dsc_caps(dsc_sink_caps, dsc_enc_caps, pixel_encoding: timing->pixel_encoding, dsc_common_caps: &dsc_common_caps); |
| 1082 | if (!is_dsc_possible) |
| 1083 | goto done; |
| 1084 | |
| 1085 | sink_per_slice_throughput_mps = 0; |
| 1086 | |
| 1087 | // Validate available DSC settings against the mode timing |
| 1088 | |
| 1089 | // Validate color format (and pick up the throughput values) |
| 1090 | dsc_cfg->ycbcr422_simple = false; |
| 1091 | switch (timing->pixel_encoding) { |
| 1092 | case PIXEL_ENCODING_RGB: |
| 1093 | is_dsc_possible = (bool)dsc_common_caps.color_formats.bits.RGB; |
| 1094 | sink_per_slice_throughput_mps = dsc_sink_caps->throughput_mode_0_mps; |
| 1095 | branch_max_throughput_mps = dsc_sink_caps->branch_overall_throughput_0_mps; |
| 1096 | break; |
| 1097 | case PIXEL_ENCODING_YCBCR444: |
| 1098 | is_dsc_possible = (bool)dsc_common_caps.color_formats.bits.YCBCR_444; |
| 1099 | sink_per_slice_throughput_mps = dsc_sink_caps->throughput_mode_0_mps; |
| 1100 | branch_max_throughput_mps = dsc_sink_caps->branch_overall_throughput_0_mps; |
| 1101 | break; |
| 1102 | case PIXEL_ENCODING_YCBCR422: |
| 1103 | is_dsc_possible = (bool)dsc_common_caps.color_formats.bits.YCBCR_NATIVE_422; |
| 1104 | sink_per_slice_throughput_mps = dsc_sink_caps->throughput_mode_1_mps; |
| 1105 | branch_max_throughput_mps = dsc_sink_caps->branch_overall_throughput_1_mps; |
| 1106 | if (!is_dsc_possible) { |
| 1107 | is_dsc_possible = (bool)dsc_common_caps.color_formats.bits.YCBCR_SIMPLE_422; |
| 1108 | dsc_cfg->ycbcr422_simple = is_dsc_possible; |
| 1109 | sink_per_slice_throughput_mps = dsc_sink_caps->throughput_mode_0_mps; |
| 1110 | } |
| 1111 | break; |
| 1112 | case PIXEL_ENCODING_YCBCR420: |
| 1113 | is_dsc_possible = (bool)dsc_common_caps.color_formats.bits.YCBCR_NATIVE_420; |
| 1114 | sink_per_slice_throughput_mps = dsc_sink_caps->throughput_mode_1_mps; |
| 1115 | branch_max_throughput_mps = dsc_sink_caps->branch_overall_throughput_1_mps; |
| 1116 | break; |
| 1117 | default: |
| 1118 | is_dsc_possible = false; |
| 1119 | } |
| 1120 | |
| 1121 | // Validate branch's maximum throughput |
| 1122 | if (branch_max_throughput_mps && dsc_div_by_10_round_up(value: timing->pix_clk_100hz) > branch_max_throughput_mps * 1000) |
| 1123 | is_dsc_possible = false; |
| 1124 | |
| 1125 | if (!is_dsc_possible) |
| 1126 | goto done; |
| 1127 | |
| 1128 | // Color depth |
| 1129 | switch (timing->display_color_depth) { |
| 1130 | case COLOR_DEPTH_888: |
| 1131 | is_dsc_possible = (bool)dsc_common_caps.color_depth.bits.COLOR_DEPTH_8_BPC; |
| 1132 | break; |
| 1133 | case COLOR_DEPTH_101010: |
| 1134 | is_dsc_possible = (bool)dsc_common_caps.color_depth.bits.COLOR_DEPTH_10_BPC; |
| 1135 | break; |
| 1136 | case COLOR_DEPTH_121212: |
| 1137 | is_dsc_possible = (bool)dsc_common_caps.color_depth.bits.COLOR_DEPTH_12_BPC; |
| 1138 | break; |
| 1139 | default: |
| 1140 | is_dsc_possible = false; |
| 1141 | } |
| 1142 | |
| 1143 | if (!is_dsc_possible) |
| 1144 | goto done; |
| 1145 | |
| 1146 | // Slice width (i.e. number of slices per line) |
| 1147 | max_slices_h = get_max_dsc_slices(slice_caps: dsc_common_caps.slice_caps); |
| 1148 | |
| 1149 | while (max_slices_h > 0) { |
| 1150 | if (pic_width % max_slices_h == 0) |
| 1151 | break; |
| 1152 | |
| 1153 | max_slices_h = dec_num_slices(slice_caps: dsc_common_caps.slice_caps, num_slices: max_slices_h); |
| 1154 | } |
| 1155 | |
| 1156 | is_dsc_possible = (dsc_common_caps.max_slice_width > 0); |
| 1157 | if (!is_dsc_possible) |
| 1158 | goto done; |
| 1159 | |
| 1160 | /* increase miniumum slice count to meet sink slice width limitations */ |
| 1161 | min_slices_h = dc_fixpt_ceil(arg: dc_fixpt_max( |
| 1162 | arg1: dc_fixpt_div_int(arg1: dc_fixpt_from_int(arg: pic_width), arg2: dsc_common_caps.max_slice_width), // sink min |
| 1163 | arg2: dc_fixpt_from_int(arg: min_slices_h))); // source min |
| 1164 | |
| 1165 | min_slices_h = fit_num_slices_up(slice_caps: dsc_common_caps.slice_caps, num_slices: min_slices_h); |
| 1166 | |
| 1167 | /* increase minimum slice count to meet sink throughput limitations */ |
| 1168 | while (min_slices_h <= max_slices_h) { |
| 1169 | int pix_clk_per_slice_khz = dsc_div_by_10_round_up(value: timing->pix_clk_100hz) / min_slices_h; |
| 1170 | if (pix_clk_per_slice_khz <= sink_per_slice_throughput_mps * 1000) |
| 1171 | break; |
| 1172 | |
| 1173 | min_slices_h = inc_num_slices(slice_caps: dsc_common_caps.slice_caps, num_slices: min_slices_h); |
| 1174 | } |
| 1175 | |
| 1176 | /* increase minimum slice count to meet divisibility requirements */ |
| 1177 | while (pic_width % min_slices_h != 0 && min_slices_h <= max_slices_h) { |
| 1178 | min_slices_h = inc_num_slices(slice_caps: dsc_common_caps.slice_caps, num_slices: min_slices_h); |
| 1179 | } |
| 1180 | |
| 1181 | is_dsc_possible = (min_slices_h <= max_slices_h) && max_slices_h != 0; |
| 1182 | if (!is_dsc_possible) |
| 1183 | goto done; |
| 1184 | |
| 1185 | if (policy.use_min_slices_h) { |
| 1186 | if (min_slices_h > 0) |
| 1187 | num_slices_h = min_slices_h; |
| 1188 | else if (max_slices_h > 0) { // Fall back to max slices if min slices is not working out |
| 1189 | if (policy.max_slices_h) |
| 1190 | num_slices_h = min(policy.max_slices_h, max_slices_h); |
| 1191 | else |
| 1192 | num_slices_h = max_slices_h; |
| 1193 | } else |
| 1194 | is_dsc_possible = false; |
| 1195 | } else { |
| 1196 | if (max_slices_h > 0) { |
| 1197 | if (policy.max_slices_h) |
| 1198 | num_slices_h = min(policy.max_slices_h, max_slices_h); |
| 1199 | else |
| 1200 | num_slices_h = max_slices_h; |
| 1201 | } else if (min_slices_h > 0) // Fall back to min slices if max slices is not possible |
| 1202 | num_slices_h = min_slices_h; |
| 1203 | else |
| 1204 | is_dsc_possible = false; |
| 1205 | } |
| 1206 | // When we force ODM, num dsc h slices must be divisible by num odm h slices |
| 1207 | switch (options->dsc_force_odm_hslice_override) { |
| 1208 | case 0: |
| 1209 | case 1: |
| 1210 | break; |
| 1211 | case 2: |
| 1212 | if (num_slices_h < 2) |
| 1213 | num_slices_h = fit_num_slices_up(slice_caps: dsc_common_caps.slice_caps, num_slices: 2); |
| 1214 | break; |
| 1215 | case 3: |
| 1216 | if (dsc_common_caps.slice_caps.bits.NUM_SLICES_12) |
| 1217 | num_slices_h = 12; |
| 1218 | else |
| 1219 | num_slices_h = 0; |
| 1220 | break; |
| 1221 | case 4: |
| 1222 | if (num_slices_h < 4) |
| 1223 | num_slices_h = fit_num_slices_up(slice_caps: dsc_common_caps.slice_caps, num_slices: 4); |
| 1224 | break; |
| 1225 | default: |
| 1226 | break; |
| 1227 | } |
| 1228 | if (num_slices_h == 0) |
| 1229 | is_dsc_possible = false; |
| 1230 | if (!is_dsc_possible) |
| 1231 | goto done; |
| 1232 | |
| 1233 | dsc_cfg->num_slices_h = num_slices_h; |
| 1234 | slice_width = pic_width / num_slices_h; |
| 1235 | |
| 1236 | is_dsc_possible = slice_width <= dsc_common_caps.max_slice_width; |
| 1237 | if (!is_dsc_possible) |
| 1238 | goto done; |
| 1239 | |
| 1240 | // Slice height (i.e. number of slices per column): start with policy and pick the first one that height is divisible by. |
| 1241 | // For 4:2:0 make sure the slice height is divisible by 2 as well. |
| 1242 | if (options->dsc_min_slice_height_override == 0) |
| 1243 | slice_height = min(policy.min_slice_height, pic_height); |
| 1244 | else |
| 1245 | slice_height = min((int)(options->dsc_min_slice_height_override), pic_height); |
| 1246 | |
| 1247 | while (slice_height < pic_height && (pic_height % slice_height != 0 || |
| 1248 | slice_height % options->slice_height_granularity != 0 || |
| 1249 | (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420 && slice_height % 2 != 0))) |
| 1250 | slice_height++; |
| 1251 | |
| 1252 | if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) // For the case when pic_height < dsc_policy.min_sice_height |
| 1253 | is_dsc_possible = (slice_height % 2 == 0); |
| 1254 | |
| 1255 | if (!is_dsc_possible) |
| 1256 | goto done; |
| 1257 | |
| 1258 | if (slice_height > 0) { |
| 1259 | dsc_cfg->num_slices_v = pic_height / slice_height; |
| 1260 | } else { |
| 1261 | is_dsc_possible = false; |
| 1262 | goto done; |
| 1263 | } |
| 1264 | |
| 1265 | if (target_bandwidth_kbps > 0) { |
| 1266 | is_dsc_possible = decide_dsc_target_bpp_x16( |
| 1267 | policy: &policy, |
| 1268 | options, |
| 1269 | dsc_common_caps: &dsc_common_caps, |
| 1270 | target_bandwidth_kbps, |
| 1271 | timing, |
| 1272 | num_slices_h, |
| 1273 | link_encoding, |
| 1274 | target_bpp_x16: &target_bpp); |
| 1275 | dsc_cfg->bits_per_pixel = target_bpp; |
| 1276 | } |
| 1277 | if (!is_dsc_possible) |
| 1278 | goto done; |
| 1279 | |
| 1280 | /* Fill out the rest of DSC settings */ |
| 1281 | dsc_cfg->block_pred_enable = dsc_common_caps.is_block_pred_supported; |
| 1282 | dsc_cfg->linebuf_depth = dsc_common_caps.lb_bit_depth; |
| 1283 | dsc_cfg->version_minor = (dsc_common_caps.dsc_version & 0xf0) >> 4; |
| 1284 | dsc_cfg->is_dp = dsc_sink_caps->is_dp; |
| 1285 | |
| 1286 | done: |
| 1287 | if (!is_dsc_possible) |
| 1288 | memset(dsc_cfg, 0, sizeof(struct dc_dsc_config)); |
| 1289 | |
| 1290 | return is_dsc_possible; |
| 1291 | } |
| 1292 | |
| 1293 | bool dc_dsc_compute_config( |
| 1294 | const struct display_stream_compressor *dsc, |
| 1295 | const struct dsc_dec_dpcd_caps *dsc_sink_caps, |
| 1296 | const struct dc_dsc_config_options *options, |
| 1297 | uint32_t target_bandwidth_kbps, |
| 1298 | const struct dc_crtc_timing *timing, |
| 1299 | const enum dc_link_encoding_format link_encoding, |
| 1300 | struct dc_dsc_config *dsc_cfg) |
| 1301 | { |
| 1302 | bool is_dsc_possible = false; |
| 1303 | struct dsc_enc_caps dsc_enc_caps; |
| 1304 | unsigned int min_dsc_slice_count; |
| 1305 | get_dsc_enc_caps(dsc, dsc_enc_caps: &dsc_enc_caps, pixel_clock_100Hz: timing->pix_clk_100hz); |
| 1306 | |
| 1307 | min_dsc_slice_count = get_min_dsc_slice_count_for_odm(dsc, dsc_enc_caps: &dsc_enc_caps, timing); |
| 1308 | |
| 1309 | is_dsc_possible = setup_dsc_config(dsc_sink_caps, |
| 1310 | dsc_enc_caps: &dsc_enc_caps, |
| 1311 | target_bandwidth_kbps, |
| 1312 | timing, |
| 1313 | options, |
| 1314 | link_encoding, |
| 1315 | min_slices_h: min_dsc_slice_count, |
| 1316 | dsc_cfg); |
| 1317 | return is_dsc_possible; |
| 1318 | } |
| 1319 | |
| 1320 | uint32_t dc_dsc_stream_bandwidth_in_kbps(const struct dc_crtc_timing *timing, |
| 1321 | uint32_t bpp_x16, uint32_t num_slices_h, bool is_dp) |
| 1322 | { |
| 1323 | uint32_t overhead_in_kbps; |
| 1324 | struct fixed31_32 bpp; |
| 1325 | struct fixed31_32 actual_bandwidth_in_kbps; |
| 1326 | |
| 1327 | overhead_in_kbps = dc_dsc_stream_bandwidth_overhead_in_kbps( |
| 1328 | timing, num_slices_h, is_dp); |
| 1329 | bpp = dc_fixpt_from_fraction(numerator: bpp_x16, denominator: 16); |
| 1330 | actual_bandwidth_in_kbps = dc_fixpt_from_fraction(numerator: timing->pix_clk_100hz, denominator: 10); |
| 1331 | actual_bandwidth_in_kbps = dc_fixpt_mul(arg1: actual_bandwidth_in_kbps, arg2: bpp); |
| 1332 | actual_bandwidth_in_kbps = dc_fixpt_add_int(arg1: actual_bandwidth_in_kbps, arg2: overhead_in_kbps); |
| 1333 | return dc_fixpt_ceil(arg: actual_bandwidth_in_kbps); |
| 1334 | } |
| 1335 | |
| 1336 | uint32_t dc_dsc_stream_bandwidth_overhead_in_kbps( |
| 1337 | const struct dc_crtc_timing *timing, |
| 1338 | const int num_slices_h, |
| 1339 | const bool is_dp) |
| 1340 | { |
| 1341 | struct fixed31_32 max_dsc_overhead; |
| 1342 | struct fixed31_32 refresh_rate; |
| 1343 | |
| 1344 | if (dsc_policy_disable_dsc_stream_overhead || !is_dp) |
| 1345 | return 0; |
| 1346 | |
| 1347 | /* use target bpp that can take entire target bandwidth */ |
| 1348 | refresh_rate = dc_fixpt_from_int(arg: timing->pix_clk_100hz); |
| 1349 | refresh_rate = dc_fixpt_div_int(arg1: refresh_rate, arg2: timing->h_total); |
| 1350 | refresh_rate = dc_fixpt_div_int(arg1: refresh_rate, arg2: timing->v_total); |
| 1351 | refresh_rate = dc_fixpt_mul_int(arg1: refresh_rate, arg2: 100); |
| 1352 | |
| 1353 | max_dsc_overhead = dc_fixpt_from_int(arg: num_slices_h); |
| 1354 | max_dsc_overhead = dc_fixpt_mul_int(arg1: max_dsc_overhead, arg2: timing->v_total); |
| 1355 | max_dsc_overhead = dc_fixpt_mul_int(arg1: max_dsc_overhead, arg2: 256); |
| 1356 | max_dsc_overhead = dc_fixpt_div_int(arg1: max_dsc_overhead, arg2: 1000); |
| 1357 | max_dsc_overhead = dc_fixpt_mul(arg1: max_dsc_overhead, arg2: refresh_rate); |
| 1358 | |
| 1359 | return dc_fixpt_ceil(arg: max_dsc_overhead); |
| 1360 | } |
| 1361 | |
| 1362 | void dc_dsc_get_policy_for_timing(const struct dc_crtc_timing *timing, |
| 1363 | uint32_t max_target_bpp_limit_override_x16, |
| 1364 | struct dc_dsc_policy *policy, |
| 1365 | const enum dc_link_encoding_format link_encoding) |
| 1366 | { |
| 1367 | uint32_t bpc = 0; |
| 1368 | |
| 1369 | policy->min_target_bpp = 0; |
| 1370 | policy->max_target_bpp = 0; |
| 1371 | |
| 1372 | /* DSC Policy: Use minimum number of slices that fits the pixel clock */ |
| 1373 | policy->use_min_slices_h = true; |
| 1374 | |
| 1375 | /* DSC Policy: Use max available slices |
| 1376 | * (in our case 4 for or 8, depending on the mode) |
| 1377 | */ |
| 1378 | policy->max_slices_h = 0; |
| 1379 | |
| 1380 | /* DSC Policy: Use slice height recommended |
| 1381 | * by VESA DSC Spreadsheet user guide |
| 1382 | */ |
| 1383 | policy->min_slice_height = 108; |
| 1384 | |
| 1385 | /* DSC Policy: follow DP specs with an internal upper limit to 16 bpp |
| 1386 | * for better interoperability |
| 1387 | */ |
| 1388 | switch (timing->display_color_depth) { |
| 1389 | case COLOR_DEPTH_888: |
| 1390 | bpc = 8; |
| 1391 | break; |
| 1392 | case COLOR_DEPTH_101010: |
| 1393 | bpc = 10; |
| 1394 | break; |
| 1395 | case COLOR_DEPTH_121212: |
| 1396 | bpc = 12; |
| 1397 | break; |
| 1398 | default: |
| 1399 | return; |
| 1400 | } |
| 1401 | switch (timing->pixel_encoding) { |
| 1402 | case PIXEL_ENCODING_RGB: |
| 1403 | case PIXEL_ENCODING_YCBCR444: |
| 1404 | case PIXEL_ENCODING_YCBCR422: /* assume no YCbCr422 native support */ |
| 1405 | /* DP specs limits to 8 */ |
| 1406 | policy->min_target_bpp = 8; |
| 1407 | /* DP specs limits to 3 x bpc */ |
| 1408 | policy->max_target_bpp = 3 * bpc; |
| 1409 | break; |
| 1410 | case PIXEL_ENCODING_YCBCR420: |
| 1411 | /* DP specs limits to 6 */ |
| 1412 | policy->min_target_bpp = 6; |
| 1413 | /* DP specs limits to 1.5 x bpc assume bpc is an even number */ |
| 1414 | policy->max_target_bpp = bpc * 3 / 2; |
| 1415 | break; |
| 1416 | default: |
| 1417 | return; |
| 1418 | } |
| 1419 | |
| 1420 | /* internal upper limit, default 16 bpp */ |
| 1421 | if (policy->max_target_bpp > dsc_policy_max_target_bpp_limit) |
| 1422 | policy->max_target_bpp = dsc_policy_max_target_bpp_limit; |
| 1423 | |
| 1424 | /* apply override */ |
| 1425 | if (max_target_bpp_limit_override_x16 && policy->max_target_bpp > max_target_bpp_limit_override_x16 / 16) |
| 1426 | policy->max_target_bpp = max_target_bpp_limit_override_x16 / 16; |
| 1427 | |
| 1428 | /* enable DSC when not needed, default false */ |
| 1429 | policy->enable_dsc_when_not_needed = dsc_policy_enable_dsc_when_not_needed; |
| 1430 | } |
| 1431 | |
| 1432 | void dc_dsc_policy_set_max_target_bpp_limit(uint32_t limit) |
| 1433 | { |
| 1434 | dsc_policy_max_target_bpp_limit = limit; |
| 1435 | } |
| 1436 | |
| 1437 | void dc_dsc_policy_set_enable_dsc_when_not_needed(bool enable) |
| 1438 | { |
| 1439 | dsc_policy_enable_dsc_when_not_needed = enable; |
| 1440 | } |
| 1441 | |
| 1442 | void dc_dsc_policy_set_disable_dsc_stream_overhead(bool disable) |
| 1443 | { |
| 1444 | dsc_policy_disable_dsc_stream_overhead = disable; |
| 1445 | } |
| 1446 | |
| 1447 | void dc_set_disable_128b_132b_stream_overhead(bool disable) |
| 1448 | { |
| 1449 | disable_128b_132b_stream_overhead = disable; |
| 1450 | } |
| 1451 | |
| 1452 | void dc_dsc_get_default_config_option(const struct dc *dc, struct dc_dsc_config_options *options) |
| 1453 | { |
| 1454 | options->dsc_min_slice_height_override = dc->debug.dsc_min_slice_height_override; |
| 1455 | options->dsc_force_odm_hslice_override = dc->debug.force_odm_combine; |
| 1456 | options->max_target_bpp_limit_override_x16 = 0; |
| 1457 | options->slice_height_granularity = 1; |
| 1458 | options->force_dsc_when_not_needed = false; |
| 1459 | } |
| 1460 | |