Commit eb815442 authored by Samson Tam's avatar Samson Tam Committed by Alex Deucher

drm/amd/display: don't create new dc_sink if nothing changed at detection

Signed-off-by: default avatarSamson Tam <Samson.Tam@amd.com>
Reviewed-by: default avatarAric Cyr <Aric.Cyr@amd.com>
Acked-by: default avatarHarry Wentland <harry.wentland@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 5103c568
...@@ -469,6 +469,13 @@ static void link_disconnect_sink(struct dc_link *link) ...@@ -469,6 +469,13 @@ static void link_disconnect_sink(struct dc_link *link)
link->dpcd_sink_count = 0; link->dpcd_sink_count = 0;
} }
static void link_disconnect_remap(struct dc_sink *prev_sink, struct dc_link *link)
{
dc_sink_release(link->local_sink);
link->local_sink = prev_sink;
}
static bool detect_dp( static bool detect_dp(
struct dc_link *link, struct dc_link *link,
struct display_sink_capability *sink_caps, struct display_sink_capability *sink_caps,
...@@ -551,6 +558,17 @@ static bool detect_dp( ...@@ -551,6 +558,17 @@ static bool detect_dp(
return true; return true;
} }
static bool is_same_edid(struct dc_edid *old_edid, struct dc_edid *new_edid)
{
if (old_edid->length != new_edid->length)
return false;
if (new_edid->length == 0)
return false;
return (memcmp(old_edid->raw_edid, new_edid->raw_edid, new_edid->length) == 0);
}
bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
{ {
struct dc_sink_init_data sink_init_data = { 0 }; struct dc_sink_init_data sink_init_data = { 0 };
...@@ -558,9 +576,13 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) ...@@ -558,9 +576,13 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
uint8_t i; uint8_t i;
bool converter_disable_audio = false; bool converter_disable_audio = false;
struct audio_support *aud_support = &link->dc->res_pool->audio_support; struct audio_support *aud_support = &link->dc->res_pool->audio_support;
bool same_edid = false;
enum dc_edid_status edid_status; enum dc_edid_status edid_status;
struct dc_context *dc_ctx = link->ctx; struct dc_context *dc_ctx = link->ctx;
struct dc_sink *sink = NULL; struct dc_sink *sink = NULL;
struct dc_sink *prev_sink = NULL;
struct dpcd_caps prev_dpcd_caps;
bool same_dpcd = true;
enum dc_connection_type new_connection_type = dc_connection_none; enum dc_connection_type new_connection_type = dc_connection_none;
DC_LOGGER_INIT(link->ctx->logger); DC_LOGGER_INIT(link->ctx->logger);
if (link->connector_signal == SIGNAL_TYPE_VIRTUAL) if (link->connector_signal == SIGNAL_TYPE_VIRTUAL)
...@@ -575,6 +597,11 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) ...@@ -575,6 +597,11 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
link->local_sink) link->local_sink)
return true; return true;
prev_sink = link->local_sink;
if (prev_sink != NULL) {
dc_sink_retain(prev_sink);
memcpy(&prev_dpcd_caps, &link->dpcd_caps, sizeof(struct dpcd_caps));
}
link_disconnect_sink(link); link_disconnect_sink(link);
if (new_connection_type != dc_connection_none) { if (new_connection_type != dc_connection_none) {
...@@ -616,14 +643,25 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) ...@@ -616,14 +643,25 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
link, link,
&sink_caps, &sink_caps,
&converter_disable_audio, &converter_disable_audio,
aud_support, reason)) aud_support, reason)) {
if (prev_sink != NULL)
dc_sink_release(prev_sink);
return false; return false;
}
// Check if dpcp block is the same
if (prev_sink != NULL) {
if (memcmp(&link->dpcd_caps, &prev_dpcd_caps, sizeof(struct dpcd_caps)))
same_dpcd = false;
}
/* Active dongle downstream unplug */ /* Active dongle downstream unplug */
if (link->type == dc_connection_active_dongle if (link->type == dc_connection_active_dongle
&& link->dpcd_caps.sink_count. && link->dpcd_caps.sink_count.
bits.SINK_COUNT == 0) bits.SINK_COUNT == 0) {
if (prev_sink != NULL)
dc_sink_release(prev_sink);
return true; return true;
}
if (link->type == dc_connection_mst_branch) { if (link->type == dc_connection_mst_branch) {
LINK_INFO("link=%d, mst branch is now Connected\n", LINK_INFO("link=%d, mst branch is now Connected\n",
...@@ -634,6 +672,8 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) ...@@ -634,6 +672,8 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
* pbn_per_slot value leading to exception on dc_fixpt_div() * pbn_per_slot value leading to exception on dc_fixpt_div()
*/ */
link->verified_link_cap = link->reported_link_cap; link->verified_link_cap = link->reported_link_cap;
if (prev_sink != NULL)
dc_sink_release(prev_sink);
return false; return false;
} }
...@@ -643,6 +683,8 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) ...@@ -643,6 +683,8 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
default: default:
DC_ERROR("Invalid connector type! signal:%d\n", DC_ERROR("Invalid connector type! signal:%d\n",
link->connector_signal); link->connector_signal);
if (prev_sink != NULL)
dc_sink_release(prev_sink);
return false; return false;
} /* switch() */ } /* switch() */
...@@ -665,6 +707,8 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) ...@@ -665,6 +707,8 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
sink = dc_sink_create(&sink_init_data); sink = dc_sink_create(&sink_init_data);
if (!sink) { if (!sink) {
DC_ERROR("Failed to create sink!\n"); DC_ERROR("Failed to create sink!\n");
if (prev_sink != NULL)
dc_sink_release(prev_sink);
return false; return false;
} }
...@@ -688,22 +732,33 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) ...@@ -688,22 +732,33 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
break; break;
} }
if (link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT && // Check if edid is the same
sink_caps.transaction_type == if ((prev_sink != NULL) && ((edid_status == EDID_THE_SAME) || (edid_status == EDID_OK)))
DDC_TRANSACTION_TYPE_I2C_OVER_AUX) { same_edid = is_same_edid(&prev_sink->dc_edid, &sink->dc_edid);
/*
* TODO debug why Dell 2413 doesn't like
* two link trainings
*/
/* deal with non-mst cases */ // If both edid and dpcd are the same, then discard new sink and revert back to original sink
dp_hbr_verify_link_cap(link, &link->reported_link_cap); if ((same_edid) && (same_dpcd)) {
} link_disconnect_remap(prev_sink, link);
sink = prev_sink;
prev_sink = NULL;
} else {
if (link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT &&
sink_caps.transaction_type ==
DDC_TRANSACTION_TYPE_I2C_OVER_AUX) {
/*
* TODO debug why Dell 2413 doesn't like
* two link trainings
*/
/* deal with non-mst cases */
dp_hbr_verify_link_cap(link, &link->reported_link_cap);
}
/* HDMI-DVI Dongle */ /* HDMI-DVI Dongle */
if (sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A && if (sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A &&
!sink->edid_caps.edid_hdmi) !sink->edid_caps.edid_hdmi)
sink->sink_signal = SIGNAL_TYPE_DVI_SINGLE_LINK; sink->sink_signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
}
/* Connectivity log: detection */ /* Connectivity log: detection */
for (i = 0; i < sink->dc_edid.length / EDID_BLOCK_SIZE; i++) { for (i = 0; i < sink->dc_edid.length / EDID_BLOCK_SIZE; i++) {
...@@ -762,10 +817,14 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) ...@@ -762,10 +817,14 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
sink_caps.signal = SIGNAL_TYPE_NONE; sink_caps.signal = SIGNAL_TYPE_NONE;
} }
LINK_INFO("link=%d, dc_sink_in=%p is now %s\n", LINK_INFO("link=%d, dc_sink_in=%p is now %s prev_sink=%p dpcd same=%d edid same=%d\n",
link->link_index, sink, link->link_index, sink,
(sink_caps.signal == SIGNAL_TYPE_NONE ? (sink_caps.signal == SIGNAL_TYPE_NONE ?
"Disconnected":"Connected")); "Disconnected":"Connected"), prev_sink,
same_dpcd, same_edid);
if (prev_sink != NULL)
dc_sink_release(prev_sink);
return true; return true;
} }
......
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