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