aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/linux-yocto-4.14.71/3637-drm-amd-display-Update-Link-Training-Fallback-logic.patch
blob: 774161ecf6c1cc1a9817d2f71947b4838225b777 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
From cc0c2a51079948fa3be7123c1bb6f34faf9aa6b9 Mon Sep 17 00:00:00 2001
From: Wenjing Liu <Wenjing.Liu@amd.com>
Date: Fri, 16 Feb 2018 14:04:16 -0500
Subject: [PATCH 3637/4131] drm/amd/display: Update Link Training Fallback
 logic

[Description]
When CR fails to minimum link rate,
we should reduce lane count to the number lowest cr_done lanes.

[Code Review]
Jun Lei

Signed-off-by: Wenjing Liu <Wenjing.Liu@amd.com>
Reviewed-by: Tony Cheng <Tony.Cheng@amd.com>
Acked-by: Harry Wentland <harry.wentland@amd.com>
---
 drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c   | 98 ++++++++++++++++------
 drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c |  1 +
 .../drm/amd/display/include/link_service_types.h   |  5 +-
 3 files changed, 79 insertions(+), 25 deletions(-)

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 604fb01..4c21da5 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
@@ -709,6 +709,22 @@ static enum hw_dp_training_pattern get_supported_tp(struct dc_link *link)
 	return HW_DP_TRAINING_PATTERN_2;
 }
 
+static enum link_training_result get_cr_failure(enum dc_lane_count ln_count,
+					union lane_status *dpcd_lane_status)
+{
+	enum link_training_result result = LINK_TRAINING_SUCCESS;
+
+	if (ln_count >= LANE_COUNT_ONE && !dpcd_lane_status[0].bits.CR_DONE_0)
+		result = LINK_TRAINING_CR_FAIL_LANE0;
+	else if (ln_count >= LANE_COUNT_TWO && !dpcd_lane_status[1].bits.CR_DONE_0)
+		result = LINK_TRAINING_CR_FAIL_LANE1;
+	else if (ln_count >= LANE_COUNT_FOUR && !dpcd_lane_status[2].bits.CR_DONE_0)
+		result = LINK_TRAINING_CR_FAIL_LANE23;
+	else if (ln_count >= LANE_COUNT_FOUR && !dpcd_lane_status[3].bits.CR_DONE_0)
+		result = LINK_TRAINING_CR_FAIL_LANE23;
+	return result;
+}
+
 static enum link_training_result perform_channel_equalization_sequence(
 	struct dc_link *link,
 	struct link_training_settings *lt_settings)
@@ -771,7 +787,7 @@ static enum link_training_result perform_channel_equalization_sequence(
 
 }
 
