blob: 3a3bce8b150f74609be12210fb98c36aba8bcebb [file] [log] [blame]
Julius Werneredf6b572013-10-25 17:49:26 -07001/*
2 * drivers/video/tegra/dc/dp.c
3 *
4 * Copyright (c) 2011-2013, NVIDIA Corporation.
Hung-Te Linc04d3dd72014-03-05 21:09:58 +08005 * Copyright 2014 Google Inc.
Julius Werneredf6b572013-10-25 17:49:26 -07006 *
7 * This software is licensed under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation, and
9 * may be copied, distributed, and modified under those terms.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 */
17
18#include <arch/io.h>
19#include <console/console.h>
Julius Wernerf0d21ff32014-10-20 13:24:14 -070020#include <delay.h>
Julius Werneredf6b572013-10-25 17:49:26 -070021#include <device/device.h>
22#include <device/i2c.h>
Hung-Te Lin3af0d312014-04-02 21:57:40 +080023#include <edid.h>
Julius Werneredf6b572013-10-25 17:49:26 -070024#include <soc/addressmap.h>
25#include <soc/nvidia/tegra/i2c.h>
26#include <soc/nvidia/tegra/dc.h>
Julius Werneredf6b572013-10-25 17:49:26 -070027#include <soc/nvidia/tegra/displayport.h>
Julius Wernerf0d21ff32014-10-20 13:24:14 -070028#include <soc/sor.h>
29#include <stdlib.h>
30#include <string.h>
31
32#include "chip.h"
Julius Werneredf6b572013-10-25 17:49:26 -070033
Neil Chen8c440a62014-09-23 17:41:59 +080034enum {
35 DP_LT_SUCCESS = 0,
36 DP_LT_FAILED = -1,
37};
38
Jimmy Zhangbd5925a2014-03-10 12:42:05 -070039struct tegra_dc_dp_data dp_data;
Julius Werneredf6b572013-10-25 17:49:26 -070040
41static inline u32 tegra_dpaux_readl(struct tegra_dc_dp_data *dp, u32 reg)
42{
43 void *addr = dp->aux_base + (u32) (reg << 2);
44 u32 reg_val = READL(addr);
45 return reg_val;
46}
47
48static inline void tegra_dpaux_writel(struct tegra_dc_dp_data *dp,
Andrew Bresticker24d4f7f2013-12-18 22:41:34 -080049 u32 reg, u32 val)
Julius Werneredf6b572013-10-25 17:49:26 -070050{
51 void *addr = dp->aux_base + (u32) (reg << 2);
52 WRITEL(val, addr);
53}
54
55static inline u32 tegra_dc_dpaux_poll_register(struct tegra_dc_dp_data *dp,
Andrew Bresticker24d4f7f2013-12-18 22:41:34 -080056 u32 reg, u32 mask, u32 exp_val,
57 u32 poll_interval_us,
58 u32 timeout_us)
Julius Werneredf6b572013-10-25 17:49:26 -070059{
60 u32 reg_val = 0;
Andrew Bresticker24d4f7f2013-12-18 22:41:34 -080061 u32 temp = timeout_us;
Julius Werneredf6b572013-10-25 17:49:26 -070062
Julius Werneredf6b572013-10-25 17:49:26 -070063 do {
Andrew Bresticker24d4f7f2013-12-18 22:41:34 -080064 udelay(poll_interval_us);
Julius Werneredf6b572013-10-25 17:49:26 -070065 reg_val = tegra_dpaux_readl(dp, reg);
Andrew Bresticker24d4f7f2013-12-18 22:41:34 -080066 if (timeout_us > poll_interval_us)
67 timeout_us -= poll_interval_us;
68 else
69 break;
70 } while ((reg_val & mask) != exp_val);
Julius Werneredf6b572013-10-25 17:49:26 -070071
72 if ((reg_val & mask) == exp_val)
73 return 0; /* success */
Andrew Bresticker24d4f7f2013-12-18 22:41:34 -080074 printk(BIOS_ERR,
Julius Werneredf6b572013-10-25 17:49:26 -070075 "dpaux_poll_register 0x%x: timeout: "
76 "(reg_val)0x%08x & (mask)0x%08x != (exp_val)0x%08x\n",
77 reg, reg_val, mask, exp_val);
Andrew Bresticker24d4f7f2013-12-18 22:41:34 -080078 return temp;
Julius Werneredf6b572013-10-25 17:49:26 -070079}
80
81static inline int tegra_dpaux_wait_transaction(struct tegra_dc_dp_data *dp)
82{
83 /* According to DP spec, each aux transaction needs to finish
84 within 40ms. */
85 if (tegra_dc_dpaux_poll_register(dp, DPAUX_DP_AUXCTL,
Andrew Bresticker24d4f7f2013-12-18 22:41:34 -080086 DPAUX_DP_AUXCTL_TRANSACTREQ_MASK,
87 DPAUX_DP_AUXCTL_TRANSACTREQ_DONE,
88 100, DP_AUX_TIMEOUT_MS * 1000) != 0) {
89 printk(BIOS_INFO, "dp: DPAUX transaction timeout\n");
Julius Werneredf6b572013-10-25 17:49:26 -070090 return -1;
91 }
92 return 0;
93}
94
95static int tegra_dc_dpaux_write_chunk(struct tegra_dc_dp_data *dp, u32 cmd,
Andrew Bresticker24d4f7f2013-12-18 22:41:34 -080096 u32 addr, u8 *data, u32 *size,
97 u32 *aux_stat)
Julius Werneredf6b572013-10-25 17:49:26 -070098{
99 int i;
100 u32 reg_val;
101 u32 timeout_retries = DP_AUX_TIMEOUT_MAX_TRIES;
102 u32 defer_retries = DP_AUX_DEFER_MAX_TRIES;
103 u32 temp_data;
104
105 if (*size > DP_AUX_MAX_BYTES)
106 return -1; /* only write one chunk of data */
107
108 /* Make sure the command is write command */
109 switch (cmd) {
110 case DPAUX_DP_AUXCTL_CMD_I2CWR:
111 case DPAUX_DP_AUXCTL_CMD_MOTWR:
112 case DPAUX_DP_AUXCTL_CMD_AUXWR:
113 break;
114 default:
Andrew Bresticker24d4f7f2013-12-18 22:41:34 -0800115 printk(BIOS_ERR, "dp: aux write cmd 0x%x is invalid\n",
116 cmd);
Julius Werneredf6b572013-10-25 17:49:26 -0700117 return -1;
118 }
119
Julius Werneredf6b572013-10-25 17:49:26 -0700120 tegra_dpaux_writel(dp, DPAUX_DP_AUXADDR, addr);
121 for (i = 0; i < DP_AUX_MAX_BYTES / 4; ++i) {
122 memcpy(&temp_data, data, 4);
123 tegra_dpaux_writel(dp, DPAUX_DP_AUXDATA_WRITE_W(i), temp_data);
124 data += 4;
125 }
126
127 reg_val = tegra_dpaux_readl(dp, DPAUX_DP_AUXCTL);
128 reg_val &= ~DPAUX_DP_AUXCTL_CMD_MASK;
129 reg_val |= cmd;
130 reg_val &= ~DPAUX_DP_AUXCTL_CMDLEN_FIELD;
131 reg_val |= ((*size - 1) << DPAUX_DP_AUXCTL_CMDLEN_SHIFT);
132
133 while ((timeout_retries > 0) && (defer_retries > 0)) {
134 if ((timeout_retries != DP_AUX_TIMEOUT_MAX_TRIES) ||
135 (defer_retries != DP_AUX_DEFER_MAX_TRIES))
136 udelay(1);
137
138 reg_val |= DPAUX_DP_AUXCTL_TRANSACTREQ_PENDING;
139 tegra_dpaux_writel(dp, DPAUX_DP_AUXCTL, reg_val);
140
141 if (tegra_dpaux_wait_transaction(dp))
Andrew Bresticker24d4f7f2013-12-18 22:41:34 -0800142 printk(BIOS_ERR, "dp: aux write transaction timeout\n");
Julius Werneredf6b572013-10-25 17:49:26 -0700143
144 *aux_stat = tegra_dpaux_readl(dp, DPAUX_DP_AUXSTAT);
145
146 if ((*aux_stat & DPAUX_DP_AUXSTAT_TIMEOUT_ERROR_PENDING) ||
147 (*aux_stat & DPAUX_DP_AUXSTAT_RX_ERROR_PENDING) ||
148 (*aux_stat & DPAUX_DP_AUXSTAT_SINKSTAT_ERROR_PENDING) ||
149 (*aux_stat & DPAUX_DP_AUXSTAT_NO_STOP_ERROR_PENDING)) {
150 if (timeout_retries-- > 0) {
Andrew Bresticker24d4f7f2013-12-18 22:41:34 -0800151 printk(BIOS_INFO, "dp: aux write retry (0x%x) -- %d\n",
Julius Werneredf6b572013-10-25 17:49:26 -0700152 *aux_stat, timeout_retries);
153 /* clear the error bits */
154 tegra_dpaux_writel(dp, DPAUX_DP_AUXSTAT, *aux_stat);
155 continue;
156 } else {
Andrew Bresticker24d4f7f2013-12-18 22:41:34 -0800157 printk(BIOS_ERR, "dp: aux write got error (0x%x)\n",
Julius Werneredf6b572013-10-25 17:49:26 -0700158 *aux_stat);
159 return -1;
160 }
161 }
162
163 if ((*aux_stat & DPAUX_DP_AUXSTAT_REPLYTYPE_I2CDEFER) ||
164 (*aux_stat & DPAUX_DP_AUXSTAT_REPLYTYPE_DEFER)) {
165 if (defer_retries-- > 0) {
Andrew Bresticker24d4f7f2013-12-18 22:41:34 -0800166 printk(BIOS_INFO, "dp: aux write defer (0x%x) -- %d\n",
Julius Werneredf6b572013-10-25 17:49:26 -0700167 *aux_stat, defer_retries);
168 /* clear the error bits */
169 tegra_dpaux_writel(dp, DPAUX_DP_AUXSTAT, *aux_stat);
170 continue;
171 } else {
Andrew Bresticker24d4f7f2013-12-18 22:41:34 -0800172 printk(BIOS_ERR, "dp: aux write defer exceeds max retries "
Julius Werneredf6b572013-10-25 17:49:26 -0700173 "(0x%x)\n", *aux_stat);
174 return -1;
175 }
176 }
177
178 if ((*aux_stat & DPAUX_DP_AUXSTAT_REPLYTYPE_MASK) ==
179 DPAUX_DP_AUXSTAT_REPLYTYPE_ACK) {
180 *size = ((*aux_stat) & DPAUX_DP_AUXSTAT_REPLY_M_MASK);
181 return 0;
182 } else {
Andrew Bresticker24d4f7f2013-12-18 22:41:34 -0800183 printk(BIOS_ERR, "dp: aux write failed (0x%x)\n",
184 *aux_stat);
Julius Werneredf6b572013-10-25 17:49:26 -0700185 return -1;
186 }
187 }
188 /* Should never come to here */
189 return -1;
190}
191
Julius Werneredf6b572013-10-25 17:49:26 -0700192static int tegra_dc_dpaux_read_chunk(struct tegra_dc_dp_data *dp, u32 cmd,
Andrew Bresticker24d4f7f2013-12-18 22:41:34 -0800193 u32 addr, u8 *data, u32 *size,
194 u32 *aux_stat)
Julius Werneredf6b572013-10-25 17:49:26 -0700195{
196 u32 reg_val;
197 u32 timeout_retries = DP_AUX_TIMEOUT_MAX_TRIES;
198 u32 defer_retries = DP_AUX_DEFER_MAX_TRIES;
199
200 if (*size > DP_AUX_MAX_BYTES)
201 return -1; /* only read one chunk */
202
203 /* Check to make sure the command is read command */
204 switch (cmd) {
205 case DPAUX_DP_AUXCTL_CMD_I2CRD:
206 case DPAUX_DP_AUXCTL_CMD_I2CREQWSTAT:
207 case DPAUX_DP_AUXCTL_CMD_MOTRD:
208 case DPAUX_DP_AUXCTL_CMD_AUXRD:
209 break;
210 default:
Andrew Bresticker24d4f7f2013-12-18 22:41:34 -0800211 printk(BIOS_ERR, "dp: aux read cmd 0x%x is invalid\n",
212 cmd);
Julius Werneredf6b572013-10-25 17:49:26 -0700213 return -1;
214 }
215
Jimmy Zhangbd5925a2014-03-10 12:42:05 -0700216 *aux_stat = tegra_dpaux_readl(dp, DPAUX_DP_AUXSTAT);
217 if (!(*aux_stat & DPAUX_DP_AUXSTAT_HPD_STATUS_PLUGGED)) {
218 printk(BIOS_SPEW, "dp: HPD is not detected\n");
219 return -1;
Julius Werneredf6b572013-10-25 17:49:26 -0700220 }
221
222 tegra_dpaux_writel(dp, DPAUX_DP_AUXADDR, addr);
223
224 reg_val = tegra_dpaux_readl(dp, DPAUX_DP_AUXCTL);
225 reg_val &= ~DPAUX_DP_AUXCTL_CMD_MASK;
226 reg_val |= cmd;
Julius Werneredf6b572013-10-25 17:49:26 -0700227 reg_val &= ~DPAUX_DP_AUXCTL_CMDLEN_FIELD;
228 reg_val |= ((*size - 1) << DPAUX_DP_AUXCTL_CMDLEN_SHIFT);
Julius Werneredf6b572013-10-25 17:49:26 -0700229 while ((timeout_retries > 0) && (defer_retries > 0)) {
230 if ((timeout_retries != DP_AUX_TIMEOUT_MAX_TRIES) ||
231 (defer_retries != DP_AUX_DEFER_MAX_TRIES))
232 udelay(DP_DPCP_RETRY_SLEEP_NS * 2);
233
234 reg_val |= DPAUX_DP_AUXCTL_TRANSACTREQ_PENDING;
Julius Werneredf6b572013-10-25 17:49:26 -0700235 tegra_dpaux_writel(dp, DPAUX_DP_AUXCTL, reg_val);
236
237 if (tegra_dpaux_wait_transaction(dp))
Andrew Bresticker24d4f7f2013-12-18 22:41:34 -0800238 printk(BIOS_INFO, "dp: aux read transaction timeout\n");
Julius Werneredf6b572013-10-25 17:49:26 -0700239
240 *aux_stat = tegra_dpaux_readl(dp, DPAUX_DP_AUXSTAT);
Julius Werneredf6b572013-10-25 17:49:26 -0700241
242 if ((*aux_stat & DPAUX_DP_AUXSTAT_TIMEOUT_ERROR_PENDING) ||
243 (*aux_stat & DPAUX_DP_AUXSTAT_RX_ERROR_PENDING) ||
244 (*aux_stat & DPAUX_DP_AUXSTAT_SINKSTAT_ERROR_PENDING) ||
245 (*aux_stat & DPAUX_DP_AUXSTAT_NO_STOP_ERROR_PENDING)) {
246 if (timeout_retries-- > 0) {
Andrew Bresticker24d4f7f2013-12-18 22:41:34 -0800247 printk(BIOS_INFO, "dp: aux read retry (0x%x)"
248 " -- %d\n", *aux_stat,
249 timeout_retries);
Julius Werneredf6b572013-10-25 17:49:26 -0700250 /* clear the error bits */
Andrew Bresticker24d4f7f2013-12-18 22:41:34 -0800251 tegra_dpaux_writel(dp, DPAUX_DP_AUXSTAT,
252 *aux_stat);
Julius Werneredf6b572013-10-25 17:49:26 -0700253 continue; /* retry */
254 } else {
Andrew Bresticker24d4f7f2013-12-18 22:41:34 -0800255 printk(BIOS_ERR, "dp: aux read got error"
256 " (0x%x)\n", *aux_stat);
Julius Werneredf6b572013-10-25 17:49:26 -0700257 return -1;
258 }
259 }
260
261 if ((*aux_stat & DPAUX_DP_AUXSTAT_REPLYTYPE_I2CDEFER) ||
262 (*aux_stat & DPAUX_DP_AUXSTAT_REPLYTYPE_DEFER)) {
263 if (defer_retries-- > 0) {
Andrew Bresticker24d4f7f2013-12-18 22:41:34 -0800264 printk(BIOS_INFO, "dp: aux read defer (0x%x) -- %d\n",
Julius Werneredf6b572013-10-25 17:49:26 -0700265 *aux_stat, defer_retries);
266 /* clear the error bits */
267 tegra_dpaux_writel(dp, DPAUX_DP_AUXSTAT, *aux_stat);
268 continue;
269 } else {
Andrew Bresticker24d4f7f2013-12-18 22:41:34 -0800270 printk(BIOS_INFO, "dp: aux read defer exceeds max retries "
Julius Werneredf6b572013-10-25 17:49:26 -0700271 "(0x%x)\n", *aux_stat);
272 return -1;
273 }
274 }
275
276 if ((*aux_stat & DPAUX_DP_AUXSTAT_REPLYTYPE_MASK) ==
277 DPAUX_DP_AUXSTAT_REPLYTYPE_ACK) {
278 int i;
279 u32 temp_data[4];
280
281 for (i = 0; i < DP_AUX_MAX_BYTES / 4; ++i)
282 temp_data[i] = tegra_dpaux_readl(dp,
Andrew Bresticker24d4f7f2013-12-18 22:41:34 -0800283 DPAUX_DP_AUXDATA_READ_W(i));
Julius Werneredf6b572013-10-25 17:49:26 -0700284
285 *size = ((*aux_stat) & DPAUX_DP_AUXSTAT_REPLY_M_MASK);
Julius Werneredf6b572013-10-25 17:49:26 -0700286 memcpy(data, temp_data, *size);
287
288 return 0;
289 } else {
Andrew Bresticker24d4f7f2013-12-18 22:41:34 -0800290 printk(BIOS_ERR, "dp: aux read failed (0x%x\n",
291 *aux_stat);
Julius Werneredf6b572013-10-25 17:49:26 -0700292 return -1;
293 }
294 }
295 /* Should never come to here */
Andrew Bresticker24d4f7f2013-12-18 22:41:34 -0800296 printk(BIOS_ERR, "%s: can't\n", __func__);
Julius Werneredf6b572013-10-25 17:49:26 -0700297 return -1;
298}
299
Jimmy Zhang75f701792014-04-21 15:58:45 -0700300static int tegra_dc_dpaux_read(struct tegra_dc_dp_data *dp, u32 cmd, u32 addr,
301 u8 *data, u32 *size, u32 *aux_stat)
302{
303 u32 finished = 0;
304 u32 cur_size;
305 int ret = 0;
306
307 do {
308 cur_size = *size - finished;
309 if (cur_size > DP_AUX_MAX_BYTES)
310 cur_size = DP_AUX_MAX_BYTES;
311
312 ret = tegra_dc_dpaux_read_chunk(dp, cmd, addr,
313 data, &cur_size, aux_stat);
314 if (ret)
315 break;
316
317 /* cur_size should be the real size returned */
318 addr += cur_size;
319 data += cur_size;
320 finished += cur_size;
321
322 } while (*size > finished);
323
324 *size = finished;
325 return ret;
326}
327
Julius Werneredf6b572013-10-25 17:49:26 -0700328static int tegra_dc_dp_dpcd_read(struct tegra_dc_dp_data *dp, u32 cmd,
Jimmy Zhangbd5925a2014-03-10 12:42:05 -0700329 u8 * data_ptr)
Julius Werneredf6b572013-10-25 17:49:26 -0700330{
331 u32 size = 1;
332 u32 status = 0;
333 int ret;
334
335 ret = tegra_dc_dpaux_read_chunk(dp, DPAUX_DP_AUXCTL_CMD_AUXRD,
Jimmy Zhangbd5925a2014-03-10 12:42:05 -0700336 cmd, data_ptr, &size, &status);
Julius Werneredf6b572013-10-25 17:49:26 -0700337 if (ret)
Andrew Bresticker24d4f7f2013-12-18 22:41:34 -0800338 printk(BIOS_ERR,
Jimmy Zhangbd5925a2014-03-10 12:42:05 -0700339 "dp: Failed to read DPCD data. CMD 0x%x, Status 0x%x\n",
340 cmd, status);
Julius Werneredf6b572013-10-25 17:49:26 -0700341
342 return ret;
343}
344
Jimmy Zhangbd5925a2014-03-10 12:42:05 -0700345static int tegra_dc_dp_dpcd_write(struct tegra_dc_dp_data *dp, u32 cmd,
346 u8 data)
347{
348 u32 size = 1;
349 u32 status = 0;
350 int ret;
351
352 ret = tegra_dc_dpaux_write_chunk(dp, DPAUX_DP_AUXCTL_CMD_AUXWR,
353 cmd, &data, &size, &status);
354 if (ret)
355 printk(BIOS_ERR,
356 "dp: Failed to write DPCD data. CMD 0x%x, Status 0x%x\n",
357 cmd, status);
358 return ret;
359}
360
Hung-Te Lin3af0d312014-04-02 21:57:40 +0800361static int tegra_dc_i2c_aux_read(struct tegra_dc_dp_data *dp, u32 i2c_addr,
362 u8 addr, u8 *data, u32 *size, u32 *aux_stat)
Hung-Te Linc04d3dd72014-03-05 21:09:58 +0800363{
364 u32 finished = 0;
365 int ret = 0;
366
367 do {
368 u32 cur_size = MIN(DP_AUX_MAX_BYTES, *size - finished);
369
370 u32 len = 1;
371 ret = tegra_dc_dpaux_write_chunk(
Ken Chang2d43a482014-04-15 17:00:17 +0800372 dp, DPAUX_DP_AUXCTL_CMD_MOTWR, i2c_addr,
Hung-Te Linc04d3dd72014-03-05 21:09:58 +0800373 &addr, &len, aux_stat);
374 if (ret) {
375 printk(BIOS_ERR, "%s: error sending address to read.\n",
376 __func__);
377 break;
378 }
379
380 ret = tegra_dc_dpaux_read_chunk(
381 dp, DPAUX_DP_AUXCTL_CMD_I2CRD, i2c_addr,
382 data, &cur_size, aux_stat);
383 if (ret) {
384 printk(BIOS_ERR, "%s: error reading data.\n", __func__);
385 break;
386 }
387
388 /* cur_size should be the real size returned */
389 addr += cur_size;
390 data += cur_size;
391 finished += cur_size;
392 } while (*size > finished);
393
394 *size = finished;
395 return ret;
396}
397
Jimmy Zhangbd5925a2014-03-10 12:42:05 -0700398static void tegra_dc_dpaux_enable(struct tegra_dc_dp_data *dp)
399{
400 /* clear interrupt */
401 tegra_dpaux_writel(dp, DPAUX_INTR_AUX, 0xffffffff);
402 /* do not enable interrupt for now. Enable them when Isr in place */
403 tegra_dpaux_writel(dp, DPAUX_INTR_EN_AUX, 0x0);
404
405 tegra_dpaux_writel(dp, DPAUX_HYBRID_PADCTL,
406 DPAUX_HYBRID_PADCTL_AUX_DRVZ_OHM_50 |
407 DPAUX_HYBRID_PADCTL_AUX_CMH_V0_70 |
408 0x18 << DPAUX_HYBRID_PADCTL_AUX_DRVI_SHIFT |
409 DPAUX_HYBRID_PADCTL_AUX_INPUT_RCV_ENABLE);
410
411 tegra_dpaux_writel(dp, DPAUX_HYBRID_SPARE,
412 DPAUX_HYBRID_SPARE_PAD_PWR_POWERUP);
413}
414
415static void tegra_dc_dp_dump_link_cfg(struct tegra_dc_dp_data *dp,
416 const struct tegra_dc_dp_link_config *link_cfg)
417{
418 printk(BIOS_INFO, "DP config: cfg_name "
419 "cfg_value\n");
420 printk(BIOS_INFO, " Lane Count %d\n",
421 link_cfg->max_lane_count);
422 printk(BIOS_INFO, " SupportEnhancedFraming %s\n",
423 link_cfg->support_enhanced_framing ? "Y" : "N");
424 printk(BIOS_INFO, " Bandwidth %d\n",
425 link_cfg->max_link_bw);
426 printk(BIOS_INFO, " bpp %d\n",
427 link_cfg->bits_per_pixel);
428 printk(BIOS_INFO, " EnhancedFraming %s\n",
429 link_cfg->enhanced_framing ? "Y" : "N");
430 printk(BIOS_INFO, " Scramble_enabled %s\n",
431 link_cfg->scramble_ena ? "Y" : "N");
432 printk(BIOS_INFO, " LinkBW %d\n",
433 link_cfg->link_bw);
434 printk(BIOS_INFO, " lane_count %d\n",
435 link_cfg->lane_count);
436 printk(BIOS_INFO, " activespolarity %d\n",
437 link_cfg->activepolarity);
438 printk(BIOS_INFO, " active_count %d\n",
439 link_cfg->active_count);
440 printk(BIOS_INFO, " tu_size %d\n",
441 link_cfg->tu_size);
442 printk(BIOS_INFO, " active_frac %d\n",
443 link_cfg->active_frac);
444 printk(BIOS_INFO, " watermark %d\n",
445 link_cfg->watermark);
446 printk(BIOS_INFO, " hblank_sym %d\n",
447 link_cfg->hblank_sym);
448 printk(BIOS_INFO, " vblank_sym %d\n",
449 link_cfg->vblank_sym);
Jimmy Zhang75f701792014-04-21 15:58:45 -0700450}
Jimmy Zhangbd5925a2014-03-10 12:42:05 -0700451
Neil Chen8c440a62014-09-23 17:41:59 +0800452static int _tegra_dp_lower_link_config(struct tegra_dc_dp_data *dp,
453 struct tegra_dc_dp_link_config *cfg)
454{
455
456 switch (cfg->link_bw){
457 case SOR_LINK_SPEED_G1_62:
458 if (cfg->max_link_bw > SOR_LINK_SPEED_G1_62)
459 cfg->link_bw = SOR_LINK_SPEED_G2_7;
460 cfg->lane_count /= 2;
461 break;
462 case SOR_LINK_SPEED_G2_7:
463 cfg->link_bw = SOR_LINK_SPEED_G1_62;
464 break;
465 case SOR_LINK_SPEED_G5_4:
466 if (cfg->lane_count == 1) {
467 cfg->link_bw = SOR_LINK_SPEED_G2_7;
468 cfg->lane_count = cfg->max_lane_count;
469 } else
470 cfg->lane_count /= 2;
471 break;
472 default:
473 printk(BIOS_ERR,"dp: Error link rate %d\n", cfg->link_bw);
474 return DP_LT_FAILED;
475 }
476
477 return (cfg->lane_count > 0) ? DP_LT_SUCCESS : DP_LT_FAILED;
478}
479
Jimmy Zhangbd5925a2014-03-10 12:42:05 -0700480/* Calcuate if given cfg can meet the mode request. */
481/* Return true if mode is possible, false otherwise. */
482static int tegra_dc_dp_calc_config(struct tegra_dc_dp_data *dp,
483 const struct soc_nvidia_tegra124_config *config,
484 struct tegra_dc_dp_link_config *link_cfg)
485{
486 const u32 link_rate = 27 * link_cfg->link_bw * 1000 * 1000;
487 const u64 f = 100000; /* precision factor */
488
489 u32 num_linkclk_line; /* Number of link clocks per line */
490 u64 ratio_f; /* Ratio of incoming to outgoing data rate */
491
492 u64 frac_f;
493 u64 activesym_f; /* Activesym per TU */
494 u64 activecount_f;
495 u32 activecount;
496 u32 activepolarity;
497 u64 approx_value_f;
498 u32 activefrac = 0;
499 u64 accumulated_error_f = 0;
500 u32 lowest_neg_activecount = 0;
501 u32 lowest_neg_activepolarity = 0;
502 u32 lowest_neg_tusize = 64;
503 u32 num_symbols_per_line;
504 u64 lowest_neg_activefrac = 0;
505 u64 lowest_neg_error_f = 64 * f;
506 u64 watermark_f;
507
508 int i;
509 int neg;
510
511 if (!link_rate || !link_cfg->lane_count || !config->pixel_clock ||
512 !link_cfg->bits_per_pixel)
513 return -1;
514
515 if ((u64)config->pixel_clock * link_cfg->bits_per_pixel >=
516 (u64)link_rate * 8 * link_cfg->lane_count)
517 return -1;
518
519 num_linkclk_line = (u32)((u64)link_rate * (u64)config->xres / config->pixel_clock);
520
521 ratio_f = (u64)config->pixel_clock * link_cfg->bits_per_pixel * f;
522 ratio_f /= 8;
523 ratio_f = (u64)(ratio_f / (link_rate * link_cfg->lane_count));
524
525 for (i = 64; i >= 32; --i) {
526 activesym_f = ratio_f * i;
527 activecount_f = (u64)(activesym_f / (u32)f) * f;
528 frac_f = activesym_f - activecount_f;
529 activecount = (u32)((u64)(activecount_f / (u32)f));
530
531 if (frac_f < (f / 2)) /* fraction < 0.5 */
532 activepolarity = 0;
533 else {
534 activepolarity = 1;
535 frac_f = f - frac_f;
536 }
537
538 if (frac_f != 0) {
539 frac_f = (u64)((f * f) / frac_f); /* 1/fraction */
540 if (frac_f > (15 * f))
541 activefrac = activepolarity ? 1 : 15;
542 else
543 activefrac = activepolarity ?
544 (u32)((u64)(frac_f / (u32)f)) + 1 :
545 (u32)((u64)(frac_f / (u32)f));
546 }
547
548 if (activefrac == 1)
549 activepolarity = 0;
550
551 if (activepolarity == 1)
552 approx_value_f = activefrac ? (u64)(
553 (activecount_f + (activefrac * f - f) * f) /
554 (activefrac * f)) :
555 activecount_f + f;
556 else
557 approx_value_f = activefrac ?
558 activecount_f + (u64)(f / activefrac) :
559 activecount_f;
560
561 if (activesym_f < approx_value_f) {
562 accumulated_error_f = num_linkclk_line *
563 (u64)((approx_value_f - activesym_f) / i);
564 neg = 1;
565 } else {
566 accumulated_error_f = num_linkclk_line *
567 (u64)((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 = (u64)((ratio_f * link_cfg->tu_size * (f - ratio_f)) / f);
598 link_cfg->watermark = (u32)((u64)((watermark_f + lowest_neg_error_f) /
599 f)) + link_cfg->bits_per_pixel / 4 - 1;
600 num_symbols_per_line = (config->xres * link_cfg->bits_per_pixel) /
601 (8 * link_cfg->lane_count);
602
603 if (link_cfg->watermark > 30) {
604 printk(BIOS_INFO,
605 "dp: sor setting: unable to get a good tusize, "
606 "force watermark to 30.\n");
607 link_cfg->watermark = 30;
608 return -1;
609 } else if (link_cfg->watermark > num_symbols_per_line) {
610 printk(BIOS_INFO,
611 "dp: sor setting: force watermark to the number "
612 "of symbols in the line.\n");
613 link_cfg->watermark = num_symbols_per_line;
614 return -1;
615 }
616
617 /* Refer to dev_disp.ref for more information. */
618 /* # symbols/hblank = ((SetRasterBlankEnd.X + SetRasterSize.Width - */
619 /* SetRasterBlankStart.X - 7) * link_clk / pclk) */
620 /* - 3 * enhanced_framing - Y */
621 /* where Y = (# lanes == 4) 3 : (# lanes == 2) ? 6 : 12 */
622 link_cfg->hblank_sym = (int)((u64)(((u64)(config->hback_porch +
623 config->hfront_porch + config->hsync_width - 7) *
624 link_rate) / config->pixel_clock)) -
625 3 * link_cfg->enhanced_framing -
626 (12 / link_cfg->lane_count);
627
628 if (link_cfg->hblank_sym < 0)
629 link_cfg->hblank_sym = 0;
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 link_cfg->vblank_sym = (int)((u64)((u64)(config->xres - 25)
638 * link_rate / config->pixel_clock)) - (36 /
639 link_cfg->lane_count) - 4;
640
641 if (link_cfg->vblank_sym < 0)
642 link_cfg->vblank_sym = 0;
643
644 link_cfg->is_valid = 1;
645 tegra_dc_dp_dump_link_cfg(dp, link_cfg);
646
647 return 0;
648}
649
Jimmy Zhang75f701792014-04-21 15:58:45 -0700650static int tegra_dc_dp_init_max_link_cfg(
Jimmy Zhangbd5925a2014-03-10 12:42:05 -0700651 struct soc_nvidia_tegra124_config *config,
652 struct tegra_dc_dp_data *dp,
653 struct tegra_dc_dp_link_config *link_cfg)
Julius Werneredf6b572013-10-25 17:49:26 -0700654{
655 u8 dpcd_data;
656 int ret;
657
Jimmy Zhang75f701792014-04-21 15:58:45 -0700658 CHECK_RET(tegra_dc_dp_dpcd_read(dp, NV_DPCD_MAX_LANE_COUNT,
659 &dpcd_data));
660 link_cfg->max_lane_count = dpcd_data & NV_DPCD_MAX_LANE_COUNT_MASK;
Neil Chen8c440a62014-09-23 17:41:59 +0800661 link_cfg->tps3_supported = (dpcd_data &
662 NV_DPCD_MAX_LANE_COUNT_TPS3_SUPPORTED_YES) ? 1 : 0;
Jimmy Zhang75f701792014-04-21 15:58:45 -0700663
664 link_cfg->support_enhanced_framing =
665 (dpcd_data & NV_DPCD_MAX_LANE_COUNT_ENHANCED_FRAMING_YES) ?
666 1 : 0;
667
668 CHECK_RET(tegra_dc_dp_dpcd_read(dp, NV_DPCD_MAX_DOWNSPREAD,
669 &dpcd_data));
670 link_cfg->downspread = (dpcd_data & NV_DPCD_MAX_DOWNSPREAD_VAL_0_5_PCT)?
671 1 : 0;
672
Neil Chen8c440a62014-09-23 17:41:59 +0800673 CHECK_RET(tegra_dc_dp_dpcd_read(dp, NV_DPCD_TRAINING_AUX_RD_INTERVAL,
674 &link_cfg->aux_rd_interval));
675
Jimmy Zhang75f701792014-04-21 15:58:45 -0700676 CHECK_RET(tegra_dc_dp_dpcd_read(dp, NV_DPCD_MAX_LINK_BANDWIDTH,
677 &link_cfg->max_link_bw));
678
679 link_cfg->bits_per_pixel = config->panel_bits_per_pixel;
680
681 /*
682 * Set to a high value for link training and attach.
683 * Will be re-programmed when dp is enabled.
684 */
Jimmy Zhangbd5925a2014-03-10 12:42:05 -0700685 link_cfg->drive_current = config->drive_current;
686 link_cfg->preemphasis = config->preemphasis;
687 link_cfg->postcursor = config->postcursor;
Julius Werneredf6b572013-10-25 17:49:26 -0700688
Jimmy Zhangbd5925a2014-03-10 12:42:05 -0700689 CHECK_RET(tegra_dc_dp_dpcd_read(dp, NV_DPCD_EDP_CONFIG_CAP,
690 &dpcd_data));
691 link_cfg->alt_scramber_reset_cap =
692 (dpcd_data & NV_DPCD_EDP_CONFIG_CAP_ASC_RESET_YES) ?
693 1 : 0;
694 link_cfg->only_enhanced_framing =
695 (dpcd_data & NV_DPCD_EDP_CONFIG_CAP_FRAMING_CHANGE_YES) ?
696 1 : 0;
Julius Werneredf6b572013-10-25 17:49:26 -0700697
Jimmy Zhangbd5925a2014-03-10 12:42:05 -0700698 link_cfg->lane_count = link_cfg->max_lane_count;
699 link_cfg->link_bw = link_cfg->max_link_bw;
700 link_cfg->enhanced_framing = link_cfg->support_enhanced_framing;
Julius Werneredf6b572013-10-25 17:49:26 -0700701
Jimmy Zhangbd5925a2014-03-10 12:42:05 -0700702 tegra_dc_dp_calc_config(dp, config, link_cfg);
Julius Werneredf6b572013-10-25 17:49:26 -0700703 return 0;
704}
705
Jimmy Zhangd712ec42014-04-14 12:47:37 -0700706static int tegra_dc_dp_set_assr(struct tegra_dc_dp_data *dp, int ena)
707{
708 int ret;
709
710 u8 dpcd_data = ena ?
711 NV_DPCD_EDP_CONFIG_SET_ASC_RESET_ENABLE :
712 NV_DPCD_EDP_CONFIG_SET_ASC_RESET_DISABLE;
713
714 CHECK_RET(tegra_dc_dp_dpcd_write(dp, NV_DPCD_EDP_CONFIG_SET,
715 dpcd_data));
716
717 /* Also reset the scrambler to 0xfffe */
718 tegra_dc_sor_set_internal_panel(&dp->sor, ena);
719 return 0;
720}
721
Jimmy Zhang75f701792014-04-21 15:58:45 -0700722static int tegra_dp_set_link_bandwidth(struct tegra_dc_dp_data *dp, u8 link_bw)
723{
724 tegra_dc_sor_set_link_bandwidth(&dp->sor, link_bw);
725
726 /* Sink side */
727 return tegra_dc_dp_dpcd_write(dp, NV_DPCD_LINK_BANDWIDTH_SET, link_bw);
728}
729
730static int tegra_dp_set_lane_count(struct tegra_dc_dp_data *dp,
731 const struct tegra_dc_dp_link_config *link_cfg)
732{
733 u8 dpcd_data;
734 int ret;
735
736 /* check if panel support enhanched_framing */
737 dpcd_data = link_cfg->lane_count;
738 if (link_cfg->enhanced_framing)
739 dpcd_data |= NV_DPCD_LANE_COUNT_SET_ENHANCEDFRAMING_T;
740 CHECK_RET(tegra_dc_dp_dpcd_write(dp, NV_DPCD_LANE_COUNT_SET,
741 dpcd_data));
742
743 tegra_dc_sor_set_lane_count(&dp->sor, link_cfg->lane_count);
744
745 /* Also power down lanes that will not be used */
746 return 0;
747}
748
749static int tegra_dc_dp_link_trained(struct tegra_dc_dp_data *dp,
750 const struct tegra_dc_dp_link_config *cfg)
751{
752 u32 lane;
753 u8 mask;
754 u8 data;
755 int ret;
756
757 for (lane = 0; lane < cfg->lane_count; ++lane) {
758 CHECK_RET(tegra_dc_dp_dpcd_read(dp, (lane/2) ?
759 NV_DPCD_LANE2_3_STATUS : NV_DPCD_LANE0_1_STATUS,
760 &data));
761 mask = (lane & 1) ?
762 NV_DPCD_STATUS_LANEXPLUS1_CR_DONE_YES |
763 NV_DPCD_STATUS_LANEXPLUS1_CHN_EQ_DONE_YES |
764 NV_DPCD_STATUS_LANEXPLUS1_SYMBOL_LOCKED_YES :
765 NV_DPCD_STATUS_LANEX_CR_DONE_YES |
766 NV_DPCD_STATUS_LANEX_CHN_EQ_DONE_YES |
767 NV_DPCD_STATUS_LANEX_SYMBOL_LOCKED_YES;
768 if ((data & mask) != mask)
769 return -1;
770 }
771 return 0;
772}
773
Neil Chen8c440a62014-09-23 17:41:59 +0800774static int tegra_dp_channel_eq_status(struct tegra_dc_dp_data *dp)
775{
776 u32 cnt;
777 u32 n_lanes = dp->link_cfg.lane_count;
778 u8 data;
779 u8 ce_done = 1;
780
781 for (cnt = 0; cnt < n_lanes / 2; cnt++) {
782 tegra_dc_dp_dpcd_read(dp, (NV_DPCD_LANE0_1_STATUS + cnt), &data);
783
784 if (n_lanes == 1) {
785 ce_done = (data &
786 (0x1 << NV_DPCD_STATUS_LANEX_CHN_EQ_DONE_SHIFT)) &&
787 (data & (0x1 << NV_DPCD_STATUS_LANEX_SYMBOL_LOCKED_SHFIT));
788 break;
789 } else if (!(data & (0x1 << NV_DPCD_STATUS_LANEX_CHN_EQ_DONE_SHIFT)) ||
790 !(data & (0x1 << NV_DPCD_STATUS_LANEX_SYMBOL_LOCKED_SHFIT)) ||
791 !(data & (0x1 << NV_DPCD_STATUS_LANEXPLUS1_CHN_EQ_DONE_SHIFT)) ||
792 !(data & (0x1 << NV_DPCD_STATUS_LANEXPLUS1_SYMBOL_LOCKED_SHIFT)))
793 return 0;
794 }
795
796 if (ce_done) {
797 tegra_dc_dp_dpcd_read(dp, NV_DPCD_LANE_ALIGN_STATUS_UPDATED, &data);
798 if (!(data & NV_DPCD_LANE_ALIGN_STATUS_UPDATED_DONE_YES))
799 ce_done = 0;
800 }
801
802 return ce_done;
803}
804
805static u8 tegra_dp_clock_recovery_status(struct tegra_dc_dp_data *dp)
806{
807 u32 cnt;
808 u32 n_lanes = dp->link_cfg.lane_count;
809 u8 data_ptr;
810
811 for (cnt = 0; cnt < n_lanes / 2; cnt++) {
812 tegra_dc_dp_dpcd_read(dp,
813 (NV_DPCD_LANE0_1_STATUS + cnt), &data_ptr);
814
815 if (n_lanes == 1)
816 return (data_ptr & NV_DPCD_STATUS_LANEX_CR_DONE_YES) ? 1 : 0;
817 else if (!(data_ptr & NV_DPCD_STATUS_LANEX_CR_DONE_YES) ||
818 !(data_ptr &
819 (NV_DPCD_STATUS_LANEXPLUS1_CR_DONE_YES)))
820 return 0;
821 }
822
823 return 1;
824}
825
826static void tegra_dp_lt_adjust(struct tegra_dc_dp_data *dp,
827 u32 pe[4], u32 vs[4], u32 pc[4],
828 u8 pc_supported)
829{
830 size_t cnt;
831 u8 data_ptr;
832 u32 n_lanes = dp->link_cfg.lane_count;
833
834 for (cnt = 0; cnt < n_lanes / 2; cnt++) {
835 tegra_dc_dp_dpcd_read(dp,
836 (NV_DPCD_LANE0_1_ADJUST_REQ + cnt), &data_ptr);
837 pe[2 * cnt] = (data_ptr & NV_DPCD_ADJUST_REQ_LANEX_PE_MASK) >>
838 NV_DPCD_ADJUST_REQ_LANEX_PE_SHIFT;
839 vs[2 * cnt] = (data_ptr & NV_DPCD_ADJUST_REQ_LANEX_DC_MASK) >>
840 NV_DPCD_ADJUST_REQ_LANEX_DC_SHIFT;
841 pe[1 + 2 * cnt] =
842 (data_ptr & NV_DPCD_ADJUST_REQ_LANEXPLUS1_PE_MASK) >>
843 NV_DPCD_ADJUST_REQ_LANEXPLUS1_PE_SHIFT;
844 vs[1 + 2 * cnt] =
845 (data_ptr & NV_DPCD_ADJUST_REQ_LANEXPLUS1_DC_MASK) >>
846 NV_DPCD_ADJUST_REQ_LANEXPLUS1_DC_SHIFT;
847 }
848 if (pc_supported) {
849 tegra_dc_dp_dpcd_read(dp,
850 NV_DPCD_ADJUST_REQ_POST_CURSOR2, &data_ptr);
851 for (cnt = 0; cnt < n_lanes; cnt++) {
852 pc[cnt] = (data_ptr >>
853 NV_DPCD_ADJUST_REQ_POST_CURSOR2_LANE_SHIFT(cnt)) &
854 NV_DPCD_ADJUST_REQ_POST_CURSOR2_LANE_MASK;
855 }
856 }
857}
858
859static inline u32 tegra_dp_wait_aux_training(struct tegra_dc_dp_data *dp,
860 u8 is_clk_recovery)
861{
862 if (!dp->link_cfg.aux_rd_interval)
863 is_clk_recovery ? udelay(200) :
864 udelay(500);
865 else
866 mdelay(dp->link_cfg.aux_rd_interval * 4);
867
868 return dp->link_cfg.aux_rd_interval;
869}
870
871static void tegra_dp_tpg(struct tegra_dc_dp_data *dp, u32 tp, u32 n_lanes)
872{
873 u8 data = (tp == training_pattern_disabled)
874 ? (tp | NV_DPCD_TRAINING_PATTERN_SET_SC_DISABLED_F)
875 : (tp | NV_DPCD_TRAINING_PATTERN_SET_SC_DISABLED_T);
876
877 tegra_dc_sor_set_dp_linkctl(&dp->sor, 1, tp, &dp->link_cfg);
878 tegra_dc_dp_dpcd_write(dp, NV_DPCD_TRAINING_PATTERN_SET, data);
879}
880
881static int tegra_dp_link_config(struct tegra_dc_dp_data *dp,
882 const struct tegra_dc_dp_link_config *link_cfg)
883{
884 u8 dpcd_data;
885 u32 retry;
886
887 if (link_cfg->lane_count == 0) {
888 printk(BIOS_ERR, "dp: error: lane count is 0. "
889 "Can not set link config.\n");
890 return DP_LT_FAILED;
891 }
892
893 /* Set power state if it is not in normal level */
894 if(tegra_dc_dp_dpcd_read(dp, NV_DPCD_SET_POWER, &dpcd_data))
895 return DP_LT_FAILED;
896
897 if (dpcd_data == NV_DPCD_SET_POWER_VAL_D3_PWRDWN) {
898 dpcd_data = NV_DPCD_SET_POWER_VAL_D0_NORMAL;
899
900 /* DP spec requires 3 retries */
901 for (retry = 3; retry > 0; --retry){
902 if (tegra_dc_dp_dpcd_write(dp, NV_DPCD_SET_POWER, dpcd_data))
903 break;
904 if (retry == 1){
905 printk(BIOS_ERR, "dp: Failed to set DP panel power\n");
906 return DP_LT_FAILED;
907 }
908 }
909 }
910
911 /* Enable ASSR if possible */
912 if (link_cfg->alt_scramber_reset_cap)
913 if(tegra_dc_dp_set_assr(dp, 1))
914 return DP_LT_FAILED;
915
916 if (tegra_dp_set_link_bandwidth(dp, link_cfg->link_bw)) {
917 printk(BIOS_ERR, "dp: Failed to set link bandwidth\n");
918 return DP_LT_FAILED;
919 }
920 if (tegra_dp_set_lane_count(dp, link_cfg)) {
921 printk(BIOS_ERR, "dp: Failed to set lane count\n");
922 return DP_LT_FAILED;
923 }
924 tegra_dc_sor_set_dp_linkctl(&dp->sor, 1, training_pattern_none,
925 link_cfg);
926 return DP_LT_SUCCESS;
927}
928
929static int tegra_dp_lower_link_config(struct tegra_dc_dp_data *dp,
930 struct tegra_dc_dp_link_config *cfg)
931{
932 struct tegra_dc_dp_link_config tmp_cfg;
933
934 tmp_cfg = dp->link_cfg;
935 cfg->is_valid = 0;
936
937 if (_tegra_dp_lower_link_config(dp, cfg))
938 goto fail;
939
940 if (tegra_dc_dp_calc_config(dp, dp->dc->config, cfg))
941 goto fail;
942 tegra_dp_link_config(dp, cfg);
943
944 return DP_LT_SUCCESS;
945fail:
946 dp->link_cfg = tmp_cfg;
947 tegra_dp_link_config(dp, &tmp_cfg);
948 return DP_LT_FAILED;
949}
950
951static void tegra_dp_lt_config(struct tegra_dc_dp_data *dp,
952 u32 pe[4], u32 vs[4], u32 pc[4])
953{
954 struct tegra_dc_sor_data *sor = &dp->sor;
955 u32 n_lanes = dp->link_cfg.lane_count;
956 u8 pc_supported = dp->link_cfg.tps3_supported;
957 u32 cnt;
958 u32 val;
959
960 for (cnt = 0; cnt < n_lanes; cnt++) {
961 u32 mask = 0;
962 u32 pe_reg, vs_reg, pc_reg;
963 u32 shift = 0;
964
965 switch (cnt) {
966 case 0:
967 mask = NV_SOR_PR_LANE2_DP_LANE0_MASK;
968 shift = NV_SOR_PR_LANE2_DP_LANE0_SHIFT;
969 break;
970 case 1:
971 mask = NV_SOR_PR_LANE1_DP_LANE1_MASK;
972 shift = NV_SOR_PR_LANE1_DP_LANE1_SHIFT;
973 break;
974 case 2:
975 mask = NV_SOR_PR_LANE0_DP_LANE2_MASK;
976 shift = NV_SOR_PR_LANE0_DP_LANE2_SHIFT;
977 break;
978 case 3:
979 mask = NV_SOR_PR_LANE3_DP_LANE3_MASK;
980 shift = NV_SOR_PR_LANE3_DP_LANE3_SHIFT;
981 break;
982 default:
983 printk(BIOS_ERR,
984 "dp: incorrect lane cnt\n");
985 }
986
987 pe_reg = tegra_dp_pe_regs[pc[cnt]][vs[cnt]][pe[cnt]];
988 vs_reg = tegra_dp_vs_regs[pc[cnt]][vs[cnt]][pe[cnt]];
989 pc_reg = tegra_dp_pc_regs[pc[cnt]][vs[cnt]][pe[cnt]];
990
991 tegra_dp_set_pe_vs_pc(sor, mask, pe_reg << shift,
992 vs_reg << shift, pc_reg << shift, pc_supported);
993 }
994
995 tegra_dp_disable_tx_pu(&dp->sor);
996 udelay(20);
997
998 for (cnt = 0; cnt < n_lanes; cnt++) {
999 u32 max_vs_flag = tegra_dp_is_max_vs(pe[cnt], vs[cnt]);
1000 u32 max_pe_flag = tegra_dp_is_max_pe(pe[cnt], vs[cnt]);
1001
1002 val = (vs[cnt] << NV_DPCD_TRAINING_LANEX_SET_DC_SHIFT) |
1003 (max_vs_flag ?
1004 NV_DPCD_TRAINING_LANEX_SET_DC_MAX_REACHED_T :
1005 NV_DPCD_TRAINING_LANEX_SET_DC_MAX_REACHED_F) |
1006 (pe[cnt] << NV_DPCD_TRAINING_LANEX_SET_PE_SHIFT) |
1007 (max_pe_flag ?
1008 NV_DPCD_TRAINING_LANEX_SET_PE_MAX_REACHED_T :
1009 NV_DPCD_TRAINING_LANEX_SET_PE_MAX_REACHED_F);
1010 tegra_dc_dp_dpcd_write(dp,
1011 (NV_DPCD_TRAINING_LANE0_SET + cnt), val);
1012 }
1013
1014 if (pc_supported) {
1015 for (cnt = 0; cnt < n_lanes / 2; cnt++) {
1016 u32 max_pc_flag0 = tegra_dp_is_max_pc(pc[cnt]);
1017 u32 max_pc_flag1 = tegra_dp_is_max_pc(pc[cnt + 1]);
1018 val = (pc[cnt] << NV_DPCD_LANEX_SET2_PC2_SHIFT) |
1019 (max_pc_flag0 ?
1020 NV_DPCD_LANEX_SET2_PC2_MAX_REACHED_T :
1021 NV_DPCD_LANEX_SET2_PC2_MAX_REACHED_F) |
1022 (pc[cnt + 1] <<
1023 NV_DPCD_LANEXPLUS1_SET2_PC2_SHIFT) |
1024 (max_pc_flag1 ?
1025 NV_DPCD_LANEXPLUS1_SET2_PC2_MAX_REACHED_T :
1026 NV_DPCD_LANEXPLUS1_SET2_PC2_MAX_REACHED_F);
1027 tegra_dc_dp_dpcd_write(dp,
1028 (NV_DPCD_TRAINING_LANE0_1_SET2 + cnt), val);
1029 }
1030 }
1031}
1032
1033static int _tegra_dp_channel_eq(struct tegra_dc_dp_data *dp, u32 pe[4],
1034 u32 vs[4], u32 pc[4], u8 pc_supported,
1035 u32 n_lanes)
1036{
1037 u32 retry_cnt;
1038
1039 for (retry_cnt = 0; retry_cnt < 4; retry_cnt++) {
1040 if (retry_cnt){
1041 tegra_dp_lt_adjust(dp, pe, vs, pc, pc_supported);
1042 tegra_dp_lt_config(dp, pe, vs, pc);
1043 }
1044
1045 tegra_dp_wait_aux_training(dp, 0);
1046
1047 if (!tegra_dp_clock_recovery_status(dp)) {
1048 printk(BIOS_ERR,"dp: CR failed in channel EQ sequence!\n");
1049 break;
1050 }
1051
1052 if (tegra_dp_channel_eq_status(dp))
1053 return DP_LT_SUCCESS;
1054 }
1055
1056 return DP_LT_FAILED;
1057}
1058
1059static int tegra_dp_channel_eq(struct tegra_dc_dp_data *dp,
1060 u32 pe[4], u32 vs[4], u32 pc[4])
1061{
1062 u32 n_lanes = dp->link_cfg.lane_count;
1063 u8 pc_supported = dp->link_cfg.tps3_supported;
1064 int err;
1065 u32 tp_src = training_pattern_2;
1066
1067 if (pc_supported)
1068 tp_src = training_pattern_3;
1069
1070 tegra_dp_tpg(dp, tp_src, n_lanes);
1071
1072 err = _tegra_dp_channel_eq(dp, pe, vs, pc, pc_supported, n_lanes);
1073
1074 tegra_dp_tpg(dp, training_pattern_disabled, n_lanes);
1075
1076 return err;
1077}
1078
1079static int _tegra_dp_clk_recovery(struct tegra_dc_dp_data *dp, u32 pe[4],
1080 u32 vs[4], u32 pc[4], u8 pc_supported,
1081 u32 n_lanes)
1082{
1083 u32 vs_temp[4];
1084 u32 retry_cnt = 0;
1085
1086 do {
1087 tegra_dp_lt_config(dp, pe, vs, pc);
1088 tegra_dp_wait_aux_training(dp, 1);
1089
1090 if (tegra_dp_clock_recovery_status(dp))
1091 return DP_LT_SUCCESS;
1092
1093 memcpy(vs_temp, vs, sizeof(vs_temp));
1094 tegra_dp_lt_adjust(dp, pe, vs, pc, pc_supported);
1095
1096 if (memcmp(vs_temp, vs, sizeof(vs_temp)))
1097 retry_cnt = 0;
1098 else
1099 ++retry_cnt;
1100 } while (retry_cnt < 5);
1101
1102 return DP_LT_FAILED;
1103}
1104
1105static int tegra_dp_clk_recovery(struct tegra_dc_dp_data *dp,
1106 u32 pe[4], u32 vs[4], u32 pc[4])
1107{
1108 u32 n_lanes = dp->link_cfg.lane_count;
1109 u8 pc_supported = dp->link_cfg.tps3_supported;
1110 int err;
1111
1112 tegra_dp_tpg(dp, training_pattern_1, n_lanes);
1113
1114 err = _tegra_dp_clk_recovery(dp, pe, vs, pc, pc_supported, n_lanes);
1115 if (err < 0)
1116 tegra_dp_tpg(dp, training_pattern_disabled, n_lanes);
1117
1118 return err;
1119}
1120
1121static int tegra_dc_dp_full_link_training(struct tegra_dc_dp_data *dp)
1122{
1123 struct tegra_dc_sor_data *sor = &dp->sor;
1124 int err;
1125 u32 pe[4], vs[4], pc[4];
1126
1127 tegra_sor_precharge_lanes(sor);
1128
1129retry_cr:
1130 memset(pe, preEmphasis_Disabled, sizeof(pe));
1131 memset(vs, driveCurrent_Level0, sizeof(vs));
1132 memset(pc, postCursor2_Level0, sizeof(pc));
1133
1134 err = tegra_dp_clk_recovery(dp, pe, vs, pc);
1135 if (err != DP_LT_SUCCESS) {
1136 if (!tegra_dp_lower_link_config(dp, &dp->link_cfg))
1137 goto retry_cr;
1138
1139 printk(BIOS_ERR, "dp: clk recovery failed\n");
1140 goto fail;
1141 }
1142
1143 err = tegra_dp_channel_eq(dp, pe, vs, pc);
1144 if (err != DP_LT_SUCCESS) {
1145 if (!tegra_dp_lower_link_config(dp, &dp->link_cfg))
1146 goto retry_cr;
1147
1148 printk(BIOS_ERR,
1149 "dp: channel equalization failed\n");
1150 goto fail;
1151 }
1152
1153 tegra_dc_dp_dump_link_cfg(dp, &dp->link_cfg);
1154
1155 return 0;
1156
1157fail:
1158 return err;
1159}
Jimmy Zhang75f701792014-04-21 15:58:45 -07001160/*
1161 * All link training functions are ported from kernel dc driver.
1162 * See more details at drivers/video/tegra/dc/dp.c
1163 */
1164static int tegra_dc_dp_fast_link_training(struct tegra_dc_dp_data *dp,
1165 const struct tegra_dc_dp_link_config *link_cfg)
1166{
1167 struct tegra_dc_sor_data *sor = &dp->sor;
1168 u8 link_bw;
1169 u8 lane_count;
1170 u16 data16;
1171 u32 data32;
1172 u32 size;
1173 u32 status;
1174 int j;
1175 u32 mask = 0xffff >> ((4 - link_cfg->lane_count) * 4);
1176
1177 tegra_dc_sor_set_lane_parm(sor, link_cfg);
1178 tegra_dc_dp_dpcd_write(dp, NV_DPCD_MAIN_LINK_CHANNEL_CODING_SET,
1179 NV_DPCD_MAIN_LINK_CHANNEL_CODING_SET_ANSI_8B10B);
1180
1181 /* Send TP1 */
1182 tegra_dc_sor_set_dp_linkctl(sor, 1, training_pattern_1, link_cfg);
1183 tegra_dc_dp_dpcd_write(dp, NV_DPCD_TRAINING_PATTERN_SET,
1184 NV_DPCD_TRAINING_PATTERN_SET_TPS_TP1);
1185
1186 for (j = 0; j < link_cfg->lane_count; ++j)
1187 tegra_dc_dp_dpcd_write(dp, NV_DPCD_TRAINING_LANE0_SET + j,
1188 0x24);
1189 udelay(520);
1190
1191 size = sizeof(data16);
1192 tegra_dc_dpaux_read(dp, DPAUX_DP_AUXCTL_CMD_AUXRD,
1193 NV_DPCD_LANE0_1_STATUS, (u8 *)&data16, &size, &status);
1194 status = mask & 0x1111;
1195 if ((data16 & status) != status) {
1196 printk(BIOS_ERR,
1197 "dp: Link training error for TP1 (%#x)\n", data16);
1198 return -EFAULT;
1199 }
1200
1201 /* enable ASSR */
1202 tegra_dc_dp_set_assr(dp, link_cfg->scramble_ena);
1203 tegra_dc_sor_set_dp_linkctl(sor, 1, training_pattern_3, link_cfg);
1204
1205 tegra_dc_dp_dpcd_write(dp, NV_DPCD_TRAINING_PATTERN_SET,
1206 link_cfg->link_bw == 20 ? 0x23 : 0x22);
1207 for (j = 0; j < link_cfg->lane_count; ++j)
1208 tegra_dc_dp_dpcd_write(dp, NV_DPCD_TRAINING_LANE0_SET + j,
1209 0x24);
1210 udelay(520);
1211
1212 size = sizeof(data32);
1213 tegra_dc_dpaux_read(dp, DPAUX_DP_AUXCTL_CMD_AUXRD,
1214 NV_DPCD_LANE0_1_STATUS, (u8 *)&data32, &size, &status);
1215 if ((data32 & mask) != (0x7777 & mask)) {
1216 printk(BIOS_ERR,
1217 "dp: Link training error for TP2/3 (0x%x)\n", data32);
1218 return -EFAULT;
1219 }
1220
1221 tegra_dc_sor_set_dp_linkctl(sor, 1, training_pattern_disabled,
1222 link_cfg);
1223 tegra_dc_dp_dpcd_write(dp, NV_DPCD_TRAINING_PATTERN_SET, 0);
1224
1225 if (tegra_dc_dp_link_trained(dp, link_cfg)) {
1226 tegra_dc_sor_read_link_config(&dp->sor, &link_bw,
1227 &lane_count);
1228 printk(BIOS_ERR,
1229 "Fast link trainging failed, link bw %d, lane # %d\n",
1230 link_bw, lane_count);
1231 return -EFAULT;
1232 }
1233
1234 printk(BIOS_INFO,
1235 "Fast link trainging succeeded, link bw %d, lane %d\n",
1236 link_cfg->link_bw, link_cfg->lane_count);
1237
1238 return 0;
1239}
1240
Neil Chen8c440a62014-09-23 17:41:59 +08001241static int tegra_dp_do_link_training(struct tegra_dc_dp_data *dp,
Jimmy Zhang75f701792014-04-21 15:58:45 -07001242 const struct tegra_dc_dp_link_config *link_cfg)
1243{
Jimmy Zhang75f701792014-04-21 15:58:45 -07001244 u8 link_bw;
1245 u8 lane_count;
Jimmy Zhang75f701792014-04-21 15:58:45 -07001246 int ret;
1247
Jimmy Zhang75f701792014-04-21 15:58:45 -07001248 /* Now do the fast link training for eDP */
1249 ret = tegra_dc_dp_fast_link_training(dp, link_cfg);
1250 if (ret) {
1251 printk(BIOS_ERR, "dp: fast link training failed\n");
Neil Chen8c440a62014-09-23 17:41:59 +08001252
1253 /* Try full link training then */
1254 if (tegra_dc_dp_full_link_training(dp)){
1255 printk(BIOS_ERR, "dp: full link training failed\n");
1256 return ret;
1257 }
Neil Chenac4fef82014-09-24 10:41:08 +08001258 } else {
1259 /* set to a known-good drive setting if fast link succeeded */
1260 tegra_dc_sor_set_voltage_swing(&dp->sor);
Jimmy Zhang75f701792014-04-21 15:58:45 -07001261 }
1262
1263 /* Everything goes well, double check the link config */
1264 /* TODO: record edc/c2 data for debugging */
1265 tegra_dc_sor_read_link_config(&dp->sor, &link_bw, &lane_count);
1266
1267 if ((link_cfg->link_bw == link_bw) &&
1268 (link_cfg->lane_count == lane_count))
1269 return 0;
1270 else
1271 return -EFAULT;
1272}
1273
1274static int tegra_dc_dp_explore_link_cfg(struct tegra_dc_dp_data *dp,
1275 struct tegra_dc_dp_link_config *link_cfg,
1276 const struct soc_nvidia_tegra124_config *config)
1277{
1278 struct tegra_dc_dp_link_config temp_cfg;
1279
1280 if (!config->pixel_clock || !config->xres || !config->yres) {
1281 printk(BIOS_ERR,
1282 "dp: error mode configuration");
1283 return -EINVAL;
1284 }
1285 if (!link_cfg->max_link_bw || !link_cfg->max_lane_count) {
1286 printk(BIOS_ERR,
1287 "dp: error link configuration");
1288 return -EINVAL;
1289 }
1290
1291 link_cfg->is_valid = 0;
1292
1293 memcpy(&temp_cfg, link_cfg, sizeof(temp_cfg));
1294
1295 temp_cfg.link_bw = temp_cfg.max_link_bw;
1296 temp_cfg.lane_count = temp_cfg.max_lane_count;
1297
1298 /*
1299 * set to max link config
1300 */
1301 if ((!tegra_dc_dp_calc_config(dp, config, &temp_cfg)) &&
Neil Chen8c440a62014-09-23 17:41:59 +08001302 (!tegra_dp_link_config(dp, &temp_cfg)) &&
1303 (!tegra_dp_do_link_training(dp, &temp_cfg)))
Jimmy Zhang75f701792014-04-21 15:58:45 -07001304 /* the max link cfg is doable */
1305 memcpy(link_cfg, &temp_cfg, sizeof(temp_cfg));
1306
1307 return link_cfg->is_valid ? 0 : -EFAULT;
1308}
1309
Hung-Te Lin3af0d312014-04-02 21:57:40 +08001310static void tegra_dp_update_config(struct tegra_dc_dp_data *dp,
1311 struct soc_nvidia_tegra124_config *config)
1312{
1313 struct edid edid;
1314 u8 buf[128] = {0};
1315 u32 size = sizeof(buf), aux_stat = 0;
1316
1317 tegra_dc_dpaux_enable(dp);
1318 if (tegra_dc_i2c_aux_read(dp, TEGRA_EDID_I2C_ADDRESS, 0, buf, &size,
1319 &aux_stat)) {
1320 printk(BIOS_ERR, "%s: Failed to read EDID. Use defaults.\n",
1321 __func__);
1322 return;
1323 }
1324
1325 if (decode_edid(buf, sizeof(buf), &edid)) {
1326 printk(BIOS_ERR, "%s: Failed to decode EDID. Use defaults.\n",
1327 __func__);
1328 return;
1329 }
1330
David Hendricks7dbf9c62015-07-30 18:49:48 -07001331 config->xres = edid.mode.ha;
1332 config->yres = edid.mode.va;
1333 config->pixel_clock = edid.mode.pixel_clock * 1000;
Hung-Te Lin3af0d312014-04-02 21:57:40 +08001334
David Hendricks7dbf9c62015-07-30 18:49:48 -07001335 config->hfront_porch = edid.mode.hso;
1336 config->hsync_width = edid.mode.hspw;
1337 config->hback_porch = edid.mode.hbl - edid.mode.hso - edid.mode.hspw;
Hung-Te Lin3af0d312014-04-02 21:57:40 +08001338
David Hendricks7dbf9c62015-07-30 18:49:48 -07001339 config->vfront_porch = edid.mode.vso;
1340 config->vsync_width = edid.mode.vspw;
1341 config->vback_porch = edid.mode.vbl - edid.mode.vso - edid.mode.vspw;
Hung-Te Lin3af0d312014-04-02 21:57:40 +08001342
1343 /**
1344 * Note edid->framebuffer_bits_per_pixel is currently hard-coded as 32,
1345 * so we should keep the default value in device config.
1346 *
1347 * EDID v1.3 panels may not have color depth info, so we need to check
1348 * if these values are zero before updating config.
1349 */
1350 if (edid.panel_bits_per_pixel)
1351 config->panel_bits_per_pixel = edid.panel_bits_per_pixel;
1352 if (edid.panel_bits_per_color)
1353 config->color_depth = edid.panel_bits_per_color;
1354 printk(BIOS_SPEW, "%s: configuration updated by EDID.\n", __func__);
1355}
1356
Jimmy Zhangbd5925a2014-03-10 12:42:05 -07001357void dp_init(void * _config)
Julius Werneredf6b572013-10-25 17:49:26 -07001358{
Jimmy Zhangbd5925a2014-03-10 12:42:05 -07001359 struct soc_nvidia_tegra124_config *config = (void *)_config;
1360 struct tegra_dc *dc = config->dc_data;
Julius Werneredf6b572013-10-25 17:49:26 -07001361 struct tegra_dc_dp_data *dp = &dp_data;
1362
Jimmy Zhangbd5925a2014-03-10 12:42:05 -07001363 // set up links among config, dc, dp and sor
1364 dp->dc = dc;
1365 dc->out = dp;
1366 dp->sor.dc = dc;
Julius Werneredf6b572013-10-25 17:49:26 -07001367
Jimmy Zhangbd5925a2014-03-10 12:42:05 -07001368 dp->sor.power_is_up = 0;
Julius Werneredf6b572013-10-25 17:49:26 -07001369 dp->sor.base = (void *)TEGRA_ARM_SOR;
Jimmy Zhangbd5925a2014-03-10 12:42:05 -07001370 dp->sor.pmc_base = (void *)TEGRA_PMC_BASE;
Julius Werneredf6b572013-10-25 17:49:26 -07001371 dp->sor.portnum = 0;
Jimmy Zhangbd5925a2014-03-10 12:42:05 -07001372 dp->sor.link_cfg = &dp->link_cfg;
Julius Werneredf6b572013-10-25 17:49:26 -07001373 dp->aux_base = (void *)TEGRA_ARM_DPAUX;
Jimmy Zhangbd5925a2014-03-10 12:42:05 -07001374 dp->link_cfg.is_valid = 0;
1375 dp->enabled = 0;
Hung-Te Lin3af0d312014-04-02 21:57:40 +08001376
1377 tegra_dp_update_config(dp, config);
Jimmy Zhangbd5925a2014-03-10 12:42:05 -07001378}
Julius Werneredf6b572013-10-25 17:49:26 -07001379
Jimmy Zhangbd5925a2014-03-10 12:42:05 -07001380static void tegra_dp_hpd_config(struct tegra_dc_dp_data *dp,
1381 struct soc_nvidia_tegra124_config *config)
1382{
1383 u32 val;
1384
1385 val = config->hpd_plug_min_us |
1386 (config->hpd_unplug_min_us <<
1387 DPAUX_HPD_CONFIG_UNPLUG_MIN_TIME_SHIFT);
1388 tegra_dpaux_writel(dp, DPAUX_HPD_CONFIG, val);
1389
1390 tegra_dpaux_writel(dp, DPAUX_HPD_IRQ_CONFIG, config->hpd_irq_min_us);
1391}
1392
1393static int tegra_dp_hpd_plug(struct tegra_dc_dp_data *dp, int timeout_ms)
1394{
1395 u32 val;
1396 u32 timeout = timeout_ms * 1000;
1397 do {
1398 val = tegra_dpaux_readl(dp, DPAUX_DP_AUXSTAT);
1399 if (val & DPAUX_DP_AUXSTAT_HPD_STATUS_PLUGGED)
1400 return 0;
1401 udelay(100);
1402 timeout -= 100;
1403 } while (timeout > 0);
1404 return -1;
1405}
1406
1407void dp_enable(void * _dp)
1408{
1409 struct tegra_dc_dp_data *dp = _dp;
1410 struct tegra_dc *dc = dp->dc;
1411 struct soc_nvidia_tegra124_config *config = dc->config;
1412
1413 u8 data;
1414 u32 retry;
1415 int ret;
1416
1417 tegra_dc_dpaux_enable(dp);
1418
1419 tegra_dp_hpd_config(dp, config);
1420 if (tegra_dp_hpd_plug(dp, config->vdd_to_hpd_delay_ms) < 0) {
1421 printk(BIOS_ERR, "dp: hpd plug failed\n");
1422 goto error_enable;
Julius Werneredf6b572013-10-25 17:49:26 -07001423 }
1424
Jimmy Zhang75f701792014-04-21 15:58:45 -07001425 if (tegra_dc_dp_init_max_link_cfg(config, dp, &dp->link_cfg)) {
Andrew Bresticker24d4f7f2013-12-18 22:41:34 -08001426 printk(BIOS_ERR, "dp: failed to init link configuration\n");
Jimmy Zhangbd5925a2014-03-10 12:42:05 -07001427 goto error_enable;
1428 }
Julius Werneredf6b572013-10-25 17:49:26 -07001429
Jimmy Zhangbd5925a2014-03-10 12:42:05 -07001430 tegra_dc_sor_enable_dp(&dp->sor);
Julius Werneredf6b572013-10-25 17:49:26 -07001431
Jimmy Zhangbd5925a2014-03-10 12:42:05 -07001432 tegra_dc_sor_set_panel_power(&dp->sor, 1);
Julius Werneredf6b572013-10-25 17:49:26 -07001433
Jimmy Zhangbd5925a2014-03-10 12:42:05 -07001434 /* Write power on to DPCD */
1435 data = NV_DPCD_SET_POWER_VAL_D0_NORMAL;
1436 retry = 0;
1437 do {
1438 ret = tegra_dc_dp_dpcd_write(dp,
1439 NV_DPCD_SET_POWER, data);
1440 } while ((retry++ < DP_POWER_ON_MAX_TRIES) && ret);
Andrew Bresticker24d4f7f2013-12-18 22:41:34 -08001441
Jimmy Zhangbd5925a2014-03-10 12:42:05 -07001442 if (ret || retry >= DP_POWER_ON_MAX_TRIES) {
1443 printk(BIOS_ERR,
1444 "dp: failed to power on panel (0x%x)\n", ret);
1445 goto error_enable;
Julius Werneredf6b572013-10-25 17:49:26 -07001446 }
1447
Jimmy Zhangbd5925a2014-03-10 12:42:05 -07001448 /* Confirm DP is plugging status */
1449 if (!(tegra_dpaux_readl(dp, DPAUX_DP_AUXSTAT) &
1450 DPAUX_DP_AUXSTAT_HPD_STATUS_PLUGGED)) {
1451 printk(BIOS_ERR, "dp: could not detect HPD\n");
1452 goto error_enable;
Julius Werneredf6b572013-10-25 17:49:26 -07001453 }
1454
Jimmy Zhangbd5925a2014-03-10 12:42:05 -07001455 /* Check DP version */
1456 if (tegra_dc_dp_dpcd_read(dp, NV_DPCD_REV, &dp->revision))
1457 printk(BIOS_ERR,
1458 "dp: failed to read the revision number from sink\n");
Julius Werneredf6b572013-10-25 17:49:26 -07001459
Jimmy Zhang75f701792014-04-21 15:58:45 -07001460 if (tegra_dc_dp_explore_link_cfg(dp, &dp->link_cfg, config)) {
1461 printk(BIOS_ERR, "dp: error to configure link\n");
1462 goto error_enable;
1463 }
1464
Jimmy Zhangbd5925a2014-03-10 12:42:05 -07001465 tegra_dc_sor_set_power_state(&dp->sor, 1);
1466 tegra_dc_sor_attach(&dp->sor);
Julius Werneredf6b572013-10-25 17:49:26 -07001467
Jimmy Zhangbd5925a2014-03-10 12:42:05 -07001468 /*
1469 * Power down the unused lanes to save power
1470 * (about hundreds milli-watts, varies from boards).
1471 */
1472 tegra_dc_sor_power_down_unused_lanes(&dp->sor);
Julius Werneredf6b572013-10-25 17:49:26 -07001473
Jimmy Zhangbd5925a2014-03-10 12:42:05 -07001474 dp->enabled = 1;
1475error_enable:
1476 return;
Julius Werneredf6b572013-10-25 17:49:26 -07001477}