]> Git Repo - J-linux.git/blob - drivers/gpu/drm/i915/display/intel_dp_test.c
Merge tag 'vfs-6.13-rc7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
[J-linux.git] / drivers / gpu / drm / i915 / display / intel_dp_test.c
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
21 void 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. */
31 void 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
75 static 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
113 static 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
175 static 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
220 static 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
306 static 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
335 static 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
353 void 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
393 update_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
402 static 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
450 static 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
491 bool 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
523 bool 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
550 static 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
608 static 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
642 static 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
649 static 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
658 static 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 }
710 DEFINE_SHOW_ATTRIBUTE(i915_displayport_test_data);
711
712 static 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 }
742 DEFINE_SHOW_ATTRIBUTE(i915_displayport_test_type);
743
744 static 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
753 void 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 }
This page took 0.070628 seconds and 4 git commands to generate.