drm/amd/display: Add support for extended DSC DPCD caps
authorNikola Cornij <nikola.cornij@amd.com>
Wed, 17 Apr 2019 23:07:08 +0000 (19:07 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Sat, 22 Jun 2019 14:34:11 +0000 (09:34 -0500)
[why]
A few of the new DSC DPCD caps were introduced by a DP 1.4a SCR in order
to give DSC branch decoders a chance to expose their maximum throughput
and maximum line width limitations.

Signed-off-by: Nikola Cornij <nikola.cornij@amd.com>
Reviewed-by: Wenjing Liu <Wenjing.Liu@amd.com>
Acked-by: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
drivers/gpu/drm/amd/display/dc/dc_dsc.h
drivers/gpu/drm/amd/display/dc/dc_types.h
drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c
drivers/gpu/drm/amd/display/include/dpcd_structs.h [new file with mode: 0644]
include/drm/drm_dp_helper.h

index effc36745671298e3d346a2655766f76d254baa3..017f88c9f2e4d16aa96f2b49ad3294f144c2f95a 100644 (file)
@@ -2383,8 +2383,8 @@ static bool retrieve_link_cap(struct dc_link *link)
        int i;
        struct dp_sink_hw_fw_revision dp_hw_fw_revision;
 #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
-       uint8_t dsc_data[16];
-       struct dsc_dec_dpcd_caps *dsc_caps;
+       uint8_t dsc_data[16]; /* DP_DSC_BITS_PER_PIXEL_INC - DP_DSC_SUPPORT + 1 == 16 */
+       struct dsc_dec_dpcd_caps *dsc_dec_caps;
 #endif
 
        memset(dpcd_data, '\0', sizeof(dpcd_data));
@@ -2558,8 +2558,8 @@ static bool retrieve_link_cap(struct dc_link *link)
                sizeof(dp_hw_fw_revision.ieee_fw_rev));
 
 #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
-       dsc_caps = &link->dpcd_caps.dsc_sink_caps;
-       memset(dsc_caps, '\0', sizeof(*dsc_caps));
+       dsc_dec_caps = &link->dpcd_caps.dsc_sink_caps;
+       memset(dsc_dec_caps, '\0', sizeof(*dsc_dec_caps));
        memset(&link->dpcd_caps.dsc_sink_caps, '\0',
                        sizeof(link->dpcd_caps.dsc_sink_caps));
        memset(&link->dpcd_caps.fec_cap, '\0', sizeof(link->dpcd_caps.fec_cap));
