root/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. dsc_buff_block_size_from_dpcd
  2. dsc_line_buff_depth_from_dpcd
  3. dsc_throughput_from_dpcd
  4. dsc_bpp_increment_div_from_dpcd
  5. get_dsc_enc_caps
  6. intersect_dsc_caps
  7. dsc_div_by_10_round_up
  8. calc_dsc_bpp_x16
  9. get_dsc_bandwidth_range
  10. decide_dsc_target_bpp_x16
  11. get_available_dsc_slices
  12. get_max_dsc_slices
  13. inc_num_slices
  14. dec_num_slices
  15. fit_num_slices_up
  16. setup_dsc_config
  17. dc_dsc_parse_dsc_dpcd
  18. dc_dsc_compute_bandwidth_range
  19. dc_dsc_compute_config

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

/* [<][>][^][v][top][bottom][index][help] */