hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/drivers/gpu/drm/drm_dp_helper.c
....@@ -20,16 +20,19 @@
2020 * OF THIS SOFTWARE.
2121 */
2222
23
+#include <linux/delay.h>
24
+#include <linux/errno.h>
25
+#include <linux/i2c.h>
26
+#include <linux/init.h>
2327 #include <linux/kernel.h>
2428 #include <linux/module.h>
25
-#include <linux/delay.h>
26
-#include <linux/init.h>
27
-#include <linux/errno.h>
2829 #include <linux/sched.h>
29
-#include <linux/i2c.h>
3030 #include <linux/seq_file.h>
31
+
3132 #include <drm/drm_dp_helper.h>
32
-#include <drm/drmP.h>
33
+#include <drm/drm_print.h>
34
+#include <drm/drm_vblank.h>
35
+#include <drm/drm_dp_mst_helper.h>
3336
3437 #include "drm_crtc_helper_internal.h"
3538
....@@ -54,6 +57,7 @@
5457 int i = DP_LANE0_1_STATUS + (lane >> 1);
5558 int s = (lane & 1) * 4;
5659 u8 l = dp_link_status(link_status, i);
60
+
5761 return (l >> s) & 0xf;
5862 }
5963
....@@ -118,68 +122,63 @@
118122 }
119123 EXPORT_SYMBOL(drm_dp_get_adjust_request_pre_emphasis);
120124
121
-void drm_dp_link_train_clock_recovery_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE]) {
122
- int rd_interval = dpcd[DP_TRAINING_AUX_RD_INTERVAL] &
123
- DP_TRAINING_AUX_RD_MASK;
125
+u8 drm_dp_get_adjust_request_post_cursor(const u8 link_status[DP_LINK_STATUS_SIZE],
126
+ unsigned int lane)
127
+{
128
+ unsigned int offset = DP_ADJUST_REQUEST_POST_CURSOR2;
129
+ u8 value = dp_link_status(link_status, offset);
130
+
131
+ return (value >> (lane << 1)) & 0x3;
132
+}
133
+EXPORT_SYMBOL(drm_dp_get_adjust_request_post_cursor);
134
+
135
+void drm_dp_link_train_clock_recovery_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
136
+{
137
+ unsigned long rd_interval = dpcd[DP_TRAINING_AUX_RD_INTERVAL] &
138
+ DP_TRAINING_AUX_RD_MASK;
124139
125140 if (rd_interval > 4)
126
- DRM_DEBUG_KMS("AUX interval %d, out of range (max 4)\n",
141
+ DRM_DEBUG_KMS("AUX interval %lu, out of range (max 4)\n",
127142 rd_interval);
128143
129144 if (rd_interval == 0 || dpcd[DP_DPCD_REV] >= DP_DPCD_REV_14)
130
- udelay(100);
145
+ rd_interval = 100;
131146 else
132
- mdelay(rd_interval * 4);
147
+ rd_interval *= 4 * USEC_PER_MSEC;
148
+
149
+ usleep_range(rd_interval, rd_interval * 2);
133150 }
134151 EXPORT_SYMBOL(drm_dp_link_train_clock_recovery_delay);
135152
136
-void drm_dp_link_train_channel_eq_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE]) {
137
- int rd_interval = dpcd[DP_TRAINING_AUX_RD_INTERVAL] &
138
- DP_TRAINING_AUX_RD_MASK;
153
+void drm_dp_link_train_channel_eq_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
154
+{
155
+ unsigned long rd_interval = dpcd[DP_TRAINING_AUX_RD_INTERVAL] &
156
+ DP_TRAINING_AUX_RD_MASK;
139157
140158 if (rd_interval > 4)
141
- DRM_DEBUG_KMS("AUX interval %d, out of range (max 4)\n",
159
+ DRM_DEBUG_KMS("AUX interval %lu, out of range (max 4)\n",
142160 rd_interval);
143161
144162 if (rd_interval == 0)
145
- udelay(400);
163
+ rd_interval = 400;
146164 else
147
- mdelay(rd_interval * 4);
165
+ rd_interval *= 4 * USEC_PER_MSEC;
166
+
167
+ usleep_range(rd_interval, rd_interval * 2);
148168 }
149169 EXPORT_SYMBOL(drm_dp_link_train_channel_eq_delay);
150170
151171 u8 drm_dp_link_rate_to_bw_code(int link_rate)
152172 {
153
- switch (link_rate) {
154
- default:
155
- WARN(1, "unknown DP link rate %d, using %x\n", link_rate,
156
- DP_LINK_BW_1_62);
157
- case 162000:
158
- return DP_LINK_BW_1_62;
159
- case 270000:
160
- return DP_LINK_BW_2_7;
161
- case 540000:
162
- return DP_LINK_BW_5_4;
163
- case 810000:
164
- return DP_LINK_BW_8_1;
165
- }
173
+ /* Spec says link_bw = link_rate / 0.27Gbps */
174
+ return link_rate / 27000;
166175 }
167176 EXPORT_SYMBOL(drm_dp_link_rate_to_bw_code);
168177
169178 int drm_dp_bw_code_to_link_rate(u8 link_bw)
170179 {
171
- switch (link_bw) {
172
- default:
173
- WARN(1, "unknown DP link BW code %x, using 162000\n", link_bw);
174
- case DP_LINK_BW_1_62:
175
- return 162000;
176
- case DP_LINK_BW_2_7:
177
- return 270000;
178
- case DP_LINK_BW_5_4:
179
- return 540000;
180
- case DP_LINK_BW_8_1:
181
- return 810000;
182
- }
180
+ /* Spec says link_rate = link_bw * 0.27Gbps */
181
+ return link_bw * 27000;
183182 }
184183 EXPORT_SYMBOL(drm_dp_bw_code_to_link_rate);
185184
....@@ -192,11 +191,11 @@
192191 const char *arrow = request == DP_AUX_NATIVE_READ ? "->" : "<-";
193192
194193 if (ret > 0)
195
- drm_dbg(DRM_UT_DP, "%s: 0x%05x AUX %s (ret=%3d) %*ph\n",
196
- aux->name, offset, arrow, ret, min(ret, 20), buffer);
194
+ DRM_DEBUG_DP("%s: 0x%05x AUX %s (ret=%3d) %*ph\n",
195
+ aux->name, offset, arrow, ret, min(ret, 20), buffer);
197196 else
198
- drm_dbg(DRM_UT_DP, "%s: 0x%05x AUX %s (ret=%3d)\n",
199
- aux->name, offset, arrow, ret);
197
+ DRM_DEBUG_DP("%s: 0x%05x AUX %s (ret=%3d)\n",
198
+ aux->name, offset, arrow, ret);
200199 }
201200
202201 /**
....@@ -239,7 +238,6 @@
239238 }
240239
241240 ret = aux->transfer(aux, &msg);
242
-
243241 if (ret >= 0) {
244242 native_reply = msg.reply & DP_AUX_NATIVE_REPLY_MASK;
245243 if (native_reply == DP_AUX_NATIVE_REPLY_ACK) {
....@@ -260,7 +258,8 @@
260258 err = ret;
261259 }
262260
263
- DRM_DEBUG_KMS("Too many retries, giving up. First error: %d\n", err);
261
+ DRM_DEBUG_KMS("%s: Too many retries, giving up. First error: %d\n",
262
+ aux->name, err);
264263 ret = err;
265264
266265 unlock:
....@@ -270,7 +269,7 @@
270269
271270 /**
272271 * drm_dp_dpcd_read() - read a series of bytes from the DPCD
273
- * @aux: DisplayPort AUX channel
272
+ * @aux: DisplayPort AUX channel (SST or MST)
274273 * @offset: address of the (first) register to read
275274 * @buffer: buffer to store the register values
276275 * @size: number of bytes in @buffer
....@@ -299,13 +298,18 @@
299298 * We just have to do it before any DPCD access and hope that the
300299 * monitor doesn't power down exactly after the throw away read.
301300 */
302
- ret = drm_dp_dpcd_access(aux, DP_AUX_NATIVE_READ, DP_DPCD_REV, buffer,
303
- 1);
304
- if (ret != 1)
305
- goto out;
301
+ if (!aux->is_remote) {
302
+ ret = drm_dp_dpcd_access(aux, DP_AUX_NATIVE_READ, DP_DPCD_REV,
303
+ buffer, 1);
304
+ if (ret != 1)
305
+ goto out;
306
+ }
306307
307
- ret = drm_dp_dpcd_access(aux, DP_AUX_NATIVE_READ, offset, buffer,
308
- size);
308
+ if (aux->is_remote)
309
+ ret = drm_dp_mst_dpcd_read(aux, offset, buffer, size);
310
+ else
311
+ ret = drm_dp_dpcd_access(aux, DP_AUX_NATIVE_READ, offset,
312
+ buffer, size);
309313
310314 out:
311315 drm_dp_dump_access(aux, DP_AUX_NATIVE_READ, offset, buffer, ret);
....@@ -315,7 +319,7 @@
315319
316320 /**
317321 * drm_dp_dpcd_write() - write a series of bytes to the DPCD
318
- * @aux: DisplayPort AUX channel
322
+ * @aux: DisplayPort AUX channel (SST or MST)
319323 * @offset: address of the (first) register to write
320324 * @buffer: buffer containing the values to write
321325 * @size: number of bytes in @buffer
....@@ -332,8 +336,12 @@
332336 {
333337 int ret;
334338
335
- ret = drm_dp_dpcd_access(aux, DP_AUX_NATIVE_WRITE, offset, buffer,
336
- size);
339
+ if (aux->is_remote)
340
+ ret = drm_dp_mst_dpcd_write(aux, offset, buffer, size);
341
+ else
342
+ ret = drm_dp_dpcd_access(aux, DP_AUX_NATIVE_WRITE, offset,
343
+ buffer, size);
344
+
337345 drm_dp_dump_access(aux, DP_AUX_NATIVE_WRITE, offset, buffer, ret);
338346 return ret;
339347 }
....@@ -355,194 +363,444 @@
355363 }
356364 EXPORT_SYMBOL(drm_dp_dpcd_read_link_status);
357365
358
-/**
359
- * drm_dp_link_probe() - probe a DisplayPort link for capabilities
360
- * @aux: DisplayPort AUX channel
361
- * @link: pointer to structure in which to return link capabilities
362
- *
363
- * The structure filled in by this function can usually be passed directly
364
- * into drm_dp_link_power_up() and drm_dp_link_configure() to power up and
365
- * configure the link based on the link's capabilities.
366
- *
367
- * Returns 0 on success or a negative error code on failure.
368
- */
369
-int drm_dp_link_probe(struct drm_dp_aux *aux, struct drm_dp_link *link)
366
+static bool is_edid_digital_input_dp(const struct edid *edid)
370367 {
371
- u8 values[3];
372
- int err;
373
-
374
- memset(link, 0, sizeof(*link));
375
-
376
- err = drm_dp_dpcd_read(aux, DP_DPCD_REV, values, sizeof(values));
377
- if (err < 0)
378
- return err;
379
-
380
- link->revision = values[0];
381
- link->rate = drm_dp_bw_code_to_link_rate(values[1]);
382
- link->num_lanes = values[2] & DP_MAX_LANE_COUNT_MASK;
383
-
384
- if (values[2] & DP_ENHANCED_FRAME_CAP)
385
- link->capabilities |= DP_LINK_CAP_ENHANCED_FRAMING;
386
-
387
- return 0;
368
+ return edid && edid->revision >= 4 &&
369
+ edid->input & DRM_EDID_INPUT_DIGITAL &&
370
+ (edid->input & DRM_EDID_DIGITAL_TYPE_MASK) == DRM_EDID_DIGITAL_TYPE_DP;
388371 }
389
-EXPORT_SYMBOL(drm_dp_link_probe);
390372
391373 /**
392
- * drm_dp_link_power_up() - power up a DisplayPort link
393
- * @aux: DisplayPort AUX channel
394
- * @link: pointer to a structure containing the link configuration
374
+ * drm_dp_downstream_is_type() - is the downstream facing port of certain type?
375
+ * @dpcd: DisplayPort configuration data
376
+ * @port_cap: port capabilities
377
+ * @type: port type to be checked. Can be:
378
+ * %DP_DS_PORT_TYPE_DP, %DP_DS_PORT_TYPE_VGA, %DP_DS_PORT_TYPE_DVI,
379
+ * %DP_DS_PORT_TYPE_HDMI, %DP_DS_PORT_TYPE_NON_EDID,
380
+ * %DP_DS_PORT_TYPE_DP_DUALMODE or %DP_DS_PORT_TYPE_WIRELESS.
395381 *
396
- * Returns 0 on success or a negative error code on failure.
382
+ * Caveat: Only works with DPCD 1.1+ port caps.
383
+ *
384
+ * Returns: whether the downstream facing port matches the type.
397385 */
398
-int drm_dp_link_power_up(struct drm_dp_aux *aux, struct drm_dp_link *link)
386
+bool drm_dp_downstream_is_type(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
387
+ const u8 port_cap[4], u8 type)
399388 {
400
- u8 value;
401
- int err;
389
+ return drm_dp_is_branch(dpcd) &&
390
+ dpcd[DP_DPCD_REV] >= 0x11 &&
391
+ (port_cap[0] & DP_DS_PORT_TYPE_MASK) == type;
392
+}
393
+EXPORT_SYMBOL(drm_dp_downstream_is_type);
402394
403
- /* DP_SET_POWER register is only available on DPCD v1.1 and later */
404
- if (link->revision < 0x11)
405
- return 0;
395
+/**
396
+ * drm_dp_downstream_is_tmds() - is the downstream facing port TMDS?
397
+ * @dpcd: DisplayPort configuration data
398
+ * @port_cap: port capabilities
399
+ * @edid: EDID
400
+ *
401
+ * Returns: whether the downstream facing port is TMDS (HDMI/DVI).
402
+ */
403
+bool drm_dp_downstream_is_tmds(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
404
+ const u8 port_cap[4],
405
+ const struct edid *edid)
406
+{
407
+ if (dpcd[DP_DPCD_REV] < 0x11) {
408
+ switch (dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_TYPE_MASK) {
409
+ case DP_DWN_STRM_PORT_TYPE_TMDS:
410
+ return true;
411
+ default:
412
+ return false;
413
+ }
414
+ }
406415
407
- err = drm_dp_dpcd_readb(aux, DP_SET_POWER, &value);
408
- if (err < 0)
409
- return err;
416
+ switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
417
+ case DP_DS_PORT_TYPE_DP_DUALMODE:
418
+ if (is_edid_digital_input_dp(edid))
419
+ return false;
420
+ fallthrough;
421
+ case DP_DS_PORT_TYPE_DVI:
422
+ case DP_DS_PORT_TYPE_HDMI:
423
+ return true;
424
+ default:
425
+ return false;
426
+ }
427
+}
428
+EXPORT_SYMBOL(drm_dp_downstream_is_tmds);
410429
411
- value &= ~DP_SET_POWER_MASK;
412
- value |= DP_SET_POWER_D0;
430
+/**
431
+ * drm_dp_send_real_edid_checksum() - send back real edid checksum value
432
+ * @aux: DisplayPort AUX channel
433
+ * @real_edid_checksum: real edid checksum for the last block
434
+ *
435
+ * Returns:
436
+ * True on success
437
+ */
438
+bool drm_dp_send_real_edid_checksum(struct drm_dp_aux *aux,
439
+ u8 real_edid_checksum)
440
+{
441
+ u8 link_edid_read = 0, auto_test_req = 0, test_resp = 0;
413442
414
- err = drm_dp_dpcd_writeb(aux, DP_SET_POWER, value);
415
- if (err < 0)
416
- return err;
443
+ if (drm_dp_dpcd_read(aux, DP_DEVICE_SERVICE_IRQ_VECTOR,
444
+ &auto_test_req, 1) < 1) {
445
+ DRM_ERROR("%s: DPCD failed read at register 0x%x\n",
446
+ aux->name, DP_DEVICE_SERVICE_IRQ_VECTOR);
447
+ return false;
448
+ }
449
+ auto_test_req &= DP_AUTOMATED_TEST_REQUEST;
450
+
451
+ if (drm_dp_dpcd_read(aux, DP_TEST_REQUEST, &link_edid_read, 1) < 1) {
452
+ DRM_ERROR("%s: DPCD failed read at register 0x%x\n",
453
+ aux->name, DP_TEST_REQUEST);
454
+ return false;
455
+ }
456
+ link_edid_read &= DP_TEST_LINK_EDID_READ;
457
+
458
+ if (!auto_test_req || !link_edid_read) {
459
+ DRM_DEBUG_KMS("%s: Source DUT does not support TEST_EDID_READ\n",
460
+ aux->name);
461
+ return false;
462
+ }
463
+
464
+ if (drm_dp_dpcd_write(aux, DP_DEVICE_SERVICE_IRQ_VECTOR,
465
+ &auto_test_req, 1) < 1) {
466
+ DRM_ERROR("%s: DPCD failed write at register 0x%x\n",
467
+ aux->name, DP_DEVICE_SERVICE_IRQ_VECTOR);
468
+ return false;
469
+ }
470
+
471
+ /* send back checksum for the last edid extension block data */
472
+ if (drm_dp_dpcd_write(aux, DP_TEST_EDID_CHECKSUM,
473
+ &real_edid_checksum, 1) < 1) {
474
+ DRM_ERROR("%s: DPCD failed write at register 0x%x\n",
475
+ aux->name, DP_TEST_EDID_CHECKSUM);
476
+ return false;
477
+ }
478
+
479
+ test_resp |= DP_TEST_EDID_CHECKSUM_WRITE;
480
+ if (drm_dp_dpcd_write(aux, DP_TEST_RESPONSE, &test_resp, 1) < 1) {
481
+ DRM_ERROR("%s: DPCD failed write at register 0x%x\n",
482
+ aux->name, DP_TEST_RESPONSE);
483
+ return false;
484
+ }
485
+
486
+ return true;
487
+}
488
+EXPORT_SYMBOL(drm_dp_send_real_edid_checksum);
489
+
490
+static u8 drm_dp_downstream_port_count(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
491
+{
492
+ u8 port_count = dpcd[DP_DOWN_STREAM_PORT_COUNT] & DP_PORT_COUNT_MASK;
493
+
494
+ if (dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DETAILED_CAP_INFO_AVAILABLE && port_count > 4)
495
+ port_count = 4;
496
+
497
+ return port_count;
498
+}
499
+
500
+static int drm_dp_read_extended_dpcd_caps(struct drm_dp_aux *aux,
501
+ u8 dpcd[DP_RECEIVER_CAP_SIZE])
502
+{
503
+ u8 dpcd_ext[6];
504
+ int ret;
417505
418506 /*
419
- * According to the DP 1.1 specification, a "Sink Device must exit the
420
- * power saving state within 1 ms" (Section 2.5.3.1, Table 5-52, "Sink
421
- * Control Field" (register 0x600).
507
+ * Prior to DP1.3 the bit represented by
508
+ * DP_EXTENDED_RECEIVER_CAP_FIELD_PRESENT was reserved.
509
+ * If it is set DP_DPCD_REV at 0000h could be at a value less than
510
+ * the true capability of the panel. The only way to check is to
511
+ * then compare 0000h and 2200h.
422512 */
423
- usleep_range(1000, 2000);
424
-
425
- return 0;
426
-}
427
-EXPORT_SYMBOL(drm_dp_link_power_up);
428
-
429
-/**
430
- * drm_dp_link_power_down() - power down a DisplayPort link
431
- * @aux: DisplayPort AUX channel
432
- * @link: pointer to a structure containing the link configuration
433
- *
434
- * Returns 0 on success or a negative error code on failure.
435
- */
436
-int drm_dp_link_power_down(struct drm_dp_aux *aux, struct drm_dp_link *link)
437
-{
438
- u8 value;
439
- int err;
440
-
441
- /* DP_SET_POWER register is only available on DPCD v1.1 and later */
442
- if (link->revision < 0x11)
513
+ if (!(dpcd[DP_TRAINING_AUX_RD_INTERVAL] &
514
+ DP_EXTENDED_RECEIVER_CAP_FIELD_PRESENT))
443515 return 0;
444516
445
- err = drm_dp_dpcd_readb(aux, DP_SET_POWER, &value);
446
- if (err < 0)
447
- return err;
517
+ ret = drm_dp_dpcd_read(aux, DP_DP13_DPCD_REV, &dpcd_ext,
518
+ sizeof(dpcd_ext));
519
+ if (ret < 0)
520
+ return ret;
521
+ if (ret != sizeof(dpcd_ext))
522
+ return -EIO;
448523
449
- value &= ~DP_SET_POWER_MASK;
450
- value |= DP_SET_POWER_D3;
524
+ if (dpcd[DP_DPCD_REV] > dpcd_ext[DP_DPCD_REV]) {
525
+ DRM_DEBUG_KMS("%s: Extended DPCD rev less than base DPCD rev (%d > %d)\n",
526
+ aux->name, dpcd[DP_DPCD_REV],
527
+ dpcd_ext[DP_DPCD_REV]);
528
+ return 0;
529
+ }
451530
452
- err = drm_dp_dpcd_writeb(aux, DP_SET_POWER, value);
453
- if (err < 0)
454
- return err;
531
+ if (!memcmp(dpcd, dpcd_ext, sizeof(dpcd_ext)))
532
+ return 0;
533
+
534
+ DRM_DEBUG_KMS("%s: Base DPCD: %*ph\n",
535
+ aux->name, DP_RECEIVER_CAP_SIZE, dpcd);
536
+
537
+ memcpy(dpcd, dpcd_ext, sizeof(dpcd_ext));
455538
456539 return 0;
457540 }
458
-EXPORT_SYMBOL(drm_dp_link_power_down);
459541
460542 /**
461
- * drm_dp_link_configure() - configure a DisplayPort link
543
+ * drm_dp_read_dpcd_caps() - read DPCD caps and extended DPCD caps if
544
+ * available
462545 * @aux: DisplayPort AUX channel
463
- * @link: pointer to a structure containing the link configuration
546
+ * @dpcd: Buffer to store the resulting DPCD in
464547 *
465
- * Returns 0 on success or a negative error code on failure.
548
+ * Attempts to read the base DPCD caps for @aux. Additionally, this function
549
+ * checks for and reads the extended DPRX caps (%DP_DP13_DPCD_REV) if
550
+ * present.
551
+ *
552
+ * Returns: %0 if the DPCD was read successfully, negative error code
553
+ * otherwise.
466554 */
467
-int drm_dp_link_configure(struct drm_dp_aux *aux, struct drm_dp_link *link)
555
+int drm_dp_read_dpcd_caps(struct drm_dp_aux *aux,
556
+ u8 dpcd[DP_RECEIVER_CAP_SIZE])
468557 {
469
- u8 values[2];
470
- int err;
558
+ int ret;
471559
472
- values[0] = drm_dp_link_rate_to_bw_code(link->rate);
473
- values[1] = link->num_lanes;
560
+ ret = drm_dp_dpcd_read(aux, DP_DPCD_REV, dpcd, DP_RECEIVER_CAP_SIZE);
561
+ if (ret < 0)
562
+ return ret;
563
+ if (ret != DP_RECEIVER_CAP_SIZE || dpcd[DP_DPCD_REV] == 0)
564
+ return -EIO;
474565
475
- if (link->capabilities & DP_LINK_CAP_ENHANCED_FRAMING)
476
- values[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
566
+ ret = drm_dp_read_extended_dpcd_caps(aux, dpcd);
567
+ if (ret < 0)
568
+ return ret;
477569
478
- err = drm_dp_dpcd_write(aux, DP_LINK_BW_SET, values, sizeof(values));
479
- if (err < 0)
480
- return err;
570
+ DRM_DEBUG_KMS("%s: DPCD: %*ph\n",
571
+ aux->name, DP_RECEIVER_CAP_SIZE, dpcd);
572
+
573
+ return ret;
574
+}
575
+EXPORT_SYMBOL(drm_dp_read_dpcd_caps);
576
+
577
+/**
578
+ * drm_dp_read_downstream_info() - read DPCD downstream port info if available
579
+ * @aux: DisplayPort AUX channel
580
+ * @dpcd: A cached copy of the port's DPCD
581
+ * @downstream_ports: buffer to store the downstream port info in
582
+ *
583
+ * See also:
584
+ * drm_dp_downstream_max_clock()
585
+ * drm_dp_downstream_max_bpc()
586
+ *
587
+ * Returns: 0 if either the downstream port info was read successfully or
588
+ * there was no downstream info to read, or a negative error code otherwise.
589
+ */
590
+int drm_dp_read_downstream_info(struct drm_dp_aux *aux,
591
+ const u8 dpcd[DP_RECEIVER_CAP_SIZE],
592
+ u8 downstream_ports[DP_MAX_DOWNSTREAM_PORTS])
593
+{
594
+ int ret;
595
+ u8 len;
596
+
597
+ memset(downstream_ports, 0, DP_MAX_DOWNSTREAM_PORTS);
598
+
599
+ /* No downstream info to read */
600
+ if (!drm_dp_is_branch(dpcd) ||
601
+ dpcd[DP_DPCD_REV] < DP_DPCD_REV_10 ||
602
+ !(dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_PRESENT))
603
+ return 0;
604
+
605
+ /* Some branches advertise having 0 downstream ports, despite also advertising they have a
606
+ * downstream port present. The DP spec isn't clear on if this is allowed or not, but since
607
+ * some branches do it we need to handle it regardless.
608
+ */
609
+ len = drm_dp_downstream_port_count(dpcd);
610
+ if (!len)
611
+ return 0;
612
+
613
+ if (dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DETAILED_CAP_INFO_AVAILABLE)
614
+ len *= 4;
615
+
616
+ ret = drm_dp_dpcd_read(aux, DP_DOWNSTREAM_PORT_0, downstream_ports, len);
617
+ if (ret < 0)
618
+ return ret;
619
+ if (ret != len)
620
+ return -EIO;
621
+
622
+ DRM_DEBUG_KMS("%s: DPCD DFP: %*ph\n",
623
+ aux->name, len, downstream_ports);
481624
482625 return 0;
483626 }
484
-EXPORT_SYMBOL(drm_dp_link_configure);
627
+EXPORT_SYMBOL(drm_dp_read_downstream_info);
485628
486629 /**
487
- * drm_dp_downstream_max_clock() - extract branch device max
488
- * pixel rate for legacy VGA
489
- * converter or max TMDS clock
490
- * rate for others
630
+ * drm_dp_downstream_max_dotclock() - extract downstream facing port max dot clock
491631 * @dpcd: DisplayPort configuration data
492632 * @port_cap: port capabilities
493633 *
494
- * Returns max clock in kHz on success or 0 if max clock not defined
634
+ * Returns: Downstream facing port max dot clock in kHz on success,
635
+ * or 0 if max clock not defined
495636 */
496
-int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
497
- const u8 port_cap[4])
637
+int drm_dp_downstream_max_dotclock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
638
+ const u8 port_cap[4])
498639 {
499
- int type = port_cap[0] & DP_DS_PORT_TYPE_MASK;
500
- bool detailed_cap_info = dpcd[DP_DOWNSTREAMPORT_PRESENT] &
501
- DP_DETAILED_CAP_INFO_AVAILABLE;
502
-
503
- if (!detailed_cap_info)
640
+ if (!drm_dp_is_branch(dpcd))
504641 return 0;
505642
506
- switch (type) {
643
+ if (dpcd[DP_DPCD_REV] < 0x11)
644
+ return 0;
645
+
646
+ switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
507647 case DP_DS_PORT_TYPE_VGA:
508
- return port_cap[1] * 8 * 1000;
509
- case DP_DS_PORT_TYPE_DVI:
510
- case DP_DS_PORT_TYPE_HDMI:
648
+ if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DETAILED_CAP_INFO_AVAILABLE) == 0)
649
+ return 0;
650
+ return port_cap[1] * 8000;
651
+ default:
652
+ return 0;
653
+ }
654
+}
655
+EXPORT_SYMBOL(drm_dp_downstream_max_dotclock);
656
+
657
+/**
658
+ * drm_dp_downstream_max_tmds_clock() - extract downstream facing port max TMDS clock
659
+ * @dpcd: DisplayPort configuration data
660
+ * @port_cap: port capabilities
661
+ * @edid: EDID
662
+ *
663
+ * Returns: HDMI/DVI downstream facing port max TMDS clock in kHz on success,
664
+ * or 0 if max TMDS clock not defined
665
+ */
666
+int drm_dp_downstream_max_tmds_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
667
+ const u8 port_cap[4],
668
+ const struct edid *edid)
669
+{
670
+ if (!drm_dp_is_branch(dpcd))
671
+ return 0;
672
+
673
+ if (dpcd[DP_DPCD_REV] < 0x11) {
674
+ switch (dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_TYPE_MASK) {
675
+ case DP_DWN_STRM_PORT_TYPE_TMDS:
676
+ return 165000;
677
+ default:
678
+ return 0;
679
+ }
680
+ }
681
+
682
+ switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
511683 case DP_DS_PORT_TYPE_DP_DUALMODE:
684
+ if (is_edid_digital_input_dp(edid))
685
+ return 0;
686
+ /*
687
+ * It's left up to the driver to check the
688
+ * DP dual mode adapter's max TMDS clock.
689
+ *
690
+ * Unfortunatley it looks like branch devices
691
+ * may not fordward that the DP dual mode i2c
692
+ * access so we just usually get i2c nak :(
693
+ */
694
+ fallthrough;
695
+ case DP_DS_PORT_TYPE_HDMI:
696
+ /*
697
+ * We should perhaps assume 165 MHz when detailed cap
698
+ * info is not available. But looks like many typical
699
+ * branch devices fall into that category and so we'd
700
+ * probably end up with users complaining that they can't
701
+ * get high resolution modes with their favorite dongle.
702
+ *
703
+ * So let's limit to 300 MHz instead since DPCD 1.4
704
+ * HDMI 2.0 DFPs are required to have the detailed cap
705
+ * info. So it's more likely we're dealing with a HDMI 1.4
706
+ * compatible* device here.
707
+ */
708
+ if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DETAILED_CAP_INFO_AVAILABLE) == 0)
709
+ return 300000;
710
+ return port_cap[1] * 2500;
711
+ case DP_DS_PORT_TYPE_DVI:
712
+ if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DETAILED_CAP_INFO_AVAILABLE) == 0)
713
+ return 165000;
714
+ /* FIXME what to do about DVI dual link? */
512715 return port_cap[1] * 2500;
513716 default:
514717 return 0;
515718 }
516719 }
517
-EXPORT_SYMBOL(drm_dp_downstream_max_clock);
720
+EXPORT_SYMBOL(drm_dp_downstream_max_tmds_clock);
518721
519722 /**
520
- * drm_dp_downstream_max_bpc() - extract branch device max
521
- * bits per component
723
+ * drm_dp_downstream_min_tmds_clock() - extract downstream facing port min TMDS clock
522724 * @dpcd: DisplayPort configuration data
523725 * @port_cap: port capabilities
726
+ * @edid: EDID
524727 *
525
- * Returns max bpc on success or 0 if max bpc not defined
728
+ * Returns: HDMI/DVI downstream facing port min TMDS clock in kHz on success,
729
+ * or 0 if max TMDS clock not defined
526730 */
527
-int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
528
- const u8 port_cap[4])
731
+int drm_dp_downstream_min_tmds_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
732
+ const u8 port_cap[4],
733
+ const struct edid *edid)
529734 {
530
- int type = port_cap[0] & DP_DS_PORT_TYPE_MASK;
531
- bool detailed_cap_info = dpcd[DP_DOWNSTREAMPORT_PRESENT] &
532
- DP_DETAILED_CAP_INFO_AVAILABLE;
533
- int bpc;
534
-
535
- if (!detailed_cap_info)
735
+ if (!drm_dp_is_branch(dpcd))
536736 return 0;
537737
538
- switch (type) {
539
- case DP_DS_PORT_TYPE_VGA:
738
+ if (dpcd[DP_DPCD_REV] < 0x11) {
739
+ switch (dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_TYPE_MASK) {
740
+ case DP_DWN_STRM_PORT_TYPE_TMDS:
741
+ return 25000;
742
+ default:
743
+ return 0;
744
+ }
745
+ }
746
+
747
+ switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
748
+ case DP_DS_PORT_TYPE_DP_DUALMODE:
749
+ if (is_edid_digital_input_dp(edid))
750
+ return 0;
751
+ fallthrough;
540752 case DP_DS_PORT_TYPE_DVI:
541753 case DP_DS_PORT_TYPE_HDMI:
542
- case DP_DS_PORT_TYPE_DP_DUALMODE:
543
- bpc = port_cap[2] & DP_DS_MAX_BPC_MASK;
754
+ /*
755
+ * Unclear whether the protocol converter could
756
+ * utilize pixel replication. Assume it won't.
757
+ */
758
+ return 25000;
759
+ default:
760
+ return 0;
761
+ }
762
+}
763
+EXPORT_SYMBOL(drm_dp_downstream_min_tmds_clock);
544764
545
- switch (bpc) {
765
+/**
766
+ * drm_dp_downstream_max_bpc() - extract downstream facing port max
767
+ * bits per component
768
+ * @dpcd: DisplayPort configuration data
769
+ * @port_cap: downstream facing port capabilities
770
+ * @edid: EDID
771
+ *
772
+ * Returns: Max bpc on success or 0 if max bpc not defined
773
+ */
774
+int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
775
+ const u8 port_cap[4],
776
+ const struct edid *edid)
777
+{
778
+ if (!drm_dp_is_branch(dpcd))
779
+ return 0;
780
+
781
+ if (dpcd[DP_DPCD_REV] < 0x11) {
782
+ switch (dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_TYPE_MASK) {
783
+ case DP_DWN_STRM_PORT_TYPE_DP:
784
+ return 0;
785
+ default:
786
+ return 8;
787
+ }
788
+ }
789
+
790
+ switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
791
+ case DP_DS_PORT_TYPE_DP:
792
+ return 0;
793
+ case DP_DS_PORT_TYPE_DP_DUALMODE:
794
+ if (is_edid_digital_input_dp(edid))
795
+ return 0;
796
+ fallthrough;
797
+ case DP_DS_PORT_TYPE_HDMI:
798
+ case DP_DS_PORT_TYPE_DVI:
799
+ case DP_DS_PORT_TYPE_VGA:
800
+ if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DETAILED_CAP_INFO_AVAILABLE) == 0)
801
+ return 8;
802
+
803
+ switch (port_cap[2] & DP_DS_MAX_BPC_MASK) {
546804 case DP_DS_8BPC:
547805 return 8;
548806 case DP_DS_10BPC:
....@@ -551,12 +809,130 @@
551809 return 12;
552810 case DP_DS_16BPC:
553811 return 16;
812
+ default:
813
+ return 8;
554814 }
815
+ break;
555816 default:
556
- return 0;
817
+ return 8;
557818 }
558819 }
559820 EXPORT_SYMBOL(drm_dp_downstream_max_bpc);
821
+
822
+/**
823
+ * drm_dp_downstream_420_passthrough() - determine downstream facing port
824
+ * YCbCr 4:2:0 pass-through capability
825
+ * @dpcd: DisplayPort configuration data
826
+ * @port_cap: downstream facing port capabilities
827
+ *
828
+ * Returns: whether the downstream facing port can pass through YCbCr 4:2:0
829
+ */
830
+bool drm_dp_downstream_420_passthrough(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
831
+ const u8 port_cap[4])
832
+{
833
+ if (!drm_dp_is_branch(dpcd))
834
+ return false;
835
+
836
+ if (dpcd[DP_DPCD_REV] < 0x13)
837
+ return false;
838
+
839
+ switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
840
+ case DP_DS_PORT_TYPE_DP:
841
+ return true;
842
+ case DP_DS_PORT_TYPE_HDMI:
843
+ if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DETAILED_CAP_INFO_AVAILABLE) == 0)
844
+ return false;
845
+
846
+ return port_cap[3] & DP_DS_HDMI_YCBCR420_PASS_THROUGH;
847
+ default:
848
+ return false;
849
+ }
850
+}
851
+EXPORT_SYMBOL(drm_dp_downstream_420_passthrough);
852
+
853
+/**
854
+ * drm_dp_downstream_444_to_420_conversion() - determine downstream facing port
855
+ * YCbCr 4:4:4->4:2:0 conversion capability
856
+ * @dpcd: DisplayPort configuration data
857
+ * @port_cap: downstream facing port capabilities
858
+ *
859
+ * Returns: whether the downstream facing port can convert YCbCr 4:4:4 to 4:2:0
860
+ */
861
+bool drm_dp_downstream_444_to_420_conversion(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
862
+ const u8 port_cap[4])
863
+{
864
+ if (!drm_dp_is_branch(dpcd))
865
+ return false;
866
+
867
+ if (dpcd[DP_DPCD_REV] < 0x13)
868
+ return false;
869
+
870
+ switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
871
+ case DP_DS_PORT_TYPE_HDMI:
872
+ if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DETAILED_CAP_INFO_AVAILABLE) == 0)
873
+ return false;
874
+
875
+ return port_cap[3] & DP_DS_HDMI_YCBCR444_TO_420_CONV;
876
+ default:
877
+ return false;
878
+ }
879
+}
880
+EXPORT_SYMBOL(drm_dp_downstream_444_to_420_conversion);
881
+
882
+/**
883
+ * drm_dp_downstream_mode() - return a mode for downstream facing port
884
+ * @dev: DRM device
885
+ * @dpcd: DisplayPort configuration data
886
+ * @port_cap: port capabilities
887
+ *
888
+ * Provides a suitable mode for downstream facing ports without EDID.
889
+ *
890
+ * Returns: A new drm_display_mode on success or NULL on failure
891
+ */
892
+struct drm_display_mode *
893
+drm_dp_downstream_mode(struct drm_device *dev,
894
+ const u8 dpcd[DP_RECEIVER_CAP_SIZE],
895
+ const u8 port_cap[4])
896
+
897
+{
898
+ u8 vic;
899
+
900
+ if (!drm_dp_is_branch(dpcd))
901
+ return NULL;
902
+
903
+ if (dpcd[DP_DPCD_REV] < 0x11)
904
+ return NULL;
905
+
906
+ switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
907
+ case DP_DS_PORT_TYPE_NON_EDID:
908
+ switch (port_cap[0] & DP_DS_NON_EDID_MASK) {
909
+ case DP_DS_NON_EDID_720x480i_60:
910
+ vic = 6;
911
+ break;
912
+ case DP_DS_NON_EDID_720x480i_50:
913
+ vic = 21;
914
+ break;
915
+ case DP_DS_NON_EDID_1920x1080i_60:
916
+ vic = 5;
917
+ break;
918
+ case DP_DS_NON_EDID_1920x1080i_50:
919
+ vic = 20;
920
+ break;
921
+ case DP_DS_NON_EDID_1280x720_60:
922
+ vic = 4;
923
+ break;
924
+ case DP_DS_NON_EDID_1280x720_50:
925
+ vic = 19;
926
+ break;
927
+ default:
928
+ return NULL;
929
+ }
930
+ return drm_display_mode_from_cea_vic(dev, vic);
931
+ default:
932
+ return NULL;
933
+ }
934
+}
935
+EXPORT_SYMBOL(drm_dp_downstream_mode);
560936
561937 /**
562938 * drm_dp_downstream_id() - identify branch device
....@@ -576,12 +952,15 @@
576952 * @m: pointer for debugfs file
577953 * @dpcd: DisplayPort configuration data
578954 * @port_cap: port capabilities
955
+ * @edid: EDID
579956 * @aux: DisplayPort AUX channel
580957 *
581958 */
582959 void drm_dp_downstream_debug(struct seq_file *m,
583960 const u8 dpcd[DP_RECEIVER_CAP_SIZE],
584
- const u8 port_cap[4], struct drm_dp_aux *aux)
961
+ const u8 port_cap[4],
962
+ const struct edid *edid,
963
+ struct drm_dp_aux *aux)
585964 {
586965 bool detailed_cap_info = dpcd[DP_DOWNSTREAMPORT_PRESENT] &
587966 DP_DETAILED_CAP_INFO_AVAILABLE;
....@@ -591,8 +970,7 @@
591970 int len;
592971 uint8_t rev[2];
593972 int type = port_cap[0] & DP_DS_PORT_TYPE_MASK;
594
- bool branch_device = dpcd[DP_DOWNSTREAMPORT_PRESENT] &
595
- DP_DWN_STRM_PORT_PRESENT;
973
+ bool branch_device = drm_dp_is_branch(dpcd);
596974
597975 seq_printf(m, "\tDP branch device present: %s\n",
598976 branch_device ? "yes" : "no");
....@@ -640,22 +1018,149 @@
6401018 seq_printf(m, "\t\tSW: %d.%d\n", rev[0], rev[1]);
6411019
6421020 if (detailed_cap_info) {
643
- clk = drm_dp_downstream_max_clock(dpcd, port_cap);
1021
+ clk = drm_dp_downstream_max_dotclock(dpcd, port_cap);
1022
+ if (clk > 0)
1023
+ seq_printf(m, "\t\tMax dot clock: %d kHz\n", clk);
6441024
645
- if (clk > 0) {
646
- if (type == DP_DS_PORT_TYPE_VGA)
647
- seq_printf(m, "\t\tMax dot clock: %d kHz\n", clk);
648
- else
649
- seq_printf(m, "\t\tMax TMDS clock: %d kHz\n", clk);
650
- }
1025
+ clk = drm_dp_downstream_max_tmds_clock(dpcd, port_cap, edid);
1026
+ if (clk > 0)
1027
+ seq_printf(m, "\t\tMax TMDS clock: %d kHz\n", clk);
6511028
652
- bpc = drm_dp_downstream_max_bpc(dpcd, port_cap);
1029
+ clk = drm_dp_downstream_min_tmds_clock(dpcd, port_cap, edid);
1030
+ if (clk > 0)
1031
+ seq_printf(m, "\t\tMin TMDS clock: %d kHz\n", clk);
1032
+
1033
+ bpc = drm_dp_downstream_max_bpc(dpcd, port_cap, edid);
6531034
6541035 if (bpc > 0)
6551036 seq_printf(m, "\t\tMax bpc: %d\n", bpc);
6561037 }
6571038 }
6581039 EXPORT_SYMBOL(drm_dp_downstream_debug);
1040
+
1041
+/**
1042
+ * drm_dp_subconnector_type() - get DP branch device type
1043
+ * @dpcd: DisplayPort configuration data
1044
+ * @port_cap: port capabilities
1045
+ */
1046
+enum drm_mode_subconnector
1047
+drm_dp_subconnector_type(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
1048
+ const u8 port_cap[4])
1049
+{
1050
+ int type;
1051
+ if (!drm_dp_is_branch(dpcd))
1052
+ return DRM_MODE_SUBCONNECTOR_Native;
1053
+ /* DP 1.0 approach */
1054
+ if (dpcd[DP_DPCD_REV] == DP_DPCD_REV_10) {
1055
+ type = dpcd[DP_DOWNSTREAMPORT_PRESENT] &
1056
+ DP_DWN_STRM_PORT_TYPE_MASK;
1057
+
1058
+ switch (type) {
1059
+ case DP_DWN_STRM_PORT_TYPE_TMDS:
1060
+ /* Can be HDMI or DVI-D, DVI-D is a safer option */
1061
+ return DRM_MODE_SUBCONNECTOR_DVID;
1062
+ case DP_DWN_STRM_PORT_TYPE_ANALOG:
1063
+ /* Can be VGA or DVI-A, VGA is more popular */
1064
+ return DRM_MODE_SUBCONNECTOR_VGA;
1065
+ case DP_DWN_STRM_PORT_TYPE_DP:
1066
+ return DRM_MODE_SUBCONNECTOR_DisplayPort;
1067
+ case DP_DWN_STRM_PORT_TYPE_OTHER:
1068
+ default:
1069
+ return DRM_MODE_SUBCONNECTOR_Unknown;
1070
+ }
1071
+ }
1072
+ type = port_cap[0] & DP_DS_PORT_TYPE_MASK;
1073
+
1074
+ switch (type) {
1075
+ case DP_DS_PORT_TYPE_DP:
1076
+ case DP_DS_PORT_TYPE_DP_DUALMODE:
1077
+ return DRM_MODE_SUBCONNECTOR_DisplayPort;
1078
+ case DP_DS_PORT_TYPE_VGA:
1079
+ return DRM_MODE_SUBCONNECTOR_VGA;
1080
+ case DP_DS_PORT_TYPE_DVI:
1081
+ return DRM_MODE_SUBCONNECTOR_DVID;
1082
+ case DP_DS_PORT_TYPE_HDMI:
1083
+ return DRM_MODE_SUBCONNECTOR_HDMIA;
1084
+ case DP_DS_PORT_TYPE_WIRELESS:
1085
+ return DRM_MODE_SUBCONNECTOR_Wireless;
1086
+ case DP_DS_PORT_TYPE_NON_EDID:
1087
+ default:
1088
+ return DRM_MODE_SUBCONNECTOR_Unknown;
1089
+ }
1090
+}
1091
+EXPORT_SYMBOL(drm_dp_subconnector_type);
1092
+
1093
+/**
1094
+ * drm_mode_set_dp_subconnector_property - set subconnector for DP connector
1095
+ * @connector: connector to set property on
1096
+ * @status: connector status
1097
+ * @dpcd: DisplayPort configuration data
1098
+ * @port_cap: port capabilities
1099
+ *
1100
+ * Called by a driver on every detect event.
1101
+ */
1102
+void drm_dp_set_subconnector_property(struct drm_connector *connector,
1103
+ enum drm_connector_status status,
1104
+ const u8 *dpcd,
1105
+ const u8 port_cap[4])
1106
+{
1107
+ enum drm_mode_subconnector subconnector = DRM_MODE_SUBCONNECTOR_Unknown;
1108
+
1109
+ if (status == connector_status_connected)
1110
+ subconnector = drm_dp_subconnector_type(dpcd, port_cap);
1111
+ drm_object_property_set_value(&connector->base,
1112
+ connector->dev->mode_config.dp_subconnector_property,
1113
+ subconnector);
1114
+}
1115
+EXPORT_SYMBOL(drm_dp_set_subconnector_property);
1116
+
1117
+/**
1118
+ * drm_dp_read_sink_count_cap() - Check whether a given connector has a valid sink
1119
+ * count
1120
+ * @connector: The DRM connector to check
1121
+ * @dpcd: A cached copy of the connector's DPCD RX capabilities
1122
+ * @desc: A cached copy of the connector's DP descriptor
1123
+ *
1124
+ * See also: drm_dp_read_sink_count()
1125
+ *
1126
+ * Returns: %True if the (e)DP connector has a valid sink count that should
1127
+ * be probed, %false otherwise.
1128
+ */
1129
+bool drm_dp_read_sink_count_cap(struct drm_connector *connector,
1130
+ const u8 dpcd[DP_RECEIVER_CAP_SIZE],
1131
+ const struct drm_dp_desc *desc)
1132
+{
1133
+ /* Some eDP panels don't set a valid value for the sink count */
1134
+ return connector->connector_type != DRM_MODE_CONNECTOR_eDP &&
1135
+ dpcd[DP_DPCD_REV] >= DP_DPCD_REV_11 &&
1136
+ dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_PRESENT &&
1137
+ !drm_dp_has_quirk(desc, 0, DP_DPCD_QUIRK_NO_SINK_COUNT);
1138
+}
1139
+EXPORT_SYMBOL(drm_dp_read_sink_count_cap);
1140
+
1141
+/**
1142
+ * drm_dp_read_sink_count() - Retrieve the sink count for a given sink
1143
+ * @aux: The DP AUX channel to use
1144
+ *
1145
+ * See also: drm_dp_read_sink_count_cap()
1146
+ *
1147
+ * Returns: The current sink count reported by @aux, or a negative error code
1148
+ * otherwise.
1149
+ */
1150
+int drm_dp_read_sink_count(struct drm_dp_aux *aux)
1151
+{
1152
+ u8 count;
1153
+ int ret;
1154
+
1155
+ ret = drm_dp_dpcd_readb(aux, DP_SINK_COUNT, &count);
1156
+ if (ret < 0)
1157
+ return ret;
1158
+ if (ret != 1)
1159
+ return -EIO;
1160
+
1161
+ return DP_GET_SINK_COUNT(count);
1162
+}
1163
+EXPORT_SYMBOL(drm_dp_read_sink_count);
6591164
6601165 /*
6611166 * I2C-over-AUX implementation
....@@ -800,10 +1305,11 @@
8001305 * Avoid spamming the kernel log with timeout errors.
8011306 */
8021307 if (ret == -ETIMEDOUT)
803
- DRM_DEBUG_KMS_RATELIMITED("transaction timed out\n");
1308
+ DRM_DEBUG_KMS_RATELIMITED("%s: transaction timed out\n",
1309
+ aux->name);
8041310 else
805
- DRM_DEBUG_KMS("transaction failed: %d\n", ret);
806
-
1311
+ DRM_DEBUG_KMS("%s: transaction failed: %d\n",
1312
+ aux->name, ret);
8071313 return ret;
8081314 }
8091315
....@@ -817,11 +1323,12 @@
8171323 break;
8181324
8191325 case DP_AUX_NATIVE_REPLY_NACK:
820
- DRM_DEBUG_KMS("native nack (result=%d, size=%zu)\n", ret, msg->size);
1326
+ DRM_DEBUG_KMS("%s: native nack (result=%d, size=%zu)\n",
1327
+ aux->name, ret, msg->size);
8211328 return -EREMOTEIO;
8221329
8231330 case DP_AUX_NATIVE_REPLY_DEFER:
824
- DRM_DEBUG_KMS("native defer\n");
1331
+ DRM_DEBUG_KMS("%s: native defer\n", aux->name);
8251332 /*
8261333 * We could check for I2C bit rate capabilities and if
8271334 * available adjust this interval. We could also be
....@@ -835,7 +1342,8 @@
8351342 continue;
8361343
8371344 default:
838
- DRM_ERROR("invalid native reply %#04x\n", msg->reply);
1345
+ DRM_ERROR("%s: invalid native reply %#04x\n",
1346
+ aux->name, msg->reply);
8391347 return -EREMOTEIO;
8401348 }
8411349
....@@ -850,12 +1358,13 @@
8501358 return ret;
8511359
8521360 case DP_AUX_I2C_REPLY_NACK:
853
- DRM_DEBUG_KMS("I2C nack (result=%d, size=%zu\n", ret, msg->size);
1361
+ DRM_DEBUG_KMS("%s: I2C nack (result=%d, size=%zu)\n",
1362
+ aux->name, ret, msg->size);
8541363 aux->i2c_nack_count++;
8551364 return -EREMOTEIO;
8561365
8571366 case DP_AUX_I2C_REPLY_DEFER:
858
- DRM_DEBUG_KMS("I2C defer\n");
1367
+ DRM_DEBUG_KMS("%s: I2C defer\n", aux->name);
8591368 /* DP Compliance Test 4.2.2.5 Requirement:
8601369 * Must have at least 7 retries for I2C defers on the
8611370 * transaction to pass this test
....@@ -869,12 +1378,13 @@
8691378 continue;
8701379
8711380 default:
872
- DRM_ERROR("invalid I2C reply %#04x\n", msg->reply);
1381
+ DRM_ERROR("%s: invalid I2C reply %#04x\n",
1382
+ aux->name, msg->reply);
8731383 return -EREMOTEIO;
8741384 }
8751385 }
8761386
877
- DRM_DEBUG_KMS("too many retries, giving up\n");
1387
+ DRM_DEBUG_KMS("%s: Too many retries, giving up\n", aux->name);
8781388 return -EREMOTEIO;
8791389 }
8801390
....@@ -883,7 +1393,8 @@
8831393 {
8841394 msg->request = (i2c_msg->flags & I2C_M_RD) ?
8851395 DP_AUX_I2C_READ : DP_AUX_I2C_WRITE;
886
- msg->request |= DP_AUX_I2C_MOT;
1396
+ if (!(i2c_msg->flags & I2C_M_STOP))
1397
+ msg->request |= DP_AUX_I2C_MOT;
8871398 }
8881399
8891400 /*
....@@ -902,8 +1413,8 @@
9021413 return err == 0 ? -EPROTO : err;
9031414
9041415 if (err < msg.size && err < ret) {
905
- DRM_DEBUG_KMS("Partial I2C reply: requested %zu bytes got %d bytes\n",
906
- msg.size, err);
1416
+ DRM_DEBUG_KMS("%s: Partial I2C reply: requested %zu bytes got %d bytes\n",
1417
+ aux->name, msg.size, err);
9071418 ret = err;
9081419 }
9091420
....@@ -1082,11 +1593,12 @@
10821593 }
10831594
10841595 if (ret == -EAGAIN) {
1085
- DRM_DEBUG_KMS("Get CRC failed after retrying: %d\n",
1086
- ret);
1596
+ DRM_DEBUG_KMS("%s: Get CRC failed after retrying: %d\n",
1597
+ aux->name, ret);
10871598 continue;
10881599 } else if (ret) {
1089
- DRM_DEBUG_KMS("Failed to get a CRC: %d\n", ret);
1600
+ DRM_DEBUG_KMS("%s: Failed to get a CRC: %d\n",
1601
+ aux->name, ret);
10901602 continue;
10911603 }
10921604
....@@ -1096,6 +1608,19 @@
10961608 drm_crtc_add_crc_entry(crtc, false, 0, crcs);
10971609 }
10981610 }
1611
+
1612
+/**
1613
+ * drm_dp_remote_aux_init() - minimally initialise a remote aux channel
1614
+ * @aux: DisplayPort AUX channel
1615
+ *
1616
+ * Used for remote aux channel in general. Merely initialize the crc work
1617
+ * struct.
1618
+ */
1619
+void drm_dp_remote_aux_init(struct drm_dp_aux *aux)
1620
+{
1621
+ INIT_WORK(&aux->crc_work, drm_dp_aux_crc_work);
1622
+}
1623
+EXPORT_SYMBOL(drm_dp_remote_aux_init);
10991624
11001625 /**
11011626 * drm_dp_aux_init() - minimally initialise an aux channel
....@@ -1125,6 +1650,14 @@
11251650 * @aux: DisplayPort AUX channel
11261651 *
11271652 * Automatically calls drm_dp_aux_init() if this hasn't been done yet.
1653
+ * This should only be called when the underlying &struct drm_connector is
1654
+ * initialiazed already. Therefore the best place to call this is from
1655
+ * &drm_connector_funcs.late_register. Not that drivers which don't follow this
1656
+ * will Oops when CONFIG_DRM_DP_AUX_CHARDEV is enabled.
1657
+ *
1658
+ * Drivers which need to use the aux channel before that point (e.g. at driver
1659
+ * load time, before drm_dev_register() has been called) need to call
1660
+ * drm_dp_aux_init().
11281661 *
11291662 * Returns 0 on success or a negative error code on failure.
11301663 */
....@@ -1256,15 +1789,30 @@
12561789
12571790 struct dpcd_quirk {
12581791 u8 oui[3];
1792
+ u8 device_id[6];
12591793 bool is_branch;
12601794 u32 quirks;
12611795 };
12621796
12631797 #define OUI(first, second, third) { (first), (second), (third) }
1798
+#define DEVICE_ID(first, second, third, fourth, fifth, sixth) \
1799
+ { (first), (second), (third), (fourth), (fifth), (sixth) }
1800
+
1801
+#define DEVICE_ID_ANY DEVICE_ID(0, 0, 0, 0, 0, 0)
12641802
12651803 static const struct dpcd_quirk dpcd_quirk_list[] = {
12661804 /* Analogix 7737 needs reduced M and N at HBR2 link rates */
1267
- { OUI(0x00, 0x22, 0xb9), true, BIT(DP_DPCD_QUIRK_LIMITED_M_N) },
1805
+ { OUI(0x00, 0x22, 0xb9), DEVICE_ID_ANY, true, BIT(DP_DPCD_QUIRK_CONSTANT_N) },
1806
+ /* LG LP140WF6-SPM1 eDP panel */
1807
+ { OUI(0x00, 0x22, 0xb9), DEVICE_ID('s', 'i', 'v', 'a', 'r', 'T'), false, BIT(DP_DPCD_QUIRK_CONSTANT_N) },
1808
+ /* Apple panels need some additional handling to support PSR */
1809
+ { OUI(0x00, 0x10, 0xfa), DEVICE_ID_ANY, false, BIT(DP_DPCD_QUIRK_NO_PSR) },
1810
+ /* CH7511 seems to leave SINK_COUNT zeroed */
1811
+ { OUI(0x00, 0x00, 0x00), DEVICE_ID('C', 'H', '7', '5', '1', '1'), false, BIT(DP_DPCD_QUIRK_NO_SINK_COUNT) },
1812
+ /* Synaptics DP1.4 MST hubs can support DSC without virtual DPCD */
1813
+ { OUI(0x90, 0xCC, 0x24), DEVICE_ID_ANY, true, BIT(DP_DPCD_QUIRK_DSC_WITHOUT_VIRTUAL_DPCD) },
1814
+ /* Apple MacBookPro 2017 15 inch eDP Retina panel reports too low DP_MAX_LINK_RATE */
1815
+ { OUI(0x00, 0x10, 0xfa), DEVICE_ID(101, 68, 21, 101, 98, 97), false, BIT(DP_DPCD_QUIRK_CAN_DO_MAX_LINK_RATE_3_24_GBPS) },
12681816 };
12691817
12701818 #undef OUI
....@@ -1283,6 +1831,7 @@
12831831 const struct dpcd_quirk *quirk;
12841832 u32 quirks = 0;
12851833 int i;
1834
+ u8 any_device[] = DEVICE_ID_ANY;
12861835
12871836 for (i = 0; i < ARRAY_SIZE(dpcd_quirk_list); i++) {
12881837 quirk = &dpcd_quirk_list[i];
....@@ -1293,16 +1842,103 @@
12931842 if (memcmp(quirk->oui, ident->oui, sizeof(ident->oui)) != 0)
12941843 continue;
12951844
1845
+ if (memcmp(quirk->device_id, any_device, sizeof(any_device)) != 0 &&
1846
+ memcmp(quirk->device_id, ident->device_id, sizeof(ident->device_id)) != 0)
1847
+ continue;
1848
+
12961849 quirks |= quirk->quirks;
12971850 }
12981851
12991852 return quirks;
13001853 }
13011854
1855
+#undef DEVICE_ID_ANY
1856
+#undef DEVICE_ID
1857
+
1858
+struct edid_quirk {
1859
+ u8 mfg_id[2];
1860
+ u8 prod_id[2];
1861
+ u32 quirks;
1862
+};
1863
+
1864
+#define MFG(first, second) { (first), (second) }
1865
+#define PROD_ID(first, second) { (first), (second) }
1866
+
1867
+/*
1868
+ * Some devices have unreliable OUIDs where they don't set the device ID
1869
+ * correctly, and as a result we need to use the EDID for finding additional
1870
+ * DP quirks in such cases.
1871
+ */
1872
+static const struct edid_quirk edid_quirk_list[] = {
1873
+ /* Optional 4K AMOLED panel in the ThinkPad X1 Extreme 2nd Generation
1874
+ * only supports DPCD backlight controls
1875
+ */
1876
+ { MFG(0x4c, 0x83), PROD_ID(0x41, 0x41), BIT(DP_QUIRK_FORCE_DPCD_BACKLIGHT) },
1877
+ /*
1878
+ * Some Dell CML 2020 systems have panels support both AUX and PWM
1879
+ * backlight control, and some only support AUX backlight control. All
1880
+ * said panels start up in AUX mode by default, and we don't have any
1881
+ * support for disabling HDR mode on these panels which would be
1882
+ * required to switch to PWM backlight control mode (plus, I'm not
1883
+ * even sure we want PWM backlight controls over DPCD backlight
1884
+ * controls anyway...). Until we have a better way of detecting these,
1885
+ * force DPCD backlight mode on all of them.
1886
+ */
1887
+ { MFG(0x06, 0xaf), PROD_ID(0x9b, 0x32), BIT(DP_QUIRK_FORCE_DPCD_BACKLIGHT) },
1888
+ { MFG(0x06, 0xaf), PROD_ID(0xeb, 0x41), BIT(DP_QUIRK_FORCE_DPCD_BACKLIGHT) },
1889
+ { MFG(0x4d, 0x10), PROD_ID(0xc7, 0x14), BIT(DP_QUIRK_FORCE_DPCD_BACKLIGHT) },
1890
+ { MFG(0x4d, 0x10), PROD_ID(0xe6, 0x14), BIT(DP_QUIRK_FORCE_DPCD_BACKLIGHT) },
1891
+ { MFG(0x4c, 0x83), PROD_ID(0x47, 0x41), BIT(DP_QUIRK_FORCE_DPCD_BACKLIGHT) },
1892
+};
1893
+
1894
+#undef MFG
1895
+#undef PROD_ID
1896
+
1897
+/**
1898
+ * drm_dp_get_edid_quirks() - Check the EDID of a DP device to find additional
1899
+ * DP-specific quirks
1900
+ * @edid: The EDID to check
1901
+ *
1902
+ * While OUIDs are meant to be used to recognize a DisplayPort device, a lot
1903
+ * of manufacturers don't seem to like following standards and neglect to fill
1904
+ * the dev-ID in, making it impossible to only use OUIDs for determining
1905
+ * quirks in some cases. This function can be used to check the EDID and look
1906
+ * up any additional DP quirks. The bits returned by this function correspond
1907
+ * to the quirk bits in &drm_dp_quirk.
1908
+ *
1909
+ * Returns: a bitmask of quirks, if any. The driver can check this using
1910
+ * drm_dp_has_quirk().
1911
+ */
1912
+u32 drm_dp_get_edid_quirks(const struct edid *edid)
1913
+{
1914
+ const struct edid_quirk *quirk;
1915
+ u32 quirks = 0;
1916
+ int i;
1917
+
1918
+ if (!edid)
1919
+ return 0;
1920
+
1921
+ for (i = 0; i < ARRAY_SIZE(edid_quirk_list); i++) {
1922
+ quirk = &edid_quirk_list[i];
1923
+ if (memcmp(quirk->mfg_id, edid->mfg_id,
1924
+ sizeof(edid->mfg_id)) == 0 &&
1925
+ memcmp(quirk->prod_id, edid->prod_code,
1926
+ sizeof(edid->prod_code)) == 0)
1927
+ quirks |= quirk->quirks;
1928
+ }
1929
+
1930
+ DRM_DEBUG_KMS("DP sink: EDID mfg %*phD prod-ID %*phD quirks: 0x%04x\n",
1931
+ (int)sizeof(edid->mfg_id), edid->mfg_id,
1932
+ (int)sizeof(edid->prod_code), edid->prod_code, quirks);
1933
+
1934
+ return quirks;
1935
+}
1936
+EXPORT_SYMBOL(drm_dp_get_edid_quirks);
1937
+
13021938 /**
13031939 * drm_dp_read_desc - read sink/branch descriptor from DPCD
13041940 * @aux: DisplayPort AUX channel
1305
- * @desc: Device decriptor to fill from DPCD
1941
+ * @desc: Device descriptor to fill from DPCD
13061942 * @is_branch: true for branch devices, false for sink devices
13071943 *
13081944 * Read DPCD 0x400 (sink) or 0x500 (branch) into @desc. Also debug log the
....@@ -1325,8 +1961,8 @@
13251961
13261962 dev_id_len = strnlen(ident->device_id, sizeof(ident->device_id));
13271963
1328
- DRM_DEBUG_KMS("DP %s: OUI %*phD dev-ID %*pE HW-rev %d.%d SW-rev %d.%d quirks 0x%04x\n",
1329
- is_branch ? "branch" : "sink",
1964
+ DRM_DEBUG_KMS("%s: DP %s: OUI %*phD dev-ID %*pE HW-rev %d.%d SW-rev %d.%d quirks 0x%04x\n",
1965
+ aux->name, is_branch ? "branch" : "sink",
13301966 (int)sizeof(ident->oui), ident->oui,
13311967 dev_id_len, ident->device_id,
13321968 ident->hw_rev >> 4, ident->hw_rev & 0xf,
....@@ -1473,3 +2109,263 @@
14732109 return num_bpc;
14742110 }
14752111 EXPORT_SYMBOL(drm_dp_dsc_sink_supported_input_bpcs);
2112
+
2113
+/**
2114
+ * drm_dp_get_phy_test_pattern() - get the requested pattern from the sink.
2115
+ * @aux: DisplayPort AUX channel
2116
+ * @data: DP phy compliance test parameters.
2117
+ *
2118
+ * Returns 0 on success or a negative error code on failure.
2119
+ */
2120
+int drm_dp_get_phy_test_pattern(struct drm_dp_aux *aux,
2121
+ struct drm_dp_phy_test_params *data)
2122
+{
2123
+ int err;
2124
+ u8 rate, lanes;
2125
+
2126
+ err = drm_dp_dpcd_readb(aux, DP_TEST_LINK_RATE, &rate);
2127
+ if (err < 0)
2128
+ return err;
2129
+ data->link_rate = drm_dp_bw_code_to_link_rate(rate);
2130
+
2131
+ err = drm_dp_dpcd_readb(aux, DP_TEST_LANE_COUNT, &lanes);
2132
+ if (err < 0)
2133
+ return err;
2134
+ data->num_lanes = lanes & DP_MAX_LANE_COUNT_MASK;
2135
+
2136
+ if (lanes & DP_ENHANCED_FRAME_CAP)
2137
+ data->enhanced_frame_cap = true;
2138
+
2139
+ err = drm_dp_dpcd_readb(aux, DP_PHY_TEST_PATTERN, &data->phy_pattern);
2140
+ if (err < 0)
2141
+ return err;
2142
+
2143
+ switch (data->phy_pattern) {
2144
+ case DP_PHY_TEST_PATTERN_80BIT_CUSTOM:
2145
+ err = drm_dp_dpcd_read(aux, DP_TEST_80BIT_CUSTOM_PATTERN_7_0,
2146
+ &data->custom80, sizeof(data->custom80));
2147
+ if (err < 0)
2148
+ return err;
2149
+
2150
+ break;
2151
+ case DP_PHY_TEST_PATTERN_CP2520:
2152
+ err = drm_dp_dpcd_read(aux, DP_TEST_HBR2_SCRAMBLER_RESET,
2153
+ &data->hbr2_reset,
2154
+ sizeof(data->hbr2_reset));
2155
+ if (err < 0)
2156
+ return err;
2157
+ }
2158
+
2159
+ return 0;
2160
+}
2161
+EXPORT_SYMBOL(drm_dp_get_phy_test_pattern);
2162
+
2163
+/**
2164
+ * drm_dp_set_phy_test_pattern() - set the pattern to the sink.
2165
+ * @aux: DisplayPort AUX channel
2166
+ * @data: DP phy compliance test parameters.
2167
+ * @dp_rev: DP revision to use for compliance testing
2168
+ *
2169
+ * Returns 0 on success or a negative error code on failure.
2170
+ */
2171
+int drm_dp_set_phy_test_pattern(struct drm_dp_aux *aux,
2172
+ struct drm_dp_phy_test_params *data, u8 dp_rev)
2173
+{
2174
+ int err, i;
2175
+ u8 test_pattern;
2176
+
2177
+ test_pattern = data->phy_pattern;
2178
+ if (dp_rev < 0x12) {
2179
+ test_pattern = (test_pattern << 2) &
2180
+ DP_LINK_QUAL_PATTERN_11_MASK;
2181
+ err = drm_dp_dpcd_writeb(aux, DP_TRAINING_PATTERN_SET,
2182
+ test_pattern);
2183
+ if (err < 0)
2184
+ return err;
2185
+ } else {
2186
+ for (i = 0; i < data->num_lanes; i++) {
2187
+ err = drm_dp_dpcd_writeb(aux,
2188
+ DP_LINK_QUAL_LANE0_SET + i,
2189
+ test_pattern);
2190
+ if (err < 0)
2191
+ return err;
2192
+ }
2193
+ }
2194
+
2195
+ return 0;
2196
+}
2197
+EXPORT_SYMBOL(drm_dp_set_phy_test_pattern);
2198
+
2199
+static const char *dp_pixelformat_get_name(enum dp_pixelformat pixelformat)
2200
+{
2201
+ if (pixelformat < 0 || pixelformat > DP_PIXELFORMAT_RESERVED)
2202
+ return "Invalid";
2203
+
2204
+ switch (pixelformat) {
2205
+ case DP_PIXELFORMAT_RGB:
2206
+ return "RGB";
2207
+ case DP_PIXELFORMAT_YUV444:
2208
+ return "YUV444";
2209
+ case DP_PIXELFORMAT_YUV422:
2210
+ return "YUV422";
2211
+ case DP_PIXELFORMAT_YUV420:
2212
+ return "YUV420";
2213
+ case DP_PIXELFORMAT_Y_ONLY:
2214
+ return "Y_ONLY";
2215
+ case DP_PIXELFORMAT_RAW:
2216
+ return "RAW";
2217
+ default:
2218
+ return "Reserved";
2219
+ }
2220
+}
2221
+
2222
+static const char *dp_colorimetry_get_name(enum dp_pixelformat pixelformat,
2223
+ enum dp_colorimetry colorimetry)
2224
+{
2225
+ if (pixelformat < 0 || pixelformat > DP_PIXELFORMAT_RESERVED)
2226
+ return "Invalid";
2227
+
2228
+ switch (colorimetry) {
2229
+ case DP_COLORIMETRY_DEFAULT:
2230
+ switch (pixelformat) {
2231
+ case DP_PIXELFORMAT_RGB:
2232
+ return "sRGB";
2233
+ case DP_PIXELFORMAT_YUV444:
2234
+ case DP_PIXELFORMAT_YUV422:
2235
+ case DP_PIXELFORMAT_YUV420:
2236
+ return "BT.601";
2237
+ case DP_PIXELFORMAT_Y_ONLY:
2238
+ return "DICOM PS3.14";
2239
+ case DP_PIXELFORMAT_RAW:
2240
+ return "Custom Color Profile";
2241
+ default:
2242
+ return "Reserved";
2243
+ }
2244
+ case DP_COLORIMETRY_RGB_WIDE_FIXED: /* and DP_COLORIMETRY_BT709_YCC */
2245
+ switch (pixelformat) {
2246
+ case DP_PIXELFORMAT_RGB:
2247
+ return "Wide Fixed";
2248
+ case DP_PIXELFORMAT_YUV444:
2249
+ case DP_PIXELFORMAT_YUV422:
2250
+ case DP_PIXELFORMAT_YUV420:
2251
+ return "BT.709";
2252
+ default:
2253
+ return "Reserved";
2254
+ }
2255
+ case DP_COLORIMETRY_RGB_WIDE_FLOAT: /* and DP_COLORIMETRY_XVYCC_601 */
2256
+ switch (pixelformat) {
2257
+ case DP_PIXELFORMAT_RGB:
2258
+ return "Wide Float";
2259
+ case DP_PIXELFORMAT_YUV444:
2260
+ case DP_PIXELFORMAT_YUV422:
2261
+ case DP_PIXELFORMAT_YUV420:
2262
+ return "xvYCC 601";
2263
+ default:
2264
+ return "Reserved";
2265
+ }
2266
+ case DP_COLORIMETRY_OPRGB: /* and DP_COLORIMETRY_XVYCC_709 */
2267
+ switch (pixelformat) {
2268
+ case DP_PIXELFORMAT_RGB:
2269
+ return "OpRGB";
2270
+ case DP_PIXELFORMAT_YUV444:
2271
+ case DP_PIXELFORMAT_YUV422:
2272
+ case DP_PIXELFORMAT_YUV420:
2273
+ return "xvYCC 709";
2274
+ default:
2275
+ return "Reserved";
2276
+ }
2277
+ case DP_COLORIMETRY_DCI_P3_RGB: /* and DP_COLORIMETRY_SYCC_601 */
2278
+ switch (pixelformat) {
2279
+ case DP_PIXELFORMAT_RGB:
2280
+ return "DCI-P3";
2281
+ case DP_PIXELFORMAT_YUV444:
2282
+ case DP_PIXELFORMAT_YUV422:
2283
+ case DP_PIXELFORMAT_YUV420:
2284
+ return "sYCC 601";
2285
+ default:
2286
+ return "Reserved";
2287
+ }
2288
+ case DP_COLORIMETRY_RGB_CUSTOM: /* and DP_COLORIMETRY_OPYCC_601 */
2289
+ switch (pixelformat) {
2290
+ case DP_PIXELFORMAT_RGB:
2291
+ return "Custom Profile";
2292
+ case DP_PIXELFORMAT_YUV444:
2293
+ case DP_PIXELFORMAT_YUV422:
2294
+ case DP_PIXELFORMAT_YUV420:
2295
+ return "OpYCC 601";
2296
+ default:
2297
+ return "Reserved";
2298
+ }
2299
+ case DP_COLORIMETRY_BT2020_RGB: /* and DP_COLORIMETRY_BT2020_CYCC */
2300
+ switch (pixelformat) {
2301
+ case DP_PIXELFORMAT_RGB:
2302
+ return "BT.2020 RGB";
2303
+ case DP_PIXELFORMAT_YUV444:
2304
+ case DP_PIXELFORMAT_YUV422:
2305
+ case DP_PIXELFORMAT_YUV420:
2306
+ return "BT.2020 CYCC";
2307
+ default:
2308
+ return "Reserved";
2309
+ }
2310
+ case DP_COLORIMETRY_BT2020_YCC:
2311
+ switch (pixelformat) {
2312
+ case DP_PIXELFORMAT_YUV444:
2313
+ case DP_PIXELFORMAT_YUV422:
2314
+ case DP_PIXELFORMAT_YUV420:
2315
+ return "BT.2020 YCC";
2316
+ default:
2317
+ return "Reserved";
2318
+ }
2319
+ default:
2320
+ return "Invalid";
2321
+ }
2322
+}
2323
+
2324
+static const char *dp_dynamic_range_get_name(enum dp_dynamic_range dynamic_range)
2325
+{
2326
+ switch (dynamic_range) {
2327
+ case DP_DYNAMIC_RANGE_VESA:
2328
+ return "VESA range";
2329
+ case DP_DYNAMIC_RANGE_CTA:
2330
+ return "CTA range";
2331
+ default:
2332
+ return "Invalid";
2333
+ }
2334
+}
2335
+
2336
+static const char *dp_content_type_get_name(enum dp_content_type content_type)
2337
+{
2338
+ switch (content_type) {
2339
+ case DP_CONTENT_TYPE_NOT_DEFINED:
2340
+ return "Not defined";
2341
+ case DP_CONTENT_TYPE_GRAPHICS:
2342
+ return "Graphics";
2343
+ case DP_CONTENT_TYPE_PHOTO:
2344
+ return "Photo";
2345
+ case DP_CONTENT_TYPE_VIDEO:
2346
+ return "Video";
2347
+ case DP_CONTENT_TYPE_GAME:
2348
+ return "Game";
2349
+ default:
2350
+ return "Reserved";
2351
+ }
2352
+}
2353
+
2354
+void drm_dp_vsc_sdp_log(const char *level, struct device *dev,
2355
+ const struct drm_dp_vsc_sdp *vsc)
2356
+{
2357
+#define DP_SDP_LOG(fmt, ...) dev_printk(level, dev, fmt, ##__VA_ARGS__)
2358
+ DP_SDP_LOG("DP SDP: %s, revision %u, length %u\n", "VSC",
2359
+ vsc->revision, vsc->length);
2360
+ DP_SDP_LOG(" pixelformat: %s\n",
2361
+ dp_pixelformat_get_name(vsc->pixelformat));
2362
+ DP_SDP_LOG(" colorimetry: %s\n",
2363
+ dp_colorimetry_get_name(vsc->pixelformat, vsc->colorimetry));
2364
+ DP_SDP_LOG(" bpc: %u\n", vsc->bpc);
2365
+ DP_SDP_LOG(" dynamic range: %s\n",
2366
+ dp_dynamic_range_get_name(vsc->dynamic_range));
2367
+ DP_SDP_LOG(" content type: %s\n",
2368
+ dp_content_type_get_name(vsc->content_type));
2369
+#undef DP_SDP_LOG
2370
+}
2371
+EXPORT_SYMBOL(drm_dp_vsc_sdp_log);