@@ -2571,7 +2571,7 @@ static bool retrieve_link_cap(struct dc_link *link)
                                dsc_data,
                                sizeof(dsc_data));
                if (status == DC_OK) {
-                       DC_LOG_DSC("DSC capability read at link %d:",
+                       DC_LOG_DSC("DSC DPCD capability read at link %d:",
                                        link->link_index);
                        DC_LOG_DSC("\t%02x %02x %02x %02x",
                                        dsc_data[0], dsc_data[1],
@@ -2590,37 +2590,43 @@ static bool retrieve_link_cap(struct dc_link *link)
                        return false;
                }
 
-               if (dc_dsc_parse_dsc_dpcd(dsc_data,
-                               dsc_caps)) {
-                       DC_LOG_DSC("DSC capability parsed at link %d:",
+               if (dc_dsc_parse_dsc_dpcd(dsc_data, NULL,
+                               dsc_dec_caps)) {
+                       DC_LOG_DSC("DSC DPCD capabilities parsed at link %d:",
                                        link->link_index);
                        DC_LOG_DSC("\tis_dsc_supported:\t%d",
-                                       dsc_caps->is_dsc_supported);
-                       DC_LOG_DSC("\tdsc_version:\t%d", dsc_caps->dsc_version);
+                                       dsc_dec_caps->is_dsc_supported);
+                       DC_LOG_DSC("\tdsc_version:\t%d", dsc_dec_caps->dsc_version);
                        DC_LOG_DSC("\trc_buffer_size:\t%d",
-                                       dsc_caps->rc_buffer_size);
+                                       dsc_dec_caps->rc_buffer_size);
                        DC_LOG_DSC("\tslice_caps1:\t0x%x20",
-                                       dsc_caps->slice_caps1.raw);
+                                       dsc_dec_caps->slice_caps1.raw);
                        DC_LOG_DSC("\tslice_caps2:\t0x%x20",
-                                       dsc_caps->slice_caps2.raw);
+                                       dsc_dec_caps->slice_caps2.raw);
                        DC_LOG_DSC("\tlb_bit_depth:\t%d",
-                                       dsc_caps->lb_bit_depth);
+                                       dsc_dec_caps->lb_bit_depth);
                        DC_LOG_DSC("\tis_block_pred_supported:\t%d",
-                                       dsc_caps->is_block_pred_supported);
+                                       dsc_dec_caps->is_block_pred_supported);
                        DC_LOG_DSC("\tedp_max_bits_per_pixel:\t%d",
-                                       dsc_caps->edp_max_bits_per_pixel);
+                                       dsc_dec_caps->edp_max_bits_per_pixel);
                        DC_LOG_DSC("\tcolor_formats:\t%d",
-                                       dsc_caps->color_formats.raw);
+                                       dsc_dec_caps->color_formats.raw);
                        DC_LOG_DSC("\tcolor_depth:\t%d",
-                                       dsc_caps->color_depth.raw);
+                                       dsc_dec_caps->color_depth.raw);
                        DC_LOG_DSC("\tthroughput_mode_0_mps:\t%d",
-                                       dsc_caps->throughput_mode_0_mps);
+                                       dsc_dec_caps->throughput_mode_0_mps);
                        DC_LOG_DSC("\tthroughput_mode_1_mps:\t%d",
-                                       dsc_caps->throughput_mode_1_mps);
+                                       dsc_dec_caps->throughput_mode_1_mps);
                        DC_LOG_DSC("\tmax_slice_width:\t%d",
-                                       dsc_caps->max_slice_width);
+                                       dsc_dec_caps->max_slice_width);
                        DC_LOG_DSC("\tbpp_increment_div:\t%d",
-                                       dsc_caps->bpp_increment_div);
+                                       dsc_dec_caps->bpp_increment_div);
+                       DC_LOG_DSC("\tbranch_overall_throughput_0_mps:\t%d",
+                                       dsc_dec_caps->branch_overall_throughput_0_mps);
+                       DC_LOG_DSC("\tbranch_overall_throughput_1_mps:\t%d",
+                                       dsc_dec_caps->branch_overall_throughput_1_mps);
+                       DC_LOG_DSC("\tbranch_max_line_width:\t%d",
+                                       dsc_dec_caps->branch_max_line_width);
                } else {
                        /* Some sinks return bogus DSC DPCD data
                         * when they don't support DSC.
index be0f7b09086a37d684d1b9ed518e9580626c3268..6de3bc9162eadfd341b1d8650236d101a32ae272 100644 (file)
@@ -34,7 +34,8 @@ struct dc_dsc_bw_range {
 };
 
 
-bool dc_dsc_parse_dsc_dpcd(const uint8_t *dpcd_dsc_data,
+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);
 
 bool dc_dsc_compute_bandwidth_range(
index b7e2c6f767aa99ef4a7752bb5cab3af370398526..5984be3cdf0cbf72d1cabf90db636b16677c43f7 100644 (file)
@@ -773,6 +773,11 @@ struct dsc_dec_dpcd_caps {
        int32_t throughput_mode_1_mps; /* In MPs */
        int32_t max_slice_width;
        uint32_t bpp_increment_div; /* bpp increment divisor, e.g. if 16, it's 1/16th of a bit */
+
+       /* Extended DSC caps */
+       uint32_t branch_overall_throughput_0_mps; /* In MPs */
+       uint32_t branch_overall_throughput_1_mps; /* In MPs */
+       uint32_t branch_max_line_width;
 };
 #endif
 #endif /* DC_TYPES_H_ */
