xref: /linux/drivers/gpu/drm/i915/display/intel_dp_test.c (revision 2783bb2a67270da3359c1b6dc9df8918877c18aa)
1 // SPDX-License-Identifier: MIT
2 /* Copyright © 2024 Intel Corporation */
3 
4 #include <drm/display/drm_dp.h>
5 #include <drm/display/drm_dp_helper.h>
6 #include <drm/drm_edid.h>
7 
8 #include "i915_drv.h"
9 #include "i915_reg.h"
10 #include "intel_ddi.h"
11 #include "intel_de.h"
12 #include "intel_display_types.h"
13 #include "intel_dp.h"
14 #include "intel_dp_link_training.h"
15 #include "intel_dp_mst.h"
16 #include "intel_dp_test.h"
17 
18 /* Adjust link config limits based on compliance test requests. */
19 void
20 intel_dp_adjust_compliance_config(struct intel_dp *intel_dp,
21 				  struct intel_crtc_state *pipe_config,
22 				  struct link_config_limits *limits)
23 {
24 	struct intel_display *display = to_intel_display(intel_dp);
25 
26 	/* For DP Compliance we override the computed bpp for the pipe */
27 	if (intel_dp->compliance.test_data.bpc != 0) {
28 		int bpp = 3 * intel_dp->compliance.test_data.bpc;
29 
30 		limits->pipe.min_bpp = bpp;
31 		limits->pipe.max_bpp = bpp;
32 		pipe_config->dither_force_disable = bpp == 6 * 3;
33 
34 		drm_dbg_kms(display->drm, "Setting pipe_bpp to %d\n", bpp);
35 	}
36 
37 	/* Use values requested by Compliance Test Request */
38 	if (intel_dp->compliance.test_type == DP_TEST_LINK_TRAINING) {
39 		int index;
40 
41 		/* Validate the compliance test data since max values
42 		 * might have changed due to link train fallback.
43 		 */
44 		if (intel_dp_link_params_valid(intel_dp, intel_dp->compliance.test_link_rate,
45 					       intel_dp->compliance.test_lane_count)) {
46 			index = intel_dp_rate_index(intel_dp->common_rates,
47 						    intel_dp->num_common_rates,
48 						    intel_dp->compliance.test_link_rate);
49 			if (index >= 0) {
50 				limits->min_rate = intel_dp->compliance.test_link_rate;
51 				limits->max_rate = intel_dp->compliance.test_link_rate;
52 			}
53 			limits->min_lane_count = intel_dp->compliance.test_lane_count;
54 			limits->max_lane_count = intel_dp->compliance.test_lane_count;
55 		}
56 	}
57 }
58 
59 /* Compliance test status bits  */
60 #define INTEL_DP_RESOLUTION_PREFERRED	1
61 #define INTEL_DP_RESOLUTION_STANDARD	2
62 #define INTEL_DP_RESOLUTION_FAILSAFE	3
63 
64 static u8 intel_dp_autotest_link_training(struct intel_dp *intel_dp)
65 {
66 	struct intel_display *display = to_intel_display(intel_dp);
67 	int status = 0;
68 	int test_link_rate;
69 	u8 test_lane_count, test_link_bw;
70 	/* (DP CTS 1.2)
71 	 * 4.3.1.11
72 	 */
73 	/* Read the TEST_LANE_COUNT and TEST_LINK_RTAE fields (DP CTS 3.1.4) */
74 	status = drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_LANE_COUNT,
75 				   &test_lane_count);
76 
77 	if (status <= 0) {
78 		drm_dbg_kms(display->drm, "Lane count read failed\n");
79 		return DP_TEST_NAK;
80 	}
81 	test_lane_count &= DP_MAX_LANE_COUNT_MASK;
82 
83 	status = drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_LINK_RATE,
84 				   &test_link_bw);
85 	if (status <= 0) {
86 		drm_dbg_kms(display->drm, "Link Rate read failed\n");
87 		return DP_TEST_NAK;
88 	}
89 	test_link_rate = drm_dp_bw_code_to_link_rate(test_link_bw);
90 
91 	/* Validate the requested link rate and lane count */
92 	if (!intel_dp_link_params_valid(intel_dp, test_link_rate,
93 					test_lane_count))
94 		return DP_TEST_NAK;
95 
96 	intel_dp->compliance.test_lane_count = test_lane_count;
97 	intel_dp->compliance.test_link_rate = test_link_rate;
98 
99 	return DP_TEST_ACK;
100 }
101 
102 static u8 intel_dp_autotest_video_pattern(struct intel_dp *intel_dp)
103 {
104 	struct intel_display *display = to_intel_display(intel_dp);
105 	u8 test_pattern;
106 	u8 test_misc;
107 	__be16 h_width, v_height;
108 	int status = 0;
109 
110 	/* Read the TEST_PATTERN (DP CTS 3.1.5) */
111 	status = drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_PATTERN,
112 				   &test_pattern);
113 	if (status <= 0) {
114 		drm_dbg_kms(display->drm, "Test pattern read failed\n");
115 		return DP_TEST_NAK;
116 	}
117 	if (test_pattern != DP_COLOR_RAMP)
118 		return DP_TEST_NAK;
119 
120 	status = drm_dp_dpcd_read(&intel_dp->aux, DP_TEST_H_WIDTH_HI,
121 				  &h_width, 2);
122 	if (status <= 0) {
123 		drm_dbg_kms(display->drm, "H Width read failed\n");
124 		return DP_TEST_NAK;
125 	}
126 
127 	status = drm_dp_dpcd_read(&intel_dp->aux, DP_TEST_V_HEIGHT_HI,
128 				  &v_height, 2);
129 	if (status <= 0) {
130 		drm_dbg_kms(display->drm, "V Height read failed\n");
131 		return DP_TEST_NAK;
132 	}
133 
134 	status = drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_MISC0,
135 				   &test_misc);
136 	if (status <= 0) {
137 		drm_dbg_kms(display->drm, "TEST MISC read failed\n");
138 		return DP_TEST_NAK;
139 	}
140 	if ((test_misc & DP_TEST_COLOR_FORMAT_MASK) != DP_COLOR_FORMAT_RGB)
141 		return DP_TEST_NAK;
142 	if (test_misc & DP_TEST_DYNAMIC_RANGE_CEA)
143 		return DP_TEST_NAK;
144 	switch (test_misc & DP_TEST_BIT_DEPTH_MASK) {
145 	case DP_TEST_BIT_DEPTH_6:
146 		intel_dp->compliance.test_data.bpc = 6;
147 		break;
148 	case DP_TEST_BIT_DEPTH_8:
149 		intel_dp->compliance.test_data.bpc = 8;
150 		break;
151 	default:
152 		return DP_TEST_NAK;
153 	}
154 
155 	intel_dp->compliance.test_data.video_pattern = test_pattern;
156 	intel_dp->compliance.test_data.hdisplay = be16_to_cpu(h_width);
157 	intel_dp->compliance.test_data.vdisplay = be16_to_cpu(v_height);
158 	/* Set test active flag here so userspace doesn't interrupt things */
159 	intel_dp->compliance.test_active = true;
160 
161 	return DP_TEST_ACK;
162 }
163 
164 static u8 intel_dp_autotest_edid(struct intel_dp *intel_dp)
165 {
166 	struct intel_display *display = to_intel_display(intel_dp);
167 	u8 test_result = DP_TEST_ACK;
168 	struct intel_connector *intel_connector = intel_dp->attached_connector;
169 	struct drm_connector *connector = &intel_connector->base;
170 
171 	if (!intel_connector->detect_edid || connector->edid_corrupt ||
172 	    intel_dp->aux.i2c_defer_count > 6) {
173 		/* Check EDID read for NACKs, DEFERs and corruption
174 		 * (DP CTS 1.2 Core r1.1)
175 		 *    4.2.2.4 : Failed EDID read, I2C_NAK
176 		 *    4.2.2.5 : Failed EDID read, I2C_DEFER
177 		 *    4.2.2.6 : EDID corruption detected
178 		 * Use failsafe mode for all cases
179 		 */
180 		if (intel_dp->aux.i2c_nack_count > 0 ||
181 		    intel_dp->aux.i2c_defer_count > 0)
182 			drm_dbg_kms(display->drm,
183 				    "EDID read had %d NACKs, %d DEFERs\n",
184 				    intel_dp->aux.i2c_nack_count,
185 				    intel_dp->aux.i2c_defer_count);
186 		intel_dp->compliance.test_data.edid = INTEL_DP_RESOLUTION_FAILSAFE;
187 	} else {
188 		/* FIXME: Get rid of drm_edid_raw() */
189 		const struct edid *block = drm_edid_raw(intel_connector->detect_edid);
190 
191 		/* We have to write the checksum of the last block read */
192 		block += block->extensions;
193 
194 		if (drm_dp_dpcd_writeb(&intel_dp->aux, DP_TEST_EDID_CHECKSUM,
195 				       block->checksum) <= 0)
196 			drm_dbg_kms(display->drm,
197 				    "Failed to write EDID checksum\n");
198 
199 		test_result = DP_TEST_ACK | DP_TEST_EDID_CHECKSUM_WRITE;
200 		intel_dp->compliance.test_data.edid = INTEL_DP_RESOLUTION_PREFERRED;
201 	}
202 
203 	/* Set test active flag here so userspace doesn't interrupt things */
204 	intel_dp->compliance.test_active = true;
205 
206 	return test_result;
207 }
208 
209 static void intel_dp_phy_pattern_update(struct intel_dp *intel_dp,
210 					const struct intel_crtc_state *crtc_state)
211 {
212 	struct intel_display *display = to_intel_display(intel_dp);
213 	struct drm_dp_phy_test_params *data =
214 			&intel_dp->compliance.test_data.phytest;
215 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
216 	struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
217 	enum pipe pipe = crtc->pipe;
218 	u32 pattern_val;
219 
220 	switch (data->phy_pattern) {
221 	case DP_LINK_QUAL_PATTERN_DISABLE:
222 		drm_dbg_kms(display->drm, "Disable Phy Test Pattern\n");
223 		intel_de_write(display, DDI_DP_COMP_CTL(pipe), 0x0);
224 		if (DISPLAY_VER(display) >= 10)
225 			intel_de_rmw(display, dp_tp_ctl_reg(encoder, crtc_state),
226 				     DP_TP_CTL_TRAIN_PAT4_SEL_MASK | DP_TP_CTL_LINK_TRAIN_MASK,
227 				     DP_TP_CTL_LINK_TRAIN_NORMAL);
228 		break;
229 	case DP_LINK_QUAL_PATTERN_D10_2:
230 		drm_dbg_kms(display->drm, "Set D10.2 Phy Test Pattern\n");
231 		intel_de_write(display, DDI_DP_COMP_CTL(pipe),
232 			       DDI_DP_COMP_CTL_ENABLE | DDI_DP_COMP_CTL_D10_2);
233 		break;
234 	case DP_LINK_QUAL_PATTERN_ERROR_RATE:
235 		drm_dbg_kms(display->drm,
236 			    "Set Error Count Phy Test Pattern\n");
237 		intel_de_write(display, DDI_DP_COMP_CTL(pipe),
238 			       DDI_DP_COMP_CTL_ENABLE |
239 			       DDI_DP_COMP_CTL_SCRAMBLED_0);
240 		break;
241 	case DP_LINK_QUAL_PATTERN_PRBS7:
242 		drm_dbg_kms(display->drm, "Set PRBS7 Phy Test Pattern\n");
243 		intel_de_write(display, DDI_DP_COMP_CTL(pipe),
244 			       DDI_DP_COMP_CTL_ENABLE | DDI_DP_COMP_CTL_PRBS7);
245 		break;
246 	case DP_LINK_QUAL_PATTERN_80BIT_CUSTOM:
247 		/*
248 		 * FIXME: Ideally pattern should come from DPCD 0x250. As
249 		 * current firmware of DPR-100 could not set it, so hardcoding
250 		 * now for complaince test.
251 		 */
252 		drm_dbg_kms(display->drm,
253 			    "Set 80Bit Custom Phy Test Pattern 0x3e0f83e0 0x0f83e0f8 0x0000f83e\n");
254 		pattern_val = 0x3e0f83e0;
255 		intel_de_write(display, DDI_DP_COMP_PAT(pipe, 0), pattern_val);
256 		pattern_val = 0x0f83e0f8;
257 		intel_de_write(display, DDI_DP_COMP_PAT(pipe, 1), pattern_val);
258 		pattern_val = 0x0000f83e;
259 		intel_de_write(display, DDI_DP_COMP_PAT(pipe, 2), pattern_val);
260 		intel_de_write(display, DDI_DP_COMP_CTL(pipe),
261 			       DDI_DP_COMP_CTL_ENABLE |
262 			       DDI_DP_COMP_CTL_CUSTOM80);
263 		break;
264 	case DP_LINK_QUAL_PATTERN_CP2520_PAT_1:
265 		/*
266 		 * FIXME: Ideally pattern should come from DPCD 0x24A. As
267 		 * current firmware of DPR-100 could not set it, so hardcoding
268 		 * now for complaince test.
269 		 */
270 		drm_dbg_kms(display->drm,
271 			    "Set HBR2 compliance Phy Test Pattern\n");
272 		pattern_val = 0xFB;
273 		intel_de_write(display, DDI_DP_COMP_CTL(pipe),
274 			       DDI_DP_COMP_CTL_ENABLE | DDI_DP_COMP_CTL_HBR2 |
275 			       pattern_val);
276 		break;
277 	case DP_LINK_QUAL_PATTERN_CP2520_PAT_3:
278 		if (DISPLAY_VER(display) < 10)  {
279 			drm_warn(display->drm,
280 				 "Platform does not support TPS4\n");
281 			break;
282 		}
283 		drm_dbg_kms(display->drm,
284 			    "Set TPS4 compliance Phy Test Pattern\n");
285 		intel_de_write(display, DDI_DP_COMP_CTL(pipe), 0x0);
286 		intel_de_rmw(display, dp_tp_ctl_reg(encoder, crtc_state),
287 			     DP_TP_CTL_TRAIN_PAT4_SEL_MASK | DP_TP_CTL_LINK_TRAIN_MASK,
288 			     DP_TP_CTL_TRAIN_PAT4_SEL_TP4A | DP_TP_CTL_LINK_TRAIN_PAT4);
289 		break;
290 	default:
291 		drm_warn(display->drm, "Invalid Phy Test Pattern\n");
292 	}
293 }
294 
295 static void intel_dp_process_phy_request(struct intel_dp *intel_dp,
296 					 const struct intel_crtc_state *crtc_state)
297 {
298 	struct intel_display *display = to_intel_display(intel_dp);
299 	struct drm_dp_phy_test_params *data =
300 		&intel_dp->compliance.test_data.phytest;
301 	u8 link_status[DP_LINK_STATUS_SIZE];
302 
303 	if (drm_dp_dpcd_read_phy_link_status(&intel_dp->aux, DP_PHY_DPRX,
304 					     link_status) < 0) {
305 		drm_dbg_kms(display->drm, "failed to get link status\n");
306 		return;
307 	}
308 
309 	/* retrieve vswing & pre-emphasis setting */
310 	intel_dp_get_adjust_train(intel_dp, crtc_state, DP_PHY_DPRX,
311 				  link_status);
312 
313 	intel_dp_set_signal_levels(intel_dp, crtc_state, DP_PHY_DPRX);
314 
315 	intel_dp_phy_pattern_update(intel_dp, crtc_state);
316 
317 	drm_dp_dpcd_write(&intel_dp->aux, DP_TRAINING_LANE0_SET,
318 			  intel_dp->train_set, crtc_state->lane_count);
319 
320 	drm_dp_set_phy_test_pattern(&intel_dp->aux, data,
321 				    intel_dp->dpcd[DP_DPCD_REV]);
322 }
323 
324 static u8 intel_dp_autotest_phy_pattern(struct intel_dp *intel_dp)
325 {
326 	struct intel_display *display = to_intel_display(intel_dp);
327 	struct drm_dp_phy_test_params *data =
328 		&intel_dp->compliance.test_data.phytest;
329 
330 	if (drm_dp_get_phy_test_pattern(&intel_dp->aux, data)) {
331 		drm_dbg_kms(display->drm,
332 			    "DP Phy Test pattern AUX read failure\n");
333 		return DP_TEST_NAK;
334 	}
335 
336 	/* Set test active flag here so userspace doesn't interrupt things */
337 	intel_dp->compliance.test_active = true;
338 
339 	return DP_TEST_ACK;
340 }
341 
342 void intel_dp_handle_test_request(struct intel_dp *intel_dp)
343 {
344 	struct intel_display *display = to_intel_display(intel_dp);
345 	u8 response = DP_TEST_NAK;
346 	u8 request = 0;
347 	int status;
348 
349 	status = drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_REQUEST, &request);
350 	if (status <= 0) {
351 		drm_dbg_kms(display->drm,
352 			    "Could not read test request from sink\n");
353 		goto update_status;
354 	}
355 
356 	switch (request) {
357 	case DP_TEST_LINK_TRAINING:
358 		drm_dbg_kms(display->drm, "LINK_TRAINING test requested\n");
359 		response = intel_dp_autotest_link_training(intel_dp);
360 		break;
361 	case DP_TEST_LINK_VIDEO_PATTERN:
362 		drm_dbg_kms(display->drm, "TEST_PATTERN test requested\n");
363 		response = intel_dp_autotest_video_pattern(intel_dp);
364 		break;
365 	case DP_TEST_LINK_EDID_READ:
366 		drm_dbg_kms(display->drm, "EDID test requested\n");
367 		response = intel_dp_autotest_edid(intel_dp);
368 		break;
369 	case DP_TEST_LINK_PHY_TEST_PATTERN:
370 		drm_dbg_kms(display->drm, "PHY_PATTERN test requested\n");
371 		response = intel_dp_autotest_phy_pattern(intel_dp);
372 		break;
373 	default:
374 		drm_dbg_kms(display->drm, "Invalid test request '%02x'\n",
375 			    request);
376 		break;
377 	}
378 
379 	if (response & DP_TEST_ACK)
380 		intel_dp->compliance.test_type = request;
381 
382 update_status:
383 	status = drm_dp_dpcd_writeb(&intel_dp->aux, DP_TEST_RESPONSE, response);
384 	if (status <= 0)
385 		drm_dbg_kms(display->drm,
386 			    "Could not write test response to sink\n");
387 }
388 
389 /* phy test */
390 
391 static int intel_dp_prep_phy_test(struct intel_dp *intel_dp,
392 				  struct drm_modeset_acquire_ctx *ctx,
393 				  u8 *pipe_mask)
394 {
395 	struct intel_display *display = to_intel_display(intel_dp);
396 	struct drm_connector_list_iter conn_iter;
397 	struct intel_connector *connector;
398 	int ret = 0;
399 
400 	*pipe_mask = 0;
401 
402 	drm_connector_list_iter_begin(display->drm, &conn_iter);
403 	for_each_intel_connector_iter(connector, &conn_iter) {
404 		struct drm_connector_state *conn_state =
405 			connector->base.state;
406 		struct intel_crtc_state *crtc_state;
407 		struct intel_crtc *crtc;
408 
409 		if (!intel_dp_has_connector(intel_dp, conn_state))
410 			continue;
411 
412 		crtc = to_intel_crtc(conn_state->crtc);
413 		if (!crtc)
414 			continue;
415 
416 		ret = drm_modeset_lock(&crtc->base.mutex, ctx);
417 		if (ret)
418 			break;
419 
420 		crtc_state = to_intel_crtc_state(crtc->base.state);
421 
422 		drm_WARN_ON(display->drm,
423 			    !intel_crtc_has_dp_encoder(crtc_state));
424 
425 		if (!crtc_state->hw.active)
426 			continue;
427 
428 		if (conn_state->commit &&
429 		    !try_wait_for_completion(&conn_state->commit->hw_done))
430 			continue;
431 
432 		*pipe_mask |= BIT(crtc->pipe);
433 	}
434 	drm_connector_list_iter_end(&conn_iter);
435 
436 	return ret;
437 }
438 
439 static int intel_dp_do_phy_test(struct intel_encoder *encoder,
440 				struct drm_modeset_acquire_ctx *ctx)
441 {
442 	struct intel_display *display = to_intel_display(encoder);
443 	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
444 	struct intel_crtc *crtc;
445 	u8 pipe_mask;
446 	int ret;
447 
448 	ret = drm_modeset_lock(&display->drm->mode_config.connection_mutex,
449 			       ctx);
450 	if (ret)
451 		return ret;
452 
453 	ret = intel_dp_prep_phy_test(intel_dp, ctx, &pipe_mask);
454 	if (ret)
455 		return ret;
456 
457 	if (pipe_mask == 0)
458 		return 0;
459 
460 	drm_dbg_kms(display->drm, "[ENCODER:%d:%s] PHY test\n",
461 		    encoder->base.base.id, encoder->base.name);
462 
463 	for_each_intel_crtc_in_pipe_mask(display->drm, crtc, pipe_mask) {
464 		const struct intel_crtc_state *crtc_state =
465 			to_intel_crtc_state(crtc->base.state);
466 
467 		/* test on the MST master transcoder */
468 		if (DISPLAY_VER(display) >= 12 &&
469 		    intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST) &&
470 		    !intel_dp_mst_is_master_trans(crtc_state))
471 			continue;
472 
473 		intel_dp_process_phy_request(intel_dp, crtc_state);
474 		break;
475 	}
476 
477 	return 0;
478 }
479 
480 void intel_dp_phy_test(struct intel_encoder *encoder)
481 {
482 	struct drm_modeset_acquire_ctx ctx;
483 	int ret;
484 
485 	drm_modeset_acquire_init(&ctx, 0);
486 
487 	for (;;) {
488 		ret = intel_dp_do_phy_test(encoder, &ctx);
489 
490 		if (ret == -EDEADLK) {
491 			drm_modeset_backoff(&ctx);
492 			continue;
493 		}
494 
495 		break;
496 	}
497 
498 	drm_modeset_drop_locks(&ctx);
499 	drm_modeset_acquire_fini(&ctx);
500 	drm_WARN(encoder->base.dev, ret,
501 		 "Acquiring modeset locks failed with %i\n", ret);
502 }
503