forked from luck/tmp_suning_uos_patched
drm/amd/display: Add support for extended DSC DPCD caps
[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>
This commit is contained in:
parent
ce76898527
commit
f446489adc
|
@ -2383,8 +2383,8 @@ static bool retrieve_link_cap(struct dc_link *link)
|
||||||
int i;
|
int i;
|
||||||
struct dp_sink_hw_fw_revision dp_hw_fw_revision;
|
struct dp_sink_hw_fw_revision dp_hw_fw_revision;
|
||||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||||
uint8_t dsc_data[16];
|
uint8_t dsc_data[16]; /* DP_DSC_BITS_PER_PIXEL_INC - DP_DSC_SUPPORT + 1 == 16 */
|
||||||
struct dsc_dec_dpcd_caps *dsc_caps;
|
struct dsc_dec_dpcd_caps *dsc_dec_caps;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
memset(dpcd_data, '\0', sizeof(dpcd_data));
|
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));
|
sizeof(dp_hw_fw_revision.ieee_fw_rev));
|
||||||
|
|
||||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||||
dsc_caps = &link->dpcd_caps.dsc_sink_caps;
|
dsc_dec_caps = &link->dpcd_caps.dsc_sink_caps;
|
||||||
memset(dsc_caps, '\0', sizeof(*dsc_caps));
|
memset(dsc_dec_caps, '\0', sizeof(*dsc_dec_caps));
|
||||||
memset(&link->dpcd_caps.dsc_sink_caps, '\0',
|
memset(&link->dpcd_caps.dsc_sink_caps, '\0',
|
||||||
sizeof(link->dpcd_caps.dsc_sink_caps));
|
sizeof(link->dpcd_caps.dsc_sink_caps));
|
||||||
memset(&link->dpcd_caps.fec_cap, '\0', sizeof(link->dpcd_caps.fec_cap));
|
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,
|
dsc_data,
|
||||||
sizeof(dsc_data));
|
sizeof(dsc_data));
|
||||||
if (status == DC_OK) {
|
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);
|
link->link_index);
|
||||||
DC_LOG_DSC("\t%02x %02x %02x %02x",
|
DC_LOG_DSC("\t%02x %02x %02x %02x",
|
||||||
dsc_data[0], dsc_data[1],
|
dsc_data[0], dsc_data[1],
|
||||||
|
@ -2590,37 +2590,43 @@ static bool retrieve_link_cap(struct dc_link *link)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dc_dsc_parse_dsc_dpcd(dsc_data,
|
if (dc_dsc_parse_dsc_dpcd(dsc_data, NULL,
|
||||||
dsc_caps)) {
|
dsc_dec_caps)) {
|
||||||
DC_LOG_DSC("DSC capability parsed at link %d:",
|
DC_LOG_DSC("DSC DPCD capabilities parsed at link %d:",
|
||||||
link->link_index);
|
link->link_index);
|
||||||
DC_LOG_DSC("\tis_dsc_supported:\t%d",
|
DC_LOG_DSC("\tis_dsc_supported:\t%d",
|
||||||
dsc_caps->is_dsc_supported);
|
dsc_dec_caps->is_dsc_supported);
|
||||||
DC_LOG_DSC("\tdsc_version:\t%d", dsc_caps->dsc_version);
|
DC_LOG_DSC("\tdsc_version:\t%d", dsc_dec_caps->dsc_version);
|
||||||
DC_LOG_DSC("\trc_buffer_size:\t%d",
|
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",
|
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",
|
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",
|
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",
|
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",
|
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",
|
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",
|
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",
|
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",
|
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",
|
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",
|
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 {
|
} else {
|
||||||
/* Some sinks return bogus DSC DPCD data
|
/* Some sinks return bogus DSC DPCD data
|
||||||
* when they don't support DSC.
|
* when they don't support DSC.
|
||||||
|
|
|
@ -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);
|
struct dsc_dec_dpcd_caps *dsc_sink_caps);
|
||||||
|
|
||||||
bool dc_dsc_compute_bandwidth_range(
|
bool dc_dsc_compute_bandwidth_range(
|
||||||
|
|
|
@ -773,6 +773,11 @@ struct dsc_dec_dpcd_caps {
|
||||||
int32_t throughput_mode_1_mps; /* In MPs */
|
int32_t throughput_mode_1_mps; /* In MPs */
|
||||||
int32_t max_slice_width;
|
int32_t max_slice_width;
|
||||||
uint32_t bpp_increment_div; /* bpp increment divisor, e.g. if 16, it's 1/16th of a bit */
|
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
|
||||||
#endif /* DC_TYPES_H_ */
|
#endif /* DC_TYPES_H_ */
|
||||||
|
|
|
@ -252,7 +252,7 @@ struct dc_dsc_policy {
|
||||||
int min_target_bpp; // Minimum target bits per pixel
|
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;
|
return (value + 9) / 10;
|
||||||
}
|
}
|
||||||
|
@ -304,7 +304,7 @@ static void get_dsc_bandwidth_range(
|
||||||
range->stream_kbps = dc_bandwidth_in_kbps_from_timing(timing);
|
range->stream_kbps = dc_bandwidth_in_kbps_from_timing(timing);
|
||||||
|
|
||||||
/* max dsc target bpp */
|
/* 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;
|
range->max_target_bpp_x16 = max_bpp * 16;
|
||||||
if (range->max_kbps > range->stream_kbps) {
|
if (range->max_kbps > range->stream_kbps) {
|
||||||
/* max dsc target bpp is capped to native bandwidth */
|
/* max dsc target bpp is capped to native bandwidth */
|
||||||
|
@ -313,7 +313,7 @@ static void get_dsc_bandwidth_range(
|
||||||
}
|
}
|
||||||
|
|
||||||
/* min dsc target bpp */
|
/* 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;
|
range->min_target_bpp_x16 = min_bpp * 16;
|
||||||
if (range->min_kbps > range->max_kbps) {
|
if (range->min_kbps > range->max_kbps) {
|
||||||
/* min dsc target bpp is capped to max dsc bandwidth*/
|
/* min dsc target bpp is capped to max dsc bandwidth*/
|
||||||
|
@ -532,16 +532,23 @@ static bool setup_dsc_config(
|
||||||
int pic_width;
|
int pic_width;
|
||||||
int slice_width;
|
int slice_width;
|
||||||
int target_bpp;
|
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;
|
bool is_dsc_possible = false;
|
||||||
int num_slices_v;
|
int num_slices_v;
|
||||||
int pic_height;
|
int pic_height;
|
||||||
|
|
||||||
memset(dsc_cfg, 0, sizeof(struct dc_dsc_config));
|
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)
|
if (!dsc_sink_caps->is_dsc_supported)
|
||||||
goto done;
|
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
|
// 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);
|
is_dsc_possible = intersect_dsc_caps(dsc_sink_caps, dsc_enc_caps, timing->pixel_encoding, &dsc_common_caps);
|
||||||
if (!is_dsc_possible)
|
if (!is_dsc_possible)
|
||||||
|
@ -554,39 +561,46 @@ static bool setup_dsc_config(
|
||||||
if (!is_dsc_possible)
|
if (!is_dsc_possible)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
sink_per_slice_throughput = 0;
|
sink_per_slice_throughput_mps = 0;
|
||||||
|
|
||||||
// Validate available DSC settings against the mode timing
|
// Validate available DSC settings against the mode timing
|
||||||
|
|
||||||
// Color format
|
// Validate color format (and pick up the throughput values)
|
||||||
dsc_cfg->ycbcr422_simple = false;
|
dsc_cfg->ycbcr422_simple = false;
|
||||||
switch (timing->pixel_encoding) {
|
switch (timing->pixel_encoding) {
|
||||||
case PIXEL_ENCODING_RGB:
|
case PIXEL_ENCODING_RGB:
|
||||||
is_dsc_possible = (bool)dsc_common_caps.color_formats.bits.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;
|
break;
|
||||||
case PIXEL_ENCODING_YCBCR444:
|
case PIXEL_ENCODING_YCBCR444:
|
||||||
is_dsc_possible = (bool)dsc_common_caps.color_formats.bits.YCBCR_444;
|
is_dsc_possible = (bool)dsc_common_caps.color_formats.bits.YCBCR_444;
|
||||||
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;
|
break;
|
||||||
case PIXEL_ENCODING_YCBCR422: {
|
case PIXEL_ENCODING_YCBCR422:
|
||||||
is_dsc_possible = (bool)dsc_common_caps.color_formats.bits.YCBCR_NATIVE_422;
|
is_dsc_possible = (bool)dsc_common_caps.color_formats.bits.YCBCR_NATIVE_422;
|
||||||
sink_per_slice_throughput = dsc_sink_caps->throughput_mode_1_mps;
|
sink_per_slice_throughput_mps = dsc_sink_caps->throughput_mode_1_mps;
|
||||||
if (!is_dsc_possible) {
|
branch_max_throughput_mps = dsc_sink_caps->branch_overall_throughput_1_mps;
|
||||||
is_dsc_possible = (bool)dsc_common_caps.color_formats.bits.YCBCR_SIMPLE_422;
|
if (!is_dsc_possible) {
|
||||||
dsc_cfg->ycbcr422_simple = is_dsc_possible;
|
is_dsc_possible = (bool)dsc_common_caps.color_formats.bits.YCBCR_SIMPLE_422;
|
||||||
sink_per_slice_throughput = dsc_sink_caps->throughput_mode_0_mps;
|
dsc_cfg->ycbcr422_simple = is_dsc_possible;
|
||||||
}
|
sink_per_slice_throughput_mps = dsc_sink_caps->throughput_mode_0_mps;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PIXEL_ENCODING_YCBCR420:
|
case PIXEL_ENCODING_YCBCR420:
|
||||||
is_dsc_possible = (bool)dsc_common_caps.color_formats.bits.YCBCR_NATIVE_420;
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
is_dsc_possible = false;
|
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)
|
if (!is_dsc_possible)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
|
@ -611,7 +625,6 @@ static bool setup_dsc_config(
|
||||||
// DSC slicing
|
// DSC slicing
|
||||||
max_slices_h = get_max_dsc_slices(dsc_common_caps.slice_caps);
|
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) {
|
while (max_slices_h > 0) {
|
||||||
if (pic_width % max_slices_h == 0)
|
if (pic_width % max_slices_h == 0)
|
||||||
break;
|
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);
|
min_slices_h = fit_num_slices_up(dsc_common_caps.slice_caps, min_slices_h);
|
||||||
|
|
||||||
while (min_slices_h <= max_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;
|
break;
|
||||||
|
|
||||||
min_slices_h = inc_num_slices(dsc_common_caps.slice_caps, min_slices_h);
|
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.
|
// 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.
|
// 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;
|
num_slices_v = dsc_policy.num_slices_v;
|
||||||
if (num_slices_v < 1)
|
if (num_slices_v < 1)
|
||||||
num_slices_v = 1;
|
num_slices_v = 1;
|
||||||
|
@ -710,41 +723,41 @@ static bool setup_dsc_config(
|
||||||
return is_dsc_possible;
|
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)
|
if (!dsc_sink_caps->is_dsc_supported)
|
||||||
return true;
|
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_block_size;
|
||||||
int buff_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;
|
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->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];
|
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_data[DP_DSC_LINE_BUF_BIT_DEPTH - DP_DSC_SUPPORT], &dsc_sink_caps->lb_bit_depth))
|
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;
|
return false;
|
||||||
|
|
||||||
dsc_sink_caps->is_block_pred_supported =
|
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 =
|
dsc_sink_caps->edp_max_bits_per_pixel =
|
||||||
dpcd_dsc_data[DP_DSC_MAX_BITS_PER_PIXEL_LOW - DP_DSC_SUPPORT] |
|
dpcd_dsc_basic_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_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_formats.raw = dpcd_dsc_basic_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_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))
|
if (!dsc_throughput_from_dpcd(dpcd_throughput & DP_DSC_THROUGHPUT_MODE_0_MASK, &dsc_sink_caps->throughput_mode_0_mps))
|
||||||
return false;
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
dsc_sink_caps->max_slice_width = dpcd_dsc_data[DP_DSC_MAX_SLICE_WIDTH - DP_DSC_SUPPORT] * 320;
|
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_data[DP_DSC_SLICE_CAP_2 - DP_DSC_SUPPORT];
|
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;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
168
drivers/gpu/drm/amd/display/include/dpcd_structs.h
Normal file
168
drivers/gpu/drm/amd/display/include/dpcd_structs.h
Normal file
|
@ -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_ */
|
|
@ -356,6 +356,11 @@
|
||||||
# define DP_FEC_CORR_BLK_ERROR_COUNT_CAP (1 << 2)
|
# define DP_FEC_CORR_BLK_ERROR_COUNT_CAP (1 << 2)
|
||||||
# define DP_FEC_BIT_ERROR_COUNT_CAP (1 << 3)
|
# 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 */
|
/* link configuration */
|
||||||
#define DP_LINK_BW_SET 0x100
|
#define DP_LINK_BW_SET 0x100
|
||||||
# define DP_LINK_RATE_TABLE 0x00 /* eDP 1.4 */
|
# define DP_LINK_RATE_TABLE 0x00 /* eDP 1.4 */
|
||||||
|
|
Loading…
Reference in New Issue
Block a user