blob: b27b1633bab56538358d2a93a199eb501efea494 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0
Simon Glass59dd5aa2015-04-14 21:03:41 -06002/*
3 * Copyright (c) 2011-2013, NVIDIA Corporation.
4 * Copyright 2014 Google Inc.
Simon Glass59dd5aa2015-04-14 21:03:41 -06005 */
6
7#include <common.h>
Simon Glass2dcf1432016-01-21 19:45:00 -07008#include <display.h>
Simon Glass59dd5aa2015-04-14 21:03:41 -06009#include <dm.h>
10#include <div64.h>
11#include <errno.h>
Simon Glassf7ae49f2020-05-10 11:40:05 -060012#include <log.h>
Simon Glassd7659212016-01-30 16:37:50 -070013#include <video_bridge.h>
Simon Glass59dd5aa2015-04-14 21:03:41 -060014#include <asm/io.h>
15#include <asm/arch-tegra/dc.h>
Simon Glassc05ed002020-05-10 11:40:11 -060016#include <linux/delay.h>
Simon Glass2dcf1432016-01-21 19:45:00 -070017#include "display.h"
Simon Glass59dd5aa2015-04-14 21:03:41 -060018#include "edid.h"
19#include "sor.h"
Simon Glass2dcf1432016-01-21 19:45:00 -070020#include "displayport.h"
Simon Glass59dd5aa2015-04-14 21:03:41 -060021
Simon Glassdedc44b2015-04-14 21:03:44 -060022#define DO_FAST_LINK_TRAINING 1
23
Simon Glass59dd5aa2015-04-14 21:03:41 -060024struct tegra_dp_plat {
25 ulong base;
26};
27
Simon Glassd7659212016-01-30 16:37:50 -070028/**
29 * struct tegra_dp_priv - private displayport driver info
30 *
31 * @dc_dev: Display controller device that is sending the video feed
32 */
Simon Glass59dd5aa2015-04-14 21:03:41 -060033struct tegra_dp_priv {
Simon Glassd7659212016-01-30 16:37:50 -070034 struct udevice *sor;
35 struct udevice *dc_dev;
Simon Glass59dd5aa2015-04-14 21:03:41 -060036 struct dpaux_ctlr *regs;
Simon Glass59dd5aa2015-04-14 21:03:41 -060037 u8 revision;
38 int enabled;
39};
40
41struct tegra_dp_priv dp_data;
42
43static inline u32 tegra_dpaux_readl(struct tegra_dp_priv *dp, u32 reg)
44{
45 return readl((u32 *)dp->regs + reg);
46}
47
48static inline void tegra_dpaux_writel(struct tegra_dp_priv *dp, u32 reg,
49 u32 val)
50{
51 writel(val, (u32 *)dp->regs + reg);
52}
53
54static inline u32 tegra_dc_dpaux_poll_register(struct tegra_dp_priv *dp,
55 u32 reg, u32 mask, u32 exp_val,
56 u32 poll_interval_us,
57 u32 timeout_us)
58{
59 u32 reg_val = 0;
60 u32 temp = timeout_us;
61
62 do {
63 udelay(poll_interval_us);
64 reg_val = tegra_dpaux_readl(dp, reg);
65 if (timeout_us > poll_interval_us)
66 timeout_us -= poll_interval_us;
67 else
68 break;
69 } while ((reg_val & mask) != exp_val);
70
71 if ((reg_val & mask) == exp_val)
72 return 0; /* success */
73 debug("dpaux_poll_register 0x%x: timeout: (reg_val)0x%08x & (mask)0x%08x != (exp_val)0x%08x\n",
74 reg, reg_val, mask, exp_val);
75 return temp;
76}
77
78static inline int tegra_dpaux_wait_transaction(struct tegra_dp_priv *dp)
79{
80 /* According to DP spec, each aux transaction needs to finish
81 within 40ms. */
82 if (tegra_dc_dpaux_poll_register(dp, DPAUX_DP_AUXCTL,
83 DPAUX_DP_AUXCTL_TRANSACTREQ_MASK,
84 DPAUX_DP_AUXCTL_TRANSACTREQ_DONE,
85 100, DP_AUX_TIMEOUT_MS * 1000) != 0) {
86 debug("dp: DPAUX transaction timeout\n");
87 return -1;
88 }
89 return 0;
90}
91
92static int tegra_dc_dpaux_write_chunk(struct tegra_dp_priv *dp, u32 cmd,
93 u32 addr, u8 *data, u32 *size,
94 u32 *aux_stat)
95{
96 int i;
97 u32 reg_val;
98 u32 timeout_retries = DP_AUX_TIMEOUT_MAX_TRIES;
99 u32 defer_retries = DP_AUX_DEFER_MAX_TRIES;
100 u32 temp_data;
101
102 if (*size > DP_AUX_MAX_BYTES)
103 return -1; /* only write one chunk of data */
104
105 /* Make sure the command is write command */
106 switch (cmd) {
107 case DPAUX_DP_AUXCTL_CMD_I2CWR:
108 case DPAUX_DP_AUXCTL_CMD_MOTWR:
109 case DPAUX_DP_AUXCTL_CMD_AUXWR:
110 break;
111 default:
112 debug("dp: aux write cmd 0x%x is invalid\n", cmd);
113 return -EINVAL;
114 }
115
116 tegra_dpaux_writel(dp, DPAUX_DP_AUXADDR, addr);
117 for (i = 0; i < DP_AUX_MAX_BYTES / 4; ++i) {
118 memcpy(&temp_data, data, 4);
119 tegra_dpaux_writel(dp, DPAUX_DP_AUXDATA_WRITE_W(i), temp_data);
120 data += 4;
121 }
122
123 reg_val = tegra_dpaux_readl(dp, DPAUX_DP_AUXCTL);
124 reg_val &= ~DPAUX_DP_AUXCTL_CMD_MASK;
125 reg_val |= cmd;
126 reg_val &= ~DPAUX_DP_AUXCTL_CMDLEN_FIELD;
127 reg_val |= ((*size - 1) << DPAUX_DP_AUXCTL_CMDLEN_SHIFT);
128
129 while ((timeout_retries > 0) && (defer_retries > 0)) {
130 if ((timeout_retries != DP_AUX_TIMEOUT_MAX_TRIES) ||
131 (defer_retries != DP_AUX_DEFER_MAX_TRIES))
132 udelay(1);
133
134 reg_val |= DPAUX_DP_AUXCTL_TRANSACTREQ_PENDING;
135 tegra_dpaux_writel(dp, DPAUX_DP_AUXCTL, reg_val);
136
137 if (tegra_dpaux_wait_transaction(dp))
138 debug("dp: aux write transaction timeout\n");
139
140 *aux_stat = tegra_dpaux_readl(dp, DPAUX_DP_AUXSTAT);
141
142 if ((*aux_stat & DPAUX_DP_AUXSTAT_TIMEOUT_ERROR_PENDING) ||
143 (*aux_stat & DPAUX_DP_AUXSTAT_RX_ERROR_PENDING) ||
144 (*aux_stat & DPAUX_DP_AUXSTAT_SINKSTAT_ERROR_PENDING) ||
145 (*aux_stat & DPAUX_DP_AUXSTAT_NO_STOP_ERROR_PENDING)) {
146 if (timeout_retries-- > 0) {
147 debug("dp: aux write retry (0x%x) -- %d\n",
148 *aux_stat, timeout_retries);
149 /* clear the error bits */
150 tegra_dpaux_writel(dp, DPAUX_DP_AUXSTAT,
151 *aux_stat);
152 continue;
153 } else {
154 debug("dp: aux write got error (0x%x)\n",
155 *aux_stat);
156 return -ETIMEDOUT;
157 }
158 }
159
160 if ((*aux_stat & DPAUX_DP_AUXSTAT_REPLYTYPE_I2CDEFER) ||
161 (*aux_stat & DPAUX_DP_AUXSTAT_REPLYTYPE_DEFER)) {
162 if (defer_retries-- > 0) {
163 debug("dp: aux write defer (0x%x) -- %d\n",
164 *aux_stat, defer_retries);
165 /* clear the error bits */
166 tegra_dpaux_writel(dp, DPAUX_DP_AUXSTAT,
167 *aux_stat);
168 continue;
169 } else {
170 debug("dp: aux write defer exceeds max retries (0x%x)\n",
171 *aux_stat);
172 return -ETIMEDOUT;
173 }
174 }
175
176 if ((*aux_stat & DPAUX_DP_AUXSTAT_REPLYTYPE_MASK) ==
177 DPAUX_DP_AUXSTAT_REPLYTYPE_ACK) {
178 *size = ((*aux_stat) & DPAUX_DP_AUXSTAT_REPLY_M_MASK);
179 return 0;
180 } else {
181 debug("dp: aux write failed (0x%x)\n", *aux_stat);
182 return -EIO;
183 }
184 }
185 /* Should never come to here */
186 return -EIO;
187}
188
189static int tegra_dc_dpaux_read_chunk(struct tegra_dp_priv *dp, u32 cmd,
190 u32 addr, u8 *data, u32 *size,
191 u32 *aux_stat)
192{
193 u32 reg_val;
194 u32 timeout_retries = DP_AUX_TIMEOUT_MAX_TRIES;
195 u32 defer_retries = DP_AUX_DEFER_MAX_TRIES;
196
197 if (*size > DP_AUX_MAX_BYTES) {
198 debug("only read one chunk\n");
199 return -EIO; /* only read one chunk */
200 }
201
202 /* Check to make sure the command is read command */
203 switch (cmd) {
204 case DPAUX_DP_AUXCTL_CMD_I2CRD:
205 case DPAUX_DP_AUXCTL_CMD_I2CREQWSTAT:
206 case DPAUX_DP_AUXCTL_CMD_MOTRD:
207 case DPAUX_DP_AUXCTL_CMD_AUXRD:
208 break;
209 default:
210 debug("dp: aux read cmd 0x%x is invalid\n", cmd);
211 return -EIO;
212 }
213
214 *aux_stat = tegra_dpaux_readl(dp, DPAUX_DP_AUXSTAT);
215 if (!(*aux_stat & DPAUX_DP_AUXSTAT_HPD_STATUS_PLUGGED)) {
216 debug("dp: HPD is not detected\n");
217 return -EIO;
218 }
219
220 tegra_dpaux_writel(dp, DPAUX_DP_AUXADDR, addr);
221
222 reg_val = tegra_dpaux_readl(dp, DPAUX_DP_AUXCTL);
223 reg_val &= ~DPAUX_DP_AUXCTL_CMD_MASK;
224 reg_val |= cmd;
225 reg_val &= ~DPAUX_DP_AUXCTL_CMDLEN_FIELD;
226 reg_val |= ((*size - 1) << DPAUX_DP_AUXCTL_CMDLEN_SHIFT);
227 while ((timeout_retries > 0) && (defer_retries > 0)) {
228 if ((timeout_retries != DP_AUX_TIMEOUT_MAX_TRIES) ||
229 (defer_retries != DP_AUX_DEFER_MAX_TRIES))
230 udelay(DP_DPCP_RETRY_SLEEP_NS * 2);
231
232 reg_val |= DPAUX_DP_AUXCTL_TRANSACTREQ_PENDING;
233 tegra_dpaux_writel(dp, DPAUX_DP_AUXCTL, reg_val);
234
235 if (tegra_dpaux_wait_transaction(dp))
236 debug("dp: aux read transaction timeout\n");
237
238 *aux_stat = tegra_dpaux_readl(dp, DPAUX_DP_AUXSTAT);
239
240 if ((*aux_stat & DPAUX_DP_AUXSTAT_TIMEOUT_ERROR_PENDING) ||
241 (*aux_stat & DPAUX_DP_AUXSTAT_RX_ERROR_PENDING) ||
242 (*aux_stat & DPAUX_DP_AUXSTAT_SINKSTAT_ERROR_PENDING) ||
243 (*aux_stat & DPAUX_DP_AUXSTAT_NO_STOP_ERROR_PENDING)) {
244 if (timeout_retries-- > 0) {
245 debug("dp: aux read retry (0x%x) -- %d\n",
246 *aux_stat, timeout_retries);
247 /* clear the error bits */
248 tegra_dpaux_writel(dp, DPAUX_DP_AUXSTAT,
249 *aux_stat);
250 continue; /* retry */
251 } else {
252 debug("dp: aux read got error (0x%x)\n",
253 *aux_stat);
254 return -ETIMEDOUT;
255 }
256 }
257
258 if ((*aux_stat & DPAUX_DP_AUXSTAT_REPLYTYPE_I2CDEFER) ||
259 (*aux_stat & DPAUX_DP_AUXSTAT_REPLYTYPE_DEFER)) {
260 if (defer_retries-- > 0) {
261 debug("dp: aux read defer (0x%x) -- %d\n",
262 *aux_stat, defer_retries);
263 /* clear the error bits */
264 tegra_dpaux_writel(dp, DPAUX_DP_AUXSTAT,
265 *aux_stat);
266 continue;
267 } else {
268 debug("dp: aux read defer exceeds max retries (0x%x)\n",
269 *aux_stat);
270 return -ETIMEDOUT;
271 }
272 }
273
274 if ((*aux_stat & DPAUX_DP_AUXSTAT_REPLYTYPE_MASK) ==
275 DPAUX_DP_AUXSTAT_REPLYTYPE_ACK) {
276 int i;
277 u32 temp_data[4];
278
279 for (i = 0; i < DP_AUX_MAX_BYTES / 4; ++i)
280 temp_data[i] = tegra_dpaux_readl(dp,
281 DPAUX_DP_AUXDATA_READ_W(i));
282
283 *size = ((*aux_stat) & DPAUX_DP_AUXSTAT_REPLY_M_MASK);
284 memcpy(data, temp_data, *size);
285
286 return 0;
287 } else {
288 debug("dp: aux read failed (0x%x\n", *aux_stat);
289 return -EIO;
290 }
291 }
292 /* Should never come to here */
293 debug("%s: can't\n", __func__);
294
295 return -EIO;
296}
297
298static int tegra_dc_dpaux_read(struct tegra_dp_priv *dp, u32 cmd, u32 addr,
299 u8 *data, u32 *size, u32 *aux_stat)
300{
301 u32 finished = 0;
302 u32 cur_size;
303 int ret = 0;
304
305 do {
306 cur_size = *size - finished;
307 if (cur_size > DP_AUX_MAX_BYTES)
308 cur_size = DP_AUX_MAX_BYTES;
309
310 ret = tegra_dc_dpaux_read_chunk(dp, cmd, addr,
311 data, &cur_size, aux_stat);
312 if (ret)
313 break;
314
315 /* cur_size should be the real size returned */
316 addr += cur_size;
317 data += cur_size;
318 finished += cur_size;
319
320 } while (*size > finished);
321 *size = finished;
322
323 return ret;
324}
325
326static int tegra_dc_dp_dpcd_read(struct tegra_dp_priv *dp, u32 cmd,
327 u8 *data_ptr)
328{
329 u32 size = 1;
330 u32 status = 0;
331 int ret;
332
333 ret = tegra_dc_dpaux_read_chunk(dp, DPAUX_DP_AUXCTL_CMD_AUXRD,
334 cmd, data_ptr, &size, &status);
335 if (ret) {
336 debug("dp: Failed to read DPCD data. CMD 0x%x, Status 0x%x\n",
337 cmd, status);
338 }
339
340 return ret;
341}
342
343static int tegra_dc_dp_dpcd_write(struct tegra_dp_priv *dp, u32 cmd,
344 u8 data)
345{
346 u32 size = 1;
347 u32 status = 0;
348 int ret;
349
350 ret = tegra_dc_dpaux_write_chunk(dp, DPAUX_DP_AUXCTL_CMD_AUXWR,
351 cmd, &data, &size, &status);
352 if (ret) {
353 debug("dp: Failed to write DPCD data. CMD 0x%x, Status 0x%x\n",
354 cmd, status);
355 }
356
357 return ret;
358}
359
360static int tegra_dc_i2c_aux_read(struct tegra_dp_priv *dp, u32 i2c_addr,
361 u8 addr, u8 *data, u32 size, u32 *aux_stat)
362{
363 u32 finished = 0;
364 int ret = 0;
365
366 do {
367 u32 cur_size = min((u32)DP_AUX_MAX_BYTES, size - finished);
368
369 u32 len = 1;
370 ret = tegra_dc_dpaux_write_chunk(
371 dp, DPAUX_DP_AUXCTL_CMD_MOTWR, i2c_addr,
372 &addr, &len, aux_stat);
373 if (ret) {
374 debug("%s: error sending address to read.\n",
375 __func__);
376 return ret;
377 }
378
379 ret = tegra_dc_dpaux_read_chunk(
380 dp, DPAUX_DP_AUXCTL_CMD_I2CRD, i2c_addr,
381 data, &cur_size, aux_stat);
382 if (ret) {
383 debug("%s: error reading data.\n", __func__);
384 return ret;
385 }
386
387 /* cur_size should be the real size returned */
388 addr += cur_size;
389 data += cur_size;
390 finished += cur_size;
391 } while (size > finished);
392
393 return finished;
394}
395
396static void tegra_dc_dpaux_enable(struct tegra_dp_priv *dp)
397{
398 /* clear interrupt */
399 tegra_dpaux_writel(dp, DPAUX_INTR_AUX, 0xffffffff);
400 /* do not enable interrupt for now. Enable them when Isr in place */
401 tegra_dpaux_writel(dp, DPAUX_INTR_EN_AUX, 0x0);
402
403 tegra_dpaux_writel(dp, DPAUX_HYBRID_PADCTL,
404 DPAUX_HYBRID_PADCTL_AUX_DRVZ_OHM_50 |
405 DPAUX_HYBRID_PADCTL_AUX_CMH_V0_70 |
406 0x18 << DPAUX_HYBRID_PADCTL_AUX_DRVI_SHIFT |
407 DPAUX_HYBRID_PADCTL_AUX_INPUT_RCV_ENABLE);
408
409 tegra_dpaux_writel(dp, DPAUX_HYBRID_SPARE,
410 DPAUX_HYBRID_SPARE_PAD_PWR_POWERUP);
411}
412
413#ifdef DEBUG
414static void tegra_dc_dp_dump_link_cfg(struct tegra_dp_priv *dp,
415 const struct tegra_dp_link_config *link_cfg)
416{
417 debug("DP config: cfg_name cfg_value\n");
418 debug(" Lane Count %d\n",
419 link_cfg->max_lane_count);
420 debug(" SupportEnhancedFraming %s\n",
421 link_cfg->support_enhanced_framing ? "Y" : "N");
422 debug(" Bandwidth %d\n",
423 link_cfg->max_link_bw);
424 debug(" bpp %d\n",
425 link_cfg->bits_per_pixel);
426 debug(" EnhancedFraming %s\n",
427 link_cfg->enhanced_framing ? "Y" : "N");
428 debug(" Scramble_enabled %s\n",
429 link_cfg->scramble_ena ? "Y" : "N");
430 debug(" LinkBW %d\n",
431 link_cfg->link_bw);
432 debug(" lane_count %d\n",
433 link_cfg->lane_count);
434 debug(" activespolarity %d\n",
435 link_cfg->activepolarity);
436 debug(" active_count %d\n",
437 link_cfg->active_count);
438 debug(" tu_size %d\n",
439 link_cfg->tu_size);
440 debug(" active_frac %d\n",
441 link_cfg->active_frac);
442 debug(" watermark %d\n",
443 link_cfg->watermark);
444 debug(" hblank_sym %d\n",
445 link_cfg->hblank_sym);
446 debug(" vblank_sym %d\n",
447 link_cfg->vblank_sym);
448}
449#endif
450
Simon Glassdedc44b2015-04-14 21:03:44 -0600451static int _tegra_dp_lower_link_config(struct tegra_dp_priv *dp,
452 struct tegra_dp_link_config *cfg)
453{
454 switch (cfg->link_bw) {
455 case SOR_LINK_SPEED_G1_62:
456 if (cfg->max_link_bw > SOR_LINK_SPEED_G1_62)
457 cfg->link_bw = SOR_LINK_SPEED_G2_7;
458 cfg->lane_count /= 2;
459 break;
460 case SOR_LINK_SPEED_G2_7:
461 cfg->link_bw = SOR_LINK_SPEED_G1_62;
462 break;
463 case SOR_LINK_SPEED_G5_4:
464 if (cfg->lane_count == 1) {
465 cfg->link_bw = SOR_LINK_SPEED_G2_7;
466 cfg->lane_count = cfg->max_lane_count;
467 } else {
468 cfg->lane_count /= 2;
469 }
470 break;
471 default:
472 debug("dp: Error link rate %d\n", cfg->link_bw);
473 return -ENOLINK;
474 }
475
476 return (cfg->lane_count > 0) ? 0 : -ENOLINK;
477}
478
Simon Glass59dd5aa2015-04-14 21:03:41 -0600479/*
480 * Calcuate if given cfg can meet the mode request.
481 * Return 0 if mode is possible, -1 otherwise
482 */
483static int tegra_dc_dp_calc_config(struct tegra_dp_priv *dp,
484 const struct display_timing *timing,
485 struct tegra_dp_link_config *link_cfg)
486{
487 const u32 link_rate = 27 * link_cfg->link_bw * 1000 * 1000;
488 const u64 f = 100000; /* precision factor */
489 u32 num_linkclk_line; /* Number of link clocks per line */
490 u64 ratio_f; /* Ratio of incoming to outgoing data rate */
491 u64 frac_f;
492 u64 activesym_f; /* Activesym per TU */
493 u64 activecount_f;
494 u32 activecount;
495 u32 activepolarity;
496 u64 approx_value_f;
497 u32 activefrac = 0;
498 u64 accumulated_error_f = 0;
499 u32 lowest_neg_activecount = 0;
500 u32 lowest_neg_activepolarity = 0;
501 u32 lowest_neg_tusize = 64;
502 u32 num_symbols_per_line;
503 u64 lowest_neg_activefrac = 0;
504 u64 lowest_neg_error_f = 64 * f;
505 u64 watermark_f;
506 int i;
507 int neg;
508
509 if (!link_rate || !link_cfg->lane_count || !timing->pixelclock.typ ||
510 !link_cfg->bits_per_pixel)
511 return -1;
512
513 if ((u64)timing->pixelclock.typ * link_cfg->bits_per_pixel >=
514 (u64)link_rate * 8 * link_cfg->lane_count)
515 return -1;
516
517 num_linkclk_line = (u32)(lldiv(link_rate * timing->hactive.typ,
518 timing->pixelclock.typ));
519
520 ratio_f = (u64)timing->pixelclock.typ * link_cfg->bits_per_pixel * f;
521 ratio_f /= 8;
522 do_div(ratio_f, link_rate * link_cfg->lane_count);
523
524 for (i = 64; i >= 32; --i) {
525 activesym_f = ratio_f * i;
526 activecount_f = lldiv(activesym_f, (u32)f) * f;
527 frac_f = activesym_f - activecount_f;
528 activecount = (u32)(lldiv(activecount_f, (u32)f));
529
530 if (frac_f < (lldiv(f, 2))) /* fraction < 0.5 */
531 activepolarity = 0;
532 else {
533 activepolarity = 1;
534 frac_f = f - frac_f;
535 }
536
537 if (frac_f != 0) {
538 /* warning: frac_f should be 64-bit */
539 frac_f = lldiv(f * f, frac_f); /* 1 / fraction */
540 if (frac_f > (15 * f))
541 activefrac = activepolarity ? 1 : 15;
542 else
543 activefrac = activepolarity ?
544 (u32)lldiv(frac_f, (u32)f) + 1 :
545 (u32)lldiv(frac_f, (u32)f);
546 }
547
548 if (activefrac == 1)
549 activepolarity = 0;
550
551 if (activepolarity == 1)
552 approx_value_f = activefrac ? lldiv(
553 (activecount_f + (activefrac * f - f) * f),
554 (activefrac * f)) :
555 activecount_f + f;
556 else
557 approx_value_f = activefrac ?
558 activecount_f + lldiv(f, activefrac) :
559 activecount_f;
560
561 if (activesym_f < approx_value_f) {
562 accumulated_error_f = num_linkclk_line *
563 lldiv(approx_value_f - activesym_f, i);
564 neg = 1;
565 } else {
566 accumulated_error_f = num_linkclk_line *
567 lldiv(activesym_f - approx_value_f, i);
568 neg = 0;
569 }
570
571 if ((neg && (lowest_neg_error_f > accumulated_error_f)) ||
572 (accumulated_error_f == 0)) {
573 lowest_neg_error_f = accumulated_error_f;
574 lowest_neg_tusize = i;
575 lowest_neg_activecount = activecount;
576 lowest_neg_activepolarity = activepolarity;
577 lowest_neg_activefrac = activefrac;
578
579 if (accumulated_error_f == 0)
580 break;
581 }
582 }
583
584 if (lowest_neg_activefrac == 0) {
585 link_cfg->activepolarity = 0;
586 link_cfg->active_count = lowest_neg_activepolarity ?
587 lowest_neg_activecount : lowest_neg_activecount - 1;
588 link_cfg->tu_size = lowest_neg_tusize;
589 link_cfg->active_frac = 1;
590 } else {
591 link_cfg->activepolarity = lowest_neg_activepolarity;
592 link_cfg->active_count = (u32)lowest_neg_activecount;
593 link_cfg->tu_size = lowest_neg_tusize;
594 link_cfg->active_frac = (u32)lowest_neg_activefrac;
595 }
596
597 watermark_f = lldiv(ratio_f * link_cfg->tu_size * (f - ratio_f), f);
598 link_cfg->watermark = (u32)(lldiv(watermark_f + lowest_neg_error_f,
599 f)) + link_cfg->bits_per_pixel / 4 - 1;
600 num_symbols_per_line = (timing->hactive.typ *
601 link_cfg->bits_per_pixel) /
602 (8 * link_cfg->lane_count);
603
604 if (link_cfg->watermark > 30) {
605 debug("dp: sor setting: unable to get a good tusize, force watermark to 30\n");
606 link_cfg->watermark = 30;
607 return -1;
608 } else if (link_cfg->watermark > num_symbols_per_line) {
609 debug("dp: sor setting: force watermark to the number of symbols in the line\n");
610 link_cfg->watermark = num_symbols_per_line;
611 return -1;
612 }
613
614 /*
615 * Refer to dev_disp.ref for more information.
616 * # symbols/hblank = ((SetRasterBlankEnd.X + SetRasterSize.Width -
617 * SetRasterBlankStart.X - 7) * link_clk / pclk)
618 * - 3 * enhanced_framing - Y
619 * where Y = (# lanes == 4) 3 : (# lanes == 2) ? 6 : 12
620 */
621 link_cfg->hblank_sym = (int)lldiv(((uint64_t)timing->hback_porch.typ +
622 timing->hfront_porch.typ + timing->hsync_len.typ - 7) *
623 link_rate, timing->pixelclock.typ) -
624 3 * link_cfg->enhanced_framing -
625 (12 / link_cfg->lane_count);
626
627 if (link_cfg->hblank_sym < 0)
628 link_cfg->hblank_sym = 0;
629
630
631 /*
632 * Refer to dev_disp.ref for more information.
633 * # symbols/vblank = ((SetRasterBlankStart.X -
634 * SetRasterBlankEen.X - 25) * link_clk / pclk)
635 * - Y - 1;
636 * where Y = (# lanes == 4) 12 : (# lanes == 2) ? 21 : 39
637 */
638 link_cfg->vblank_sym = (int)lldiv(((uint64_t)timing->hactive.typ - 25)
639 * link_rate, timing->pixelclock.typ) - (36 /
640 link_cfg->lane_count) - 4;
641
642 if (link_cfg->vblank_sym < 0)
643 link_cfg->vblank_sym = 0;
644
645 link_cfg->is_valid = 1;
646#ifdef DEBUG
647 tegra_dc_dp_dump_link_cfg(dp, link_cfg);
648#endif
649
650 return 0;
651}
652
653static int tegra_dc_dp_init_max_link_cfg(
654 const struct display_timing *timing,
655 struct tegra_dp_priv *dp,
656 struct tegra_dp_link_config *link_cfg)
657{
658 const int drive_current = 0x40404040;
659 const int preemphasis = 0x0f0f0f0f;
660 const int postcursor = 0;
661 u8 dpcd_data;
662 int ret;
663
664 ret = tegra_dc_dp_dpcd_read(dp, DP_MAX_LANE_COUNT, &dpcd_data);
665 if (ret)
666 return ret;
667 link_cfg->max_lane_count = dpcd_data & DP_MAX_LANE_COUNT_MASK;
Simon Glassdedc44b2015-04-14 21:03:44 -0600668 link_cfg->tps3_supported = (dpcd_data &
669 DP_MAX_LANE_COUNT_TPS3_SUPPORTED_YES) ? 1 : 0;
Simon Glass59dd5aa2015-04-14 21:03:41 -0600670
671 link_cfg->support_enhanced_framing =
672 (dpcd_data & DP_MAX_LANE_COUNT_ENHANCED_FRAMING_YES) ?
673 1 : 0;
674
675 ret = tegra_dc_dp_dpcd_read(dp, DP_MAX_DOWNSPREAD, &dpcd_data);
676 if (ret)
677 return ret;
678 link_cfg->downspread = (dpcd_data & DP_MAX_DOWNSPREAD_VAL_0_5_PCT) ?
679 1 : 0;
680
Simon Glassdedc44b2015-04-14 21:03:44 -0600681 ret = tegra_dc_dp_dpcd_read(dp, NV_DPCD_TRAINING_AUX_RD_INTERVAL,
682 &link_cfg->aux_rd_interval);
683 if (ret)
684 return ret;
Simon Glass59dd5aa2015-04-14 21:03:41 -0600685 ret = tegra_dc_dp_dpcd_read(dp, DP_MAX_LINK_RATE,
686 &link_cfg->max_link_bw);
687 if (ret)
688 return ret;
689
690 /*
691 * Set to a high value for link training and attach.
692 * Will be re-programmed when dp is enabled.
693 */
694 link_cfg->drive_current = drive_current;
695 link_cfg->preemphasis = preemphasis;
696 link_cfg->postcursor = postcursor;
697
698 ret = tegra_dc_dp_dpcd_read(dp, DP_EDP_CONFIGURATION_CAP, &dpcd_data);
699 if (ret)
700 return ret;
701
702 link_cfg->alt_scramber_reset_cap =
703 (dpcd_data & DP_EDP_CONFIGURATION_CAP_ASC_RESET_YES) ?
704 1 : 0;
705 link_cfg->only_enhanced_framing =
706 (dpcd_data & DP_EDP_CONFIGURATION_CAP_FRAMING_CHANGE_YES) ?
707 1 : 0;
708
709 link_cfg->lane_count = link_cfg->max_lane_count;
710 link_cfg->link_bw = link_cfg->max_link_bw;
711 link_cfg->enhanced_framing = link_cfg->support_enhanced_framing;
Simon Glassdedc44b2015-04-14 21:03:44 -0600712 link_cfg->frame_in_ms = (1000 / 60) + 1;
Simon Glass59dd5aa2015-04-14 21:03:41 -0600713
714 tegra_dc_dp_calc_config(dp, timing, link_cfg);
715 return 0;
716}
717
Simon Glassd7659212016-01-30 16:37:50 -0700718static int tegra_dc_dp_set_assr(struct tegra_dp_priv *priv,
719 struct udevice *sor, int ena)
Simon Glass59dd5aa2015-04-14 21:03:41 -0600720{
721 int ret;
722
723 u8 dpcd_data = ena ?
724 DP_MAIN_LINK_CHANNEL_CODING_SET_ASC_RESET_ENABLE :
725 DP_MAIN_LINK_CHANNEL_CODING_SET_ASC_RESET_DISABLE;
726
Simon Glassd7659212016-01-30 16:37:50 -0700727 ret = tegra_dc_dp_dpcd_write(priv, DP_EDP_CONFIGURATION_SET,
Simon Glass59dd5aa2015-04-14 21:03:41 -0600728 dpcd_data);
729 if (ret)
730 return ret;
731
732 /* Also reset the scrambler to 0xfffe */
733 tegra_dc_sor_set_internal_panel(sor, ena);
734 return 0;
735}
736
737static int tegra_dp_set_link_bandwidth(struct tegra_dp_priv *dp,
Simon Glassd7659212016-01-30 16:37:50 -0700738 struct udevice *sor,
Simon Glass59dd5aa2015-04-14 21:03:41 -0600739 u8 link_bw)
740{
741 tegra_dc_sor_set_link_bandwidth(sor, link_bw);
742
743 /* Sink side */
744 return tegra_dc_dp_dpcd_write(dp, DP_LINK_BW_SET, link_bw);
745}
746
747static int tegra_dp_set_lane_count(struct tegra_dp_priv *dp,
748 const struct tegra_dp_link_config *link_cfg,
Simon Glassd7659212016-01-30 16:37:50 -0700749 struct udevice *sor)
Simon Glass59dd5aa2015-04-14 21:03:41 -0600750{
751 u8 dpcd_data;
752 int ret;
753
754 /* check if panel support enhanched_framing */
755 dpcd_data = link_cfg->lane_count;
756 if (link_cfg->enhanced_framing)
757 dpcd_data |= DP_LANE_COUNT_SET_ENHANCEDFRAMING_T;
758 ret = tegra_dc_dp_dpcd_write(dp, DP_LANE_COUNT_SET, dpcd_data);
759 if (ret)
760 return ret;
761
762 tegra_dc_sor_set_lane_count(sor, link_cfg->lane_count);
763
764 /* Also power down lanes that will not be used */
765 return 0;
766}
767
768static int tegra_dc_dp_link_trained(struct tegra_dp_priv *dp,
769 const struct tegra_dp_link_config *cfg)
770{
771 u32 lane;
772 u8 mask;
773 u8 data;
774 int ret;
775
776 for (lane = 0; lane < cfg->lane_count; ++lane) {
777 ret = tegra_dc_dp_dpcd_read(dp, (lane / 2) ?
778 DP_LANE2_3_STATUS : DP_LANE0_1_STATUS,
779 &data);
780 if (ret)
781 return ret;
782 mask = (lane & 1) ?
783 NV_DPCD_STATUS_LANEXPLUS1_CR_DONE_YES |
784 NV_DPCD_STATUS_LANEXPLUS1_CHN_EQ_DONE_YES |
785 NV_DPCD_STATUS_LANEXPLUS1_SYMBOL_LOCKED_YES :
786 DP_LANE_CR_DONE |
787 DP_LANE_CHANNEL_EQ_DONE |
788 DP_LANE_SYMBOL_LOCKED;
789 if ((data & mask) != mask)
790 return -1;
791 }
792 return 0;
793}
794
Simon Glassdedc44b2015-04-14 21:03:44 -0600795static int tegra_dp_channel_eq_status(struct tegra_dp_priv *dp,
796 const struct tegra_dp_link_config *cfg)
797{
798 u32 cnt;
799 u32 n_lanes = cfg->lane_count;
800 u8 data;
801 u8 ce_done = 1;
802 int ret;
803
804 for (cnt = 0; cnt < n_lanes / 2; cnt++) {
805 ret = tegra_dc_dp_dpcd_read(dp, DP_LANE0_1_STATUS + cnt, &data);
806 if (ret)
807 return ret;
808
809 if (n_lanes == 1) {
810 ce_done = (data & (0x1 <<
811 NV_DPCD_STATUS_LANEX_CHN_EQ_DONE_SHIFT)) &&
812 (data & (0x1 <<
813 NV_DPCD_STATUS_LANEX_SYMBOL_LOCKED_SHFIT));
814 break;
815 } else if (!(data & (0x1 <<
816 NV_DPCD_STATUS_LANEX_CHN_EQ_DONE_SHIFT)) ||
817 !(data & (0x1 <<
818 NV_DPCD_STATUS_LANEX_SYMBOL_LOCKED_SHFIT)) ||
819 !(data & (0x1 <<
820 NV_DPCD_STATUS_LANEXPLUS1_CHN_EQ_DONE_SHIFT)) ||
821 !(data & (0x1 <<
822 NV_DPCD_STATUS_LANEXPLUS1_SYMBOL_LOCKED_SHIFT)))
823 return -EIO;
824 }
825
826 if (ce_done) {
827 ret = tegra_dc_dp_dpcd_read(dp,
828 DP_LANE_ALIGN_STATUS_UPDATED,
829 &data);
830 if (ret)
831 return ret;
832 if (!(data & NV_DPCD_LANE_ALIGN_STATUS_UPDATED_DONE_YES))
833 ce_done = 0;
834 }
835
836 return ce_done ? 0 : -EIO;
837}
838
839static int tegra_dp_clock_recovery_status(struct tegra_dp_priv *dp,
840 const struct tegra_dp_link_config *cfg)
841{
842 u32 cnt;
843 u32 n_lanes = cfg->lane_count;
844 u8 data_ptr;
845 int ret;
846
847 for (cnt = 0; cnt < n_lanes / 2; cnt++) {
848 ret = tegra_dc_dp_dpcd_read(dp, (DP_LANE0_1_STATUS + cnt),
849 &data_ptr);
850 if (ret)
851 return ret;
852
853 if (n_lanes == 1)
854 return (data_ptr & NV_DPCD_STATUS_LANEX_CR_DONE_YES) ?
855 1 : 0;
856 else if (!(data_ptr & NV_DPCD_STATUS_LANEX_CR_DONE_YES) ||
857 !(data_ptr & (NV_DPCD_STATUS_LANEXPLUS1_CR_DONE_YES)))
858 return 0;
859 }
860
861 return 1;
862}
863
864static int tegra_dp_lt_adjust(struct tegra_dp_priv *dp, u32 pe[4], u32 vs[4],
865 u32 pc[4], u8 pc_supported,
866 const struct tegra_dp_link_config *cfg)
867{
868 size_t cnt;
869 u8 data_ptr;
870 u32 n_lanes = cfg->lane_count;
871 int ret;
872
873 for (cnt = 0; cnt < n_lanes / 2; cnt++) {
874 ret = tegra_dc_dp_dpcd_read(dp, DP_ADJUST_REQUEST_LANE0_1 + cnt,
875 &data_ptr);
876 if (ret)
877 return ret;
878 pe[2 * cnt] = (data_ptr & NV_DPCD_ADJUST_REQ_LANEX_PE_MASK) >>
879 NV_DPCD_ADJUST_REQ_LANEX_PE_SHIFT;
880 vs[2 * cnt] = (data_ptr & NV_DPCD_ADJUST_REQ_LANEX_DC_MASK) >>
881 NV_DPCD_ADJUST_REQ_LANEX_DC_SHIFT;
882 pe[1 + 2 * cnt] =
883 (data_ptr & NV_DPCD_ADJUST_REQ_LANEXPLUS1_PE_MASK) >>
884 NV_DPCD_ADJUST_REQ_LANEXPLUS1_PE_SHIFT;
885 vs[1 + 2 * cnt] =
886 (data_ptr & NV_DPCD_ADJUST_REQ_LANEXPLUS1_DC_MASK) >>
887 NV_DPCD_ADJUST_REQ_LANEXPLUS1_DC_SHIFT;
888 }
889 if (pc_supported) {
890 ret = tegra_dc_dp_dpcd_read(dp, NV_DPCD_ADJUST_REQ_POST_CURSOR2,
891 &data_ptr);
892 if (ret)
893 return ret;
894 for (cnt = 0; cnt < n_lanes; cnt++) {
895 pc[cnt] = (data_ptr >>
896 NV_DPCD_ADJUST_REQ_POST_CURSOR2_LANE_SHIFT(cnt)) &
897 NV_DPCD_ADJUST_REQ_POST_CURSOR2_LANE_MASK;
898 }
899 }
900
901 return 0;
902}
903
904static void tegra_dp_wait_aux_training(struct tegra_dp_priv *dp,
905 bool is_clk_recovery,
906 const struct tegra_dp_link_config *cfg)
907{
908 if (!cfg->aux_rd_interval)
909 udelay(is_clk_recovery ? 200 : 500);
910 else
911 mdelay(cfg->aux_rd_interval * 4);
912}
913
914static void tegra_dp_tpg(struct tegra_dp_priv *dp, u32 tp, u32 n_lanes,
915 const struct tegra_dp_link_config *cfg)
916{
917 u8 data = (tp == training_pattern_disabled)
918 ? (tp | NV_DPCD_TRAINING_PATTERN_SET_SC_DISABLED_F)
919 : (tp | NV_DPCD_TRAINING_PATTERN_SET_SC_DISABLED_T);
920
921 tegra_dc_sor_set_dp_linkctl(dp->sor, 1, tp, cfg);
922 tegra_dc_dp_dpcd_write(dp, DP_TRAINING_PATTERN_SET, data);
923}
924
925static int tegra_dp_link_config(struct tegra_dp_priv *dp,
926 const struct tegra_dp_link_config *link_cfg)
927{
928 u8 dpcd_data;
929 u32 retry;
930 int ret;
931
932 if (link_cfg->lane_count == 0) {
933 debug("dp: error: lane count is 0. Can not set link config.\n");
934 return -ENOLINK;
935 }
936
937 /* Set power state if it is not in normal level */
938 ret = tegra_dc_dp_dpcd_read(dp, DP_SET_POWER, &dpcd_data);
939 if (ret)
940 return ret;
941
942 if (dpcd_data == DP_SET_POWER_D3) {
943 dpcd_data = DP_SET_POWER_D0;
944
945 /* DP spec requires 3 retries */
946 for (retry = 3; retry > 0; --retry) {
947 ret = tegra_dc_dp_dpcd_write(dp, DP_SET_POWER,
948 dpcd_data);
949 if (!ret)
950 break;
951 if (retry == 1) {
952 debug("dp: Failed to set DP panel power\n");
953 return ret;
954 }
955 }
956 }
957
958 /* Enable ASSR if possible */
959 if (link_cfg->alt_scramber_reset_cap) {
960 ret = tegra_dc_dp_set_assr(dp, dp->sor, 1);
961 if (ret)
962 return ret;
963 }
964
965 ret = tegra_dp_set_link_bandwidth(dp, dp->sor, link_cfg->link_bw);
966 if (ret) {
967 debug("dp: Failed to set link bandwidth\n");
968 return ret;
969 }
970 ret = tegra_dp_set_lane_count(dp, link_cfg, dp->sor);
971 if (ret) {
972 debug("dp: Failed to set lane count\n");
973 return ret;
974 }
975 tegra_dc_sor_set_dp_linkctl(dp->sor, 1, training_pattern_none,
976 link_cfg);
977
978 return 0;
979}
980
981static int tegra_dp_lower_link_config(struct tegra_dp_priv *dp,
982 const struct display_timing *timing,
983 struct tegra_dp_link_config *cfg)
984{
985 struct tegra_dp_link_config tmp_cfg;
986 int ret;
987
988 tmp_cfg = *cfg;
989 cfg->is_valid = 0;
990
991 ret = _tegra_dp_lower_link_config(dp, cfg);
992 if (!ret)
993 ret = tegra_dc_dp_calc_config(dp, timing, cfg);
994 if (!ret)
995 ret = tegra_dp_link_config(dp, cfg);
996 if (ret)
997 goto fail;
998
999 return 0;
1000
1001fail:
1002 *cfg = tmp_cfg;
1003 tegra_dp_link_config(dp, &tmp_cfg);
1004 return ret;
1005}
1006
1007static int tegra_dp_lt_config(struct tegra_dp_priv *dp, u32 pe[4], u32 vs[4],
1008 u32 pc[4], const struct tegra_dp_link_config *cfg)
1009{
Simon Glassd7659212016-01-30 16:37:50 -07001010 struct udevice *sor = dp->sor;
Simon Glassdedc44b2015-04-14 21:03:44 -06001011 u32 n_lanes = cfg->lane_count;
1012 u8 pc_supported = cfg->tps3_supported;
1013 u32 cnt;
1014 u32 val;
1015
1016 for (cnt = 0; cnt < n_lanes; cnt++) {
1017 u32 mask = 0;
1018 u32 pe_reg, vs_reg, pc_reg;
1019 u32 shift = 0;
1020
1021 switch (cnt) {
1022 case 0:
1023 mask = PR_LANE2_DP_LANE0_MASK;
1024 shift = PR_LANE2_DP_LANE0_SHIFT;
1025 break;
1026 case 1:
1027 mask = PR_LANE1_DP_LANE1_MASK;
1028 shift = PR_LANE1_DP_LANE1_SHIFT;
1029 break;
1030 case 2:
1031 mask = PR_LANE0_DP_LANE2_MASK;
1032 shift = PR_LANE0_DP_LANE2_SHIFT;
1033 break;
1034 case 3:
1035 mask = PR_LANE3_DP_LANE3_MASK;
1036 shift = PR_LANE3_DP_LANE3_SHIFT;
1037 break;
1038 default:
1039 debug("dp: incorrect lane cnt\n");
1040 return -EINVAL;
1041 }
1042
1043 pe_reg = tegra_dp_pe_regs[pc[cnt]][vs[cnt]][pe[cnt]];
1044 vs_reg = tegra_dp_vs_regs[pc[cnt]][vs[cnt]][pe[cnt]];
1045 pc_reg = tegra_dp_pc_regs[pc[cnt]][vs[cnt]][pe[cnt]];
1046
1047 tegra_dp_set_pe_vs_pc(sor, mask, pe_reg << shift,
1048 vs_reg << shift, pc_reg << shift,
1049 pc_supported);
1050 }
1051
1052 tegra_dp_disable_tx_pu(dp->sor);
1053 udelay(20);
1054
1055 for (cnt = 0; cnt < n_lanes; cnt++) {
1056 u32 max_vs_flag = tegra_dp_is_max_vs(pe[cnt], vs[cnt]);
1057 u32 max_pe_flag = tegra_dp_is_max_pe(pe[cnt], vs[cnt]);
1058
1059 val = (vs[cnt] << NV_DPCD_TRAINING_LANEX_SET_DC_SHIFT) |
1060 (max_vs_flag ?
1061 NV_DPCD_TRAINING_LANEX_SET_DC_MAX_REACHED_T :
1062 NV_DPCD_TRAINING_LANEX_SET_DC_MAX_REACHED_F) |
1063 (pe[cnt] << NV_DPCD_TRAINING_LANEX_SET_PE_SHIFT) |
1064 (max_pe_flag ?
1065 NV_DPCD_TRAINING_LANEX_SET_PE_MAX_REACHED_T :
1066 NV_DPCD_TRAINING_LANEX_SET_PE_MAX_REACHED_F);
1067 tegra_dc_dp_dpcd_write(dp, (DP_TRAINING_LANE0_SET + cnt), val);
1068 }
1069
1070 if (pc_supported) {
1071 for (cnt = 0; cnt < n_lanes / 2; cnt++) {
1072 u32 max_pc_flag0 = tegra_dp_is_max_pc(pc[cnt]);
1073 u32 max_pc_flag1 = tegra_dp_is_max_pc(pc[cnt + 1]);
1074 val = (pc[cnt] << NV_DPCD_LANEX_SET2_PC2_SHIFT) |
1075 (max_pc_flag0 ?
1076 NV_DPCD_LANEX_SET2_PC2_MAX_REACHED_T :
1077 NV_DPCD_LANEX_SET2_PC2_MAX_REACHED_F) |
1078 (pc[cnt + 1] <<
1079 NV_DPCD_LANEXPLUS1_SET2_PC2_SHIFT) |
1080 (max_pc_flag1 ?
1081 NV_DPCD_LANEXPLUS1_SET2_PC2_MAX_REACHED_T :
1082 NV_DPCD_LANEXPLUS1_SET2_PC2_MAX_REACHED_F);
1083 tegra_dc_dp_dpcd_write(dp,
1084 NV_DPCD_TRAINING_LANE0_1_SET2 +
1085 cnt, val);
1086 }
1087 }
1088
1089 return 0;
1090}
1091
1092static int _tegra_dp_channel_eq(struct tegra_dp_priv *dp, u32 pe[4],
1093 u32 vs[4], u32 pc[4], u8 pc_supported,
1094 u32 n_lanes,
1095 const struct tegra_dp_link_config *cfg)
1096{
1097 u32 retry_cnt;
1098
1099 for (retry_cnt = 0; retry_cnt < 4; retry_cnt++) {
1100 int ret;
1101
1102 if (retry_cnt) {
1103 ret = tegra_dp_lt_adjust(dp, pe, vs, pc, pc_supported,
1104 cfg);
1105 if (ret)
1106 return ret;
1107 tegra_dp_lt_config(dp, pe, vs, pc, cfg);
1108 }
1109
1110 tegra_dp_wait_aux_training(dp, false, cfg);
1111
1112 if (!tegra_dp_clock_recovery_status(dp, cfg)) {
1113 debug("dp: CR failed in channel EQ sequence!\n");
1114 break;
1115 }
1116
1117 if (!tegra_dp_channel_eq_status(dp, cfg))
1118 return 0;
1119 }
1120
1121 return -EIO;
1122}
1123
1124static int tegra_dp_channel_eq(struct tegra_dp_priv *dp, u32 pe[4], u32 vs[4],
1125 u32 pc[4],
1126 const struct tegra_dp_link_config *cfg)
1127{
1128 u32 n_lanes = cfg->lane_count;
1129 u8 pc_supported = cfg->tps3_supported;
1130 int ret;
1131 u32 tp_src = training_pattern_2;
1132
1133 if (pc_supported)
1134 tp_src = training_pattern_3;
1135
1136 tegra_dp_tpg(dp, tp_src, n_lanes, cfg);
1137
1138 ret = _tegra_dp_channel_eq(dp, pe, vs, pc, pc_supported, n_lanes, cfg);
1139
1140 tegra_dp_tpg(dp, training_pattern_disabled, n_lanes, cfg);
1141
1142 return ret;
1143}
1144
1145static int _tegra_dp_clk_recovery(struct tegra_dp_priv *dp, u32 pe[4],
1146 u32 vs[4], u32 pc[4], u8 pc_supported,
1147 u32 n_lanes,
1148 const struct tegra_dp_link_config *cfg)
1149{
1150 u32 vs_temp[4];
1151 u32 retry_cnt = 0;
1152
1153 do {
1154 tegra_dp_lt_config(dp, pe, vs, pc, cfg);
1155 tegra_dp_wait_aux_training(dp, true, cfg);
1156
1157 if (tegra_dp_clock_recovery_status(dp, cfg))
1158 return 0;
1159
1160 memcpy(vs_temp, vs, sizeof(vs_temp));
1161 tegra_dp_lt_adjust(dp, pe, vs, pc, pc_supported, cfg);
1162
1163 if (memcmp(vs_temp, vs, sizeof(vs_temp)))
1164 retry_cnt = 0;
1165 else
1166 ++retry_cnt;
1167 } while (retry_cnt < 5);
1168
1169 return -EIO;
1170}
1171
1172static int tegra_dp_clk_recovery(struct tegra_dp_priv *dp, u32 pe[4],
1173 u32 vs[4], u32 pc[4],
1174 const struct tegra_dp_link_config *cfg)
1175{
1176 u32 n_lanes = cfg->lane_count;
1177 u8 pc_supported = cfg->tps3_supported;
1178 int err;
1179
1180 tegra_dp_tpg(dp, training_pattern_1, n_lanes, cfg);
1181
1182 err = _tegra_dp_clk_recovery(dp, pe, vs, pc, pc_supported, n_lanes,
1183 cfg);
1184 if (err < 0)
1185 tegra_dp_tpg(dp, training_pattern_disabled, n_lanes, cfg);
1186
1187 return err;
1188}
1189
1190static int tegra_dc_dp_full_link_training(struct tegra_dp_priv *dp,
1191 const struct display_timing *timing,
1192 struct tegra_dp_link_config *cfg)
1193{
Simon Glassd7659212016-01-30 16:37:50 -07001194 struct udevice *sor = dp->sor;
Simon Glassdedc44b2015-04-14 21:03:44 -06001195 int err;
1196 u32 pe[4], vs[4], pc[4];
1197
1198 tegra_sor_precharge_lanes(sor, cfg);
1199
1200retry_cr:
1201 memset(pe, PREEMPHASIS_DISABLED, sizeof(pe));
1202 memset(vs, DRIVECURRENT_LEVEL0, sizeof(vs));
1203 memset(pc, POSTCURSOR2_LEVEL0, sizeof(pc));
1204
1205 err = tegra_dp_clk_recovery(dp, pe, vs, pc, cfg);
1206 if (err) {
1207 if (!tegra_dp_lower_link_config(dp, timing, cfg))
1208 goto retry_cr;
1209
1210 debug("dp: clk recovery failed\n");
1211 goto fail;
1212 }
1213
1214 err = tegra_dp_channel_eq(dp, pe, vs, pc, cfg);
1215 if (err) {
1216 if (!tegra_dp_lower_link_config(dp, timing, cfg))
1217 goto retry_cr;
1218
1219 debug("dp: channel equalization failed\n");
1220 goto fail;
1221 }
1222#ifdef DEBUG
1223 tegra_dc_dp_dump_link_cfg(dp, cfg);
1224#endif
1225 return 0;
1226
1227fail:
1228 return err;
1229}
1230
Simon Glass59dd5aa2015-04-14 21:03:41 -06001231/*
1232 * All link training functions are ported from kernel dc driver.
1233 * See more details at drivers/video/tegra/dc/dp.c
1234 */
1235static int tegra_dc_dp_fast_link_training(struct tegra_dp_priv *dp,
1236 const struct tegra_dp_link_config *link_cfg,
Simon Glassd7659212016-01-30 16:37:50 -07001237 struct udevice *sor)
Simon Glass59dd5aa2015-04-14 21:03:41 -06001238{
1239 u8 link_bw;
1240 u8 lane_count;
1241 u16 data16;
1242 u32 data32;
1243 u32 size;
1244 u32 status;
1245 int j;
1246 u32 mask = 0xffff >> ((4 - link_cfg->lane_count) * 4);
1247
1248 tegra_dc_sor_set_lane_parm(sor, link_cfg);
1249 tegra_dc_dp_dpcd_write(dp, DP_MAIN_LINK_CHANNEL_CODING_SET,
1250 DP_SET_ANSI_8B10B);
1251
1252 /* Send TP1 */
1253 tegra_dc_sor_set_dp_linkctl(sor, 1, training_pattern_1, link_cfg);
1254 tegra_dc_dp_dpcd_write(dp, DP_TRAINING_PATTERN_SET,
1255 DP_TRAINING_PATTERN_1);
1256
1257 for (j = 0; j < link_cfg->lane_count; ++j)
1258 tegra_dc_dp_dpcd_write(dp, DP_TRAINING_LANE0_SET + j, 0x24);
1259 udelay(520);
1260
1261 size = sizeof(data16);
1262 tegra_dc_dpaux_read(dp, DPAUX_DP_AUXCTL_CMD_AUXRD,
1263 DP_LANE0_1_STATUS, (u8 *)&data16, &size, &status);
1264 status = mask & 0x1111;
1265 if ((data16 & status) != status) {
1266 debug("dp: Link training error for TP1 (%#x, status %#x)\n",
1267 data16, status);
1268 return -EFAULT;
1269 }
1270
1271 /* enable ASSR */
1272 tegra_dc_dp_set_assr(dp, sor, link_cfg->scramble_ena);
1273 tegra_dc_sor_set_dp_linkctl(sor, 1, training_pattern_3, link_cfg);
1274
1275 tegra_dc_dp_dpcd_write(dp, DP_TRAINING_PATTERN_SET,
1276 link_cfg->link_bw == 20 ? 0x23 : 0x22);
1277 for (j = 0; j < link_cfg->lane_count; ++j)
1278 tegra_dc_dp_dpcd_write(dp, DP_TRAINING_LANE0_SET + j, 0x24);
1279 udelay(520);
1280
1281 size = sizeof(data32);
1282 tegra_dc_dpaux_read(dp, DPAUX_DP_AUXCTL_CMD_AUXRD, DP_LANE0_1_STATUS,
1283 (u8 *)&data32, &size, &status);
1284 if ((data32 & mask) != (0x7777 & mask)) {
1285 debug("dp: Link training error for TP2/3 (0x%x)\n", data32);
1286 return -EFAULT;
1287 }
1288
1289 tegra_dc_sor_set_dp_linkctl(sor, 1, training_pattern_disabled,
1290 link_cfg);
1291 tegra_dc_dp_dpcd_write(dp, DP_TRAINING_PATTERN_SET, 0);
1292
1293 if (tegra_dc_dp_link_trained(dp, link_cfg)) {
1294 tegra_dc_sor_read_link_config(sor, &link_bw, &lane_count);
1295 debug("Fast link training failed, link bw %d, lane # %d\n",
1296 link_bw, lane_count);
1297 return -EFAULT;
1298 }
1299
1300 debug("Fast link training succeeded, link bw %d, lane %d\n",
1301 link_cfg->link_bw, link_cfg->lane_count);
1302
1303 return 0;
1304}
1305
Simon Glassdedc44b2015-04-14 21:03:44 -06001306static int tegra_dp_do_link_training(struct tegra_dp_priv *dp,
1307 struct tegra_dp_link_config *link_cfg,
1308 const struct display_timing *timing,
Simon Glassd7659212016-01-30 16:37:50 -07001309 struct udevice *sor)
Simon Glass59dd5aa2015-04-14 21:03:41 -06001310{
Simon Glass59dd5aa2015-04-14 21:03:41 -06001311 u8 link_bw;
1312 u8 lane_count;
Simon Glass59dd5aa2015-04-14 21:03:41 -06001313 int ret;
1314
Simon Glassdedc44b2015-04-14 21:03:44 -06001315 if (DO_FAST_LINK_TRAINING) {
1316 ret = tegra_dc_dp_fast_link_training(dp, link_cfg, sor);
Simon Glass59dd5aa2015-04-14 21:03:41 -06001317 if (ret) {
Simon Glassdedc44b2015-04-14 21:03:44 -06001318 debug("dp: fast link training failed\n");
1319 } else {
1320 /*
1321 * set to a known-good drive setting if fast link
1322 * succeeded. Ignore any error.
1323 */
1324 ret = tegra_dc_sor_set_voltage_swing(dp->sor, link_cfg);
1325 if (ret)
1326 debug("Failed to set voltage swing\n");
1327 }
1328 } else {
1329 ret = -ENOSYS;
1330 }
1331 if (ret) {
1332 /* Try full link training then */
1333 ret = tegra_dc_dp_full_link_training(dp, timing, link_cfg);
1334 if (ret) {
1335 debug("dp: full link training failed\n");
Simon Glass59dd5aa2015-04-14 21:03:41 -06001336 return ret;
1337 }
1338 }
1339
Simon Glass59dd5aa2015-04-14 21:03:41 -06001340 /* Everything is good; double check the link config */
1341 tegra_dc_sor_read_link_config(sor, &link_bw, &lane_count);
1342
1343 if ((link_cfg->link_bw == link_bw) &&
1344 (link_cfg->lane_count == lane_count))
1345 return 0;
1346 else
1347 return -EFAULT;
1348}
1349
1350static int tegra_dc_dp_explore_link_cfg(struct tegra_dp_priv *dp,
1351 struct tegra_dp_link_config *link_cfg,
Simon Glassd7659212016-01-30 16:37:50 -07001352 struct udevice *sor,
Simon Glass59dd5aa2015-04-14 21:03:41 -06001353 const struct display_timing *timing)
1354{
1355 struct tegra_dp_link_config temp_cfg;
1356
1357 if (!timing->pixelclock.typ || !timing->hactive.typ ||
1358 !timing->vactive.typ) {
1359 debug("dp: error mode configuration");
1360 return -EINVAL;
1361 }
1362 if (!link_cfg->max_link_bw || !link_cfg->max_lane_count) {
1363 debug("dp: error link configuration");
1364 return -EINVAL;
1365 }
1366
1367 link_cfg->is_valid = 0;
1368
1369 memcpy(&temp_cfg, link_cfg, sizeof(temp_cfg));
1370
1371 temp_cfg.link_bw = temp_cfg.max_link_bw;
1372 temp_cfg.lane_count = temp_cfg.max_lane_count;
1373
1374 /*
1375 * set to max link config
1376 */
1377 if ((!tegra_dc_dp_calc_config(dp, timing, &temp_cfg)) &&
Simon Glassdedc44b2015-04-14 21:03:44 -06001378 (!tegra_dp_link_config(dp, &temp_cfg)) &&
1379 (!tegra_dp_do_link_training(dp, &temp_cfg, timing, sor)))
Simon Glass59dd5aa2015-04-14 21:03:41 -06001380 /* the max link cfg is doable */
1381 memcpy(link_cfg, &temp_cfg, sizeof(temp_cfg));
1382
1383 return link_cfg->is_valid ? 0 : -EFAULT;
1384}
1385
1386static int tegra_dp_hpd_plug(struct tegra_dp_priv *dp)
1387{
1388 const int vdd_to_hpd_delay_ms = 200;
1389 u32 val;
1390 ulong start;
1391
1392 start = get_timer(0);
1393 do {
1394 val = tegra_dpaux_readl(dp, DPAUX_DP_AUXSTAT);
1395 if (val & DPAUX_DP_AUXSTAT_HPD_STATUS_PLUGGED)
1396 return 0;
1397 udelay(100);
1398 } while (get_timer(start) < vdd_to_hpd_delay_ms);
1399
1400 return -EIO;
1401}
1402
Simon Glassdedc44b2015-04-14 21:03:44 -06001403static int tegra_dc_dp_sink_out_of_sync(struct tegra_dp_priv *dp, u32 delay_ms)
1404{
1405 u8 dpcd_data;
1406 int out_of_sync;
1407 int ret;
1408
1409 debug("%s: delay=%d\n", __func__, delay_ms);
1410 mdelay(delay_ms);
1411 ret = tegra_dc_dp_dpcd_read(dp, DP_SINK_STATUS, &dpcd_data);
1412 if (ret)
1413 return ret;
1414
1415 out_of_sync = !(dpcd_data & DP_SINK_STATUS_PORT0_IN_SYNC);
1416 if (out_of_sync)
1417 debug("SINK receive port 0 out of sync, data=%x\n", dpcd_data);
1418 else
1419 debug("SINK is in synchronization\n");
1420
1421 return out_of_sync;
1422}
1423
1424static int tegra_dc_dp_check_sink(struct tegra_dp_priv *dp,
1425 struct tegra_dp_link_config *link_cfg,
1426 const struct display_timing *timing)
1427{
1428 const int max_retry = 5;
1429 int delay_frame;
1430 int retries;
1431
1432 /*
1433 * DP TCON may skip some main stream frames, thus we need to wait
1434 * some delay before reading the DPCD SINK STATUS register, starting
1435 * from 5
1436 */
1437 delay_frame = 5;
1438
1439 retries = max_retry;
1440 do {
1441 int ret;
1442
1443 if (!tegra_dc_dp_sink_out_of_sync(dp, link_cfg->frame_in_ms *
1444 delay_frame))
1445 return 0;
1446
1447 debug("%s: retries left %d\n", __func__, retries);
1448 if (!retries--) {
1449 printf("DP: Out of sync after %d retries\n", max_retry);
1450 return -EIO;
1451 }
Simon Glassd7659212016-01-30 16:37:50 -07001452 ret = tegra_dc_sor_detach(dp->dc_dev, dp->sor);
Simon Glassdedc44b2015-04-14 21:03:44 -06001453 if (ret)
1454 return ret;
1455 if (tegra_dc_dp_explore_link_cfg(dp, link_cfg, dp->sor,
1456 timing)) {
1457 debug("dp: %s: error to configure link\n", __func__);
1458 continue;
1459 }
1460
1461 tegra_dc_sor_set_power_state(dp->sor, 1);
Simon Glassd7659212016-01-30 16:37:50 -07001462 tegra_dc_sor_attach(dp->dc_dev, dp->sor, link_cfg, timing);
Simon Glassdedc44b2015-04-14 21:03:44 -06001463
1464 /* Increase delay_frame for next try in case the sink is
1465 skipping more frames */
1466 delay_frame += 10;
1467 } while (1);
1468}
1469
Simon Glass59dd5aa2015-04-14 21:03:41 -06001470int tegra_dp_enable(struct udevice *dev, int panel_bpp,
1471 const struct display_timing *timing)
1472{
1473 struct tegra_dp_priv *priv = dev_get_priv(dev);
1474 struct tegra_dp_link_config slink_cfg, *link_cfg = &slink_cfg;
Simon Glassd7659212016-01-30 16:37:50 -07001475 struct udevice *sor;
Simon Glass59dd5aa2015-04-14 21:03:41 -06001476 int data;
1477 int retry;
1478 int ret;
1479
1480 memset(link_cfg, '\0', sizeof(*link_cfg));
1481 link_cfg->is_valid = 0;
1482 link_cfg->scramble_ena = 1;
1483
1484 tegra_dc_dpaux_enable(priv);
1485
1486 if (tegra_dp_hpd_plug(priv) < 0) {
1487 debug("dp: hpd plug failed\n");
1488 return -EIO;
1489 }
1490
1491 link_cfg->bits_per_pixel = panel_bpp;
1492 if (tegra_dc_dp_init_max_link_cfg(timing, priv, link_cfg)) {
1493 debug("dp: failed to init link configuration\n");
1494 return -ENOLINK;
1495 }
1496
Michal Suchanekc726fc02022-10-12 21:57:59 +02001497 ret = uclass_first_device_err(UCLASS_VIDEO_BRIDGE, &sor);
1498 if (ret) {
Simon Glassd7659212016-01-30 16:37:50 -07001499 debug("dp: failed to find SOR device: ret=%d\n", ret);
Simon Glass59dd5aa2015-04-14 21:03:41 -06001500 return ret;
Simon Glassd7659212016-01-30 16:37:50 -07001501 }
Simon Glass59dd5aa2015-04-14 21:03:41 -06001502 priv->sor = sor;
1503 ret = tegra_dc_sor_enable_dp(sor, link_cfg);
1504 if (ret)
1505 return ret;
1506
1507 tegra_dc_sor_set_panel_power(sor, 1);
1508
1509 /* Write power on to DPCD */
1510 data = DP_SET_POWER_D0;
1511 retry = 0;
1512 do {
1513 ret = tegra_dc_dp_dpcd_write(priv, DP_SET_POWER, data);
1514 } while ((retry++ < DP_POWER_ON_MAX_TRIES) && ret);
1515
1516 if (ret || retry >= DP_POWER_ON_MAX_TRIES) {
1517 debug("dp: failed to power on panel (0x%x)\n", ret);
1518 return -ENETUNREACH;
1519 goto error_enable;
1520 }
1521
1522 /* Confirm DP plugging status */
1523 if (!(tegra_dpaux_readl(priv, DPAUX_DP_AUXSTAT) &
1524 DPAUX_DP_AUXSTAT_HPD_STATUS_PLUGGED)) {
1525 debug("dp: could not detect HPD\n");
1526 return -ENXIO;
1527 }
1528
1529 /* Check DP version */
1530 if (tegra_dc_dp_dpcd_read(priv, DP_DPCD_REV, &priv->revision)) {
1531 debug("dp: failed to read the revision number from sink\n");
1532 return -EIO;
1533 }
1534
1535 if (tegra_dc_dp_explore_link_cfg(priv, link_cfg, sor, timing)) {
1536 debug("dp: error configuring link\n");
1537 return -ENOMEDIUM;
1538 }
1539
1540 tegra_dc_sor_set_power_state(sor, 1);
Simon Glassd7659212016-01-30 16:37:50 -07001541 ret = tegra_dc_sor_attach(priv->dc_dev, sor, link_cfg, timing);
Simon Glass59dd5aa2015-04-14 21:03:41 -06001542 if (ret && ret != -EEXIST)
1543 return ret;
1544
Simon Glassdedc44b2015-04-14 21:03:44 -06001545 /*
1546 * This takes a long time, but can apparently resolve a failure to
1547 * bring up the display correctly.
1548 */
1549 if (0) {
1550 ret = tegra_dc_dp_check_sink(priv, link_cfg, timing);
1551 if (ret)
1552 return ret;
1553 }
1554
Simon Glass59dd5aa2015-04-14 21:03:41 -06001555 /* Power down the unused lanes to save power - a few hundred mW */
1556 tegra_dc_sor_power_down_unused_lanes(sor, link_cfg);
1557
Simon Glassd7659212016-01-30 16:37:50 -07001558 ret = video_bridge_set_backlight(sor, 80);
1559 if (ret) {
1560 debug("dp: failed to set backlight\n");
1561 return ret;
1562 }
1563
Simon Glass59dd5aa2015-04-14 21:03:41 -06001564 priv->enabled = true;
1565error_enable:
1566 return 0;
1567}
1568
Simon Glassd1998a92020-12-03 16:55:21 -07001569static int tegra_dp_of_to_plat(struct udevice *dev)
Simon Glass59dd5aa2015-04-14 21:03:41 -06001570{
Simon Glassc69cda22020-12-03 16:55:20 -07001571 struct tegra_dp_plat *plat = dev_get_plat(dev);
Simon Glass59dd5aa2015-04-14 21:03:41 -06001572
Simon Glass079ff3b2017-07-25 08:30:01 -06001573 plat->base = dev_read_addr(dev);
Simon Glass59dd5aa2015-04-14 21:03:41 -06001574
1575 return 0;
1576}
1577
1578static int tegra_dp_read_edid(struct udevice *dev, u8 *buf, int buf_size)
1579{
1580 struct tegra_dp_priv *priv = dev_get_priv(dev);
1581 const int tegra_edid_i2c_address = 0x50;
1582 u32 aux_stat = 0;
1583
1584 tegra_dc_dpaux_enable(priv);
1585
1586 return tegra_dc_i2c_aux_read(priv, tegra_edid_i2c_address, 0, buf,
1587 buf_size, &aux_stat);
1588}
1589
Simon Glass2dcf1432016-01-21 19:45:00 -07001590static const struct dm_display_ops dp_tegra_ops = {
Simon Glass59dd5aa2015-04-14 21:03:41 -06001591 .read_edid = tegra_dp_read_edid,
1592 .enable = tegra_dp_enable,
1593};
1594
1595static int dp_tegra_probe(struct udevice *dev)
1596{
Simon Glassc69cda22020-12-03 16:55:20 -07001597 struct tegra_dp_plat *plat = dev_get_plat(dev);
Simon Glass59dd5aa2015-04-14 21:03:41 -06001598 struct tegra_dp_priv *priv = dev_get_priv(dev);
Simon Glasscaa4daa2020-12-03 16:55:18 -07001599 struct display_plat *disp_uc_plat = dev_get_uclass_plat(dev);
Simon Glass59dd5aa2015-04-14 21:03:41 -06001600
1601 priv->regs = (struct dpaux_ctlr *)plat->base;
1602 priv->enabled = false;
1603
Simon Glassd7659212016-01-30 16:37:50 -07001604 /* Remember the display controller that is sending us video */
1605 priv->dc_dev = disp_uc_plat->src_dev;
1606
Simon Glass59dd5aa2015-04-14 21:03:41 -06001607 return 0;
1608}
1609
1610static const struct udevice_id tegra_dp_ids[] = {
1611 { .compatible = "nvidia,tegra124-dpaux" },
Peter Robinson0d2105a2022-05-03 09:32:54 +01001612 { .compatible = "nvidia,tegra210-dpaux" },
Simon Glass59dd5aa2015-04-14 21:03:41 -06001613 { }
1614};
1615
1616U_BOOT_DRIVER(dp_tegra) = {
1617 .name = "dpaux_tegra",
Simon Glass2dcf1432016-01-21 19:45:00 -07001618 .id = UCLASS_DISPLAY,
Simon Glass59dd5aa2015-04-14 21:03:41 -06001619 .of_match = tegra_dp_ids,
Simon Glassd1998a92020-12-03 16:55:21 -07001620 .of_to_plat = tegra_dp_of_to_plat,
Simon Glass59dd5aa2015-04-14 21:03:41 -06001621 .probe = dp_tegra_probe,
1622 .ops = &dp_tegra_ops,
Simon Glass41575d82020-12-03 16:55:17 -07001623 .priv_auto = sizeof(struct tegra_dp_priv),
Simon Glasscaa4daa2020-12-03 16:55:18 -07001624 .plat_auto = sizeof(struct tegra_dp_plat),
Simon Glass59dd5aa2015-04-14 21:03:41 -06001625};