Blob Blame History Raw
From 7047e2b27a1945c2f521d3f84f57972d0f4ffc9b Mon Sep 17 00:00:00 2001
From: Wenjing Liu <wenjing.liu@amd.com>
Date: Fri, 28 Jan 2022 22:04:01 +0800
Subject: drm/amd/display: refactor destructive verify link cap sequence
Git-commit: 2426d71c52876a5558b40af06143688b3978ddb2
Patch-mainline: v5.18-rc1
References: jsc#PED-1166 jsc#PED-1168 jsc#PED-1170 jsc#PED-1218 jsc#PED-1220 jsc#PED-1222 jsc#PED-1223 jsc#PED-1225

[how]
1. move decide det link training link resource before each link training.
2. move disable link for handling vbios case into set all streams
dpms off for link sequence.
3. extract usbc hotplug workaround into its own wa function.
4. Minor syntax changes to improve code readability.

Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Acked-by: Wayne Lin <wayne.lin@amd.com>
Signed-off-by: Wenjing Liu <wenjing.liu@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Acked-by: Patrik Jakobsson <pjakobsson@suse.de>
---
 drivers/gpu/drm/amd/display/dc/core/dc_link.c |  17 +--
 .../gpu/drm/amd/display/dc/core/dc_link_dp.c  | 134 +++++++-----------
 .../gpu/drm/amd/display/dc/core/dc_resource.c |  22 ++-
 .../gpu/drm/amd/display/dc/inc/dc_link_dp.h   |   7 -
 drivers/gpu/drm/amd/display/dc/inc/resource.h |   7 +-
 5 files changed, 83 insertions(+), 104 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 2c5d67abad3e..c99e06afc769 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
@@ -893,6 +893,7 @@ static void set_all_streams_dpms_off_for_link(struct dc_link *link)
 	struct pipe_ctx *pipe_ctx;
 	struct dc_stream_update stream_update;
 	bool dpms_off = true;
+	struct link_resource link_res = {0};
 
 	memset(&stream_update, 0, sizeof(stream_update));
 	stream_update.dpms_off = &dpms_off;
@@ -907,33 +908,29 @@ static void set_all_streams_dpms_off_for_link(struct dc_link *link)
 					link->ctx->dc->current_state);
 		}
 	}