-static bool perform_clock_recovery_sequence(
+static enum link_training_result perform_clock_recovery_sequence(
 	struct dc_link *link,
 	struct link_training_settings *lt_settings)
 {
@@ -846,11 +862,11 @@ static bool perform_clock_recovery_sequence(
 
 		/* 5. check CR done*/
 		if (is_cr_done(lane_count, dpcd_lane_status))
-			return true;
+			return LINK_TRAINING_SUCCESS;
 
 		/* 6. max VS reached*/
 		if (is_max_vs_reached(lt_settings))
-			return false;
+			break;
 
 		/* 7. same voltage*/
 		/* Note: VS same for all lanes,
@@ -876,13 +892,13 @@ static bool perform_clock_recovery_sequence(
 
 	}
 
-	return false;
+	return get_cr_failure(lane_count, dpcd_lane_status);
 }
 
-static inline bool perform_link_training_int(
+static inline enum link_training_result perform_link_training_int(
 	struct dc_link *link,
 	struct link_training_settings *lt_settings,
-	bool status)
+	enum link_training_result status)
 {
 	union lane_count_set lane_count_set = { {0} };
 	union dpcd_training_pattern dpcd_pattern = { {0} };
@@ -903,9 +919,9 @@ static inline bool perform_link_training_int(
 			get_supported_tp(link) == HW_DP_TRAINING_PATTERN_4)
 		return status;
 
-	if (status &&
+	if (status == LINK_TRAINING_SUCCESS &&
 		perform_post_lt_adj_req_sequence(link, lt_settings) == false)
-		status = false;
+		status = LINK_TRAINING_LQA_FAIL;
 
 	lane_count_set.bits.LANE_COUNT_SET = lt_settings->link_settings.lane_count;
 	lane_count_set.bits.ENHANCED_FRAMING = 1;
@@ -928,6 +944,8 @@ enum link_training_result dc_link_dp_perform_link_training(
 	enum link_training_result status = LINK_TRAINING_SUCCESS;
 
 	char *link_rate = "Unknown";
+	char *lt_result = "Unknown";
+
 	struct link_training_settings lt_settings;
 
 	memset(&lt_settings, '\0', sizeof(lt_settings));
@@ -951,22 +969,16 @@ enum link_training_result dc_link_dp_perform_link_training(
 
 	/* 2. perform link training (set link training done
 	 *  to false is done as well)*/
-	if (!perform_clock_recovery_sequence(link, &lt_settings)) {
-		status = LINK_TRAINING_CR_FAIL;
-	} else {
+	status = perform_clock_recovery_sequence(link, &lt_settings);
+	if (status == LINK_TRAINING_SUCCESS) {
 		status = perform_channel_equalization_sequence(link,
 				&lt_settings);
 	}
 
 	if ((status == LINK_TRAINING_SUCCESS) || !skip_video_pattern) {
-		if (!perform_link_training_int(link,
+		status = perform_link_training_int(link,
 				&lt_settings,
-				status == LINK_TRAINING_SUCCESS)) {
-			/* the next link training setting in this case
-			 * would be the same as CR failure case.
-			 */
-			status = LINK_TRAINING_CR_FAIL;
-		}
+				status);
 	}
 
 	/* 6. print status message*/
@@ -991,13 +1003,37 @@ enum link_training_result dc_link_dp_perform_link_training(
 		break;
 	}
 
+	switch (status) {
+	case LINK_TRAINING_SUCCESS:
+		lt_result = "pass";
+		break;
+	case LINK_TRAINING_CR_FAIL_LANE0:
+		lt_result = "CR failed lane0";
+		break;
+	case LINK_TRAINING_CR_FAIL_LANE1:
+		lt_result = "CR failed lane1";
+		break;
+	case LINK_TRAINING_CR_FAIL_LANE23:
+		lt_result = "CR failed lane23";
+		break;
+	case LINK_TRAINING_EQ_FAIL_CR:
+		lt_result = "CR failed in EQ";
+		break;
+	case LINK_TRAINING_EQ_FAIL_EQ:
+		lt_result = "EQ failed";
+		break;
+	case LINK_TRAINING_LQA_FAIL:
+		lt_result = "LQA failed";
+		break;
+	default:
+		break;
+	}
+
 	/* Connectivity log: link training */
 	CONN_MSG_LT(link, "%sx%d %s VS=%d, PE=%d",
 			link_rate,
 			lt_settings.link_settings.lane_count,
-			(status ==  LINK_TRAINING_SUCCESS) ? "pass" :
-			((status == LINK_TRAINING_CR_FAIL) ? "CR failed" :
-			"EQ failed"),
+			lt_result,
 			lt_settings.lane_settings[0].VOLTAGE_SWING,
 			lt_settings.lane_settings[0].PRE_EMPHASIS);
 
@@ -1115,6 +1151,7 @@ bool dp_hbr_verify_link_cap(
 				dp_cs_id,
 				cur);
 
+
 		if (skip_link_training)
 			success = true;
 		else {
@@ -1279,7 +1316,10 @@ static bool decide_fallback_link_setting(
 		return false;
 
 	switch (training_result) {
-	case LINK_TRAINING_CR_FAIL:
+	case LINK_TRAINING_CR_FAIL_LANE0:
+	case LINK_TRAINING_CR_FAIL_LANE1:
+	case LINK_TRAINING_CR_FAIL_LANE23:
+	case LINK_TRAINING_LQA_FAIL:
 	{
 		if (!reached_minimum_link_rate
 				(current_link_setting->link_rate)) {
@@ -1290,8 +1330,18 @@ static bool decide_fallback_link_setting(
 				(current_link_setting->lane_count)) {
 			current_link_setting->link_rate =
 				initial_link_settings.link_rate;
-			current_link_setting->lane_count =
-				reduce_lane_count(
+			if (training_result == LINK_TRAINING_CR_FAIL_LANE0)
+				return false;
+			else if (training_result == LINK_TRAINING_CR_FAIL_LANE1)
+				current_link_setting->lane_count =
+						LANE_COUNT_ONE;
+			else if (training_result ==
+					LINK_TRAINING_CR_FAIL_LANE23)
+				current_link_setting->lane_count =
+						LANE_COUNT_TWO;
+			else
+				current_link_setting->lane_count =
+					reduce_lane_count(
 					current_link_setting->lane_count);
 		} else {
 			return false;
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c
index bae9b05..7c866a7 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c
@@ -279,6 +279,7 @@ void dp_retrain_link_dp_test(struct dc_link *link,
 
 	for (i = 0; i < MAX_PIPES; i++) {
 		if (pipes[i].stream != NULL &&
+			!pipes[i].top_pipe &&
 			pipes[i].stream->sink != NULL &&
 			pipes[i].stream->sink->link != NULL &&
 			pipes[i].stream_res.stream_enc != NULL &&
diff --git a/drivers/gpu/drm/amd/display/include/link_service_types.h b/drivers/gpu/drm/amd/display/include/link_service_types.h
index adea1a5..80f0d93 100644
--- a/drivers/gpu/drm/amd/display/include/link_service_types.h
+++ b/drivers/gpu/drm/amd/display/include/link_service_types.h
@@ -58,11 +58,14 @@ enum {
 
 enum link_training_result {
 	LINK_TRAINING_SUCCESS,
-	LINK_TRAINING_CR_FAIL,
+	LINK_TRAINING_CR_FAIL_LANE0,
+	LINK_TRAINING_CR_FAIL_LANE1,
+	LINK_TRAINING_CR_FAIL_LANE23,
 	/* CR DONE bit is cleared during EQ step */
 	LINK_TRAINING_EQ_FAIL_CR,
 	/* other failure during EQ step */
 	LINK_TRAINING_EQ_FAIL_EQ,
+	LINK_TRAINING_LQA_FAIL,
 };
 
 struct link_training_settings {
-- 
2.7.4