xref: /rk3399_rockchip-uboot/drivers/video/drm/drm_dp_helper.c (revision 7efec348ce3c05852b4e4f7aa93b5e8ecd946ac1)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright © 2009 Keith Packard
4  *
5  * Permission to use, copy, modify, distribute, and sell this software and its
6  * documentation for any purpose is hereby granted without fee, provided that
7  * the above copyright notice appear in all copies and that both that copyright
8  * notice and this permission notice appear in supporting documentation, and
9  * that the name of the copyright holders not be used in advertising or
10  * publicity pertaining to distribution of the software without specific,
11  * written prior permission.  The copyright holders make no representations
12  * about the suitability of this software for any purpose.  It is provided "as
13  * is" without express or implied warranty.
14  *
15  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
17  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
19  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
21  * OF THIS SOFTWARE.
22  */
23 
24 #include <common.h>
25 #include <drm/drm_dp_helper.h>
26 
27 /**
28  * DOC: dp helpers
29  *
30  * These functions contain some common logic and helpers at various abstraction
31  * levels to deal with Display Port sink devices and related things like DP aux
32  * channel transfers, EDID reading over DP aux channels, decoding certain DPCD
33  * blocks, ...
34  */
35 
36 /* Helpers for DP link training */
dp_link_status(const u8 link_status[DP_LINK_STATUS_SIZE],int r)37 static u8 dp_link_status(const u8 link_status[DP_LINK_STATUS_SIZE], int r)
38 {
39 	return link_status[r - DP_LANE0_1_STATUS];
40 }
41 
dp_get_lane_status(const u8 link_status[DP_LINK_STATUS_SIZE],int lane)42 static u8 dp_get_lane_status(const u8 link_status[DP_LINK_STATUS_SIZE],
43 			     int lane)
44 {
45 	int i = DP_LANE0_1_STATUS + (lane >> 1);
46 	int s = (lane & 1) * 4;
47 	u8 l = dp_link_status(link_status, i);
48 
49 	return (l >> s) & 0xf;
50 }
51 
drm_dp_channel_eq_ok(const u8 link_status[DP_LINK_STATUS_SIZE],int lane_count)52 bool drm_dp_channel_eq_ok(const u8 link_status[DP_LINK_STATUS_SIZE],
53 			  int lane_count)
54 {
55 	u8 lane_align;
56 	u8 lane_status;
57 	int lane;
58 
59 	lane_align = dp_link_status(link_status,
60 				    DP_LANE_ALIGN_STATUS_UPDATED);
61 	if ((lane_align & DP_INTERLANE_ALIGN_DONE) == 0)
62 		return false;
63 	for (lane = 0; lane < lane_count; lane++) {
64 		lane_status = dp_get_lane_status(link_status, lane);
65 		if ((lane_status & DP_CHANNEL_EQ_BITS) != DP_CHANNEL_EQ_BITS)
66 			return false;
67 	}
68 	return true;
69 }
70 
drm_dp_clock_recovery_ok(const u8 link_status[DP_LINK_STATUS_SIZE],int lane_count)71 bool drm_dp_clock_recovery_ok(const u8 link_status[DP_LINK_STATUS_SIZE],
72 			      int lane_count)
73 {
74 	int lane;
75 	u8 lane_status;
76 
77 	for (lane = 0; lane < lane_count; lane++) {
78 		lane_status = dp_get_lane_status(link_status, lane);
79 		if ((lane_status & DP_LANE_CR_DONE) == 0)
80 			return false;
81 	}
82 	return true;
83 }
84 
drm_dp_get_adjust_request_voltage(const u8 link_status[DP_LINK_STATUS_SIZE],int lane)85 u8 drm_dp_get_adjust_request_voltage(const u8 link_status[DP_LINK_STATUS_SIZE],
86 				     int lane)
87 {
88 	int i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1);
89 	int s = ((lane & 1) ?
90 		 DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT :
91 		 DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT);
92 	u8 l = dp_link_status(link_status, i);
93 
94 	return ((l >> s) & 0x3) << DP_TRAIN_VOLTAGE_SWING_SHIFT;
95 }
96 
drm_dp_get_adjust_request_pre_emphasis(const u8 link_status[DP_LINK_STATUS_SIZE],int lane)97 u8 drm_dp_get_adjust_request_pre_emphasis(const u8 link_status[DP_LINK_STATUS_SIZE],
98 					  int lane)
99 {
100 	int i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1);
101 	int s = ((lane & 1) ?
102 		 DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT :
103 		 DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT);
104 	u8 l = dp_link_status(link_status, i);
105 
106 	return ((l >> s) & 0x3) << DP_TRAIN_PRE_EMPHASIS_SHIFT;
107 }
108 
drm_dp_link_train_clock_recovery_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE])109 void drm_dp_link_train_clock_recovery_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
110 {
111 	int rd_interval = dpcd[DP_TRAINING_AUX_RD_INTERVAL] &
112 			  DP_TRAINING_AUX_RD_MASK;
113 
114 	if (rd_interval > 4)
115 		printf("AUX interval %d, out of range (max 4)\n", rd_interval);
116 
117 	if (rd_interval == 0 || dpcd[DP_DPCD_REV] >= DP_DPCD_REV_14)
118 		udelay(100);
119 	else
120 		mdelay(rd_interval * 4);
121 }
122 
drm_dp_link_train_channel_eq_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE])123 void drm_dp_link_train_channel_eq_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
124 {
125 	int rd_interval = dpcd[DP_TRAINING_AUX_RD_INTERVAL] &
126 			  DP_TRAINING_AUX_RD_MASK;
127 
128 	if (rd_interval > 4)
129 		printf("AUX interval %d, out of range (max 4)\n", rd_interval);
130 
131 	if (rd_interval == 0)
132 		udelay(400);
133 	else
134 		mdelay(rd_interval * 4);
135 }
136 
drm_dp_link_rate_to_bw_code(int link_rate)137 u8 drm_dp_link_rate_to_bw_code(int link_rate)
138 {
139 	/* Spec says link_bw = link_rate / 0.27Gbps */
140 	return link_rate / 27000;
141 }
142 
drm_dp_bw_code_to_link_rate(u8 link_bw)143 int drm_dp_bw_code_to_link_rate(u8 link_bw)
144 {
145 	/* Spec says link_rate = link_bw * 0.27Gbps */
146 	return link_bw * 27000;
147 }
148 
149 #define AUX_RETRY_INTERVAL 500 /* us */
150 
drm_dp_dpcd_access(struct drm_dp_aux * aux,u8 request,unsigned int offset,void * buffer,size_t size)151 static int drm_dp_dpcd_access(struct drm_dp_aux *aux, u8 request,
152 			      unsigned int offset, void *buffer, size_t size)
153 {
154 	struct drm_dp_aux_msg msg;
155 	unsigned int retry, native_reply;
156 	int err = 0, ret = 0;
157 
158 	memset(&msg, 0, sizeof(msg));
159 	msg.address = offset;
160 	msg.request = request;
161 	msg.buffer = buffer;
162 	msg.size = size;
163 
164 	/*
165 	 * The specification doesn't give any recommendation on how often to
166 	 * retry native transactions. We used to retry 7 times like for
167 	 * aux i2c transactions but real world devices this wasn't
168 	 * sufficient, bump to 32 which makes Dell 4k monitors happier.
169 	 */
170 	for (retry = 0; retry < 32; retry++) {
171 		if (ret != 0 && ret != -ETIMEDOUT)
172 			udelay(AUX_RETRY_INTERVAL);
173 
174 		ret = aux->transfer(aux, &msg);
175 		if (ret >= 0) {
176 			native_reply = msg.reply & DP_AUX_NATIVE_REPLY_MASK;
177 			if (native_reply == DP_AUX_NATIVE_REPLY_ACK) {
178 				if (ret == size)
179 					goto out;
180 
181 				ret = -EPROTO;
182 			} else {
183 				ret = -EIO;
184 			}
185 		}
186 
187 		/*
188 		 * We want the error we return to be the error we received on
189 		 * the first transaction, since we may get a different error the
190 		 * next time we retry
191 		 */
192 		if (!err)
193 			err = ret;
194 	}
195 
196 	printf("%s: Too many retries, giving up. First error: %d\n",
197 	       aux->name, err);
198 	ret = err;
199 
200 out:
201 	return ret;
202 }
203 
drm_dp_dpcd_read(struct drm_dp_aux * aux,unsigned int offset,void * buffer,size_t size)204 ssize_t drm_dp_dpcd_read(struct drm_dp_aux *aux, unsigned int offset,
205 			 void *buffer, size_t size)
206 {
207 	int ret;
208 
209 	ret = drm_dp_dpcd_access(aux, DP_AUX_NATIVE_READ, DP_DPCD_REV,
210 				 buffer, 1);
211 	if (ret != 1)
212 		goto out;
213 
214 	ret = drm_dp_dpcd_access(aux, DP_AUX_NATIVE_READ, offset,
215 				 buffer, size);
216 
217 out:
218 	return ret;
219 }
220 
drm_dp_dpcd_write(struct drm_dp_aux * aux,unsigned int offset,void * buffer,size_t size)221 ssize_t drm_dp_dpcd_write(struct drm_dp_aux *aux, unsigned int offset,
222 			  void *buffer, size_t size)
223 {
224 	int ret;
225 
226 	ret = drm_dp_dpcd_access(aux, DP_AUX_NATIVE_WRITE, offset,
227 				 buffer, size);
228 
229 	return ret;
230 }
231 
drm_dp_dpcd_read_link_status(struct drm_dp_aux * aux,u8 status[DP_LINK_STATUS_SIZE])232 int drm_dp_dpcd_read_link_status(struct drm_dp_aux *aux,
233 				 u8 status[DP_LINK_STATUS_SIZE])
234 {
235 	return drm_dp_dpcd_read(aux, DP_LANE0_1_STATUS, status,
236 				DP_LINK_STATUS_SIZE);
237 }
238 
drm_dp_read_extended_dpcd_caps(struct drm_dp_aux * aux,u8 dpcd[DP_RECEIVER_CAP_SIZE])239 static int drm_dp_read_extended_dpcd_caps(struct drm_dp_aux *aux,
240 					  u8 dpcd[DP_RECEIVER_CAP_SIZE])
241 {
242 	u8 dpcd_ext[6];
243 	int ret;
244 
245 	/*
246 	 * Prior to DP1.3 the bit represented by
247 	 * DP_EXTENDED_RECEIVER_CAP_FIELD_PRESENT was reserved.
248 	 * If it is set DP_DPCD_REV at 0000h could be at a value less than
249 	 * the true capability of the panel. The only way to check is to
250 	 * then compare 0000h and 2200h.
251 	 */
252 	if (!(dpcd[DP_TRAINING_AUX_RD_INTERVAL] &
253 	      DP_EXTENDED_RECEIVER_CAP_FIELD_PRESENT))
254 		return 0;
255 
256 	ret = drm_dp_dpcd_read(aux, DP_DP13_DPCD_REV, &dpcd_ext,
257 			       sizeof(dpcd_ext));
258 	if (ret < 0)
259 		return ret;
260 	if (ret != sizeof(dpcd_ext))
261 		return -EIO;
262 
263 	if (dpcd[DP_DPCD_REV] > dpcd_ext[DP_DPCD_REV]) {
264 		printf("%s: Extended DPCD rev less than base DPCD rev (%d > %d)\n",
265 		       aux->name, dpcd[DP_DPCD_REV], dpcd_ext[DP_DPCD_REV]);
266 		return 0;
267 	}
268 
269 	if (!memcmp(dpcd, dpcd_ext, sizeof(dpcd_ext)))
270 		return 0;
271 
272 	debug("%s: Base DPCD: %*ph\n",
273 	       aux->name, DP_RECEIVER_CAP_SIZE, dpcd);
274 
275 	memcpy(dpcd, dpcd_ext, sizeof(dpcd_ext));
276 
277 	return 0;
278 }
279 
drm_dp_read_dpcd_caps(struct drm_dp_aux * aux,u8 dpcd[DP_RECEIVER_CAP_SIZE])280 int drm_dp_read_dpcd_caps(struct drm_dp_aux *aux,
281 			  u8 dpcd[DP_RECEIVER_CAP_SIZE])
282 {
283 	int ret;
284 
285 	ret = drm_dp_dpcd_read(aux, DP_DPCD_REV, dpcd, DP_RECEIVER_CAP_SIZE);
286 	if (ret < 0)
287 		return ret;
288 	if (ret != DP_RECEIVER_CAP_SIZE || dpcd[DP_DPCD_REV] == 0)
289 		return -EIO;
290 
291 	ret = drm_dp_read_extended_dpcd_caps(aux, dpcd);
292 	if (ret < 0)
293 		return ret;
294 
295 	debug("%s: DPCD: %*ph\n",
296 	       aux->name, DP_RECEIVER_CAP_SIZE, dpcd);
297 
298 	return ret;
299 }
300 
drm_dp_i2c_msg_write_status_update(struct drm_dp_aux_msg * msg)301 static void drm_dp_i2c_msg_write_status_update(struct drm_dp_aux_msg *msg)
302 {
303 	/*
304 	 * In case of i2c defer or short i2c ack reply to a write,
305 	 * we need to switch to WRITE_STATUS_UPDATE to drain the
306 	 * rest of the message
307 	 */
308 	if ((msg->request & ~DP_AUX_I2C_MOT) == DP_AUX_I2C_WRITE) {
309 		msg->request &= DP_AUX_I2C_MOT;
310 		msg->request |= DP_AUX_I2C_WRITE_STATUS_UPDATE;
311 	}
312 }
313 
drm_dp_i2c_do_msg(struct drm_dp_aux * aux,struct drm_dp_aux_msg * msg)314 static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
315 {
316 	unsigned int retry, defer_i2c;
317 	int ret;
318 	/*
319 	 * DP1.2 sections 2.7.7.1.5.6.1 and 2.7.7.1.6.6.1: A DP Source device
320 	 * is required to retry at least seven times upon receiving AUX_DEFER
321 	 * before giving up the AUX transaction.
322 	 *
323 	 * We also try to account for the i2c bus speed.
324 	 */
325 	int max_retries = 7;
326 
327 	for (retry = 0, defer_i2c = 0; retry < (max_retries + defer_i2c);
328 	     retry++) {
329 		ret = aux->transfer(aux, msg);
330 		if (ret < 0) {
331 			if (ret == -EBUSY)
332 				continue;
333 
334 			/*
335 			 * While timeouts can be errors, they're usually normal
336 			 * behavior (for instance, when a driver tries to
337 			 * communicate with a non-existent DisplayPort device).
338 			 * Avoid spamming the kernel log with timeout errors.
339 			 */
340 			if (ret == -ETIMEDOUT)
341 				printf("%s: transaction timed out\n",
342 				       aux->name);
343 			else
344 				printf("%s: transaction failed: %d\n",
345 				       aux->name, ret);
346 			return ret;
347 		}
348 
349 		switch (msg->reply & DP_AUX_NATIVE_REPLY_MASK) {
350 		case DP_AUX_NATIVE_REPLY_ACK:
351 			/*
352 			 * For I2C-over-AUX transactions this isn't enough, we
353 			 * need to check for the I2C ACK reply.
354 			 */
355 			break;
356 
357 		case DP_AUX_NATIVE_REPLY_NACK:
358 			printf("%s: native nack (result=%d, size=%zu)\n",
359 			       aux->name, ret, msg->size);
360 			return -EREMOTEIO;
361 
362 		case DP_AUX_NATIVE_REPLY_DEFER:
363 			printf("%s: native defer\n", aux->name);
364 			/*
365 			 * We could check for I2C bit rate capabilities and if
366 			 * available adjust this interval. We could also be
367 			 * more careful with DP-to-legacy adapters where a
368 			 * long legacy cable may force very low I2C bit rates.
369 			 *
370 			 * For now just defer for long enough to hopefully be
371 			 * safe for all use-cases.
372 			 */
373 			udelay(AUX_RETRY_INTERVAL);
374 			continue;
375 
376 		default:
377 			printf("%s: invalid native reply %#04x\n",
378 			       aux->name, msg->reply);
379 			return -EREMOTEIO;
380 		}
381 
382 		switch (msg->reply & DP_AUX_I2C_REPLY_MASK) {
383 		case DP_AUX_I2C_REPLY_ACK:
384 			/*
385 			 * Both native ACK and I2C ACK replies received. We
386 			 * can assume the transfer was successful.
387 			 */
388 			if (ret != msg->size)
389 				drm_dp_i2c_msg_write_status_update(msg);
390 			return ret;
391 
392 		case DP_AUX_I2C_REPLY_NACK:
393 			printf("%s: I2C nack (result=%d, size=%zu)\n",
394 			       aux->name, ret, msg->size);
395 			aux->i2c_nack_count++;
396 			return -EREMOTEIO;
397 
398 		case DP_AUX_I2C_REPLY_DEFER:
399 			printf("%s: I2C defer\n", aux->name);
400 			/* DP Compliance Test 4.2.2.5 Requirement:
401 			 * Must have at least 7 retries for I2C defers on the
402 			 * transaction to pass this test
403 			 */
404 			aux->i2c_defer_count++;
405 			if (defer_i2c < 7)
406 				defer_i2c++;
407 			udelay(AUX_RETRY_INTERVAL);
408 			drm_dp_i2c_msg_write_status_update(msg);
409 
410 			continue;
411 
412 		default:
413 			printf("%s: invalid I2C reply %#04x\n",
414 			       aux->name, msg->reply);
415 			return -EREMOTEIO;
416 		}
417 	}
418 
419 	printf("%s: Too many retries, giving up\n", aux->name);
420 	return -EREMOTEIO;
421 }
422 
drm_dp_i2c_msg_set_request(struct drm_dp_aux_msg * msg,const struct i2c_msg * i2c_msg)423 static void drm_dp_i2c_msg_set_request(struct drm_dp_aux_msg *msg,
424 				       const struct i2c_msg *i2c_msg)
425 {
426 	msg->request = (i2c_msg->flags & I2C_M_RD) ?
427 		DP_AUX_I2C_READ : DP_AUX_I2C_WRITE;
428 	if (!(i2c_msg->flags & I2C_M_STOP))
429 		msg->request |= DP_AUX_I2C_MOT;
430 }
431 
432 /*
433  * Keep retrying drm_dp_i2c_do_msg until all data has been transferred.
434  *
435  * Returns an error code on failure, or a recommended transfer size on success.
436  */
drm_dp_i2c_drain_msg(struct drm_dp_aux * aux,struct drm_dp_aux_msg * orig_msg)437 static int drm_dp_i2c_drain_msg(struct drm_dp_aux *aux,
438 				struct drm_dp_aux_msg *orig_msg)
439 {
440 	int err, ret = orig_msg->size;
441 	struct drm_dp_aux_msg msg = *orig_msg;
442 
443 	while (msg.size > 0) {
444 		err = drm_dp_i2c_do_msg(aux, &msg);
445 		if (err <= 0)
446 			return err == 0 ? -EPROTO : err;
447 
448 		if (err < msg.size && err < ret) {
449 			printf("%s: Reply: requested %zu bytes got %d bytes\n",
450 			       aux->name, msg.size, err);
451 			ret = err;
452 		}
453 
454 		msg.size -= err;
455 		msg.buffer += err;
456 	}
457 
458 	return ret;
459 }
460 
drm_dp_i2c_xfer(struct ddc_adapter * adapter,struct i2c_msg * msgs,int num)461 int drm_dp_i2c_xfer(struct ddc_adapter *adapter, struct i2c_msg *msgs,
462 		    int num)
463 {
464 	struct drm_dp_aux *aux = container_of(adapter, struct drm_dp_aux, ddc);
465 	unsigned int i, j;
466 	unsigned int transfer_size;
467 	struct drm_dp_aux_msg msg;
468 	int err = 0;
469 
470 	memset(&msg, 0, sizeof(msg));
471 
472 	for (i = 0; i < num; i++) {
473 		msg.address = msgs[i].addr;
474 		drm_dp_i2c_msg_set_request(&msg, &msgs[i]);
475 		/* Send a bare address packet to start the transaction.
476 		 * Zero sized messages specify an address only (bare
477 		 * address) transaction.
478 		 */
479 		msg.buffer = NULL;
480 		msg.size = 0;
481 		err = drm_dp_i2c_do_msg(aux, &msg);
482 
483 		/*
484 		 * Reset msg.request in case in case it got
485 		 * changed into a WRITE_STATUS_UPDATE.
486 		 */
487 		drm_dp_i2c_msg_set_request(&msg, &msgs[i]);
488 
489 		if (err < 0)
490 			break;
491 		/* We want each transaction to be as large as possible, but
492 		 * we'll go to smaller sizes if the hardware gives us a
493 		 * short reply.
494 		 */
495 		transfer_size = DP_AUX_MAX_PAYLOAD_BYTES;
496 		for (j = 0; j < msgs[i].len; j += msg.size) {
497 			msg.buffer = msgs[i].buf + j;
498 			msg.size = min(transfer_size, msgs[i].len - j);
499 
500 			err = drm_dp_i2c_drain_msg(aux, &msg);
501 
502 			/*
503 			 * Reset msg.request in case in case it got
504 			 * changed into a WRITE_STATUS_UPDATE.
505 			 */
506 			drm_dp_i2c_msg_set_request(&msg, &msgs[i]);
507 
508 			if (err < 0)
509 				break;
510 			transfer_size = err;
511 		}
512 		if (err < 0)
513 			break;
514 	}
515 	if (err >= 0)
516 		err = num;
517 	/* Send a bare address packet to close out the transaction.
518 	 * Zero sized messages specify an address only (bare
519 	 * address) transaction.
520 	 */
521 	msg.request &= ~DP_AUX_I2C_MOT;
522 	msg.buffer = NULL;
523 	msg.size = 0;
524 	(void)drm_dp_i2c_do_msg(aux, &msg);
525 
526 	return err;
527 }
528 
529