+
+	/* link can be also enabled by vbios. In this case it is not recorded
+	 * in pipe_ctx. Disable link phy here to make sure it is completely off
+	 */
+	dp_disable_link_phy(link, &link_res, link->connector_signal);
 }
 
 static void verify_link_capability_destructive(struct dc_link *link,
 		struct dc_sink *sink,
 		enum dc_detect_reason reason)
 {
-	struct link_resource link_res = { 0 };
 	bool should_prepare_phy_clocks =
 			should_prepare_phy_clocks_for_link_verification(link->dc, reason);
 
 	if (should_prepare_phy_clocks)
 		prepare_phy_clocks_for_destructive_link_verification(link->dc);
 
-
 	if (dc_is_dp_signal(link->local_sink->sink_signal)) {
 		struct dc_link_settings known_limit_link_setting =
 				dp_get_max_link_cap(link);
-
 		set_all_streams_dpms_off_for_link(link);
-		if (dp_get_link_encoding_format(&known_limit_link_setting) ==
-				DP_128b_132b_ENCODING)
-			link_res.hpo_dp_link_enc = resource_get_hpo_dp_link_enc_for_det_lt(
-					&link->dc->current_state->res_ctx,
-					link->dc->res_pool,
-					link);
 		dp_verify_link_cap_with_retries(
-				link, &link_res, &known_limit_link_setting,
+				link, &known_limit_link_setting,
 				LINK_TRAINING_MAX_VERIFY_RETRY);
 	} else {
 		ASSERT(0);
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 18187a0cbf6c..9c44eb8901ee 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
@@ -97,6 +97,12 @@ static const struct dp_lt_fallback_entry dp_lt_fallbacks[] = {
 		{LANE_COUNT_ONE, LINK_RATE_LOW},
 };
 
+static const struct dc_link_settings fail_safe_link_settings = {
+		.lane_count = LANE_COUNT_ONE,
+		.link_rate = LINK_RATE_LOW,
+		.link_spread = LINK_SPREAD_DISABLED,
+};
+
 static bool decide_fallback_link_setting(
 		struct dc_link *link,
 		struct dc_link_settings initial_link_settings,
@@ -3182,25 +3188,22 @@ bool hpd_rx_irq_check_link_loss_status(
 	return return_code;
 }
 
-bool dp_verify_link_cap(
+static bool dp_verify_link_cap(
 	struct dc_link *link,
-	const struct link_resource *link_res,
 	struct dc_link_settings *known_limit_link_setting,
 	int *fail_count)
 {
-	struct dc_link_settings cur_link_setting = {0};
-	struct dc_link_settings *cur = &cur_link_setting;
+	struct dc_link_settings cur_link_settings = {0};
 	struct dc_link_settings initial_link_settings = *known_limit_link_setting;
-	bool success;
-	bool skip_link_training;
+	bool success = false;
 	bool skip_video_pattern;
-	enum clock_source_id dp_cs_id = CLOCK_SOURCE_ID_EXTERNAL;
+	enum clock_source_id dp_cs_id = get_clock_source_id(link);
 	enum link_training_result status;
 	union hpd_irq_data irq_data;
+	struct link_resource link_res;
 
 	memset(&irq_data, 0, sizeof(irq_data));
-	success = false;
-	skip_link_training = false;
+	cur_link_settings = initial_link_settings;
 
 	/* Grant extended timeout request */
 	if ((link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) && (link->dpcd_caps.lttpr_caps.max_ext_timeout > 0)) {
@@ -3209,100 +3212,72 @@ bool dp_verify_link_cap(
 		core_link_write_dpcd(link, DP_PHY_REPEATER_EXTENDED_WAIT_TIMEOUT, &grant, sizeof(grant));
 	}
 
-	/* TODO implement override and monitor patch later */
-
-	/* try to train the link from high to low to
-	 * find the physical link capability
-	 */
-	/* disable PHY done possible by BIOS, will be done by driver itself */
-	dp_disable_link_phy(link, link_res, link->connector_signal);
-
-	dp_cs_id = get_clock_source_id(link);
-
-	cur_link_setting = initial_link_settings;
-
-	/* Temporary Renoir-specific workaround for SWDEV-215184;
-	 * PHY will sometimes be in bad state on hotplugging display from certain USB-C dongle,
-	 * so add extra cycle of enabling and disabling the PHY before first link training.
-	 */
-	if (link->link_enc && link->link_enc->features.flags.bits.DP_IS_USB_C &&
-			link->dc->debug.usbc_combo_phy_reset_wa) {
-		dp_enable_link_phy(link, link_res, link->connector_signal, dp_cs_id, cur);
-		dp_disable_link_phy(link, link_res, link->connector_signal);
-	}
-
 	do {
-		skip_video_pattern = true;
-
-		if (cur->link_rate == LINK_RATE_LOW)
-			skip_video_pattern = false;
+		if (!get_temp_dp_link_res(link, &link_res, &cur_link_settings))
+			continue;
 
+		skip_video_pattern = cur_link_settings.link_rate != LINK_RATE_LOW;
 		dp_enable_link_phy(
 				link,
-				link_res,
+				&link_res,
 				link->connector_signal,
 				dp_cs_id,
-				cur);
+				&cur_link_settings);
 
+		status = dc_link_dp_perform_link_training(
+				link,
+				&link_res,
+				&cur_link_settings,
+				skip_video_pattern);
 
-		if (skip_link_training)
+		if (status == LINK_TRAINING_SUCCESS) {
 			success = true;
-		else {
-			status = dc_link_dp_perform_link_training(
+			udelay(1000);
+			if (read_hpd_rx_irq_data(link, &irq_data) == DC_OK &&
+					hpd_rx_irq_check_link_loss_status(
 							link,
-							link_res,
-							cur,
-							skip_video_pattern);
-			if (status == LINK_TRAINING_SUCCESS)
-				success = true;
-			else
+							&irq_data))
 				(*fail_count)++;
-		}
 
-		if (success) {
-			link->verified_link_cap = *cur;
-			udelay(1000);
-			if (read_hpd_rx_irq_data(link, &irq_data) == DC_OK)
-				if (hpd_rx_irq_check_link_loss_status(
-						link,
-						&irq_data))
-					(*fail_count)++;
+		} else {
+			(*fail_count)++;
 		}
-		/* always disable the link before trying another
-		 * setting or before returning we'll enable it later
-		 * based on the actual mode we're driving
-		 */
-		dp_disable_link_phy(link, link_res, link->connector_signal);
+		dp_disable_link_phy(link, &link_res, link->connector_signal);
 	} while (!success && decide_fallback_link_setting(link,
-			initial_link_settings, cur, status));
+			initial_link_settings, &cur_link_settings, status));
 
-	/* Link Training failed for all Link Settings
-	 *  (Lane Count is still unknown)
-	 */
-	if (!success) {
-		/* If all LT fails for all settings,
-		 * set verified = failed safe (1 lane low)
-		 */
-		link->verified_link_cap.lane_count = LANE_COUNT_ONE;
-		link->verified_link_cap.link_rate = LINK_RATE_LOW;
-
-		link->verified_link_cap.link_spread =
-		LINK_SPREAD_DISABLED;
-	}
+	link->verified_link_cap = success ?
+			cur_link_settings : fail_safe_link_settings;
+	return success;
+}
 
+static void apply_usbc_combo_phy_reset_wa(struct dc_link *link,
+		struct dc_link_settings *link_settings)
+{
+	/* Temporary Renoir-specific workaround PHY will sometimes be in bad
+	 * state on hotplugging display from certain USB-C dongle, so add extra
+	 * cycle of enabling and disabling the PHY before first link training.
+	 */
+	struct link_resource link_res = {0};
+	enum clock_source_id dp_cs_id = get_clock_source_id(link);
 
-	return success;
+	dp_enable_link_phy(link, &link_res, link->connector_signal,
+			dp_cs_id, link_settings);
+	dp_disable_link_phy(link, &link_res, link->connector_signal);
 }
 
 bool dp_verify_link_cap_with_retries(
 	struct dc_link *link,
-	const struct link_resource *link_res,
 	struct dc_link_settings *known_limit_link_setting,
 	int attempts)
 {
 	int i = 0;
 	bool success = false;
 
+	if (link->link_enc && link->link_enc->features.flags.bits.DP_IS_USB_C &&
+			link->dc->debug.usbc_combo_phy_reset_wa)
+		apply_usbc_combo_phy_reset_wa(link, known_limit_link_setting);
+
 	for (i = 0; i < attempts; i++) {
 		int fail_count = 0;
 		enum dc_connection_type type = dc_connection_none;
@@ -3310,12 +3285,9 @@ bool dp_verify_link_cap_with_retries(
 		memset(&link->verified_link_cap, 0,
 				sizeof(struct dc_link_settings));
 		if (!dc_link_detect_sink(link, &type) || type == dc_connection_none) {
-			link->verified_link_cap.lane_count = LANE_COUNT_ONE;
-			link->verified_link_cap.link_rate = LINK_RATE_LOW;
-			link->verified_link_cap.link_spread = LINK_SPREAD_DISABLED;
+			link->verified_link_cap = fail_safe_link_settings;
 			break;
-		} else if (dp_verify_link_cap(link, link_res,
-				known_limit_link_setting,
+		} else if (dp_verify_link_cap(link, known_limit_link_setting,
 				&fail_count) && fail_count == 0) {
 			success = true;
 			break;
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
index 226e49655cab..356d3eb2aec7 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
@@ -3183,9 +3183,9 @@ void get_audio_check(struct audio_info *aud_modes,
 	}
 }
 
-struct hpo_dp_link_encoder *resource_get_hpo_dp_link_enc_for_det_lt(
+static struct hpo_dp_link_encoder *get_temp_hpo_dp_link_enc(
 		const struct resource_context *res_ctx,
-		const struct resource_pool *pool,
+		const struct resource_pool *const pool,
 		const struct dc_link *link)
 {
 	struct hpo_dp_link_encoder *hpo_dp_link_enc = NULL;
@@ -3202,6 +3202,24 @@ struct hpo_dp_link_encoder *resource_get_hpo_dp_link_enc_for_det_lt(
 	return hpo_dp_link_enc;
 }
 
+bool get_temp_dp_link_res(struct dc_link *link,
+		struct link_resource *link_res,
+		struct dc_link_settings *link_settings)
+{
+	const struct dc *dc  = link->dc;
+	const struct resource_context *res_ctx = &dc->current_state->res_ctx;
+
+	memset(link_res, 0, sizeof(*link_res));
+
+	if (dp_get_link_encoding_format(link_settings) == DP_128b_132b_ENCODING) {
+		link_res->hpo_dp_link_enc = get_temp_hpo_dp_link_enc(res_ctx,
+				dc->res_pool, link);
+		if (!link_res->hpo_dp_link_enc)
+			return false;
+	}
+	return true;
+}
+
 void reset_syncd_pipes_from_disabled_pipes(struct dc *dc,
 		struct dc_state *context)
 {
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 3ed2dbbf5642..67286950fe5a 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
@@ -56,15 +56,8 @@ enum {
 
 struct dc_link_settings dp_get_max_link_cap(struct dc_link *link);
 
-bool dp_verify_link_cap(
-	struct dc_link *link,
-	const struct link_resource *link_res,
-	struct dc_link_settings *known_limit_link_setting,
-	int *fail_count);
-
 bool dp_verify_link_cap_with_retries(
 	struct dc_link *link,
-	const struct link_resource *link_res,
 	struct dc_link_settings *known_limit_link_setting,
 	int attempts);
 
diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h
index 2a123622564d..b2d09330de78 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/resource.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h
@@ -201,10 +201,9 @@ int get_num_mpc_splits(struct pipe_ctx *pipe);
 
 int get_num_odm_splits(struct pipe_ctx *pipe);
 
-struct hpo_dp_link_encoder *resource_get_hpo_dp_link_enc_for_det_lt(
-		const struct resource_context *res_ctx,
-		const struct resource_pool *pool,
-		const struct dc_link *link);
+bool get_temp_dp_link_res(struct dc_link *link,
+		struct link_resource *link_res,
+		struct dc_link_settings *link_settings);
 
 void reset_syncd_pipes_from_disabled_pipes(struct dc *dc,
 	struct dc_state *context);
-- 
2.38.1