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