]> git.ipfire.org Git - thirdparty/kernel/stable.git/blob - drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
drm/amd/display: Check hpd_gpio for NULL before accessing it
[thirdparty/kernel/stable.git] / drivers / gpu / drm / amd / display / amdgpu_dm / amdgpu_dm_helpers.c
1 /*
2 * Copyright 2015 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/string.h>
27 #include <linux/acpi.h>
28 #include <linux/version.h>
29 #include <linux/i2c.h>
30
31 #include <drm/drmP.h>
32 #include <drm/drm_crtc_helper.h>
33 #include <drm/amdgpu_drm.h>
34 #include <drm/drm_edid.h>
35
36 #include "dm_services.h"
37 #include "amdgpu.h"
38 #include "dc.h"
39 #include "amdgpu_dm.h"
40 #include "amdgpu_dm_irq.h"
41
42 #include "dm_helpers.h"
43
44 /* dm_helpers_parse_edid_caps
45 *
46 * Parse edid caps
47 *
48 * @edid: [in] pointer to edid
49 * edid_caps: [in] pointer to edid caps
50 * @return
51 * void
52 * */
53 enum dc_edid_status dm_helpers_parse_edid_caps(
54 struct dc_context *ctx,
55 const struct dc_edid *edid,
56 struct dc_edid_caps *edid_caps)
57 {
58 struct edid *edid_buf = (struct edid *) edid->raw_edid;
59 struct cea_sad *sads;
60 int sad_count = -1;
61 int sadb_count = -1;
62 int i = 0;
63 int j = 0;
64 uint8_t *sadb = NULL;
65
66 enum dc_edid_status result = EDID_OK;
67
68 if (!edid_caps || !edid)
69 return EDID_BAD_INPUT;
70
71 if (!drm_edid_is_valid(edid_buf))
72 result = EDID_BAD_CHECKSUM;
73
74 edid_caps->manufacturer_id = (uint16_t) edid_buf->mfg_id[0] |
75 ((uint16_t) edid_buf->mfg_id[1])<<8;
76 edid_caps->product_id = (uint16_t) edid_buf->prod_code[0] |
77 ((uint16_t) edid_buf->prod_code[1])<<8;
78 edid_caps->serial_number = edid_buf->serial;
79 edid_caps->manufacture_week = edid_buf->mfg_week;
80 edid_caps->manufacture_year = edid_buf->mfg_year;
81
82 /* One of the four detailed_timings stores the monitor name. It's
83 * stored in an array of length 13. */
84 for (i = 0; i < 4; i++) {
85 if (edid_buf->detailed_timings[i].data.other_data.type == 0xfc) {
86 while (j < 13 && edid_buf->detailed_timings[i].data.other_data.data.str.str[j]) {
87 if (edid_buf->detailed_timings[i].data.other_data.data.str.str[j] == '\n')
88 break;
89
90 edid_caps->display_name[j] =
91 edid_buf->detailed_timings[i].data.other_data.data.str.str[j];
92 j++;
93 }
94 }
95 }
96
97 edid_caps->edid_hdmi = drm_detect_hdmi_monitor(
98 (struct edid *) edid->raw_edid);
99
100 sad_count = drm_edid_to_sad((struct edid *) edid->raw_edid, &sads);
101 if (sad_count <= 0) {
102 DRM_INFO("SADs count is: %d, don't need to read it\n",
103 sad_count);
104 return result;
105 }
106
107 edid_caps->audio_mode_count = sad_count < DC_MAX_AUDIO_DESC_COUNT ? sad_count : DC_MAX_AUDIO_DESC_COUNT;
108 for (i = 0; i < edid_caps->audio_mode_count; ++i) {
109 struct cea_sad *sad = &sads[i];
110
111 edid_caps->audio_modes[i].format_code = sad->format;
112 edid_caps->audio_modes[i].channel_count = sad->channels + 1;
113 edid_caps->audio_modes[i].sample_rate = sad->freq;
114 edid_caps->audio_modes[i].sample_size = sad->byte2;
115 }
116
117 sadb_count = drm_edid_to_speaker_allocation((struct edid *) edid->raw_edid, &sadb);
118
119 if (sadb_count < 0) {
120 DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sadb_count);
121 sadb_count = 0;
122 }
123
124 if (sadb_count)
125 edid_caps->speaker_flags = sadb[0];
126 else
127 edid_caps->speaker_flags = DEFAULT_SPEAKER_LOCATION;
128
129 kfree(sads);
130 kfree(sadb);
131
132 return result;
133 }
134
135 static void get_payload_table(
136 struct amdgpu_dm_connector *aconnector,
137 struct dp_mst_stream_allocation_table *proposed_table)
138 {
139 int i;
140 struct drm_dp_mst_topology_mgr *mst_mgr =
141 &aconnector->mst_port->mst_mgr;
142
143 mutex_lock(&mst_mgr->payload_lock);
144
145 proposed_table->stream_count = 0;
146
147 /* number of active streams */
148 for (i = 0; i < mst_mgr->max_payloads; i++) {
149 if (mst_mgr->payloads[i].num_slots == 0)
150 break; /* end of vcp_id table */
151
152 ASSERT(mst_mgr->payloads[i].payload_state !=
153 DP_PAYLOAD_DELETE_LOCAL);
154
155 if (mst_mgr->payloads[i].payload_state == DP_PAYLOAD_LOCAL ||
156 mst_mgr->payloads[i].payload_state ==
157 DP_PAYLOAD_REMOTE) {
158
159 struct dp_mst_stream_allocation *sa =
160 &proposed_table->stream_allocations[
161 proposed_table->stream_count];
162
163 sa->slot_count = mst_mgr->payloads[i].num_slots;
164 sa->vcp_id = mst_mgr->proposed_vcpis[i]->vcpi;
165 proposed_table->stream_count++;
166 }
167 }
168
169 mutex_unlock(&mst_mgr->payload_lock);
170 }
171
172 void dm_helpers_dp_update_branch_info(
173 struct dc_context *ctx,
174 const struct dc_link *link)
175 {}
176
177 /*
178 * Writes payload allocation table in immediate downstream device.
179 */
180 bool dm_helpers_dp_mst_write_payload_allocation_table(
181 struct dc_context *ctx,
182 const struct dc_stream_state *stream,
183 struct dp_mst_stream_allocation_table *proposed_table,
184 bool enable)
185 {
186 struct amdgpu_dm_connector *aconnector;
187 struct drm_dp_mst_topology_mgr *mst_mgr;
188 struct drm_dp_mst_port *mst_port;
189 int slots = 0;
190 bool ret;
191 int clock;
192 int bpp = 0;
193 int pbn = 0;
194
195 aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context;
196
197 if (!aconnector || !aconnector->mst_port)
198 return false;
199
200 mst_mgr = &aconnector->mst_port->mst_mgr;
201
202 if (!mst_mgr->mst_state)
203 return false;
204
205 mst_port = aconnector->port;
206
207 if (enable) {
208 clock = stream->timing.pix_clk_100hz / 10;
209
210 switch (stream->timing.display_color_depth) {
211
212 case COLOR_DEPTH_666:
213 bpp = 6;
214 break;
215 case COLOR_DEPTH_888:
216 bpp = 8;
217 break;
218 case COLOR_DEPTH_101010:
219 bpp = 10;
220 break;
221 case COLOR_DEPTH_121212:
222 bpp = 12;
223 break;
224 case COLOR_DEPTH_141414:
225 bpp = 14;
226 break;
227 case COLOR_DEPTH_161616:
228 bpp = 16;
229 break;
230 default:
231 ASSERT(bpp != 0);
232 break;
233 }
234
235 bpp = bpp * 3;
236
237 /* TODO need to know link rate */
238
239 pbn = drm_dp_calc_pbn_mode(clock, bpp);
240
241 slots = drm_dp_find_vcpi_slots(mst_mgr, pbn);
242 ret = drm_dp_mst_allocate_vcpi(mst_mgr, mst_port, pbn, slots);
243
244 if (!ret)
245 return false;
246
247 } else {
248 drm_dp_mst_reset_vcpi_slots(mst_mgr, mst_port);
249 }
250
251 ret = drm_dp_update_payload_part1(mst_mgr);
252
253 /* mst_mgr->->payloads are VC payload notify MST branch using DPCD or
254 * AUX message. The sequence is slot 1-63 allocated sequence for each
255 * stream. AMD ASIC stream slot allocation should follow the same
256 * sequence. copy DRM MST allocation to dc */
257
258 get_payload_table(aconnector, proposed_table);
259
260 if (ret)
261 return false;
262
263 return true;
264 }
265
266 /*
267 * poll pending down reply before clear payload allocation table
268 */
269 void dm_helpers_dp_mst_poll_pending_down_reply(
270 struct dc_context *ctx,
271 const struct dc_link *link)
272 {}
273
274 /*
275 * Clear payload allocation table before enable MST DP link.
276 */
277 void dm_helpers_dp_mst_clear_payload_allocation_table(
278 struct dc_context *ctx,
279 const struct dc_link *link)
280 {}
281
282 /*
283 * Polls for ACT (allocation change trigger) handled and sends
284 * ALLOCATE_PAYLOAD message.
285 */
286 bool dm_helpers_dp_mst_poll_for_allocation_change_trigger(
287 struct dc_context *ctx,
288 const struct dc_stream_state *stream)
289 {
290 struct amdgpu_dm_connector *aconnector;
291 struct drm_dp_mst_topology_mgr *mst_mgr;
292 int ret;
293
294 aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context;
295
296 if (!aconnector || !aconnector->mst_port)
297 return false;
298
299 mst_mgr = &aconnector->mst_port->mst_mgr;
300
301 if (!mst_mgr->mst_state)
302 return false;
303
304 ret = drm_dp_check_act_status(mst_mgr);
305
306 if (ret)
307 return false;
308
309 return true;
310 }
311
312 bool dm_helpers_dp_mst_send_payload_allocation(
313 struct dc_context *ctx,
314 const struct dc_stream_state *stream,
315 bool enable)
316 {
317 struct amdgpu_dm_connector *aconnector;
318 struct drm_dp_mst_topology_mgr *mst_mgr;
319 struct drm_dp_mst_port *mst_port;
320 int ret;
321
322 aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context;
323
324 if (!aconnector || !aconnector->mst_port)
325 return false;
326
327 mst_port = aconnector->port;
328
329 mst_mgr = &aconnector->mst_port->mst_mgr;
330
331 if (!mst_mgr->mst_state)
332 return false;
333
334 ret = drm_dp_update_payload_part2(mst_mgr);
335
336 if (ret)
337 return false;
338
339 if (!enable)
340 drm_dp_mst_deallocate_vcpi(mst_mgr, mst_port);
341
342 return true;
343 }
344
345 void dm_dtn_log_begin(struct dc_context *ctx,
346 struct dc_log_buffer_ctx *log_ctx)
347 {
348 static const char msg[] = "[dtn begin]\n";
349
350 if (!log_ctx) {
351 pr_info("%s", msg);
352 return;
353 }
354
355 dm_dtn_log_append_v(ctx, log_ctx, "%s", msg);
356 }
357
358 void dm_dtn_log_append_v(struct dc_context *ctx,
359 struct dc_log_buffer_ctx *log_ctx,
360 const char *msg, ...)
361 {
362 va_list args;
363 size_t total;
364 int n;
365
366 if (!log_ctx) {
367 /* No context, redirect to dmesg. */
368 struct va_format vaf;
369
370 vaf.fmt = msg;
371 vaf.va = &args;
372
373 va_start(args, msg);
374 pr_info("%pV", &vaf);
375 va_end(args);
376
377 return;
378 }
379
380 /* Measure the output. */
381 va_start(args, msg);
382 n = vsnprintf(NULL, 0, msg, args);
383 va_end(args);
384
385 if (n <= 0)
386 return;
387
388 /* Reallocate the string buffer as needed. */
389 total = log_ctx->pos + n + 1;
390
391 if (total > log_ctx->size) {
392 char *buf = (char *)kvcalloc(total, sizeof(char), GFP_KERNEL);
393
394 if (buf) {
395 memcpy(buf, log_ctx->buf, log_ctx->pos);
396 kfree(log_ctx->buf);
397
398 log_ctx->buf = buf;
399 log_ctx->size = total;
400 }
401 }
402
403 if (!log_ctx->buf)
404 return;
405
406 /* Write the formatted string to the log buffer. */
407 va_start(args, msg);
408 n = vscnprintf(
409 log_ctx->buf + log_ctx->pos,
410 log_ctx->size - log_ctx->pos,
411 msg,
412 args);
413 va_end(args);
414
415 if (n > 0)
416 log_ctx->pos += n;
417 }
418
419 void dm_dtn_log_end(struct dc_context *ctx,
420 struct dc_log_buffer_ctx *log_ctx)
421 {
422 static const char msg[] = "[dtn end]\n";
423
424 if (!log_ctx) {
425 pr_info("%s", msg);
426 return;
427 }
428
429 dm_dtn_log_append_v(ctx, log_ctx, "%s", msg);
430 }
431
432 bool dm_helpers_dp_mst_start_top_mgr(
433 struct dc_context *ctx,
434 const struct dc_link *link,
435 bool boot)
436 {
437 struct amdgpu_dm_connector *aconnector = link->priv;
438
439 if (!aconnector) {
440 DRM_ERROR("Failed to found connector for link!");
441 return false;
442 }
443
444 if (boot) {
445 DRM_INFO("DM_MST: Differing MST start on aconnector: %p [id: %d]\n",
446 aconnector, aconnector->base.base.id);
447 return true;
448 }
449
450 DRM_INFO("DM_MST: starting TM on aconnector: %p [id: %d]\n",
451 aconnector, aconnector->base.base.id);
452
453 return (drm_dp_mst_topology_mgr_set_mst(&aconnector->mst_mgr, true) == 0);
454 }
455
456 void dm_helpers_dp_mst_stop_top_mgr(
457 struct dc_context *ctx,
458 const struct dc_link *link)
459 {
460 struct amdgpu_dm_connector *aconnector = link->priv;
461
462 if (!aconnector) {
463 DRM_ERROR("Failed to found connector for link!");
464 return;
465 }
466
467 DRM_INFO("DM_MST: stopping TM on aconnector: %p [id: %d]\n",
468 aconnector, aconnector->base.base.id);
469
470 if (aconnector->mst_mgr.mst_state == true)
471 drm_dp_mst_topology_mgr_set_mst(&aconnector->mst_mgr, false);
472 }
473
474 bool dm_helpers_dp_read_dpcd(
475 struct dc_context *ctx,
476 const struct dc_link *link,
477 uint32_t address,
478 uint8_t *data,
479 uint32_t size)
480 {
481
482 struct amdgpu_dm_connector *aconnector = link->priv;
483
484 if (!aconnector) {
485 DRM_ERROR("Failed to found connector for link!");
486 return false;
487 }
488
489 return drm_dp_dpcd_read(&aconnector->dm_dp_aux.aux, address,
490 data, size) > 0;
491 }
492
493 bool dm_helpers_dp_write_dpcd(
494 struct dc_context *ctx,
495 const struct dc_link *link,
496 uint32_t address,
497 const uint8_t *data,
498 uint32_t size)
499 {
500 struct amdgpu_dm_connector *aconnector = link->priv;
501
502 if (!aconnector) {
503 DRM_ERROR("Failed to found connector for link!");
504 return false;
505 }
506
507 return drm_dp_dpcd_write(&aconnector->dm_dp_aux.aux,
508 address, (uint8_t *)data, size) > 0;
509 }
510
511 bool dm_helpers_submit_i2c(
512 struct dc_context *ctx,
513 const struct dc_link *link,
514 struct i2c_command *cmd)
515 {
516 struct amdgpu_dm_connector *aconnector = link->priv;
517 struct i2c_msg *msgs;
518 int i = 0;
519 int num = cmd->number_of_payloads;
520 bool result;
521
522 if (!aconnector) {
523 DRM_ERROR("Failed to found connector for link!");
524 return false;
525 }
526
527 msgs = kcalloc(num, sizeof(struct i2c_msg), GFP_KERNEL);
528
529 if (!msgs)
530 return false;
531
532 for (i = 0; i < num; i++) {
533 msgs[i].flags = cmd->payloads[i].write ? 0 : I2C_M_RD;
534 msgs[i].addr = cmd->payloads[i].address;
535 msgs[i].len = cmd->payloads[i].length;
536 msgs[i].buf = cmd->payloads[i].data;
537 }
538
539 result = i2c_transfer(&aconnector->i2c->base, msgs, num) == num;
540
541 kfree(msgs);
542
543 return result;
544 }
545
546 bool dm_helpers_is_dp_sink_present(struct dc_link *link)
547 {
548 bool dp_sink_present;
549 struct amdgpu_dm_connector *aconnector = link->priv;
550
551 if (!aconnector) {
552 BUG_ON("Failed to found connector for link!");
553 return true;
554 }
555
556 mutex_lock(&aconnector->dm_dp_aux.aux.hw_mutex);
557 dp_sink_present = dc_link_is_dp_sink_present(link);
558 mutex_unlock(&aconnector->dm_dp_aux.aux.hw_mutex);
559 return dp_sink_present;
560 }
561
562 enum dc_edid_status dm_helpers_read_local_edid(
563 struct dc_context *ctx,
564 struct dc_link *link,
565 struct dc_sink *sink)
566 {
567 struct amdgpu_dm_connector *aconnector = link->priv;
568 struct i2c_adapter *ddc;
569 int retry = 3;
570 enum dc_edid_status edid_status;
571 struct edid *edid;
572
573 if (link->aux_mode)
574 ddc = &aconnector->dm_dp_aux.aux.ddc;
575 else
576 ddc = &aconnector->i2c->base;
577
578 /* some dongles read edid incorrectly the first time,
579 * do check sum and retry to make sure read correct edid.
580 */
581 do {
582
583 edid = drm_get_edid(&aconnector->base, ddc);
584
585 if (!edid)
586 return EDID_NO_RESPONSE;
587
588 sink->dc_edid.length = EDID_LENGTH * (edid->extensions + 1);
589 memmove(sink->dc_edid.raw_edid, (uint8_t *)edid, sink->dc_edid.length);
590
591 /* We don't need the original edid anymore */
592 kfree(edid);
593
594 edid_status = dm_helpers_parse_edid_caps(
595 ctx,
596 &sink->dc_edid,
597 &sink->edid_caps);
598
599 } while (edid_status == EDID_BAD_CHECKSUM && --retry > 0);
600
601 if (edid_status != EDID_OK)
602 DRM_ERROR("EDID err: %d, on connector: %s",
603 edid_status,
604 aconnector->base.name);
605 if (link->aux_mode) {
606 union test_request test_request = { {0} };
607 union test_response test_response = { {0} };
608
609 dm_helpers_dp_read_dpcd(ctx,
610 link,
611 DP_TEST_REQUEST,
612 &test_request.raw,
613 sizeof(union test_request));
614
615 if (!test_request.bits.EDID_READ)
616 return edid_status;
617
618 test_response.bits.EDID_CHECKSUM_WRITE = 1;
619
620 dm_helpers_dp_write_dpcd(ctx,
621 link,
622 DP_TEST_EDID_CHECKSUM,
623 &sink->dc_edid.raw_edid[sink->dc_edid.length-1],
624 1);
625
626 dm_helpers_dp_write_dpcd(ctx,
627 link,
628 DP_TEST_RESPONSE,
629 &test_response.raw,
630 sizeof(test_response));
631
632 }
633
634 return edid_status;
635 }
636
637 void dm_set_dcn_clocks(struct dc_context *ctx, struct dc_clocks *clks)
638 {
639 /* TODO: something */
640 }