aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/files/0682-drm-amd-dal-Split-sinks-into-physical-sink-pointer-a.patch
blob: 0a94c886115170e228fd0a0f34bc1f9d670427eb (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
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
From b92469fcc4bf7e3291852123f38c4f66c6d58545 Mon Sep 17 00:00:00 2001
From: Andrey Grodzovsky <Andrey.Grodzovsky@amd.com>
Date: Fri, 8 Jan 2016 16:28:50 -0500
Subject: [PATCH 0682/1110] drm/amd/dal: Split sinks into physical sink pointer
 and array of sinks for MST

Signed-off-by: Andrey Grodzovsky <Andrey.Grodzovsky@amd.com>
Acked-by: Jordan Lazare <Jordan.Lazare@amd.com>
---
 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.c      | 38 +++-------------------
 .../drm/amd/dal/amdgpu_dm/amdgpu_dm_mst_types.c    |  8 ++---
 drivers/gpu/drm/amd/dal/dc/core/dc.c               | 12 +++----
 drivers/gpu/drm/amd/dal/dc/core/dc_link.c          | 26 +++++----------
 drivers/gpu/drm/amd/dal/dc/dc.h                    |  7 ++--
 .../drm/amd/dal/dc/dce_base/dce_base_resource.c    |  6 +++-
 6 files changed, 31 insertions(+), 66 deletions(-)

diff --git a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.c
index a98d1dd..118821d 100644
--- a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.c
@@ -698,47 +698,19 @@ static struct drm_mode_config_funcs amdgpu_dm_mode_funcs = {
 	.atomic_commit = amdgpu_dm_atomic_commit
 };
 
-static bool dm_get_sink_from_link(const struct dc_link *link,
-						struct amdgpu_connector *aconnector,
-						const struct dc_sink **sink)
-{
-	int i;
-	*sink = NULL;
-
-	if (!link->sink_count) {
-		DRM_INFO("No sinks on link!\n");
-		return true;
-	} else if (link->sink_count > 1 && !aconnector) {
-		DRM_ERROR("Multi sink link but no connector given!\n");
-		return false;
-	}
-
-	if (link->sink_count == 1) {
-		*sink = link->sink[0];
-		return true;
-	}
-
-	for (i = 0; i < link->sink_count; i++)
-		if (aconnector->dc_sink == link->sink[i])
-			*sink =  aconnector->dc_sink;
-
-	return true;
-}
 
 void amdgpu_dm_update_connector_after_detect(
 	struct amdgpu_connector *aconnector)
 {
 	struct drm_connector *connector = &aconnector->base;
 	struct drm_device *dev = connector->dev;
-	const struct dc_link *dc_link = aconnector->dc_link;
 	const struct dc_sink *sink;
 
 	/* MST handled by drm_mst framework */
 	if (aconnector->mst_mgr.mst_state == true)
 		return;
 
-	if (!dm_get_sink_from_link(dc_link, aconnector, &sink))
-		return;
+	sink = aconnector->dc_link->local_sink;
 
 	/*
 	 * TODO: temporary guard to look for proper fix
@@ -789,13 +761,11 @@ static void handle_hpd_irq(void *param)
 	struct amdgpu_connector *aconnector = (struct amdgpu_connector *)param;
 	struct drm_connector *connector = &aconnector->base;
 	struct drm_device *dev = connector->dev;
-	bool mst_connector = aconnector->mst_mgr.mst_state;
 
 	dc_link_detect(aconnector->dc_link);
-	/*Wait for complition of all MST connectors reset
-	 * so the link is clean from sinks. */
-	if (mst_connector && aconnector->dc_link->type == dc_connection_none)
-		flush_work(&aconnector->mst_mgr.destroy_connector_work);
+	if (aconnector->dc_link->type == dc_connection_mst_branch)
+		return;
+
 	amdgpu_dm_update_connector_after_detect(aconnector);
 	drm_kms_helper_hotplug_event(dev);
 }
diff --git a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_mst_types.c
index 61e12ad..88b9730 100644
--- a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_mst_types.c
+++ b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -147,7 +147,7 @@ static struct dc_sink *dm_dp_mst_add_mst_sink(
 	dc_service_memmove(dc_sink->dc_edid.raw_edid, edid, len);
 	dc_sink->dc_edid.length = len;
 
-	if (!dc_link_add_sink(
+	if (!dc_link_add_remote_sink(
 			dc_link,
 			dc_sink))
 		goto fail_add_sink;
@@ -163,7 +163,7 @@ static struct dc_sink *dm_dp_mst_add_mst_sink(
 
 	return dc_sink;
 fail:
-	dc_link_remove_sink(dc_link, dc_sink);
+	dc_link_remove_remote_sink(dc_link, dc_sink);
 fail_add_sink:
 	return NULL;
 }
@@ -190,7 +190,7 @@ static int dm_dp_mst_get_modes(struct drm_connector *connector)
 		aconnector->edid = edid;
 
 		if (aconnector->dc_sink)
-			dc_link_remove_sink(
+			dc_link_remove_remote_sink(
 				aconnector->dc_link,
 				aconnector->dc_sink);
 
@@ -354,7 +354,7 @@ static void dm_dp_destroy_mst_connector(
 
 	aconnector->port = NULL;
 	if (aconnector->dc_sink)
-		dc_link_remove_sink(aconnector->dc_link, aconnector->dc_sink);
+		dc_link_remove_remote_sink(aconnector->dc_link, aconnector->dc_sink);
 }
 
 static void dm_dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr)
diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc.c b/drivers/gpu/drm/amd/dal/dc/core/dc.c
index 397b664..e003f78 100644
--- a/drivers/gpu/drm/amd/dal/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/dal/dc/core/dc.c
@@ -838,7 +838,7 @@ bool dc_write_dpcd(
 	return r == DDC_RESULT_SUCESSFULL;
 }
 
-bool dc_link_add_sink(const struct dc_link *link, struct dc_sink *sink)
+bool dc_link_add_remote_sink(const struct dc_link *link, struct dc_sink *sink)
 {
 	struct core_link *core_link = DC_LINK_TO_LINK(link);
 	struct dc_link *dc_link = &core_link->public;
@@ -848,7 +848,7 @@ bool dc_link_add_sink(const struct dc_link *link, struct dc_sink *sink)
 		return false;
 	}
 
-	dc_link->sink[link->sink_count] = sink;
+	dc_link->remote_sinks[link->sink_count] = sink;
 	dc_link->sink_count++;
 	if (sink->sink_signal == SIGNAL_TYPE_VIRTUAL
 		&& link->connector_signal == SIGNAL_TYPE_VIRTUAL)
@@ -858,7 +858,7 @@ bool dc_link_add_sink(const struct dc_link *link, struct dc_sink *sink)
 }
 
 
-void dc_link_remove_sink(const struct dc_link *link, const struct dc_sink *sink)
+void dc_link_remove_remote_sink(const struct dc_link *link, const struct dc_sink *sink)
 {
 	int i;
 	struct core_link *core_link = DC_LINK_TO_LINK(link);
@@ -870,13 +870,13 @@ void dc_link_remove_sink(const struct dc_link *link, const struct dc_sink *sink)
 	}
 
 	for (i = 0; i < dc_link->sink_count; i++) {
-		if (dc_link->sink[i] == sink) {
+		if (dc_link->remote_sinks[i] == sink) {
 			dc_sink_release(sink);
-			dc_link->sink[i] = NULL;
+			dc_link->remote_sinks[i] = NULL;
 
 			/* shrink array to remove empty place */
 			while (i < dc_link->sink_count - 1) {
-				dc_link->sink[i] = dc_link->sink[i+1];
+				dc_link->remote_sinks[i] = dc_link->remote_sinks[i+1];
 				i++;
 			}
 
diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_link.c b/drivers/gpu/drm/amd/dal/dc/core/dc_link.c
index 2ef0451..c5ff145 100644
--- a/drivers/gpu/drm/amd/dal/dc/core/dc_link.c
+++ b/drivers/gpu/drm/amd/dal/dc/core/dc_link.c
@@ -427,15 +427,12 @@ static bool is_dp_active_dongle(enum display_dongle_type dongle_type)
 		dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER);
 }
 
-static void link_disconnect_all_sinks(struct core_link *link)
+static void link_disconnect_sink(struct core_link *link)
 {
-	/*
-	 * as sink_count changed inside dc_link_remove_sink, we should not
-	 * use it for range check for loop, because half of sinks will not
-	 * be removed
-	 */
-	while (link->public.sink_count)
-		dc_link_remove_sink(&link->public, link->public.sink[0]);
+	if (link->public.local_sink) {
+		dc_sink_release(link->public.local_sink);
+		link->public.local_sink = NULL;
+	}
 
 	link->dpcd_sink_count = 0;
 }
@@ -496,7 +493,7 @@ static void dc_link_detect_dp(
 				/*
 				 * active dongle unplug processing for short irq
 				 */
-				link_disconnect_all_sinks(link);
+				link_disconnect_sink(link);
 				return;
 			}
 
@@ -574,10 +571,7 @@ void dc_link_detect(const struct dc_link *dc_link)
 		return;
 	}
 
-	/* Free existing state before doing detection on SST
-	 * TODO: For MST, need to investigate if the same is required. */
-	if (link->public.type != dc_connection_mst_branch)
-		link_disconnect_all_sinks(link);
+	link_disconnect_sink(link);
 
 	if (new_connection_type != dc_connection_none) {
 		link->public.type = new_connection_type;
@@ -657,11 +651,7 @@ void dc_link_detect(const struct dc_link *dc_link)
 		}
 
 		sink = DC_SINK_TO_CORE(dc_sink);
-
-		/*AG TODO handle failure */
-		/*Only non MST case here */
-		if (!dc_link_add_sink(&link->public, &sink->public))
-				BREAK_TO_DEBUGGER();
+		link->public.local_sink = &sink->public;
 
 		edid_status = read_edid(link, sink);
 
diff --git a/drivers/gpu/drm/amd/dal/dc/dc.h b/drivers/gpu/drm/amd/dal/dc/dc.h
index bcfd96d..df7e34b 100644
--- a/drivers/gpu/drm/amd/dal/dc/dc.h
+++ b/drivers/gpu/drm/amd/dal/dc/dc.h
@@ -272,8 +272,9 @@ void dc_update_stream(const struct dc_stream *dc_stream,
  * The currently active signal type (HDMI, DP-SST, DP-MST) is also reported.
  */
 struct dc_link {
-	const struct dc_sink *sink[MAX_SINKS_PER_LINK];
+	const struct dc_sink *remote_sinks[MAX_SINKS_PER_LINK];
 	unsigned int sink_count;
+	const struct dc_sink *local_sink;
 	unsigned int link_index;
 	enum dc_connection_type type;
 	enum signal_type connector_signal;
@@ -306,9 +307,9 @@ void dc_link_detect(const struct dc_link *dc_link);
  * from DM. */
 bool dc_link_handle_hpd_rx_irq(const struct dc_link *dc_link);
 
-bool dc_link_add_sink(const struct dc_link *link, struct dc_sink *sink);
+bool dc_link_add_remote_sink(const struct dc_link *link, struct dc_sink *sink);
 
-void dc_link_remove_sink(
+void dc_link_remove_remote_sink(
 	const struct dc_link *link,
 	const struct dc_sink *sink);
 
diff --git a/drivers/gpu/drm/amd/dal/dc/dce_base/dce_base_resource.c b/drivers/gpu/drm/amd/dal/dc/dce_base/dce_base_resource.c
index 85cff3b..0907f3c 100644
--- a/drivers/gpu/drm/amd/dal/dc/dce_base/dce_base_resource.c
+++ b/drivers/gpu/drm/amd/dal/dc/dce_base/dce_base_resource.c
@@ -93,6 +93,7 @@ static struct stream_encoder *find_first_free_match_stream_enc_for_link(
 {
 	uint8_t i;
 	int8_t j = -1;
+	const struct dc_sink *sink = NULL;
 
 	for (i = 0; i < res_ctx->pool.stream_enc_count; i++) {
 		if (!res_ctx->is_stream_enc_acquired[i] &&
@@ -118,7 +119,10 @@ static struct stream_encoder *find_first_free_match_stream_enc_for_link(
 	 * TODO - This is just a patch up and a generic solution is
 	 * required for non DP connectors.
 	 */
-	if (j >= 0 &&  dc_is_dp_signal(link->public.sink[0]->sink_signal))
+
+	sink = link->public.local_sink ? link->public.local_sink : link->public.remote_sinks[0];
+
+	if (sink && j >= 0 &&  dc_is_dp_signal(sink->sink_signal))
 		return res_ctx->pool.stream_enc[j];
 
 	return NULL;
-- 
2.7.4