drm/amd/display: dp mst detection code refactor

[why]
Move mst start top mgr in dc_link_detect layer.
Remove unused same_dpcd variable.
Move PEAK_FACTOR_X1000 and LINK_TRAINING_MAX_VERIFY_RETRY
to the proper header for defining dc link internal constant.

Signed-off-by: Wenjing Liu <wenjing.liu@amd.com>
Reviewed-by: George Shen <George.Shen@amd.com>
Acked-by: Anson Jacob <Anson.Jacob@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
Wenjing Liu 2021-05-14 14:39:55 -04:00 committed by Alex Deucher
parent a161f8cb67
commit 8a58e25b8b
2 changed files with 73 additions and 99 deletions

View file

@ -59,20 +59,6 @@
#define RETIMER_REDRIVER_INFO(...) \
DC_LOG_RETIMER_REDRIVER( \
__VA_ARGS__)
/*******************************************************************************
* Private structures
******************************************************************************/
enum {
PEAK_FACTOR_X1000 = 1006,
/*
* Some receivers fail to train on first try and are good
* on subsequent tries. 2 retries should be plenty. If we
* don't have a successful training then we don't expect to
* ever get one.
*/
LINK_TRAINING_MAX_VERIFY_RETRY = 2
};
/*******************************************************************************
* Private functions
@ -718,11 +704,9 @@ static void read_current_link_settings_on_detect(struct dc_link *link)
static bool detect_dp(struct dc_link *link,
struct display_sink_capability *sink_caps,
bool *converter_disable_audio,
struct audio_support *audio_support,
enum dc_detect_reason reason)
{
bool boot = false;
struct audio_support *audio_support = &link->dc->res_pool->audio_support;
sink_caps->signal = link_detect_sink(link, reason);
sink_caps->transaction_type =
@ -745,60 +729,12 @@ static bool detect_dp(struct dc_link *link,
* of this function). */
query_hdcp_capability(SIGNAL_TYPE_DISPLAY_PORT_MST, link);
#endif
/*
* This call will initiate MST topology discovery. Which
* will detect MST ports and add new DRM connector DRM
* framework. Then read EDID via remote i2c over aux. In
* the end, will notify DRM detect result and save EDID
* into DRM framework.
*
* .detect is called by .fill_modes.
* .fill_modes is called by user mode ioctl
* DRM_IOCTL_MODE_GETCONNECTOR.
*
* .get_modes is called by .fill_modes.
*
* call .get_modes, AMDGPU DM implementation will create
* new dc_sink and add to dc_link. For long HPD plug
* in/out, MST has its own handle.
*
* Therefore, just after dc_create, link->sink is not
* created for MST until user mode app calls
* DRM_IOCTL_MODE_GETCONNECTOR.
*
* Need check ->sink usages in case ->sink = NULL
* TODO: s3 resume check
*/
if (reason == DETECT_REASON_BOOT)
boot = true;
dm_helpers_dp_update_branch_info(link->ctx, link);
if (!dm_helpers_dp_mst_start_top_mgr(link->ctx,
link, boot)) {
/* MST not supported */
link->type = dc_connection_single;
sink_caps->signal = SIGNAL_TYPE_DISPLAY_PORT;
}
}
if (link->type != dc_connection_mst_branch &&
is_dp_branch_device(link)) {
is_dp_branch_device(link))
/* DP SST branch */
link->type = dc_connection_sst_branch;
if (!link->dpcd_caps.sink_count.bits.SINK_COUNT) {
/*
* SST branch unplug processing for short irq
*/
link_disconnect_sink(link);
return true;
}
if (is_dp_active_dongle(link) &&
(link->dpcd_caps.dongle_type !=
DISPLAY_DONGLE_DP_HDMI_CONVERTER))
*converter_disable_audio = true;
}
} else {
/* DP passive dongles */
sink_caps->signal = dp_passive_dongle_detection(link->ddc,
@ -893,7 +829,6 @@ static bool dc_link_detect_helper(struct dc_link *link,
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 pre_connection_type = dc_connection_none;
bool perform_dp_seamless_boot = false;
@ -984,35 +919,12 @@ static bool dc_link_detect_helper(struct dc_link *link,
return false;
}
if (!detect_dp(link, &sink_caps,
&converter_disable_audio,
aud_support, reason)) {
if (!detect_dp(link, &sink_caps, reason)) {
if (prev_sink)
dc_sink_release(prev_sink);
return false;
}
// Check if dpcp block is the same
if (prev_sink) {
if (memcmp(&link->dpcd_caps, &prev_dpcd_caps,
sizeof(struct dpcd_caps)))
same_dpcd = false;
}
/* Active SST downstream branch device unplug*/
if (link->type == dc_connection_sst_branch &&
link->dpcd_caps.sink_count.bits.SINK_COUNT == 0) {
if (prev_sink)
/* Downstream unplug */
dc_sink_release(prev_sink);
return true;
}
// link switch from MST to non-MST stop topology manager
if (pre_connection_type == dc_connection_mst_branch &&
link->type != dc_connection_mst_branch) {
dm_helpers_dp_mst_stop_top_mgr(link->ctx, link);
}
if (link->type == dc_connection_mst_branch) {
LINK_INFO("link=%d, mst branch is now Connected\n",
link->link_index);
@ -1023,15 +935,69 @@ static bool dc_link_detect_helper(struct dc_link *link,
*/
dp_verify_mst_link_cap(link);
if (prev_sink)
dc_sink_release(prev_sink);
return false;
/*
* This call will initiate MST topology discovery. Which
* will detect MST ports and add new DRM connector DRM
* framework. Then read EDID via remote i2c over aux. In
* the end, will notify DRM detect result and save EDID
* into DRM framework.
*
* .detect is called by .fill_modes.
* .fill_modes is called by user mode ioctl
* DRM_IOCTL_MODE_GETCONNECTOR.
*
* .get_modes is called by .fill_modes.
*
* call .get_modes, AMDGPU DM implementation will create
* new dc_sink and add to dc_link. For long HPD plug
* in/out, MST has its own handle.
*
* Therefore, just after dc_create, link->sink is not
* created for MST until user mode app calls
* DRM_IOCTL_MODE_GETCONNECTOR.
*
* Need check ->sink usages in case ->sink = NULL
* TODO: s3 resume check
*/
dm_helpers_dp_update_branch_info(link->ctx, link);
if (dm_helpers_dp_mst_start_top_mgr(link->ctx,
link, reason == DETECT_REASON_BOOT)) {
if (prev_sink)
dc_sink_release(prev_sink);
return false;
} else {
link->type = dc_connection_sst_branch;
sink_caps.signal = SIGNAL_TYPE_DISPLAY_PORT;
}
}
/* Active SST downstream branch device unplug*/
if (link->type == dc_connection_sst_branch &&
link->dpcd_caps.sink_count.bits.SINK_COUNT == 0) {
if (prev_sink)
/* Downstream unplug */
dc_sink_release(prev_sink);
return true;
}
/* disable audio for non DP to HDMI active sst converter */
if (link->type == dc_connection_sst_branch &&
is_dp_active_dongle(link) &&
(link->dpcd_caps.dongle_type !=
DISPLAY_DONGLE_DP_HDMI_CONVERTER))
converter_disable_audio = true;
// link switch from MST to non-MST stop topology manager
if (pre_connection_type == dc_connection_mst_branch &&
link->type != dc_connection_mst_branch)
dm_helpers_dp_mst_stop_top_mgr(link->ctx, link);
// For seamless boot, to skip verify link cap, we read UEFI settings and set them as verified.
if (reason == DETECT_REASON_BOOT &&
!dc_ctx->dc->config.power_down_display_on_boot &&
link->link_status.link_active)
!dc_ctx->dc->config.power_down_display_on_boot &&
link->link_status.link_active)
perform_dp_seamless_boot = true;
if (perform_dp_seamless_boot) {
@ -1214,11 +1180,11 @@ static bool dc_link_detect_helper(struct dc_link *link,
link->dongle_max_pix_clk = 0;
}
LINK_INFO("link=%d, dc_sink_in=%p is now %s prev_sink=%p dpcd same=%d edid same=%d\n",
LINK_INFO("link=%d, dc_sink_in=%p is now %s prev_sink=%p edid same=%d\n",
link->link_index, sink,
(sink_caps.signal ==
SIGNAL_TYPE_NONE ? "Disconnected" : "Connected"),
prev_sink, same_dpcd, same_edid);
prev_sink, same_edid);
if (prev_sink)
dc_sink_release(prev_sink);

View file

@ -42,7 +42,15 @@ enum {
/* to avoid infinite loop where-in the receiver
* switches between different VS
*/
LINK_TRAINING_MAX_CR_RETRY = 100
LINK_TRAINING_MAX_CR_RETRY = 100,
/*
* Some receivers fail to train on first try and are good
* on subsequent tries. 2 retries should be plenty. If we
* don't have a successful training then we don't expect to
* ever get one.
*/
LINK_TRAINING_MAX_VERIFY_RETRY = 2,
PEAK_FACTOR_X1000 = 1006,
};
bool dp_verify_link_cap(