Loading...
Note: File does not exist in v3.1.
1// SPDX-License-Identifier: MIT
2/* Copyright © 2024 Intel Corporation */
3
4#include <linux/debugfs.h>
5
6#include <drm/display/drm_dp.h>
7#include <drm/display/drm_dp_helper.h>
8#include <drm/drm_edid.h>
9#include <drm/drm_probe_helper.h>
10
11#include "i915_drv.h"
12#include "i915_reg.h"
13#include "intel_ddi.h"
14#include "intel_de.h"
15#include "intel_display_types.h"
16#include "intel_dp.h"
17#include "intel_dp_link_training.h"
18#include "intel_dp_mst.h"
19#include "intel_dp_test.h"
20
21void intel_dp_test_reset(struct intel_dp *intel_dp)
22{
23 /*
24 * Clearing compliance test variables to allow capturing
25 * of values for next automated test request.
26 */
27 memset(&intel_dp->compliance, 0, sizeof(intel_dp->compliance));
28}
29
30/* Adjust link config limits based on compliance test requests. */
31void intel_dp_test_compute_config(struct intel_dp *intel_dp,
32 struct intel_crtc_state *pipe_config,
33 struct link_config_limits *limits)
34{
35 struct intel_display *display = to_intel_display(intel_dp);
36
37 /* For DP Compliance we override the computed bpp for the pipe */
38 if (intel_dp->compliance.test_data.bpc != 0) {
39 int bpp = 3 * intel_dp->compliance.test_data.bpc;
40
41 limits->pipe.min_bpp = bpp;
42 limits->pipe.max_bpp = bpp;
43 pipe_config->dither_force_disable = bpp == 6 * 3;
44
45 drm_dbg_kms(display->drm, "Setting pipe_bpp to %d\n", bpp);
46 }
47
48 /* Use values requested by Compliance Test Request */
49 if (intel_dp->compliance.test_type == DP_TEST_LINK_TRAINING) {
50 int index;
51
52 /* Validate the compliance test data since max values
53 * might have changed due to link train fallback.
54 */
55 if (intel_dp_link_params_valid(intel_dp, intel_dp->compliance.test_link_rate,
56 intel_dp->compliance.test_lane_count)) {
57 index = intel_dp_rate_index(intel_dp->common_rates,
58 intel_dp->num_common_rates,
59 intel_dp->compliance.test_link_rate);
60 if (index >= 0) {
61 limits->min_rate = intel_dp->compliance.test_link_rate;
62 limits->max_rate = intel_dp->compliance.test_link_rate;
63 }
64 limits->min_lane_count = intel_dp->compliance.test_lane_count;
65 limits->max_lane_count = intel_dp->compliance.test_lane_count;
66 }
67 }
68}
69
70/* Compliance test status bits */
71#define INTEL_DP_RESOLUTION_PREFERRED 1
72#define INTEL_DP_RESOLUTION_STANDARD 2
73#define INTEL_DP_RESOLUTION_FAILSAFE 3
74
75static u8 intel_dp_autotest_link_training(struct intel_dp *intel_dp)
76{
77 struct intel_display *display = to_intel_display(intel_dp);
78 int status = 0;
79 int test_link_rate;
80 u8 test_lane_count, test_link_bw;
81 /* (DP CTS 1.2)
82 * 4.3.1.11
83 */
84 /* Read the TEST_LANE_COUNT and TEST_LINK_RTAE fields (DP CTS 3.1.4) */
85 status = drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_LANE_COUNT,
86 &test_lane_count);
87
88 if (status <= 0) {
89 drm_dbg_kms(display->drm, "Lane count read failed\n");
90 return DP_TEST_NAK;
91 }
92 test_lane_count &= DP_MAX_LANE_COUNT_MASK;
93
94 status = drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_LINK_RATE,
95 &test_link_bw);
96 if (status <= 0) {
97 drm_dbg_kms(display->drm, "Link Rate read failed\n");
98 return DP_TEST_NAK;
99 }
100 test_link_rate = drm_dp_bw_code_to_link_rate(test_link_bw);
101
102 /* Validate the requested link rate and lane count */
103 if (!intel_dp_link_params_valid(intel_dp, test_link_rate,
104 test_lane_count))
105 return DP_TEST_NAK;
106
107 intel_dp->compliance.test_lane_count = test_lane_count;
108 intel_dp->compliance.test_link_rate = test_link_rate;
109
110 return DP_TEST_ACK;
111}
112
113static u8 intel_dp_autotest_video_pattern(struct intel_dp *intel_dp)
114{
115 struct intel_display *display = to_intel_display(intel_dp);
116 u8 test_pattern;
117 u8 test_misc;
118 __be16 h_width, v_height;
119 int status = 0;
120
121 /* Read the TEST_PATTERN (DP CTS 3.1.5) */
122 status = drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_PATTERN,
123 &test_pattern);
124 if (status <= 0) {
125 drm_dbg_kms(display->drm, "Test pattern read failed\n");
126 return DP_TEST_NAK;
127 }
128 if (test_pattern != DP_COLOR_RAMP)
129 return DP_TEST_NAK;
130
131 status = drm_dp_dpcd_read(&intel_dp->aux, DP_TEST_H_WIDTH_HI,
132 &h_width, 2);
133 if (status <= 0) {
134 drm_dbg_kms(display->drm, "H Width read failed\n");
135 return DP_TEST_NAK;
136 }
137
138 status = drm_dp_dpcd_read(&intel_dp->aux, DP_TEST_V_HEIGHT_HI,
139 &v_height, 2);
140 if (status <= 0) {
141 drm_dbg_kms(display->drm, "V Height read failed\n");
142 return DP_TEST_NAK;
143 }
144
145 status = drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_MISC0,
146 &test_misc);
147 if (status <= 0) {
148 drm_dbg_kms(display->drm, "TEST MISC read failed\n");
149 return DP_TEST_NAK;
150 }
151 if ((test_misc & DP_TEST_COLOR_FORMAT_MASK) != DP_COLOR_FORMAT_RGB)
152 return DP_TEST_NAK;
153 if (test_misc & DP_TEST_DYNAMIC_RANGE_CEA)
154 return DP_TEST_NAK;
155 switch (test_misc & DP_TEST_BIT_DEPTH_MASK) {
156 case DP_TEST_BIT_DEPTH_6:
157 intel_dp->compliance.test_data.bpc = 6;
158 break;
159 case DP_TEST_BIT_DEPTH_8:
160 intel_dp->compliance.test_data.bpc = 8;
161 break;
162 default:
163 return DP_TEST_NAK;
164 }
165
166 intel_dp->compliance.test_data.video_pattern = test_pattern;
167 intel_dp->compliance.test_data.hdisplay = be16_to_cpu(h_width);
168 intel_dp->compliance.test_data.vdisplay = be16_to_cpu(v_height);
169 /* Set test active flag here so userspace doesn't interrupt things */
170 intel_dp->compliance.test_active = true;
171
172 return DP_TEST_ACK;
173}
174
175static u8 intel_dp_autotest_edid(struct intel_dp *intel_dp)
176{
177 struct intel_display *display = to_intel_display(intel_dp);
178 u8 test_result = DP_TEST_ACK;
179 struct intel_connector *intel_connector = intel_dp->attached_connector;
180 struct drm_connector *connector = &intel_connector->base;
181
182 if (!intel_connector->detect_edid || connector->edid_corrupt ||
183 intel_dp->aux.i2c_defer_count > 6) {
184 /* Check EDID read for NACKs, DEFERs and corruption
185 * (DP CTS 1.2 Core r1.1)
186 * 4.2.2.4 : Failed EDID read, I2C_NAK
187 * 4.2.2.5 : Failed EDID read, I2C_DEFER
188 * 4.2.2.6 : EDID corruption detected
189 * Use failsafe mode for all cases
190 */
191 if (intel_dp->aux.i2c_nack_count > 0 ||
192 intel_dp->aux.i2c_defer_count > 0)
193 drm_dbg_kms(display->drm,
194 "EDID read had %d NACKs, %d DEFERs\n",
195 intel_dp->aux.i2c_nack_count,
196 intel_dp->aux.i2c_defer_count);
197 intel_dp->compliance.test_data.edid = INTEL_DP_RESOLUTION_FAILSAFE;
198 } else {
199 /* FIXME: Get rid of drm_edid_raw() */
200 const struct edid *block = drm_edid_raw(intel_connector->detect_edid);
201
202 /* We have to write the checksum of the last block read */
203 block += block->extensions;
204
205 if (drm_dp_dpcd_writeb(&intel_dp->aux, DP_TEST_EDID_CHECKSUM,
206 block->checksum) <= 0)
207 drm_dbg_kms(display->drm,
208 "Failed to write EDID checksum\n");
209
210 test_result = DP_TEST_ACK | DP_TEST_EDID_CHECKSUM_WRITE;
211 intel_dp->compliance.test_data.edid = INTEL_DP_RESOLUTION_PREFERRED;
212 }
213
214 /* Set test active flag here so userspace doesn't interrupt things */
215 intel_dp->compliance.test_active = true;
216
217 return test_result;
218}
219
220static void intel_dp_phy_pattern_update(struct intel_dp *intel_dp,
221 const struct intel_crtc_state *crtc_state)
222{
223 struct intel_display *display = to_intel_display(intel_dp);
224 struct drm_dp_phy_test_params *data =
225 &intel_dp->compliance.test_data.phytest;
226 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
227 struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
228 enum pipe pipe = crtc->pipe;
229 u32 pattern_val;
230
231 switch (data->phy_pattern) {
232 case DP_LINK_QUAL_PATTERN_DISABLE:
233 drm_dbg_kms(display->drm, "Disable Phy Test Pattern\n");
234 intel_de_write(display, DDI_DP_COMP_CTL(pipe), 0x0);
235 if (DISPLAY_VER(display) >= 10)
236 intel_de_rmw(display, dp_tp_ctl_reg(encoder, crtc_state),
237 DP_TP_CTL_TRAIN_PAT4_SEL_MASK | DP_TP_CTL_LINK_TRAIN_MASK,
238 DP_TP_CTL_LINK_TRAIN_NORMAL);
239 break;
240 case DP_LINK_QUAL_PATTERN_D10_2:
241 drm_dbg_kms(display->drm, "Set D10.2 Phy Test Pattern\n");
242 intel_de_write(display, DDI_DP_COMP_CTL(pipe),
243 DDI_DP_COMP_CTL_ENABLE | DDI_DP_COMP_CTL_D10_2);
244 break;
245 case DP_LINK_QUAL_PATTERN_ERROR_RATE:
246 drm_dbg_kms(display->drm,
247 "Set Error Count Phy Test Pattern\n");
248 intel_de_write(display, DDI_DP_COMP_CTL(pipe),
249 DDI_DP_COMP_CTL_ENABLE |
250 DDI_DP_COMP_CTL_SCRAMBLED_0);
251 break;
252 case DP_LINK_QUAL_PATTERN_PRBS7:
253 drm_dbg_kms(display->drm, "Set PRBS7 Phy Test Pattern\n");
254 intel_de_write(display, DDI_DP_COMP_CTL(pipe),
255 DDI_DP_COMP_CTL_ENABLE | DDI_DP_COMP_CTL_PRBS7);
256 break;
257 case DP_LINK_QUAL_PATTERN_80BIT_CUSTOM:
258 /*
259 * FIXME: Ideally pattern should come from DPCD 0x250. As
260 * current firmware of DPR-100 could not set it, so hardcoding
261 * now for complaince test.
262 */
263 drm_dbg_kms(display->drm,
264 "Set 80Bit Custom Phy Test Pattern 0x3e0f83e0 0x0f83e0f8 0x0000f83e\n");
265 pattern_val = 0x3e0f83e0;
266 intel_de_write(display, DDI_DP_COMP_PAT(pipe, 0), pattern_val);
267 pattern_val = 0x0f83e0f8;
268 intel_de_write(display, DDI_DP_COMP_PAT(pipe, 1), pattern_val);
269 pattern_val = 0x0000f83e;
270 intel_de_write(display, DDI_DP_COMP_PAT(pipe, 2), pattern_val);
271 intel_de_write(display, DDI_DP_COMP_CTL(pipe),
272 DDI_DP_COMP_CTL_ENABLE |
273 DDI_DP_COMP_CTL_CUSTOM80);
274 break;
275 case DP_LINK_QUAL_PATTERN_CP2520_PAT_1:
276 /*
277 * FIXME: Ideally pattern should come from DPCD 0x24A. As
278 * current firmware of DPR-100 could not set it, so hardcoding
279 * now for complaince test.
280 */
281 drm_dbg_kms(display->drm,
282 "Set HBR2 compliance Phy Test Pattern\n");
283 pattern_val = 0xFB;
284 intel_de_write(display, DDI_DP_COMP_CTL(pipe),
285 DDI_DP_COMP_CTL_ENABLE | DDI_DP_COMP_CTL_HBR2 |
286 pattern_val);
287 break;
288 case DP_LINK_QUAL_PATTERN_CP2520_PAT_3:
289 if (DISPLAY_VER(display) < 10) {
290 drm_warn(display->drm,
291 "Platform does not support TPS4\n");
292 break;
293 }
294 drm_dbg_kms(display->drm,
295 "Set TPS4 compliance Phy Test Pattern\n");
296 intel_de_write(display, DDI_DP_COMP_CTL(pipe), 0x0);
297 intel_de_rmw(display, dp_tp_ctl_reg(encoder, crtc_state),
298 DP_TP_CTL_TRAIN_PAT4_SEL_MASK | DP_TP_CTL_LINK_TRAIN_MASK,
299 DP_TP_CTL_TRAIN_PAT4_SEL_TP4A | DP_TP_CTL_LINK_TRAIN_PAT4);
300 break;
301 default:
302 drm_warn(display->drm, "Invalid Phy Test Pattern\n");
303 }
304}
305
306static void intel_dp_process_phy_request(struct intel_dp *intel_dp,
307 const struct intel_crtc_state *crtc_state)
308{
309 struct intel_display *display = to_intel_display(intel_dp);
310 struct drm_dp_phy_test_params *data =
311 &intel_dp->compliance.test_data.phytest;
312 u8 link_status[DP_LINK_STATUS_SIZE];
313
314 if (drm_dp_dpcd_read_phy_link_status(&intel_dp->aux, DP_PHY_DPRX,
315 link_status) < 0) {
316 drm_dbg_kms(display->drm, "failed to get link status\n");
317 return;
318 }
319
320 /* retrieve vswing & pre-emphasis setting */
321 intel_dp_get_adjust_train(intel_dp, crtc_state, DP_PHY_DPRX,
322 link_status);
323
324 intel_dp_set_signal_levels(intel_dp, crtc_state, DP_PHY_DPRX);
325
326 intel_dp_phy_pattern_update(intel_dp, crtc_state);
327
328 drm_dp_dpcd_write(&intel_dp->aux, DP_TRAINING_LANE0_SET,
329 intel_dp->train_set, crtc_state->lane_count);
330
331 drm_dp_set_phy_test_pattern(&intel_dp->aux, data,
332 intel_dp->dpcd[DP_DPCD_REV]);
333}
334
335static u8 intel_dp_autotest_phy_pattern(struct intel_dp *intel_dp)
336{
337 struct intel_display *display = to_intel_display(intel_dp);
338 struct drm_dp_phy_test_params *data =
339 &intel_dp->compliance.test_data.phytest;
340
341 if (drm_dp_get_phy_test_pattern(&intel_dp->aux, data)) {
342 drm_dbg_kms(display->drm,
343 "DP Phy Test pattern AUX read failure\n");
344 return DP_TEST_NAK;
345 }
346
347 /* Set test active flag here so userspace doesn't interrupt things */
348 intel_dp->compliance.test_active = true;
349
350 return DP_TEST_ACK;
351}
352
353void intel_dp_test_request(struct intel_dp *intel_dp)
354{
355 struct intel_display *display = to_intel_display(intel_dp);
356 u8 response = DP_TEST_NAK;
357 u8 request = 0;
358 int status;
359
360 status = drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_REQUEST, &request);
361 if (status <= 0) {
362 drm_dbg_kms(display->drm,
363 "Could not read test request from sink\n");
364 goto update_status;
365 }
366
367 switch (request) {
368 case DP_TEST_LINK_TRAINING:
369 drm_dbg_kms(display->drm, "LINK_TRAINING test requested\n");
370 response = intel_dp_autotest_link_training(intel_dp);
371 break;
372 case DP_TEST_LINK_VIDEO_PATTERN:
373 drm_dbg_kms(display->drm, "TEST_PATTERN test requested\n");
374 response = intel_dp_autotest_video_pattern(intel_dp);
375 break;
376 case DP_TEST_LINK_EDID_READ:
377 drm_dbg_kms(display->drm, "EDID test requested\n");
378 response = intel_dp_autotest_edid(intel_dp);
379 break;
380 case DP_TEST_LINK_PHY_TEST_PATTERN:
381 drm_dbg_kms(display->drm, "PHY_PATTERN test requested\n");
382 response = intel_dp_autotest_phy_pattern(intel_dp);
383 break;
384 default:
385 drm_dbg_kms(display->drm, "Invalid test request '%02x'\n",
386 request);
387 break;
388 }
389
390 if (response & DP_TEST_ACK)
391 intel_dp->compliance.test_type = request;
392
393update_status:
394 status = drm_dp_dpcd_writeb(&intel_dp->aux, DP_TEST_RESPONSE, response);
395 if (status <= 0)
396 drm_dbg_kms(display->drm,
397 "Could not write test response to sink\n");
398}
399
400/* phy test */
401
402static int intel_dp_prep_phy_test(struct intel_dp *intel_dp,
403 struct drm_modeset_acquire_ctx *ctx,
404 u8 *pipe_mask)
405{
406 struct intel_display *display = to_intel_display(intel_dp);
407 struct drm_connector_list_iter conn_iter;
408 struct intel_connector *connector;
409 int ret = 0;
410
411 *pipe_mask = 0;
412
413 drm_connector_list_iter_begin(display->drm, &conn_iter);
414 for_each_intel_connector_iter(connector, &conn_iter) {
415 struct drm_connector_state *conn_state =
416 connector->base.state;
417 struct intel_crtc_state *crtc_state;
418 struct intel_crtc *crtc;
419
420 if (!intel_dp_has_connector(intel_dp, conn_state))
421 continue;
422
423 crtc = to_intel_crtc(conn_state->crtc);
424 if (!crtc)
425 continue;
426
427 ret = drm_modeset_lock(&crtc->base.mutex, ctx);
428 if (ret)
429 break;
430
431 crtc_state = to_intel_crtc_state(crtc->base.state);
432
433 drm_WARN_ON(display->drm,
434 !intel_crtc_has_dp_encoder(crtc_state));
435
436 if (!crtc_state->hw.active)
437 continue;
438
439 if (conn_state->commit &&
440 !try_wait_for_completion(&conn_state->commit->hw_done))
441 continue;
442
443 *pipe_mask |= BIT(crtc->pipe);
444 }
445 drm_connector_list_iter_end(&conn_iter);
446
447 return ret;
448}
449
450static int intel_dp_do_phy_test(struct intel_encoder *encoder,
451 struct drm_modeset_acquire_ctx *ctx)
452{
453 struct intel_display *display = to_intel_display(encoder);
454 struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
455 struct intel_crtc *crtc;
456 u8 pipe_mask;
457 int ret;
458
459 ret = drm_modeset_lock(&display->drm->mode_config.connection_mutex,
460 ctx);
461 if (ret)
462 return ret;
463
464 ret = intel_dp_prep_phy_test(intel_dp, ctx, &pipe_mask);
465 if (ret)
466 return ret;
467
468 if (pipe_mask == 0)
469 return 0;
470
471 drm_dbg_kms(display->drm, "[ENCODER:%d:%s] PHY test\n",
472 encoder->base.base.id, encoder->base.name);
473
474 for_each_intel_crtc_in_pipe_mask(display->drm, crtc, pipe_mask) {
475 const struct intel_crtc_state *crtc_state =
476 to_intel_crtc_state(crtc->base.state);
477
478 /* test on the MST master transcoder */
479 if (DISPLAY_VER(display) >= 12 &&
480 intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST) &&
481 !intel_dp_mst_is_master_trans(crtc_state))
482 continue;
483
484 intel_dp_process_phy_request(intel_dp, crtc_state);
485 break;
486 }
487
488 return 0;
489}
490
491bool intel_dp_test_phy(struct intel_dp *intel_dp)
492{
493 struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
494 struct intel_encoder *encoder = &dig_port->base;
495 struct drm_modeset_acquire_ctx ctx;
496 int ret;
497
498 if (!intel_dp->compliance.test_active ||
499 intel_dp->compliance.test_type != DP_TEST_LINK_PHY_TEST_PATTERN)
500 return false;
501
502 drm_modeset_acquire_init(&ctx, 0);
503
504 for (;;) {
505 ret = intel_dp_do_phy_test(encoder, &ctx);
506
507 if (ret == -EDEADLK) {
508 drm_modeset_backoff(&ctx);
509 continue;
510 }
511
512 break;
513 }
514
515 drm_modeset_drop_locks(&ctx);
516 drm_modeset_acquire_fini(&ctx);
517 drm_WARN(encoder->base.dev, ret,
518 "Acquiring modeset locks failed with %i\n", ret);
519
520 return true;
521}
522
523bool intel_dp_test_short_pulse(struct intel_dp *intel_dp)
524{
525 struct intel_display *display = to_intel_display(intel_dp);
526 bool reprobe_needed = false;
527
528 switch (intel_dp->compliance.test_type) {
529 case DP_TEST_LINK_TRAINING:
530 drm_dbg_kms(display->drm,
531 "Link Training Compliance Test requested\n");
532 /* Send a Hotplug Uevent to userspace to start modeset */
533 drm_kms_helper_hotplug_event(display->drm);
534 break;
535 case DP_TEST_LINK_PHY_TEST_PATTERN:
536 drm_dbg_kms(display->drm,
537 "PHY test pattern Compliance Test requested\n");
538 /*
539 * Schedule long hpd to do the test
540 *
541 * FIXME get rid of the ad-hoc phy test modeset code
542 * and properly incorporate it into the normal modeset.
543 */
544 reprobe_needed = true;
545 }
546
547 return reprobe_needed;
548}
549
550static ssize_t i915_displayport_test_active_write(struct file *file,
551 const char __user *ubuf,
552 size_t len, loff_t *offp)
553{
554 struct seq_file *m = file->private_data;
555 struct intel_display *display = m->private;
556 char *input_buffer;
557 int status = 0;
558 struct drm_connector *connector;
559 struct drm_connector_list_iter conn_iter;
560 struct intel_dp *intel_dp;
561 int val = 0;
562
563 if (len == 0)
564 return 0;
565
566 input_buffer = memdup_user_nul(ubuf, len);
567 if (IS_ERR(input_buffer))
568 return PTR_ERR(input_buffer);
569
570 drm_dbg_kms(display->drm, "Copied %d bytes from user\n", (unsigned int)len);
571
572 drm_connector_list_iter_begin(display->drm, &conn_iter);
573 drm_for_each_connector_iter(connector, &conn_iter) {
574 struct intel_encoder *encoder;
575
576 if (connector->connector_type !=
577 DRM_MODE_CONNECTOR_DisplayPort)
578 continue;
579
580 encoder = to_intel_encoder(connector->encoder);
581 if (encoder && encoder->type == INTEL_OUTPUT_DP_MST)
582 continue;
583
584 if (encoder && connector->status == connector_status_connected) {
585 intel_dp = enc_to_intel_dp(encoder);
586 status = kstrtoint(input_buffer, 10, &val);
587 if (status < 0)
588 break;
589 drm_dbg_kms(display->drm, "Got %d for test active\n", val);
590 /* To prevent erroneous activation of the compliance
591 * testing code, only accept an actual value of 1 here
592 */
593 if (val == 1)
594 intel_dp->compliance.test_active = true;
595 else
596 intel_dp->compliance.test_active = false;
597 }
598 }
599 drm_connector_list_iter_end(&conn_iter);
600 kfree(input_buffer);
601 if (status < 0)
602 return status;
603
604 *offp += len;
605 return len;
606}
607
608static int i915_displayport_test_active_show(struct seq_file *m, void *data)
609{
610 struct intel_display *display = m->private;
611 struct drm_connector *connector;
612 struct drm_connector_list_iter conn_iter;
613 struct intel_dp *intel_dp;
614
615 drm_connector_list_iter_begin(display->drm, &conn_iter);
616 drm_for_each_connector_iter(connector, &conn_iter) {
617 struct intel_encoder *encoder;
618
619 if (connector->connector_type !=
620 DRM_MODE_CONNECTOR_DisplayPort)
621 continue;
622
623 encoder = to_intel_encoder(connector->encoder);
624 if (encoder && encoder->type == INTEL_OUTPUT_DP_MST)
625 continue;
626
627 if (encoder && connector->status == connector_status_connected) {
628 intel_dp = enc_to_intel_dp(encoder);
629 if (intel_dp->compliance.test_active)
630 seq_puts(m, "1");
631 else
632 seq_puts(m, "0");
633 } else {
634 seq_puts(m, "0");
635 }
636 }
637 drm_connector_list_iter_end(&conn_iter);
638
639 return 0;
640}
641
642static int i915_displayport_test_active_open(struct inode *inode,
643 struct file *file)
644{
645 return single_open(file, i915_displayport_test_active_show,
646 inode->i_private);
647}
648
649static const struct file_operations i915_displayport_test_active_fops = {
650 .owner = THIS_MODULE,
651 .open = i915_displayport_test_active_open,
652 .read = seq_read,
653 .llseek = seq_lseek,
654 .release = single_release,
655 .write = i915_displayport_test_active_write
656};
657
658static int i915_displayport_test_data_show(struct seq_file *m, void *data)
659{
660 struct intel_display *display = m->private;
661 struct drm_connector *connector;
662 struct drm_connector_list_iter conn_iter;
663 struct intel_dp *intel_dp;
664
665 drm_connector_list_iter_begin(display->drm, &conn_iter);
666 drm_for_each_connector_iter(connector, &conn_iter) {
667 struct intel_encoder *encoder;
668
669 if (connector->connector_type !=
670 DRM_MODE_CONNECTOR_DisplayPort)
671 continue;
672
673 encoder = to_intel_encoder(connector->encoder);
674 if (encoder && encoder->type == INTEL_OUTPUT_DP_MST)
675 continue;
676
677 if (encoder && connector->status == connector_status_connected) {
678 intel_dp = enc_to_intel_dp(encoder);
679 if (intel_dp->compliance.test_type ==
680 DP_TEST_LINK_EDID_READ)
681 seq_printf(m, "%lx",
682 intel_dp->compliance.test_data.edid);
683 else if (intel_dp->compliance.test_type ==
684 DP_TEST_LINK_VIDEO_PATTERN) {
685 seq_printf(m, "hdisplay: %d\n",
686 intel_dp->compliance.test_data.hdisplay);
687 seq_printf(m, "vdisplay: %d\n",
688 intel_dp->compliance.test_data.vdisplay);
689 seq_printf(m, "bpc: %u\n",
690 intel_dp->compliance.test_data.bpc);
691 } else if (intel_dp->compliance.test_type ==
692 DP_TEST_LINK_PHY_TEST_PATTERN) {
693 seq_printf(m, "pattern: %d\n",
694 intel_dp->compliance.test_data.phytest.phy_pattern);
695 seq_printf(m, "Number of lanes: %d\n",
696 intel_dp->compliance.test_data.phytest.num_lanes);
697 seq_printf(m, "Link Rate: %d\n",
698 intel_dp->compliance.test_data.phytest.link_rate);
699 seq_printf(m, "level: %02x\n",
700 intel_dp->train_set[0]);
701 }
702 } else {
703 seq_puts(m, "0");
704 }
705 }
706 drm_connector_list_iter_end(&conn_iter);
707
708 return 0;
709}
710DEFINE_SHOW_ATTRIBUTE(i915_displayport_test_data);
711
712static int i915_displayport_test_type_show(struct seq_file *m, void *data)
713{
714 struct intel_display *display = m->private;
715 struct drm_connector *connector;
716 struct drm_connector_list_iter conn_iter;
717 struct intel_dp *intel_dp;
718
719 drm_connector_list_iter_begin(display->drm, &conn_iter);
720 drm_for_each_connector_iter(connector, &conn_iter) {
721 struct intel_encoder *encoder;
722
723 if (connector->connector_type !=
724 DRM_MODE_CONNECTOR_DisplayPort)
725 continue;
726
727 encoder = to_intel_encoder(connector->encoder);
728 if (encoder && encoder->type == INTEL_OUTPUT_DP_MST)
729 continue;
730
731 if (encoder && connector->status == connector_status_connected) {
732 intel_dp = enc_to_intel_dp(encoder);
733 seq_printf(m, "%02lx\n", intel_dp->compliance.test_type);
734 } else {
735 seq_puts(m, "0");
736 }
737 }
738 drm_connector_list_iter_end(&conn_iter);
739
740 return 0;
741}
742DEFINE_SHOW_ATTRIBUTE(i915_displayport_test_type);
743
744static const struct {
745 const char *name;
746 const struct file_operations *fops;
747} intel_display_debugfs_files[] = {
748 {"i915_dp_test_data", &i915_displayport_test_data_fops},
749 {"i915_dp_test_type", &i915_displayport_test_type_fops},
750 {"i915_dp_test_active", &i915_displayport_test_active_fops},
751};
752
753void intel_dp_test_debugfs_register(struct intel_display *display)
754{
755 struct drm_minor *minor = display->drm->primary;
756 int i;
757
758 for (i = 0; i < ARRAY_SIZE(intel_display_debugfs_files); i++) {
759 debugfs_create_file(intel_display_debugfs_files[i].name,
760 0644,
761 minor->debugfs_root,
762 display,
763 intel_display_debugfs_files[i].fops);
764 }
765}