Commit 39a4eb85 authored by Wenjing Liu's avatar Wenjing Liu Committed by Alex Deucher

drm/amd/display: update DSC MST DP virtual DPCD peer device enumeration policy

[why]
Current policy assumes virtual DPCD peer device as
an individual MST branch device with 1 input and 1 output.
However this is only true for virtual DP-to-DP peer device.
In general there are three types of virtual DP peer devices.
1. Sink peer device with virtual DPCD.
2. Virtual DP-to-DP Peer device with virtual DPCD.
3. Virtual DP-to-HDMI Protocol Converter Peer Device with
Virtual DPCD.
So we should break the assumption and handle all three types.

[how]
DP-to-DP peer device will have virtual DPCD cap upstream.
Sink peer device will have virtual DPCD on the logical port.
Dp to HDMI protocol converter peer device will have virtual DPCD
on its converter port.
For DSC capable Synaptics non VGA port we workaround by enumerating
a virutal DPCD peer device on its upstream
even if it doesn't have one.
Signed-off-by: default avatarWenjing Liu <Wenjing.Liu@amd.com>
Reviewed-by: default avatarJun Lei <Jun.Lei@amd.com>
Acked-by: default avatarBhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 2131f655
......@@ -3421,6 +3421,20 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
fill_stream_properties_from_drm_display_mode(stream,
&mode, &aconnector->base, con_state, old_stream);
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
/* stream->timing.flags.DSC = 0; */
/* */
/* if (aconnector->dc_link && */
/* aconnector->dc_link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT #<{(|&& */
/* aconnector->dc_link->dpcd_caps.dsc_caps.dsc_basic_caps.is_dsc_supported|)}>#) */
/* if (dc_dsc_compute_config(aconnector->dc_link->ctx->dc, */
/* &aconnector->dc_link->dpcd_caps.dsc_caps, */
/* dc_link_bandwidth_kbps(aconnector->dc_link, dc_link_get_link_cap(aconnector->dc_link)), */
/* &stream->timing, */
/* &stream->timing.dsc_cfg)) */
/* stream->timing.flags.DSC = 1; */
#endif
update_stream_scaling_settings(&mode, dm_state, stream);
fill_audio_info(
......
......@@ -2382,10 +2382,6 @@ static bool retrieve_link_cap(struct dc_link *link)
uint32_t read_dpcd_retry_cnt = 3;
int i;
struct dp_sink_hw_fw_revision dp_hw_fw_revision;
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
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));
memset(&down_strm_port_count,
......@@ -2558,93 +2554,26 @@ 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_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.dsc_caps, '\0',
sizeof(link->dpcd_caps.dsc_caps));
memset(&link->dpcd_caps.fec_cap, '\0', sizeof(link->dpcd_caps.fec_cap));
/* Read DSC and FEC sink capabilities if DP revision is 1.4 and up */
if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_14) {
status = core_link_read_dpcd(
link,
DP_DSC_SUPPORT,
dsc_data,
sizeof(dsc_data));
if (status == DC_OK) {
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],
dsc_data[2], dsc_data[3]);
DC_LOG_DSC("\t%02x %02x %02x %02x",
dsc_data[4], dsc_data[5],
dsc_data[6], dsc_data[7]);
DC_LOG_DSC("\t%02x %02x %02x %02x",
dsc_data[8], dsc_data[9],
dsc_data[10], dsc_data[11]);
DC_LOG_DSC("\t%02x %02x %02x %02x",
dsc_data[12], dsc_data[13],
dsc_data[14], dsc_data[15]);
} else {
dm_error("%s: Read DSC dpcd data failed.\n", __func__);
return false;
}
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_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_dec_caps->rc_buffer_size);
DC_LOG_DSC("\tslice_caps1:\t0x%x20",
dsc_dec_caps->slice_caps1.raw);
DC_LOG_DSC("\tslice_caps2:\t0x%x20",
dsc_dec_caps->slice_caps2.raw);
DC_LOG_DSC("\tlb_bit_depth:\t%d",
dsc_dec_caps->lb_bit_depth);
DC_LOG_DSC("\tis_block_pred_supported:\t%d",
dsc_dec_caps->is_block_pred_supported);
DC_LOG_DSC("\tedp_max_bits_per_pixel:\t%d",
dsc_dec_caps->edp_max_bits_per_pixel);
DC_LOG_DSC("\tcolor_formats:\t%d",
dsc_dec_caps->color_formats.raw);
DC_LOG_DSC("\tcolor_depth:\t%d",
dsc_dec_caps->color_depth.raw);
DC_LOG_DSC("\tthroughput_mode_0_mps:\t%d",
dsc_dec_caps->throughput_mode_0_mps);
DC_LOG_DSC("\tthroughput_mode_1_mps:\t%d",
dsc_dec_caps->throughput_mode_1_mps);
DC_LOG_DSC("\tmax_slice_width:\t%d",
dsc_dec_caps->max_slice_width);
DC_LOG_DSC("\tbpp_increment_div:\t%d",
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.
*/
dm_error("%s: DSC DPCD data doesn't make sense. "
"DSC will be disabled.\n", __func__);
memset(&link->dpcd_caps.dsc_sink_caps, '\0',
sizeof(link->dpcd_caps.dsc_sink_caps));
}
status = core_link_read_dpcd(
link,
DP_FEC_CAPABILITY,
&link->dpcd_caps.fec_cap.raw,
sizeof(link->dpcd_caps.fec_cap.raw));
if (status != DC_OK)
dm_error("%s: Read FEC dpcd register failed.\n",
__func__);
status = core_link_read_dpcd(
link,
DP_DSC_SUPPORT,
link->dpcd_caps.dsc_caps.dsc_basic_caps.raw,
sizeof(link->dpcd_caps.dsc_caps.dsc_basic_caps.raw));
status = core_link_read_dpcd(
link,
DP_DSC_BRANCH_OVERALL_THROUGHPUT_0,
link->dpcd_caps.dsc_caps.dsc_ext_caps.raw,
sizeof(link->dpcd_caps.dsc_caps.dsc_ext_caps.raw));
}
#endif
......
......@@ -910,8 +910,8 @@ struct dpcd_caps {
bool dpcd_display_control_capable;
bool ext_receiver_cap_field_present;
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
union fec_capability fec_cap;
struct dsc_dec_dpcd_caps dsc_sink_caps;
union dpcd_fec_capability fec_cap;
struct dpcd_dsc_capabilities dsc_caps;
#endif
};
......@@ -933,6 +933,14 @@ struct dc_container_id {
};
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
struct dc_sink_dsc_caps {
// 'true' if these are virtual DPCD's DSC caps (immediately upstream of sink in MST topology),
// 'false' if they are sink's DSC caps
bool is_virtual_dpcd_dsc;
struct dsc_dec_dpcd_caps dsc_dec_caps;
};
#endif
/*
* The sink structure contains EDID and other display device properties
......@@ -948,12 +956,7 @@ struct dc_sink {
bool converter_disable_audio;
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
struct dc_sink_dsc_caps {
// 'true' if these are virtual DPCD's DSC caps (immediately upstream of sink in MST topology),
// 'false' if they are sink's DSC caps
bool is_virtual_dpcd_dsc;
struct dsc_dec_dpcd_caps dsc_dec_caps;
} sink_dsc_caps;
struct dc_sink_dsc_caps sink_dsc_caps;
#endif
/* private to DC core */
......
......@@ -514,7 +514,7 @@ union test_misc {
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
/* FEC capability DPCD register field bits-*/
union fec_capability {
union dpcd_fec_capability {
struct {
uint8_t FEC_CAPABLE:1;
uint8_t UNCORRECTED_BLOCK_ERROR_COUNT_CAPABLE:1;
......@@ -524,6 +524,119 @@ union fec_capability {
} bits;
uint8_t raw;
};
/* DSC capability DPCD register field bits-*/
struct dpcd_dsc_support {
uint8_t DSC_SUPPORT :1;
uint8_t DSC_PASSTHROUGH_SUPPORT :1;
uint8_t RESERVED :6;
};
struct dpcd_dsc_algorithm_revision {
uint8_t DSC_VERSION_MAJOR :4;
uint8_t DSC_VERSION_MINOR :4;
};
struct dpcd_dsc_rc_buffer_block_size {
uint8_t RC_BLOCK_BUFFER_SIZE :2;
uint8_t RESERVED :6;
};
struct dpcd_dsc_slice_capability1 {
uint8_t ONE_SLICE_PER_DP_DSC_SINK_DEVICE :1;
uint8_t TWO_SLICES_PER_DP_DSC_SINK_DEVICE :1;
uint8_t RESERVED :1;
uint8_t FOUR_SLICES_PER_DP_DSC_SINK_DEVICE :1;
uint8_t SIX_SLICES_PER_DP_DSC_SINK_DEVICE :1;
uint8_t EIGHT_SLICES_PER_DP_DSC_SINK_DEVICE :1;
uint8_t TEN_SLICES_PER_DP_DSC_SINK_DEVICE :1;
uint8_t TWELVE_SLICES_PER_DP_DSC_SINK_DEVICE :1;
};
struct dpcd_dsc_line_buffer_bit_depth {
uint8_t LINE_BUFFER_BIT_DEPTH :4;
uint8_t RESERVED :4;
};
struct dpcd_dsc_block_prediction_support {
uint8_t BLOCK_PREDICTION_SUPPORT:1;
uint8_t RESERVED :7;
};
struct dpcd_maximum_bits_per_pixel_supported_by_the_decompressor {
uint8_t MAXIMUM_BITS_PER_PIXEL_SUPPORTED_BY_THE_DECOMPRESSOR_LOW :7;
uint8_t MAXIMUM_BITS_PER_PIXEL_SUPPORTED_BY_THE_DECOMPRESSOR_HIGH :7;
uint8_t RESERVED :2;
};
struct dpcd_dsc_decoder_color_format_capabilities {
uint8_t RGB_SUPPORT :1;
uint8_t Y_CB_CR_444_SUPPORT :1;
uint8_t Y_CB_CR_SIMPLE_422_SUPPORT :1;
uint8_t Y_CB_CR_NATIVE_422_SUPPORT :1;
uint8_t Y_CB_CR_NATIVE_420_SUPPORT :1;
uint8_t RESERVED :3;
};
struct dpcd_dsc_decoder_color_depth_capabilities {
uint8_t RESERVED0 :1;
uint8_t EIGHT_BITS_PER_COLOR_SUPPORT :1;
uint8_t TEN_BITS_PER_COLOR_SUPPORT :1;
uint8_t TWELVE_BITS_PER_COLOR_SUPPORT :1;
uint8_t RESERVED1 :4;
};
struct dpcd_peak_dsc_throughput_dsc_sink {
uint8_t THROUGHPUT_MODE_0:4;
uint8_t THROUGHPUT_MODE_1:4;
};
struct dpcd_dsc_slice_capabilities_2 {
uint8_t SIXTEEN_SLICES_PER_DSC_SINK_DEVICE :1;
uint8_t TWENTY_SLICES_PER_DSC_SINK_DEVICE :1;
uint8_t TWENTYFOUR_SLICES_PER_DSC_SINK_DEVICE :1;
uint8_t RESERVED :5;
};
struct dpcd_bits_per_pixel_increment{
uint8_t INCREMENT_OF_BITS_PER_PIXEL_SUPPORTED :3;
uint8_t RESERVED :5;
};
union dpcd_dsc_basic_capabilities {
struct {
struct dpcd_dsc_support dsc_support;
struct dpcd_dsc_algorithm_revision dsc_algorithm_revision;
struct dpcd_dsc_rc_buffer_block_size dsc_rc_buffer_block_size;
uint8_t dsc_rc_buffer_size;
struct dpcd_dsc_slice_capability1 dsc_slice_capabilities_1;
struct dpcd_dsc_line_buffer_bit_depth dsc_line_buffer_bit_depth;
struct dpcd_dsc_block_prediction_support dsc_block_prediction_support;
struct dpcd_maximum_bits_per_pixel_supported_by_the_decompressor maximum_bits_per_pixel_supported_by_the_decompressor;
struct dpcd_dsc_decoder_color_format_capabilities dsc_decoder_color_format_capabilities;
struct dpcd_dsc_decoder_color_depth_capabilities dsc_decoder_color_depth_capabilities;
struct dpcd_peak_dsc_throughput_dsc_sink peak_dsc_throughput_dsc_sink;
uint8_t dsc_maximum_slice_width;
struct dpcd_dsc_slice_capabilities_2 dsc_slice_capabilities_2;
uint8_t reserved;
struct dpcd_bits_per_pixel_increment bits_per_pixel_increment;
} fields;
uint8_t raw[16];
};
union dpcd_dsc_ext_capabilities {
struct {
uint8_t BRANCH_OVERALL_THROUGHPUT_0;
uint8_t BRANCH_OVERALL_THROUGHPUT_1;
uint8_t BRANCH_MAX_LINE_WIDTH;
} fields;
uint8_t raw[3];
};
struct dpcd_dsc_capabilities {
union dpcd_dsc_basic_capabilities dsc_basic_caps;
union dpcd_dsc_ext_capabilities dsc_ext_caps;
};
#endif /* CONFIG_DRM_AMD_DC_DSC_SUPPORT */
#endif /* DC_DP_TYPES_H */
......@@ -25,6 +25,12 @@
* Author: AMD
*/
/* put it here temporarily until linux has the new addresses official defined */
/* 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
struct dc_dsc_bw_range {
uint32_t min_kbps; /* Bandwidth if min_target_bpp_x16 is used */
uint32_t min_target_bpp_x16;
......
......@@ -725,9 +725,12 @@ static bool setup_dsc_config(
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)
{
if (!dpcd_dsc_basic_data)
return false;
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;
return false;
dsc_sink_caps->dsc_version = dpcd_dsc_basic_data[DP_DSC_REV - DP_DSC_SUPPORT];
......
/*
* 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 dsc_passthrough_support :1; // Bit1
unsigned char reserved :6;
} 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_ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment