summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_link.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c59
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_dp_types.h16
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_link.h7
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h3
6 files changed, 92 insertions, 0 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
index 08fbf0ab047a..47cced994bfb 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
@@ -1291,6 +1291,8 @@ static bool detect_link_and_local_sink(struct dc_link *link,
* Clear dongle_max_pix_clk on disconnect to fix this
*/
link->dongle_max_pix_clk = 0;
+
+ dc_link_dp_clear_rx_status(link);
}
LINK_INFO("link=%d, dc_sink_in=%p is now %s prev_sink=%p edid same=%d\n",
@@ -1970,6 +1972,9 @@ static enum dc_status enable_link_dp(struct dc_state *state,
if (link->dpcd_sink_ext_caps.raw != 0)
msleep(post_oui_delay);
+ // similarly, mode switch can cause loss of cable ID
+ dpcd_update_cable_id(link);
+
skip_video_pattern = true;
if (link_settings.link_rate == LINK_RATE_LOW)
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
index a514f19d8f8b..062bdbadc781 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
@@ -2981,6 +2981,20 @@ static enum dc_link_rate get_lttpr_max_link_rate(struct dc_link *link)
return lttpr_max_link_rate;
}
+static enum dc_link_rate get_cable_max_link_rate(struct dc_link *link)
+{
+ enum dc_link_rate cable_max_link_rate = LINK_RATE_HIGH3;
+
+ if (link->dpcd_caps.cable_attributes.bits.UHBR10_20_CAPABILITY & DP_UHBR20)
+ cable_max_link_rate = LINK_RATE_UHBR20;
+ else if (link->dpcd_caps.cable_attributes.bits.UHBR13_5_CAPABILITY)
+ cable_max_link_rate = LINK_RATE_UHBR13_5;
+ else if (link->dpcd_caps.cable_attributes.bits.UHBR10_20_CAPABILITY & DP_UHBR10)
+ cable_max_link_rate = LINK_RATE_UHBR10;
+
+ return cable_max_link_rate;
+}
+
bool dc_link_dp_get_max_link_enc_cap(const struct dc_link *link, struct dc_link_settings *max_link_enc_cap)
{
struct link_encoder *link_enc = NULL;
@@ -3009,8 +3023,10 @@ struct dc_link_settings dp_get_max_link_cap(struct dc_link *link)
{
struct dc_link_settings max_link_cap = {0};
enum dc_link_rate lttpr_max_link_rate;
+ enum dc_link_rate cable_max_link_rate;
struct link_encoder *link_enc = NULL;
+
link_enc = link_enc_cfg_get_link_enc(link);
ASSERT(link_enc);
@@ -3029,6 +3045,14 @@ struct dc_link_settings dp_get_max_link_cap(struct dc_link *link)
max_link_cap.link_spread)
max_link_cap.link_spread =
link->reported_link_cap.link_spread;
+
+ /* Lower link settings based on cable attributes */
+ cable_max_link_rate = get_cable_max_link_rate(link);
+
+ if (!link->dc->debug.ignore_cable_id &&
+ cable_max_link_rate < max_link_cap.link_rate)
+ max_link_cap.link_rate = cable_max_link_rate;
+
/*
* account for lttpr repeaters cap
* notes: repeaters do not snoop in the DPRX Capabilities addresses (3.6.3).
@@ -5059,6 +5083,13 @@ bool dp_retrieve_lttpr_cap(struct dc_link *link)
return is_lttpr_present;
}
+
+static bool is_usbc_connector(struct dc_link *link)
+{
+ return link->link_enc &&
+ link->link_enc->features.flags.bits.DP_IS_USB_C;
+}
+
static bool retrieve_link_cap(struct dc_link *link)
{
/* DP_ADAPTER_CAP - DP_DPCD_REV + 1 == 16 and also DP_DSC_BITS_PER_PIXEL_INC - DP_DSC_SUPPORT + 1 == 16,
@@ -5115,6 +5146,9 @@ static bool retrieve_link_cap(struct dc_link *link)
*/
msleep(post_oui_delay);
+ /* Read cable ID and update receiver */
+ dpcd_update_cable_id(link);
+
for (i = 0; i < read_dpcd_retry_cnt; i++) {
status = core_link_read_dpcd(
link,
@@ -6292,6 +6326,26 @@ void dpcd_set_source_specific_data(struct dc_link *link)
}
}
+void dpcd_update_cable_id(struct dc_link *link)
+{
+ if (!link->link_enc->features.flags.bits.IS_UHBR10_CAPABLE ||
+ link->dprx_status.cable_id_updated)
+ return;
+
+ /* Retrieve cable attributes */
+ if (!is_usbc_connector(link))
+ core_link_read_dpcd(link, DP_CABLE_ATTRIBUTES_UPDATED_BY_DPRX,
+ &link->dpcd_caps.cable_attributes.raw,
+ sizeof(uint8_t));
+
+ /* Update receiver with cable attributes */
+ core_link_write_dpcd(link, DP_CABLE_ATTRIBUTES_UPDATED_BY_DPTX,
+ &link->dpcd_caps.cable_attributes.raw,
+ sizeof(link->dpcd_caps.cable_attributes.raw));
+
+ link->dprx_status.cable_id_updated = 1;
+}
+
bool dc_link_set_backlight_level_nits(struct dc_link *link,
bool isHDR,
uint32_t backlight_millinits,
@@ -6689,3 +6743,8 @@ void edp_panel_backlight_power_on(struct dc_link *link)
if (link->dc->hwss.edp_backlight_control)
link->dc->hwss.edp_backlight_control(link, true);
}
+
+void dc_link_dp_clear_rx_status(struct dc_link *link)
+{
+ memset(&link->dprx_status, 0, sizeof(link->dprx_status));
+}
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
index ff5093e52f2d..0dc183d6af5d 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -687,6 +687,7 @@ struct dc_debug_options {
bool set_mst_en_for_sst;
bool disable_uhbr;
bool force_dp2_lt_fallback_method;
+ bool ignore_cable_id;
union mem_low_power_enable_options enable_mem_low_power;
union root_clock_optimization_options root_clock_optimization;
bool hpo_optimization;
@@ -1234,6 +1235,7 @@ struct dpcd_caps {
union dp_main_line_channel_coding_cap channel_coding_cap;
union dp_sink_video_fallback_formats fallback_formats;
union dp_fec_capability1 fec_cap1;
+ union dp_cable_attributes cable_attributes;
};
union dpcd_sink_ext_caps {
diff --git a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h
index 7b1103e9f7a2..772084406795 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h
@@ -901,6 +901,9 @@ struct dpcd_usb4_dp_tunneling_info {
#ifndef DP_LINK_SQUARE_PATTERN
#define DP_LINK_SQUARE_PATTERN 0x10F
#endif
+#ifndef DP_CABLE_ATTRIBUTES_UPDATED_BY_DPTX
+#define DP_CABLE_ATTRIBUTES_UPDATED_BY_DPTX 0x110
+#endif
#ifndef DP_DSC_CONFIGURATION
#define DP_DSC_CONFIGURATION 0x161
#endif
@@ -913,6 +916,9 @@ struct dpcd_usb4_dp_tunneling_info {
#ifndef DP_128b_132b_TRAINING_AUX_RD_INTERVAL
#define DP_128b_132b_TRAINING_AUX_RD_INTERVAL 0x2216
#endif
+#ifndef DP_CABLE_ATTRIBUTES_UPDATED_BY_DPRX
+#define DP_CABLE_ATTRIBUTES_UPDATED_BY_DPRX 0x2217
+#endif
#ifndef DP_TEST_264BIT_CUSTOM_PATTERN_7_0
#define DP_TEST_264BIT_CUSTOM_PATTERN_7_0 0X2230
#endif
@@ -1012,6 +1018,16 @@ union dp_fec_capability1 {
uint8_t raw;
};
+union dp_cable_attributes {
+ struct {
+ uint8_t UHBR10_20_CAPABILITY :2;
+ uint8_t UHBR13_5_CAPABILITY :1;
+ uint8_t CABLE_TYPE :3;
+ uint8_t RESERVED :2;
+ } bits;
+ uint8_t raw;
+};
+
struct dp_color_depth_caps {
uint8_t support_6bpc :1;
uint8_t support_8bpc :1;
diff --git a/drivers/gpu/drm/amd/display/dc/dc_link.h b/drivers/gpu/drm/amd/display/dc/dc_link.h
index 9014c0a0a63b..b1c79b3f26aa 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_link.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_link.h
@@ -43,6 +43,10 @@ struct dc_link_status {
struct dpcd_caps *dpcd_caps;
};
+struct dp_receiver_status {
+ bool cable_id_updated;
+};
+
/* DP MST stream allocation (payload bandwidth number) */
struct link_mst_stream_allocation {
/* DIG front */
@@ -201,6 +205,7 @@ struct dc_link {
struct link_mst_stream_allocation_table mst_stream_alloc_table;
struct dc_link_status link_status;
+ struct dp_receiver_status dprx_status;
struct link_trace link_trace;
struct gpio *hpd_gpio;
@@ -459,4 +464,6 @@ const struct link_resource *dc_link_get_cur_link_res(const struct dc_link *link)
void dc_get_cur_link_res_map(const struct dc *dc, uint32_t *map);
/* restore link resource allocation state from a snapshot */
void dc_restore_link_res_map(const struct dc *dc, uint32_t *map);
+
+void dc_link_dp_clear_rx_status(struct dc_link *link);
#endif /* DC_LINK_H_ */
diff --git a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h
index b7c5c42d67ed..3ed2dbbf5642 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h
@@ -112,6 +112,9 @@ void dp_set_panel_mode(struct dc_link *link, enum dp_panel_mode panel_mode);
bool dp_overwrite_extended_receiver_cap(struct dc_link *link);
void dpcd_set_source_specific_data(struct dc_link *link);
+
+void dpcd_update_cable_id(struct dc_link *link);
+
/* Write DPCD link configuration data. */
enum dc_status dpcd_set_link_settings(
struct dc_link *link,