Blob Blame History Raw
From: Zeyu Fan <Zeyu.Fan@amd.com>
Date: Fri, 23 Dec 2016 16:53:12 -0500
Subject: drm/amd/display: Fix link retraining hw sequence
Git-commit: 886391680cce3b7c4543b88bbd4eb49c80c26532
Patch-mainline: v4.15-rc1
References: FATE#326289 FATE#326079 FATE#326049 FATE#322398 FATE#326166

Signed-off-by: Zeyu Fan <Zeyu.Fan@amd.com>
Reviewed-by: Hersen Wu <hersenxs.wu@amd.com>
Acked-by: Harry Wentland <Harry.Wentland@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Acked-by: Petr Tesarik <ptesarik@suse.com>
---
 drivers/gpu/drm/amd/display/dc/core/dc.c           |   15 +++---
 drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c |   49 ++++++++++++++++++++-
 drivers/gpu/drm/amd/display/dc/dc.h                |    3 -
 drivers/gpu/drm/amd/display/dc/inc/link_hwss.h     |    4 +
 4 files changed, 62 insertions(+), 9 deletions(-)

--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -357,17 +357,18 @@ static void perform_link_training(struct
 }
 
 static void set_preferred_link_settings(struct dc *dc,
-		struct dc_link_settings *link_setting)
+		struct dc_link_settings *link_setting,
+		const struct dc_link *link)
 {
-	struct core_dc *core_dc = DC_TO_CORE(dc);
-	int i;
+	struct core_link *core_link = DC_LINK_TO_CORE(link);
 
-	for (i = 0; i < core_dc->link_count; i++) {
-		core_dc->links[i]->public.verified_link_cap.lane_count =
+	core_link->public.verified_link_cap.lane_count =
 				link_setting->lane_count;
-		core_dc->links[i]->public.verified_link_cap.link_rate =
+	core_link->public.verified_link_cap.link_rate =
 				link_setting->link_rate;
-	}
+	dp_retrain_link_physi(core_link,
+			link_setting,
+			false);
 }
 
 static void enable_hpd(const struct dc_link *link)
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c
@@ -200,7 +200,6 @@ void dp_set_hw_test_pattern(
 	encoder->funcs->dp_set_phy_pattern(encoder, &pattern_param);
 }
 
-
 void dp_retrain_link(struct core_link *link)
 {
 	struct pipe_ctx *pipes = link->dc->current_context->res_ctx.pipe_ctx;
@@ -221,3 +220,51 @@ void dp_retrain_link(struct core_link *l
 		}
 	}
 }
+
+void dp_retrain_link_physi(struct core_link *link,
+			struct dc_link_settings *link_setting,
+			bool skip_video_pattern)
+{
+	struct pipe_ctx *pipes =
+			&link->dc->current_context->res_ctx.pipe_ctx[0];
+	unsigned int i;
+
+	for (i = 0; i < MAX_PIPES; i++) {
+		if (pipes[i].stream != NULL &&
+			pipes[i].stream->sink != NULL &&
+			pipes[i].stream->sink->link != NULL &&
+			pipes[i].stream_enc != NULL &&
+			pipes[i].stream->sink->link == link) {
+			dm_delay_in_microseconds(link->ctx, 100);
+
+			pipes[i].stream_enc->funcs->dp_blank(
+					pipes[i].stream_enc);
+
+			dp_receiver_power_ctrl(link, false);
+
+			link->link_enc->funcs->disable_output(
+					link->link_enc,
+					SIGNAL_TYPE_DISPLAY_PORT);
+
+			/* Clear current link setting.
+			 * memset(&link->public.cur_link_settings, 0,
+			 * 	sizeof(link->public.cur_link_settings));
+			 */
+
+			link->link_enc->funcs->enable_dp_output(
+						link->link_enc,
+						link_setting,
+						pipes[i].clock_source->id);
+
+			dp_receiver_power_ctrl(link, true);
+
+			dc_link_dp_perform_link_training(
+					&link->public,
+					link_setting,
+					skip_video_pattern);
+
+			link->dc->hwss.unblank_stream(&pipes[i],
+					link_setting);
+		}
+	}
+}
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -117,7 +117,8 @@ struct dc_link_funcs {
 			struct dc_link_settings *link_setting,
 			bool skip_video_pattern);
 	void (*set_preferred_link_settings)(struct dc *dc,
-			struct dc_link_settings *link_setting);
+			struct dc_link_settings *link_setting,
+			const struct dc_link *link);
 	void (*enable_hpd)(const struct dc_link *link);
 	void (*disable_hpd)(const struct dc_link *link);
 	void (*set_test_pattern)(
--- a/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h
@@ -70,4 +70,8 @@ enum dp_panel_mode dp_get_panel_mode(str
 
 void dp_retrain_link(struct core_link *link);
 
+void dp_retrain_link_physi(struct core_link *link,
+		struct dc_link_settings *link_setting,
+		bool skip_video_pattern);
+
 #endif /* __DC_LINK_HWSS_H__ */