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;
{
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);
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).
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,
*/
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,
}
}
+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,
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));
+}
#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
#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
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;
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 */
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;
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_ */