]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
Merge branch 'sched-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[mirror_ubuntu-bionic-kernel.git] / drivers / gpu / drm / amd / display / amdgpu_dm / amdgpu_dm_mst_types.c
1 /*
2 * Copyright 2012-15 Advanced Micro Devices, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: AMD
23 *
24 */
25
26 #include <linux/version.h>
27 #include <drm/drm_atomic_helper.h>
28 #include "dm_services.h"
29 #include "amdgpu.h"
30 #include "amdgpu_dm.h"
31 #include "amdgpu_dm_mst_types.h"
32
33 #include "dc.h"
34 #include "dm_helpers.h"
35
36 #include "dc_link_ddc.h"
37
38 /* #define TRACE_DPCD */
39
40 #ifdef TRACE_DPCD
41 #define SIDE_BAND_MSG(address) (address >= DP_SIDEBAND_MSG_DOWN_REQ_BASE && address < DP_SINK_COUNT_ESI)
42
43 static inline char *side_band_msg_type_to_str(uint32_t address)
44 {
45 static char str[10] = {0};
46
47 if (address < DP_SIDEBAND_MSG_UP_REP_BASE)
48 strcpy(str, "DOWN_REQ");
49 else if (address < DP_SIDEBAND_MSG_DOWN_REP_BASE)
50 strcpy(str, "UP_REP");
51 else if (address < DP_SIDEBAND_MSG_UP_REQ_BASE)
52 strcpy(str, "DOWN_REP");
53 else
54 strcpy(str, "UP_REQ");
55
56 return str;
57 }
58
59 static void log_dpcd(uint8_t type,
60 uint32_t address,
61 uint8_t *data,
62 uint32_t size,
63 bool res)
64 {
65 DRM_DEBUG_KMS("Op: %s, addr: %04x, SideBand Msg: %s, Op res: %s\n",
66 (type == DP_AUX_NATIVE_READ) ||
67 (type == DP_AUX_I2C_READ) ?
68 "Read" : "Write",
69 address,
70 SIDE_BAND_MSG(address) ?
71 side_band_msg_type_to_str(address) : "Nop",
72 res ? "OK" : "Fail");
73
74 if (res) {
75 print_hex_dump(KERN_INFO, "Body: ", DUMP_PREFIX_NONE, 16, 1, data, size, false);
76 }
77 }
78 #endif
79
80 static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux,
81 struct drm_dp_aux_msg *msg)
82 {
83 enum i2c_mot_mode mot = (msg->request & DP_AUX_I2C_MOT) ?
84 I2C_MOT_TRUE : I2C_MOT_FALSE;
85 enum ddc_result res;
86
87 switch (msg->request & ~DP_AUX_I2C_MOT) {
88 case DP_AUX_NATIVE_READ:
89 res = dal_ddc_service_read_dpcd_data(
90 TO_DM_AUX(aux)->ddc_service,
91 false,
92 I2C_MOT_UNDEF,
93 msg->address,
94 msg->buffer,
95 msg->size);
96 break;
97 case DP_AUX_NATIVE_WRITE:
98 res = dal_ddc_service_write_dpcd_data(
99 TO_DM_AUX(aux)->ddc_service,
100 false,
101 I2C_MOT_UNDEF,
102 msg->address,
103 msg->buffer,
104 msg->size);
105 break;
106 case DP_AUX_I2C_READ:
107 res = dal_ddc_service_read_dpcd_data(
108 TO_DM_AUX(aux)->ddc_service,
109 true,
110 mot,
111 msg->address,
112 msg->buffer,
113 msg->size);
114 break;
115 case DP_AUX_I2C_WRITE:
116 res = dal_ddc_service_write_dpcd_data(
117 TO_DM_AUX(aux)->ddc_service,
118 true,
119 mot,
120 msg->address,
121 msg->buffer,
122 msg->size);
123 break;
124 default:
125 return 0;
126 }
127
128 #ifdef TRACE_DPCD
129 log_dpcd(msg->request,
130 msg->address,
131 msg->buffer,
132 msg->size,
133 r == DDC_RESULT_SUCESSFULL);
134 #endif
135
136 return msg->size;
137 }
138
139 static enum drm_connector_status
140 dm_dp_mst_detect(struct drm_connector *connector, bool force)
141 {
142 struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
143 struct amdgpu_dm_connector *master = aconnector->mst_port;
144
145 enum drm_connector_status status =
146 drm_dp_mst_detect_port(
147 connector,
148 &master->mst_mgr,
149 aconnector->port);
150
151 return status;
152 }
153
154 static void
155 dm_dp_mst_connector_destroy(struct drm_connector *connector)
156 {
157 struct amdgpu_dm_connector *amdgpu_dm_connector = to_amdgpu_dm_connector(connector);
158 struct amdgpu_encoder *amdgpu_encoder = amdgpu_dm_connector->mst_encoder;
159
160 drm_encoder_cleanup(&amdgpu_encoder->base);
161 kfree(amdgpu_encoder);
162 drm_connector_cleanup(connector);
163 kfree(amdgpu_dm_connector);
164 }
165
166 static const struct drm_connector_funcs dm_dp_mst_connector_funcs = {
167 .detect = dm_dp_mst_detect,
168 .fill_modes = drm_helper_probe_single_connector_modes,
169 .destroy = dm_dp_mst_connector_destroy,
170 .reset = amdgpu_dm_connector_funcs_reset,
171 .atomic_duplicate_state = amdgpu_dm_connector_atomic_duplicate_state,
172 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
173 .atomic_set_property = amdgpu_dm_connector_atomic_set_property,
174 .atomic_get_property = amdgpu_dm_connector_atomic_get_property
175 };
176
177 static int dm_connector_update_modes(struct drm_connector *connector,
178 struct edid *edid)
179 {
180 int ret;
181
182 ret = drm_add_edid_modes(connector, edid);
183 drm_edid_to_eld(connector, edid);
184
185 return ret;
186 }
187
188 void dm_dp_mst_dc_sink_create(struct drm_connector *connector)
189 {
190 struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
191 struct edid *edid;
192 struct dc_sink *dc_sink;
193 struct dc_sink_init_data init_params = {
194 .link = aconnector->dc_link,
195 .sink_signal = SIGNAL_TYPE_DISPLAY_PORT_MST };
196
197 edid = drm_dp_mst_get_edid(connector, &aconnector->mst_port->mst_mgr, aconnector->port);
198
199 if (!edid) {
200 drm_mode_connector_update_edid_property(
201 &aconnector->base,
202 NULL);
203 return;
204 }
205
206 aconnector->edid = edid;
207
208 dc_sink = dc_link_add_remote_sink(
209 aconnector->dc_link,
210 (uint8_t *)aconnector->edid,
211 (aconnector->edid->extensions + 1) * EDID_LENGTH,
212 &init_params);
213
214 dc_sink->priv = aconnector;
215 aconnector->dc_sink = dc_sink;
216
217 amdgpu_dm_add_sink_to_freesync_module(
218 connector, aconnector->edid);
219
220 drm_mode_connector_update_edid_property(
221 &aconnector->base, aconnector->edid);
222 }
223
224 static int dm_dp_mst_get_modes(struct drm_connector *connector)
225 {
226 struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
227 int ret = 0;
228
229 if (!aconnector)
230 return dm_connector_update_modes(connector, NULL);
231
232 if (!aconnector->edid) {
233 struct edid *edid;
234 struct dc_sink *dc_sink;
235 struct dc_sink_init_data init_params = {
236 .link = aconnector->dc_link,
237 .sink_signal = SIGNAL_TYPE_DISPLAY_PORT_MST };
238 edid = drm_dp_mst_get_edid(connector, &aconnector->mst_port->mst_mgr, aconnector->port);
239
240 if (!edid) {
241 drm_mode_connector_update_edid_property(
242 &aconnector->base,
243 NULL);
244 return ret;
245 }
246
247 aconnector->edid = edid;
248
249 dc_sink = dc_link_add_remote_sink(
250 aconnector->dc_link,
251 (uint8_t *)edid,
252 (edid->extensions + 1) * EDID_LENGTH,
253 &init_params);
254
255 dc_sink->priv = aconnector;
256 aconnector->dc_sink = dc_sink;
257
258 if (aconnector->dc_sink)
259 amdgpu_dm_add_sink_to_freesync_module(
260 connector, edid);
261
262 drm_mode_connector_update_edid_property(
263 &aconnector->base, edid);
264 }
265
266 ret = dm_connector_update_modes(connector, aconnector->edid);
267
268 return ret;
269 }
270
271 static struct drm_encoder *dm_mst_best_encoder(struct drm_connector *connector)
272 {
273 struct amdgpu_dm_connector *amdgpu_dm_connector = to_amdgpu_dm_connector(connector);
274
275 return &amdgpu_dm_connector->mst_encoder->base;
276 }
277
278 static const struct drm_connector_helper_funcs dm_dp_mst_connector_helper_funcs = {
279 .get_modes = dm_dp_mst_get_modes,
280 .mode_valid = amdgpu_dm_connector_mode_valid,
281 .best_encoder = dm_mst_best_encoder,
282 };
283
284 static void amdgpu_dm_encoder_destroy(struct drm_encoder *encoder)
285 {
286 drm_encoder_cleanup(encoder);
287 kfree(encoder);
288 }
289
290 static const struct drm_encoder_funcs amdgpu_dm_encoder_funcs = {
291 .destroy = amdgpu_dm_encoder_destroy,
292 };
293
294 static struct amdgpu_encoder *
295 dm_dp_create_fake_mst_encoder(struct amdgpu_dm_connector *connector)
296 {
297 struct drm_device *dev = connector->base.dev;
298 struct amdgpu_device *adev = dev->dev_private;
299 struct amdgpu_encoder *amdgpu_encoder;
300 struct drm_encoder *encoder;
301 const struct drm_connector_helper_funcs *connector_funcs =
302 connector->base.helper_private;
303 struct drm_encoder *enc_master =
304 connector_funcs->best_encoder(&connector->base);
305
306 DRM_DEBUG_KMS("enc master is %p\n", enc_master);
307 amdgpu_encoder = kzalloc(sizeof(*amdgpu_encoder), GFP_KERNEL);
308 if (!amdgpu_encoder)
309 return NULL;
310
311 encoder = &amdgpu_encoder->base;
312 encoder->possible_crtcs = amdgpu_dm_get_encoder_crtc_mask(adev);
313
314 drm_encoder_init(
315 dev,
316 &amdgpu_encoder->base,
317 &amdgpu_dm_encoder_funcs,
318 DRM_MODE_ENCODER_DPMST,
319 NULL);
320
321 drm_encoder_helper_add(encoder, &amdgpu_dm_encoder_helper_funcs);
322
323 return amdgpu_encoder;
324 }
325
326 static struct drm_connector *
327 dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
328 struct drm_dp_mst_port *port,
329 const char *pathprop)
330 {
331 struct amdgpu_dm_connector *master = container_of(mgr, struct amdgpu_dm_connector, mst_mgr);
332 struct drm_device *dev = master->base.dev;
333 struct amdgpu_device *adev = dev->dev_private;
334 struct amdgpu_dm_connector *aconnector;
335 struct drm_connector *connector;
336 struct drm_connector_list_iter conn_iter;
337
338 drm_connector_list_iter_begin(dev, &conn_iter);
339 drm_for_each_connector_iter(connector, &conn_iter) {
340 aconnector = to_amdgpu_dm_connector(connector);
341 if (aconnector->mst_port == master
342 && !aconnector->port) {
343 DRM_INFO("DM_MST: reusing connector: %p [id: %d] [master: %p]\n",
344 aconnector, connector->base.id, aconnector->mst_port);
345
346 aconnector->port = port;
347 drm_mode_connector_set_path_property(connector, pathprop);
348
349 drm_connector_list_iter_end(&conn_iter);
350 aconnector->mst_connected = true;
351 return &aconnector->base;
352 }
353 }
354 drm_connector_list_iter_end(&conn_iter);
355
356 aconnector = kzalloc(sizeof(*aconnector), GFP_KERNEL);
357 if (!aconnector)
358 return NULL;
359
360 connector = &aconnector->base;
361 aconnector->port = port;
362 aconnector->mst_port = master;
363
364 if (drm_connector_init(
365 dev,
366 connector,
367 &dm_dp_mst_connector_funcs,
368 DRM_MODE_CONNECTOR_DisplayPort)) {
369 kfree(aconnector);
370 return NULL;
371 }
372 drm_connector_helper_add(connector, &dm_dp_mst_connector_helper_funcs);
373
374 amdgpu_dm_connector_init_helper(
375 &adev->dm,
376 aconnector,
377 DRM_MODE_CONNECTOR_DisplayPort,
378 master->dc_link,
379 master->connector_id);
380
381 aconnector->mst_encoder = dm_dp_create_fake_mst_encoder(master);
382
383 /*
384 * TODO: understand why this one is needed
385 */
386 drm_object_attach_property(
387 &connector->base,
388 dev->mode_config.path_property,
389 0);
390 drm_object_attach_property(
391 &connector->base,
392 dev->mode_config.tile_property,
393 0);
394
395 drm_mode_connector_set_path_property(connector, pathprop);
396
397 /*
398 * Initialize connector state before adding the connectror to drm and
399 * framebuffer lists
400 */
401 amdgpu_dm_connector_funcs_reset(connector);
402
403 aconnector->mst_connected = true;
404
405 DRM_INFO("DM_MST: added connector: %p [id: %d] [master: %p]\n",
406 aconnector, connector->base.id, aconnector->mst_port);
407
408 DRM_DEBUG_KMS(":%d\n", connector->base.id);
409
410 return connector;
411 }
412
413 static void dm_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
414 struct drm_connector *connector)
415 {
416 struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
417
418 DRM_INFO("DM_MST: Disabling connector: %p [id: %d] [master: %p]\n",
419 aconnector, connector->base.id, aconnector->mst_port);
420
421 aconnector->port = NULL;
422 if (aconnector->dc_sink) {
423 amdgpu_dm_remove_sink_from_freesync_module(connector);
424 dc_link_remove_remote_sink(aconnector->dc_link, aconnector->dc_sink);
425 dc_sink_release(aconnector->dc_sink);
426 aconnector->dc_sink = NULL;
427 }
428 if (aconnector->edid) {
429 kfree(aconnector->edid);
430 aconnector->edid = NULL;
431 }
432
433 drm_mode_connector_update_edid_property(
434 &aconnector->base,
435 NULL);
436
437 aconnector->mst_connected = false;
438 }
439
440 static void dm_dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr)
441 {
442 struct amdgpu_dm_connector *master = container_of(mgr, struct amdgpu_dm_connector, mst_mgr);
443 struct drm_device *dev = master->base.dev;
444
445 drm_kms_helper_hotplug_event(dev);
446 }
447
448 static void dm_dp_mst_link_status_reset(struct drm_connector *connector)
449 {
450 mutex_lock(&connector->dev->mode_config.mutex);
451 drm_mode_connector_set_link_status_property(connector, DRM_MODE_LINK_STATUS_BAD);
452 mutex_unlock(&connector->dev->mode_config.mutex);
453 }
454
455 static void dm_dp_mst_register_connector(struct drm_connector *connector)
456 {
457 struct drm_device *dev = connector->dev;
458 struct amdgpu_device *adev = dev->dev_private;
459 struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
460
461 if (adev->mode_info.rfbdev)
462 drm_fb_helper_add_one_connector(&adev->mode_info.rfbdev->helper, connector);
463 else
464 DRM_ERROR("adev->mode_info.rfbdev is NULL\n");
465
466 drm_connector_register(connector);
467
468 if (aconnector->mst_connected)
469 dm_dp_mst_link_status_reset(connector);
470 }
471
472 static const struct drm_dp_mst_topology_cbs dm_mst_cbs = {
473 .add_connector = dm_dp_add_mst_connector,
474 .destroy_connector = dm_dp_destroy_mst_connector,
475 .hotplug = dm_dp_mst_hotplug,
476 .register_connector = dm_dp_mst_register_connector
477 };
478
479 void amdgpu_dm_initialize_dp_connector(struct amdgpu_display_manager *dm,
480 struct amdgpu_dm_connector *aconnector)
481 {
482 aconnector->dm_dp_aux.aux.name = "dmdc";
483 aconnector->dm_dp_aux.aux.dev = dm->adev->dev;
484 aconnector->dm_dp_aux.aux.transfer = dm_dp_aux_transfer;
485 aconnector->dm_dp_aux.ddc_service = aconnector->dc_link->ddc;
486
487 drm_dp_aux_register(&aconnector->dm_dp_aux.aux);
488 aconnector->mst_mgr.cbs = &dm_mst_cbs;
489 drm_dp_mst_topology_mgr_init(
490 &aconnector->mst_mgr,
491 dm->adev->ddev,
492 &aconnector->dm_dp_aux.aux,
493 16,
494 4,
495 aconnector->connector_id);
496 }
497