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