[PATCH 05/24] drm/amd/display: dp mst detection code refactor
Anson Jacob
Anson.Jacob at amd.com
Thu Jun 10 16:28:19 UTC 2021
From: Wenjing Liu <wenjing.liu at amd.com>
[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 at amd.com>
Reviewed-by: George Shen <George.Shen at amd.com>
Acked-by: Anson Jacob <Anson.Jacob at amd.com>
---
drivers/gpu/drm/amd/display/dc/core/dc_link.c | 156 +++++++-----------
.../gpu/drm/amd/display/dc/inc/dc_link_dp.h | 10 +-
2 files changed, 70 insertions(+), 96 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 33e83c033284..05c963a5b789 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
@@ -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,20 +919,59 @@ 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;
+ if (link->type == dc_connection_mst_branch) {
+ LINK_INFO("link=%d, mst branch is now Connected\n",
+ link->link_index);
+ /* Need to setup mst link_cap struct here
+ * otherwise dc_link_detect() will leave mst link_cap
+ * empty which leads to allocate_mst_payload() has "0"
+ * pbn_per_slot value leading to exception on dc_fixpt_div()
+ */
+ dp_verify_mst_link_cap(link);
+
+ /*
+ * 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) {
@@ -1007,31 +981,23 @@ static bool dc_link_detect_helper(struct dc_link *link,
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) {
+ 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);
- /* Need to setup mst link_cap struct here
- * otherwise dc_link_detect() will leave mst link_cap
- * empty which leads to allocate_mst_payload() has "0"
- * pbn_per_slot value leading to exception on dc_fixpt_div()
- */
- dp_verify_mst_link_cap(link);
-
- if (prev_sink)
- dc_sink_release(prev_sink);
- return false;
- }
// 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);
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 883c3af51022..dd38dd63697f 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
@@ -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(
--
2.25.1
More information about the amd-gfx
mailing list