index f09f23707a94248b37566847617ceff6ec58cada..94a623dc37f4e6e8d5ff11fc949b3a69de0b4e4d 100644 (file)
@@ -252,7 +252,7 @@ struct dc_dsc_policy {
        int min_target_bpp; // Minimum target bits per pixel
 };
 
-static inline uint32_t dsc_round_up(uint32_t value)
+static inline uint32_t dsc_div_by_10_round_up(uint32_t value)
 {
        return (value + 9) / 10;
 }
@@ -304,7 +304,7 @@ static void get_dsc_bandwidth_range(
        range->stream_kbps = dc_bandwidth_in_kbps_from_timing(timing);
 
        /* max dsc target bpp */
-       range->max_kbps = dsc_round_up(max_bpp * timing->pix_clk_100hz);
+       range->max_kbps = dsc_div_by_10_round_up(max_bpp * timing->pix_clk_100hz);
        range->max_target_bpp_x16 = max_bpp * 16;
        if (range->max_kbps > range->stream_kbps) {
                /* max dsc target bpp is capped to native bandwidth */
@@ -313,7 +313,7 @@ static void get_dsc_bandwidth_range(
        }
 
        /* min dsc target bpp */
-       range->min_kbps = dsc_round_up(min_bpp * timing->pix_clk_100hz);
+       range->min_kbps = dsc_div_by_10_round_up(min_bpp * timing->pix_clk_100hz);
        range->min_target_bpp_x16 = min_bpp * 16;
        if (range->min_kbps > range->max_kbps) {
                /* min dsc target bpp is capped to max dsc bandwidth*/
@@ -532,16 +532,23 @@ static bool setup_dsc_config(
        int pic_width;
        int slice_width;
        int target_bpp;
-       int sink_per_slice_throughput;
+       int sink_per_slice_throughput_mps;
+       int branch_max_throughput_mps = 0;
        bool is_dsc_possible = false;
        int num_slices_v;
        int pic_height;
 
        memset(dsc_cfg, 0, sizeof(struct dc_dsc_config));
 
+       pic_width = timing->h_addressable + timing->h_border_left + timing->h_border_right;
+       pic_height = timing->v_addressable + timing->v_border_top + timing->v_border_bottom;
+
        if (!dsc_sink_caps->is_dsc_supported)
                goto done;
 
+       if (dsc_sink_caps->branch_max_line_width && dsc_sink_caps->branch_max_line_width < pic_width)
+               goto done;
+
        // Intersect decoder with encoder DSC caps and validate DSC settings
        is_dsc_possible = intersect_dsc_caps(dsc_sink_caps, dsc_enc_caps, timing->pixel_encoding, &dsc_common_caps);
        if (!is_dsc_possible)
@@ -554,39 +561,46 @@ static bool setup_dsc_config(
        if (!is_dsc_possible)
                goto done;
 
-       sink_per_slice_throughput = 0;
+       sink_per_slice_throughput_mps = 0;
 
        // Validate available DSC settings against the mode timing
 
-       // Color format
+       // Validate color format (and pick up the throughput values)
        dsc_cfg->ycbcr422_simple = false;
        switch (timing->pixel_encoding) {
        case PIXEL_ENCODING_RGB:
                is_dsc_possible = (bool)dsc_common_caps.color_formats.bits.RGB;
-               sink_per_slice_throughput = dsc_sink_caps->throughput_mode_0_mps;
+               sink_per_slice_throughput_mps = dsc_sink_caps->throughput_mode_0_mps;
+               branch_max_throughput_mps = dsc_sink_caps->branch_overall_throughput_0_mps;
                break;
        case PIXEL_ENCODING_YCBCR444:
                is_dsc_possible = (bool)dsc_common_caps.color_formats.bits.YCBCR_444;
-               sink_per_slice_throughput = dsc_sink_caps->throughput_mode_0_mps;
-               break;
-       case PIXEL_ENCODING_YCBCR422: {
-                       is_dsc_possible = (bool)dsc_common_caps.color_formats.bits.YCBCR_NATIVE_422;
-                       sink_per_slice_throughput = dsc_sink_caps->throughput_mode_1_mps;
-                       if (!is_dsc_possible) {
-                               is_dsc_possible = (bool)dsc_common_caps.color_formats.bits.YCBCR_SIMPLE_422;
-                               dsc_cfg->ycbcr422_simple = is_dsc_possible;
-                               sink_per_slice_throughput = dsc_sink_caps->throughput_mode_0_mps;
-                       }
+               sink_per_slice_throughput_mps = dsc_sink_caps->throughput_mode_0_mps;
+               branch_max_throughput_mps = dsc_sink_caps->branch_overall_throughput_0_mps;
+               break;
+       case PIXEL_ENCODING_YCBCR422:
+               is_dsc_possible = (bool)dsc_common_caps.color_formats.bits.YCBCR_NATIVE_422;
+               sink_per_slice_throughput_mps = dsc_sink_caps->throughput_mode_1_mps;
+               branch_max_throughput_mps = dsc_sink_caps->branch_overall_throughput_1_mps;
+               if (!is_dsc_possible) {
+                       is_dsc_possible = (bool)dsc_common_caps.color_formats.bits.YCBCR_SIMPLE_422;
+                       dsc_cfg->ycbcr422_simple = is_dsc_possible;
+                       sink_per_slice_throughput_mps = dsc_sink_caps->throughput_mode_0_mps;
                }
                break;
        case PIXEL_ENCODING_YCBCR420:
                is_dsc_possible = (bool)dsc_common_caps.color_formats.bits.YCBCR_NATIVE_420;
-               sink_per_slice_throughput = dsc_sink_caps->throughput_mode_1_mps;
+               sink_per_slice_throughput_mps = dsc_sink_caps->throughput_mode_1_mps;
+               branch_max_throughput_mps = dsc_sink_caps->branch_overall_throughput_1_mps;
                break;
        default:
                is_dsc_possible = false;
        }
 
+       // Validate branch's maximum throughput
+       if (branch_max_throughput_mps && dsc_div_by_10_round_up(timing->pix_clk_100hz) > branch_max_throughput_mps * 1000)
+               is_dsc_possible = false;
+
        if (!is_dsc_possible)
                goto done;
 
@@ -611,7 +625,6 @@ static bool setup_dsc_config(
        // DSC slicing
        max_slices_h = get_max_dsc_slices(dsc_common_caps.slice_caps);
 
-       pic_width = timing->h_addressable + timing->h_border_left + timing->h_border_right;
        while (max_slices_h > 0) {
                if (pic_width % max_slices_h == 0)
                        break;
@@ -630,7 +643,8 @@ static bool setup_dsc_config(
        min_slices_h = fit_num_slices_up(dsc_common_caps.slice_caps, min_slices_h);
 
        while (min_slices_h <= max_slices_h) {
-               if (dsc_round_up(timing->pix_clk_100hz) / (min_slices_h) <= sink_per_slice_throughput * 1000)
+               int pix_clk_per_slice_khz = dsc_div_by_10_round_up(timing->pix_clk_100hz) / min_slices_h;
+               if (pix_clk_per_slice_khz <= sink_per_slice_throughput_mps * 1000)
                        break;
 
                min_slices_h = inc_num_slices(dsc_common_caps.slice_caps, min_slices_h);
@@ -673,7 +687,6 @@ static bool setup_dsc_config(
 
        // Vertical number of slices: start from policy and pick the first one that height is divisible by.
        // For 4:2:0 make sure the slice height is divisible by 2 as well.
-       pic_height = timing->v_addressable + timing->v_border_top + timing->v_border_bottom;
        num_slices_v = dsc_policy.num_slices_v;
        if (num_slices_v < 1)
                num_slices_v = 1;
@@ -710,41 +723,41 @@ done:
        return is_dsc_possible;
 }
 
-bool dc_dsc_parse_dsc_dpcd(const uint8_t *dpcd_dsc_data, struct dsc_dec_dpcd_caps *dsc_sink_caps)
+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)
 {
-       dsc_sink_caps->is_dsc_supported = (dpcd_dsc_data[DP_DSC_SUPPORT - DP_DSC_SUPPORT] & DP_DSC_DECOMPRESSION_IS_SUPPORTED) != 0;
+       dsc_sink_caps->is_dsc_supported = (dpcd_dsc_basic_data[DP_DSC_SUPPORT - DP_DSC_SUPPORT] & DP_DSC_DECOMPRESSION_IS_SUPPORTED) != 0;
        if (!dsc_sink_caps->is_dsc_supported)
                return true;
 
-       dsc_sink_caps->dsc_version = dpcd_dsc_data[DP_DSC_REV - DP_DSC_SUPPORT];
+       dsc_sink_caps->dsc_version = dpcd_dsc_basic_data[DP_DSC_REV - DP_DSC_SUPPORT];
 
        {
                int buff_block_size;
                int buff_size;
 
-               if (!dsc_buff_block_size_from_dpcd(dpcd_dsc_data[DP_DSC_RC_BUF_BLK_SIZE - DP_DSC_SUPPORT], &buff_block_size))
+               if (!dsc_buff_block_size_from_dpcd(dpcd_dsc_basic_data[DP_DSC_RC_BUF_BLK_SIZE - DP_DSC_SUPPORT], &buff_block_size))
                        return false;
 
-               buff_size = dpcd_dsc_data[DP_DSC_RC_BUF_SIZE - DP_DSC_SUPPORT] + 1;
+               buff_size = dpcd_dsc_basic_data[DP_DSC_RC_BUF_SIZE - DP_DSC_SUPPORT] + 1;
                dsc_sink_caps->rc_buffer_size = buff_size * buff_block_size;
        }
 
-       dsc_sink_caps->slice_caps1.raw = dpcd_dsc_data[DP_DSC_SLICE_CAP_1 - DP_DSC_SUPPORT];
-       if (!dsc_line_buff_depth_from_dpcd(dpcd_dsc_data[DP_DSC_LINE_BUF_BIT_DEPTH - DP_DSC_SUPPORT], &dsc_sink_caps->lb_bit_depth))
+       dsc_sink_caps->slice_caps1.raw = dpcd_dsc_basic_data[DP_DSC_SLICE_CAP_1 - DP_DSC_SUPPORT];
+       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))
                return false;
 
        dsc_sink_caps->is_block_pred_supported =
-               (dpcd_dsc_data[DP_DSC_BLK_PREDICTION_SUPPORT - DP_DSC_SUPPORT] & DP_DSC_BLK_PREDICTION_IS_SUPPORTED) != 0;
+               (dpcd_dsc_basic_data[DP_DSC_BLK_PREDICTION_SUPPORT - DP_DSC_SUPPORT] & DP_DSC_BLK_PREDICTION_IS_SUPPORTED) != 0;
 
        dsc_sink_caps->edp_max_bits_per_pixel =
-               dpcd_dsc_data[DP_DSC_MAX_BITS_PER_PIXEL_LOW - DP_DSC_SUPPORT] |
-               dpcd_dsc_data[DP_DSC_MAX_BITS_PER_PIXEL_HI - DP_DSC_SUPPORT] << 8;
+               dpcd_dsc_basic_data[DP_DSC_MAX_BITS_PER_PIXEL_LOW - DP_DSC_SUPPORT] |
+               dpcd_dsc_basic_data[DP_DSC_MAX_BITS_PER_PIXEL_HI - DP_DSC_SUPPORT] << 8;
 
-       dsc_sink_caps->color_formats.raw = dpcd_dsc_data[DP_DSC_DEC_COLOR_FORMAT_CAP - DP_DSC_SUPPORT];
-       dsc_sink_caps->color_depth.raw = dpcd_dsc_data[DP_DSC_DEC_COLOR_DEPTH_CAP - DP_DSC_SUPPORT];
+       dsc_sink_caps->color_formats.raw = dpcd_dsc_basic_data[DP_DSC_DEC_COLOR_FORMAT_CAP - DP_DSC_SUPPORT];
+       dsc_sink_caps->color_depth.raw = dpcd_dsc_basic_data[DP_DSC_DEC_COLOR_DEPTH_CAP - DP_DSC_SUPPORT];
 
        {
-               int dpcd_throughput = dpcd_dsc_data[DP_DSC_PEAK_THROUGHPUT - DP_DSC_SUPPORT];
+               int dpcd_throughput = dpcd_dsc_basic_data[DP_DSC_PEAK_THROUGHPUT - DP_DSC_SUPPORT];
 
                if (!dsc_throughput_from_dpcd(dpcd_throughput & DP_DSC_THROUGHPUT_MODE_0_MASK, &dsc_sink_caps->throughput_mode_0_mps))
                        return false;
@@ -754,12 +767,43 @@ bool dc_dsc_parse_dsc_dpcd(const uint8_t *dpcd_dsc_data, struct dsc_dec_dpcd_cap
                        return false;
        }
 
-       dsc_sink_caps->max_slice_width = dpcd_dsc_data[DP_DSC_MAX_SLICE_WIDTH - DP_DSC_SUPPORT] * 320;
-       dsc_sink_caps->slice_caps2.raw = dpcd_dsc_data[DP_DSC_SLICE_CAP_2 - DP_DSC_SUPPORT];
+       dsc_sink_caps->max_slice_width = dpcd_dsc_basic_data[DP_DSC_MAX_SLICE_WIDTH - DP_DSC_SUPPORT] * 320;
+       dsc_sink_caps->slice_caps2.raw = dpcd_dsc_basic_data[DP_DSC_SLICE_CAP_2 - DP_DSC_SUPPORT];
 
-       if (!dsc_bpp_increment_div_from_dpcd(dpcd_dsc_data[DP_DSC_BITS_PER_PIXEL_INC - DP_DSC_SUPPORT], &dsc_sink_caps->bpp_increment_div))
+       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))
                return false;
 
+       /* Extended caps */
+       if (dpcd_dsc_ext_data == NULL) { // Extended DPCD DSC data can be null, e.g. because it doesn't apply to SST
+               dsc_sink_caps->branch_overall_throughput_0_mps = 0;
+               dsc_sink_caps->branch_overall_throughput_1_mps = 0;
+               dsc_sink_caps->branch_max_line_width = 0;
+               return true;
+       }
+
+       dsc_sink_caps->branch_overall_throughput_0_mps = dpcd_dsc_ext_data[DP_DSC_BRANCH_OVERALL_THROUGHPUT_0 - DP_DSC_BRANCH_OVERALL_THROUGHPUT_0];
+       if (dsc_sink_caps->branch_overall_throughput_0_mps == 0)
+               dsc_sink_caps->branch_overall_throughput_0_mps = 0;
+       else if (dsc_sink_caps->branch_overall_throughput_0_mps == 1)
+               dsc_sink_caps->branch_overall_throughput_0_mps = 680;
+       else {
+               dsc_sink_caps->branch_overall_throughput_0_mps *= 50;
+               dsc_sink_caps->branch_overall_throughput_0_mps += 600;
+       }
+
+       dsc_sink_caps->branch_overall_throughput_1_mps = dpcd_dsc_ext_data[DP_DSC_BRANCH_OVERALL_THROUGHPUT_1 - DP_DSC_BRANCH_OVERALL_THROUGHPUT_0];
+       if (dsc_sink_caps->branch_overall_throughput_1_mps == 0)
+               dsc_sink_caps->branch_overall_throughput_1_mps = 0;
+       else if (dsc_sink_caps->branch_overall_throughput_1_mps == 1)
+               dsc_sink_caps->branch_overall_throughput_1_mps = 680;
+       else {
+               dsc_sink_caps->branch_overall_throughput_1_mps *= 50;
+               dsc_sink_caps->branch_overall_throughput_1_mps += 600;
+       }
+
+       dsc_sink_caps->branch_max_line_width = dpcd_dsc_ext_data[DP_DSC_BRANCH_MAX_LINE_WIDTH - DP_DSC_BRANCH_OVERALL_THROUGHPUT_0] * 320;
+       ASSERT(dsc_sink_caps->branch_max_line_width == 0 || dsc_sink_caps->branch_max_line_width >= 5120);
+
        return true;
 }
 
diff --git a/drivers/gpu/drm/amd/display/include/dpcd_structs.h b/drivers/gpu/drm/amd/display/include/dpcd_structs.h
new file mode 100644 (file)
index 0000000..6f417e0
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ * dpcd_structs.h
+ *
+ *  Created on: Oct 31, 2018
+ *      Author: jlei
+ */
+
+#ifndef DAL_INCLUDE_DPCD_STRUCTS_H_
+#define DAL_INCLUDE_DPCD_STRUCTS_H_
+
+struct dpcd_receive_port0_cap01 {
+       union {
+               struct {
+                       // Byte 0
+                       unsigned char reserved0                         :1; // Bit0
+                       unsigned char local_edid_present                :1;
+                       unsigned char associated_to_preceding_port      :1;
+                       unsigned char hblank_expansion_capable          :1;
+                       unsigned char buffer_size_unit                  :1; // Bit4
+                       unsigned char buffer_size_per_port              :1;
+                       unsigned char reserved1                         :2;
+
+                       // Byte 1
+                       unsigned char buffer_size                       :8;
+               } fields;
+               unsigned char raw[2];
+       };
+};
+
+#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
+
+struct dpcd_dsc_basic_capabilities {
+       union {
+               struct {
+                       // Byte 0
+                       struct {
+
+                               unsigned char dsc_support                               :1; // Bit0
+                               unsigned char reserved                                  :7;
+                       } dsc_support;
+
+                       // Byte 1
+                       struct {
+                               unsigned char dsc_version_major :4;
+                               unsigned char dsc_version_minor :4;
+                       } dsc_algorithm_revision;
+
+                       // Byte 2
+                       struct {
+                               unsigned char rc_block_buffer_size      :2;
+                               unsigned char reserved  :6;
+                       } dsc_rc_buffer_block_size;
+
+                       // Byte 3
+                       unsigned char dsc_rc_buffer_size;
+
+                       // Byte 4
+                       struct {
+                               unsigned char one_slice_per_dp_dsc_sink_device          :1; // Bit0
+                               unsigned char two_slices_per_dp_dsc_sink_device         :1;
+                               unsigned char reserved                                  :1;
+                               unsigned char four_slices_per_dp_dsc_sink_device        :1;
+                               unsigned char six_slices_per_dp_dsc_sink_device         :1; // Bit 4
+                               unsigned char eight_slices_per_dp_dsc_sink_device       :1;
+                               unsigned char ten_slices_per_dp_dsc_sink_device         :1;
+                               unsigned char twelve_slices_per_dp_dsc_sink_device      :1;
+                       } dsc_slice_capabilities_1;
+
+                       // Byte 5
+                       struct {
+                               unsigned char line_buffer_bit_depth     :4;
+                               unsigned char reserved                  :4;
+                       } dsc_line_buffer_bit_depth;
+
+                       // Byte 6
+                       struct {
+                               unsigned char block_prediction_support  :1;
+                               unsigned char reserved                  :7;
+                       } dsc_block_prediction_support;
+
+                       // Byte 7,8
+                       struct {
+                               unsigned char maximum_bits_per_pixel_supported_by_the_decompressor_low  :7;
+                               unsigned char maximum_bits_per_pixel_supported_by_the_decompressor_high :7;
+                       } maximum_bits_per_pixel_supported_by_the_decompressor;
+
+                       // Byte 9
+                       struct {
+                               unsigned char rgb_support                       :1; // Bit0
+                               unsigned char y_cb_cr_444_support               :1;
+                               unsigned char y_cb_cr_simple_422_support        :1;
+                               unsigned char y_cb_cr_native_422_support        :1;
+                               unsigned char y_cb_cr_native_420_support        :1; // Bit 4
+                               unsigned char reserved                          :3;
+                       } dsc_decoder_color_format_capabilities;
+
+                       // Byte 10
+                       struct {
+                               unsigned char reserved0                         :1; // Bit0
+                               unsigned char eight_bits_per_color_support      :1;
+                               unsigned char ten_bits_per_color_support        :1;
+                               unsigned char twelve_bits_per_color_support     :1;
+                               unsigned char reserved1                         :4; // Bit 4
+                       } dsc_decoder_color_depth_capabilities;
+
+                       // Byte 11
+                       struct {
+                               unsigned char throughput_mode_0                 :4;
+                               unsigned char throughput_mode_1                 :4;
+                       } peak_dsc_throughput_dsc_sink;
+
+                       // Byte 12
+                       unsigned char dsc_maximum_slice_width;
+
+                       // Byte 13
+                       struct {
+                               unsigned char sixteen_slices_per_dsc_sink_device        :1;
+                               unsigned char twenty_slices_per_dsc_sink_device         :1;
+                               unsigned char twentyfour_slices_per_dsc_sink_device     :1;
+                               unsigned char reserved                                  :5;
+                       } dsc_slice_capabilities_2;
+
+                       // Byte 14
+                       unsigned char reserved;
+
+                       // Byte 15
+                       struct {
+                               unsigned char increment_of_bits_per_pixel_supported     :3;
+                               unsigned char reserved                                  :5;
+                       } bits_per_pixel_increment;
+               } fields;
+               unsigned char raw[16];
+       };
+};
+
+struct dpcd_dsc_ext_capabilities {
+       union {
+               struct {
+                       unsigned char branch_overall_throughput_0; // Byte 0
+                       unsigned char branch_overall_throughput_1; // Byte 1
+                       unsigned char branch_max_line_width; // Byte 2
+               } fields;
+               unsigned char raw[3];
+       };
+};
+
+struct dpcd_dsc_capabilities {
+       struct dpcd_dsc_basic_capabilities dsc_basic_caps;
+       struct dpcd_dsc_ext_capabilities dsc_ext_caps;
+};
+
+struct dpcd_fec_capability {
+       union {
+               struct {
+                       // Byte 0
+                       unsigned char fec_capable                               :1; // Bit0
+                       unsigned char uncorrected_block_error_count_capable     :1;
+                       unsigned char corrected_block_error_count_capable       :1;
+                       unsigned char bit_error_count_capable                   :1;
+                       unsigned char reserved                                  :4; // Bit4
+               } fields;
+               unsigned char raw[1];
+       };
+};
+
+#endif
+
+#endif /* DAL_INCLUDE_DPCD_STRUCTS_H_ */
index c0c947a42a59f3fe7d12c8cb8d332186ff42c558..6d10b455b80a643c754c0aa73ba176e691a4f390 100644 (file)
 # define DP_FEC_CORR_BLK_ERROR_COUNT_CAP    (1 << 2)
 # define DP_FEC_BIT_ERROR_COUNT_CAP        (1 << 3)
 
+/* DP Extended DSC Capabilities */
+#define DP_DSC_BRANCH_OVERALL_THROUGHPUT_0  0x0a0   /* DP 1.4a SCR */
+#define DP_DSC_BRANCH_OVERALL_THROUGHPUT_1  0x0a1
+#define DP_DSC_BRANCH_MAX_LINE_WIDTH        0x0a2
+
 /* link configuration */
 #define        DP_LINK_BW_SET                      0x100
 # define DP_LINK_RATE_TABLE                0x00    /* eDP 1.4 */