summaryrefslogtreecommitdiffstats
path: root/drivers/video/tegra/dc/dp.c
diff options
context:
space:
mode:
authorChao Xu <cxu@nvidia.com>2013-05-24 18:35:22 -0400
committerDan Willemsen <dwillemsen@nvidia.com>2015-03-18 15:05:19 -0400
commitf41eddb73288de4568e5d026b1ae3d08ccc1fef0 (patch)
tree296b448159c8d695830f2d0edde28ec7d3d579f3 /drivers/video/tegra/dc/dp.c
parentbb38f885525b59e5d0c5778072e45defc10f97f7 (diff)
video: tegra: dc: Update eDP code
Verified on FPGA (bug 1258447). Change-Id: Ie95880b99f453d57d659579e6f3b9e6aed393190 Signed-off-by: Chao Xu <cxu@nvidia.com> Reviewed-on: http://git-master/r/242513
Diffstat (limited to 'drivers/video/tegra/dc/dp.c')
-rw-r--r--drivers/video/tegra/dc/dp.c508
1 files changed, 332 insertions, 176 deletions
diff --git a/drivers/video/tegra/dc/dp.c b/drivers/video/tegra/dc/dp.c
index dec8da9df..5aa6f9009 100644
--- a/drivers/video/tegra/dc/dp.c
+++ b/drivers/video/tegra/dc/dp.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * drivers/video/tegra/dc/dp.c 2 * drivers/video/tegra/dc/dp.c
3 * 3 *
4 * Copyright (c) 2011-2012, NVIDIA Corporation. 4 * Copyright (c) 2011-2013, NVIDIA Corporation.
5 * 5 *
6 * This software is licensed under the terms of the GNU General Public 6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and 7 * License version 2, as published by the Free Software Foundation, and
@@ -15,19 +15,17 @@
15 */ 15 */
16 16
17 17
18#include <linux/clk.h>
19#include <linux/err.h> 18#include <linux/err.h>
20#include <linux/fb.h>
21#include <linux/gpio.h> 19#include <linux/gpio.h>
22#include <linux/kernel.h>
23#include <linux/nvhost.h>
24#include <linux/wait.h> 20#include <linux/wait.h>
25#include <linux/delay.h> 21#include <linux/delay.h>
26#include <linux/interrupt.h> 22#include <linux/interrupt.h>
23#include <linux/seq_file.h>
24#include <linux/debugfs.h>
27 25
28#include <mach/clk.h>
29#include <mach/dc.h> 26#include <mach/dc.h>
30#include <mach/fb.h> 27#include <mach/fb.h>
28#include <mach/hardware.h>
31 29
32#include "dp.h" 30#include "dp.h"
33#include "sor.h" 31#include "sor.h"
@@ -37,24 +35,23 @@
37 35
38 36
39 37
40static inline unsigned long tegra_dpaux_readl(struct tegra_dc_dp_data *dp, 38static inline u32 tegra_dpaux_readl(struct tegra_dc_dp_data *dp, u32 reg)
41 unsigned long reg)
42{ 39{
43 return readl(dp->aux_base + reg * 4); 40 return readl(dp->aux_base + reg * 4);
44} 41}
45 42
46static inline void tegra_dpaux_writel(struct tegra_dc_dp_data *dp, 43static inline void tegra_dpaux_writel(struct tegra_dc_dp_data *dp,
47 unsigned long reg, unsigned long val) 44 u32 reg, u32 val)
48{ 45{
49 writel(val, dp->aux_base + reg * 4); 46 writel(val, dp->aux_base + reg * 4);
50} 47}
51 48
52 49
53static unsigned long tegra_dc_dpaux_poll_register(struct tegra_dc_dp_data *dp, 50static inline u32 tegra_dc_dpaux_poll_register(struct tegra_dc_dp_data *dp,
54 u32 reg, u32 mask, u32 exp_val, u32 poll_interval_us, u32 timeout_ms) 51 u32 reg, u32 mask, u32 exp_val, u32 poll_interval_us, u32 timeout_ms)
55{ 52{
56 unsigned long timeout_jf = jiffies + msecs_to_jiffies(timeout_ms); 53 unsigned long timeout_jf = jiffies + msecs_to_jiffies(timeout_ms);
57 u32 reg_val = 0; 54 u32 reg_val = 0;
58 55
59 do { 56 do {
60 usleep_range(poll_interval_us, poll_interval_us << 1); 57 usleep_range(poll_interval_us, poll_interval_us << 1);
@@ -70,7 +67,7 @@ static unsigned long tegra_dc_dpaux_poll_register(struct tegra_dc_dp_data *dp,
70} 67}
71 68
72 69
73static int tegra_dpaux_wait_transaction(struct tegra_dc_dp_data *dp) 70static inline int tegra_dpaux_wait_transaction(struct tegra_dc_dp_data *dp)
74{ 71{
75 /* According to DP spec, each aux transaction needs to finish 72 /* According to DP spec, each aux transaction needs to finish
76 within 40ms. */ 73 within 40ms. */
@@ -86,46 +83,13 @@ static int tegra_dpaux_wait_transaction(struct tegra_dc_dp_data *dp)
86} 83}
87 84
88 85
89static void tegra_dc_dpaux_enable(struct tegra_dc_dp_data *dp)
90{
91 unsigned long reg_val;
92
93 /* clear interrupt */
94 tegra_dpaux_writel(dp, DPAUX_INTR_AUX, 0xffffffff);
95 /* do not enable interrupt for now. Enable them when Isr in place */
96 tegra_dpaux_writel(dp, DPAUX_INTR_EN_AUX, 0x0);
97
98 /* Power up aux/hybrid pads */
99 /* TODO: this may not needed for t124 */
100 reg_val = DPAUX_HYBRID_SPARE_PAD_PWR_POWERUP;
101 tegra_dpaux_writel(dp, DPAUX_HYBRID_SPARE, reg_val);
102
103 /* Put HYBRID PAD in AUX mode */
104 reg_val = tegra_dpaux_readl(dp, DPAUX_HYBRID_PADCTL);
105 reg_val &= ~DPAUX_HYBRID_PADCTL_MODE_I2C;
106 reg_val |= DPAUX_HYBRID_PADCTL_AUX_INPUT_RCV_ENABLE;
107 reg_val &= ~DPAUX_HYBRID_PADCTL_I2C_SDA_INPUT_RCV_ENABLE;
108 reg_val &= ~DPAUX_HYBRID_PADCTL_I2C_SCL_INPUT_RCV_ENABLE;
109 tegra_dpaux_writel(dp, DPAUX_HYBRID_PADCTL, reg_val);
110
111}
112
113static void tegra_dc_dpaux_disable(struct tegra_dc_dp_data *dp)
114{
115 tegra_dpaux_writel(dp, NV_DPCD_SET_POWER,
116 NV_DPCD_SET_POWER_VAL_D3_PWRDWN);
117
118 /* TODO: power down DPAUX_HYBRID_SPARE too? */
119}
120
121
122static int tegra_dc_dpaux_write_chunk(struct tegra_dc_dp_data *dp, u32 cmd, 86static int tegra_dc_dpaux_write_chunk(struct tegra_dc_dp_data *dp, u32 cmd,
123 u32 addr, u8 *data, u32 *size, u32 *aux_stat) 87 u32 addr, u8 *data, u32 *size, u32 *aux_stat)
124{ 88{
125 int i; 89 int i;
126 unsigned long reg_val; 90 u32 reg_val;
127 u32 timeout_retries = DP_AUX_TIMEOUT_MAX_TRIES; 91 u32 timeout_retries = DP_AUX_TIMEOUT_MAX_TRIES;
128 u32 defer_retries = DP_AUX_DEFER_MAX_TRIES; 92 u32 defer_retries = DP_AUX_DEFER_MAX_TRIES;
129 93
130 if (*size >= DP_AUX_MAX_BYTES) 94 if (*size >= DP_AUX_MAX_BYTES)
131 return -EINVAL; /* only write one chunk of data */ 95 return -EINVAL; /* only write one chunk of data */
@@ -142,24 +106,24 @@ static int tegra_dc_dpaux_write_chunk(struct tegra_dc_dp_data *dp, u32 cmd,
142 return -EINVAL; 106 return -EINVAL;
143 } 107 }
144 108
145#ifndef CONFIG_TEGRA_SIMULATION_PLATFORM 109 if (tegra_platform_is_silicon()) {
146 *aux_stat = tegra_dpaux_readl(dp, DPAUX_DP_AUXSTAT); 110 *aux_stat = tegra_dpaux_readl(dp, DPAUX_DP_AUXSTAT);
147 if (!(*aux_stat & DPAUX_DP_AUXSTAT_HPD_STATUS_PLUGGED)) { 111 if (!(*aux_stat & DPAUX_DP_AUXSTAT_HPD_STATUS_PLUGGED)) {
148 dev_err(&dp->dc->ndev->dev, "dp: HPD is not detected\n"); 112 dev_err(&dp->dc->ndev->dev, "dp: HPD is not detected\n");
149 return -EFAULT; 113 return -EFAULT;
114 }
150 } 115 }
151#endif
152 116
153 tegra_dpaux_writel(dp, DPAUX_DP_AUXADDR, addr); 117 tegra_dpaux_writel(dp, DPAUX_DP_AUXADDR, addr);
154 for (i = 0; i < DP_AUX_MAX_BYTES/4; ++i) { 118 for (i = 0; i < DP_AUX_MAX_BYTES/4; ++i) {
155 tegra_dpaux_writel(dp, DPAUX_DP_AUXDATA_WRITE_W(i), 119 tegra_dpaux_writel(dp, DPAUX_DP_AUXDATA_WRITE_W(i),
156 (unsigned long)*data); 120 (u32)*data);
157 data += 4; 121 data += 4;
158 } 122 }
159 123
160 reg_val = tegra_dpaux_readl(dp, DPAUX_DP_AUXCTL); 124 reg_val = tegra_dpaux_readl(dp, DPAUX_DP_AUXCTL);
161 reg_val &= ~DPAUX_DP_AUXCTL_CMD_MASK; 125 reg_val &= ~DPAUX_DP_AUXCTL_CMD_MASK;
162 reg_val |= (cmd << DPAUX_DP_AUXCTL_CMD_SHIFT); 126 reg_val |= cmd;
163 reg_val &= ~DPAUX_DP_AUXCTL_CMDLEN_FIELD; 127 reg_val &= ~DPAUX_DP_AUXCTL_CMDLEN_FIELD;
164 reg_val |= (*size << DPAUX_DP_AUXCTL_CMDLEN_SHIFT); 128 reg_val |= (*size << DPAUX_DP_AUXCTL_CMDLEN_SHIFT);
165 129
@@ -178,6 +142,10 @@ static int tegra_dc_dpaux_write_chunk(struct tegra_dc_dp_data *dp, u32 cmd,
178 142
179 *aux_stat = tegra_dpaux_readl(dp, DPAUX_DP_AUXSTAT); 143 *aux_stat = tegra_dpaux_readl(dp, DPAUX_DP_AUXSTAT);
180 144
145 /* Ignore I2C errors on fpga */
146 if (tegra_platform_is_fpga())
147 *aux_stat &= ~DPAUX_DP_AUXSTAT_REPLYTYPE_I2CNACK;
148
181 if ((*aux_stat & DPAUX_DP_AUXSTAT_TIMEOUT_ERROR_PENDING) || 149 if ((*aux_stat & DPAUX_DP_AUXSTAT_TIMEOUT_ERROR_PENDING) ||
182 (*aux_stat & DPAUX_DP_AUXSTAT_RX_ERROR_PENDING) || 150 (*aux_stat & DPAUX_DP_AUXSTAT_RX_ERROR_PENDING) ||
183 (*aux_stat & DPAUX_DP_AUXSTAT_SINKSTAT_ERROR_PENDING) || 151 (*aux_stat & DPAUX_DP_AUXSTAT_SINKSTAT_ERROR_PENDING) ||
@@ -186,9 +154,13 @@ static int tegra_dc_dpaux_write_chunk(struct tegra_dc_dp_data *dp, u32 cmd,
186 dev_dbg(&dp->dc->ndev->dev, 154 dev_dbg(&dp->dc->ndev->dev,
187 "dp: aux write retry (0x%x) -- %d\n", 155 "dp: aux write retry (0x%x) -- %d\n",
188 *aux_stat, timeout_retries); 156 *aux_stat, timeout_retries);
157 /* clear the error bits */
158 tegra_dpaux_writel(dp, DPAUX_DP_AUXSTAT,
159 *aux_stat);
189 continue; 160 continue;
190 } else { 161 } else {
191 dev_err(&dp->dc->ndev->dev, "dp: aux write got error (0x%x)\n", 162 dev_err(&dp->dc->ndev->dev,
163 "dp: aux write got error (0x%x)\n",
192 *aux_stat); 164 *aux_stat);
193 return -EFAULT; 165 return -EFAULT;
194 } 166 }
@@ -200,10 +172,14 @@ static int tegra_dc_dpaux_write_chunk(struct tegra_dc_dp_data *dp, u32 cmd,
200 dev_dbg(&dp->dc->ndev->dev, 172 dev_dbg(&dp->dc->ndev->dev,
201 "dp: aux write defer (0x%x) -- %d\n", 173 "dp: aux write defer (0x%x) -- %d\n",
202 *aux_stat, defer_retries); 174 *aux_stat, defer_retries);
175 /* clear the error bits */
176 tegra_dpaux_writel(dp, DPAUX_DP_AUXSTAT,
177 *aux_stat);
203 continue; 178 continue;
204 } else { 179 } else {
205 dev_err(&dp->dc->ndev->dev, 180 dev_err(&dp->dc->ndev->dev,
206 "dp: aux write defer exceeds max retries (0x%x)\n", 181 "dp: aux write defer exceeds max retries "
182 "(0x%x)\n",
207 *aux_stat); 183 *aux_stat);
208 return -EFAULT; 184 return -EFAULT;
209 } 185 }
@@ -252,9 +228,9 @@ static int tegra_dc_dpaux_write(struct tegra_dc_dp_data *dp, u32 cmd, u32 addr,
252static int tegra_dc_dpaux_read_chunk(struct tegra_dc_dp_data *dp, u32 cmd, 228static int tegra_dc_dpaux_read_chunk(struct tegra_dc_dp_data *dp, u32 cmd,
253 u32 addr, u8 *data, u32 *size, u32 *aux_stat) 229 u32 addr, u8 *data, u32 *size, u32 *aux_stat)
254{ 230{
255 unsigned long reg_val; 231 u32 reg_val;
256 u32 timeout_retries = DP_AUX_TIMEOUT_MAX_TRIES; 232 u32 timeout_retries = DP_AUX_TIMEOUT_MAX_TRIES;
257 u32 defer_retries = DP_AUX_DEFER_MAX_TRIES; 233 u32 defer_retries = DP_AUX_DEFER_MAX_TRIES;
258 234
259 if (*size >= DP_AUX_MAX_BYTES) 235 if (*size >= DP_AUX_MAX_BYTES)
260 return -EINVAL; /* only read one chunk */ 236 return -EINVAL; /* only read one chunk */
@@ -272,19 +248,19 @@ static int tegra_dc_dpaux_read_chunk(struct tegra_dc_dp_data *dp, u32 cmd,
272 return -EINVAL; 248 return -EINVAL;
273 } 249 }
274 250
275#ifndef CONFIG_TEGRA_SIMULATION_PLATFORM 251 if (tegra_platform_is_silicon()) {
276 *aux_stat = tegra_dpaux_readl(dp, DPAUX_DP_AUXSTAT); 252 *aux_stat = tegra_dpaux_readl(dp, DPAUX_DP_AUXSTAT);
277 if (!(*aux_stat & DPAUX_DP_AUXSTAT_HPD_STATUS_PLUGGED)) { 253 if (!(*aux_stat & DPAUX_DP_AUXSTAT_HPD_STATUS_PLUGGED)) {
278 dev_err(&dp->dc->ndev->dev, "dp: HPD is not detected\n"); 254 dev_err(&dp->dc->ndev->dev, "dp: HPD is not detected\n");
279 return -EFAULT; 255 return -EFAULT;
256 }
280 } 257 }
281#endif
282 258
283 tegra_dpaux_writel(dp, DPAUX_DP_AUXADDR, addr); 259 tegra_dpaux_writel(dp, DPAUX_DP_AUXADDR, addr);
284 260
285 reg_val = tegra_dpaux_readl(dp, DPAUX_DP_AUXCTL); 261 reg_val = tegra_dpaux_readl(dp, DPAUX_DP_AUXCTL);
286 reg_val &= ~DPAUX_DP_AUXCTL_CMD_MASK; 262 reg_val &= ~DPAUX_DP_AUXCTL_CMD_MASK;
287 reg_val |= (cmd << DPAUX_DP_AUXCTL_CMD_SHIFT); 263 reg_val |= cmd;
288 reg_val &= ~DPAUX_DP_AUXCTL_CMDLEN_FIELD; 264 reg_val &= ~DPAUX_DP_AUXCTL_CMDLEN_FIELD;
289 reg_val |= (*size << DPAUX_DP_AUXCTL_CMDLEN_SHIFT); 265 reg_val |= (*size << DPAUX_DP_AUXCTL_CMDLEN_SHIFT);
290 266
@@ -294,7 +270,6 @@ static int tegra_dc_dpaux_read_chunk(struct tegra_dc_dp_data *dp, u32 cmd,
294 usleep_range(DP_DPCP_RETRY_SLEEP_NS, 270 usleep_range(DP_DPCP_RETRY_SLEEP_NS,
295 DP_DPCP_RETRY_SLEEP_NS << 1); 271 DP_DPCP_RETRY_SLEEP_NS << 1);
296 272
297
298 reg_val |= DPAUX_DP_AUXCTL_TRANSACTREQ_PENDING; 273 reg_val |= DPAUX_DP_AUXCTL_TRANSACTREQ_PENDING;
299 tegra_dpaux_writel(dp, DPAUX_DP_AUXCTL, reg_val); 274 tegra_dpaux_writel(dp, DPAUX_DP_AUXCTL, reg_val);
300 275
@@ -304,6 +279,10 @@ static int tegra_dc_dpaux_read_chunk(struct tegra_dc_dp_data *dp, u32 cmd,
304 279
305 *aux_stat = tegra_dpaux_readl(dp, DPAUX_DP_AUXSTAT); 280 *aux_stat = tegra_dpaux_readl(dp, DPAUX_DP_AUXSTAT);
306 281
282 /* Ignore I2C errors on fpga */
283 if (tegra_platform_is_fpga())
284 *aux_stat &= ~DPAUX_DP_AUXSTAT_REPLYTYPE_I2CNACK;
285
307 if ((*aux_stat & DPAUX_DP_AUXSTAT_TIMEOUT_ERROR_PENDING) || 286 if ((*aux_stat & DPAUX_DP_AUXSTAT_TIMEOUT_ERROR_PENDING) ||
308 (*aux_stat & DPAUX_DP_AUXSTAT_RX_ERROR_PENDING) || 287 (*aux_stat & DPAUX_DP_AUXSTAT_RX_ERROR_PENDING) ||
309 (*aux_stat & DPAUX_DP_AUXSTAT_SINKSTAT_ERROR_PENDING) || 288 (*aux_stat & DPAUX_DP_AUXSTAT_SINKSTAT_ERROR_PENDING) ||
@@ -312,9 +291,13 @@ static int tegra_dc_dpaux_read_chunk(struct tegra_dc_dp_data *dp, u32 cmd,
312 dev_dbg(&dp->dc->ndev->dev, 291 dev_dbg(&dp->dc->ndev->dev,
313 "dp: aux read retry (0x%x) -- %d\n", 292 "dp: aux read retry (0x%x) -- %d\n",
314 *aux_stat, timeout_retries); 293 *aux_stat, timeout_retries);
294 /* clear the error bits */
295 tegra_dpaux_writel(dp, DPAUX_DP_AUXSTAT,
296 *aux_stat);
315 continue; /* retry */ 297 continue; /* retry */
316 } else { 298 } else {
317 dev_err(&dp->dc->ndev->dev, "dp: aux read got error (0x%x)\n", 299 dev_err(&dp->dc->ndev->dev,
300 "dp: aux read got error (0x%x)\n",
318 *aux_stat); 301 *aux_stat);
319 return -EFAULT; 302 return -EFAULT;
320 } 303 }
@@ -326,11 +309,14 @@ static int tegra_dc_dpaux_read_chunk(struct tegra_dc_dp_data *dp, u32 cmd,
326 dev_dbg(&dp->dc->ndev->dev, 309 dev_dbg(&dp->dc->ndev->dev,
327 "dp: aux read defer (0x%x) -- %d\n", 310 "dp: aux read defer (0x%x) -- %d\n",
328 *aux_stat, defer_retries); 311 *aux_stat, defer_retries);
312 /* clear the error bits */
313 tegra_dpaux_writel(dp, DPAUX_DP_AUXSTAT,
314 *aux_stat);
329 continue; 315 continue;
330 } else { 316 } else {
331 dev_err(&dp->dc->ndev->dev, 317 dev_err(&dp->dc->ndev->dev,
332 "dp: aux read defer exceeds max retries (0x%x)\n", 318 "dp: aux read defer exceeds max retries "
333 *aux_stat); 319 "(0x%x)\n", *aux_stat);
334 return -EFAULT; 320 return -EFAULT;
335 } 321 }
336 } 322 }
@@ -345,7 +331,7 @@ static int tegra_dc_dpaux_read_chunk(struct tegra_dc_dp_data *dp, u32 cmd,
345 DPAUX_DP_AUXDATA_READ_W(i)); 331 DPAUX_DP_AUXDATA_READ_W(i));
346 332
347 *size = ((*aux_stat) & DPAUX_DP_AUXSTAT_REPLY_M_MASK); 333 *size = ((*aux_stat) & DPAUX_DP_AUXSTAT_REPLY_M_MASK);
348 memcpy(temp_data, data, *size); 334 memcpy(data, temp_data, *size);
349 335
350 return 0; 336 return 0;
351 } else { 337 } else {
@@ -386,7 +372,7 @@ static int tegra_dc_dpaux_read(struct tegra_dc_dp_data *dp, u32 cmd, u32 addr,
386 return ret; 372 return ret;
387} 373}
388 374
389static inline int tegra_dc_dp_dpcd_read(struct tegra_dc_dp_data *dp, u32 cmd, 375static int tegra_dc_dp_dpcd_read(struct tegra_dc_dp_data *dp, u32 cmd,
390 u8 *data_ptr) 376 u8 *data_ptr)
391{ 377{
392 u32 size = 0; 378 u32 size = 0;
@@ -395,7 +381,7 @@ static inline int tegra_dc_dp_dpcd_read(struct tegra_dc_dp_data *dp, u32 cmd,
395 381
396 ret = tegra_dc_dpaux_read_chunk(dp, DPAUX_DP_AUXCTL_CMD_AUXRD, 382 ret = tegra_dc_dpaux_read_chunk(dp, DPAUX_DP_AUXCTL_CMD_AUXRD,
397 cmd, data_ptr, &size, &status); 383 cmd, data_ptr, &size, &status);
398 if (!ret) 384 if (ret)
399 dev_err(&dp->dc->ndev->dev, 385 dev_err(&dp->dc->ndev->dev,
400 "dp: Failed to read DPCD data. CMD 0x%x, Status 0x%x\n", 386 "dp: Failed to read DPCD data. CMD 0x%x, Status 0x%x\n",
401 cmd, status); 387 cmd, status);
@@ -403,7 +389,7 @@ static inline int tegra_dc_dp_dpcd_read(struct tegra_dc_dp_data *dp, u32 cmd,
403 return ret; 389 return ret;
404} 390}
405 391
406static inline int tegra_dc_dp_dpcd_write(struct tegra_dc_dp_data *dp, u32 cmd, 392static int tegra_dc_dp_dpcd_write(struct tegra_dc_dp_data *dp, u32 cmd,
407 u8 data) 393 u8 data)
408{ 394{
409 u32 size = 0; 395 u32 size = 0;
@@ -412,7 +398,7 @@ static inline int tegra_dc_dp_dpcd_write(struct tegra_dc_dp_data *dp, u32 cmd,
412 398
413 ret = tegra_dc_dpaux_write_chunk(dp, DPAUX_DP_AUXCTL_CMD_AUXWR, 399 ret = tegra_dc_dpaux_write_chunk(dp, DPAUX_DP_AUXCTL_CMD_AUXWR,
414 cmd, &data, &size, &status); 400 cmd, &data, &size, &status);
415 if (!ret) 401 if (ret)
416 dev_err(&dp->dc->ndev->dev, 402 dev_err(&dp->dc->ndev->dev,
417 "dp: Failed to read DPCD data. CMD 0x%x, Status 0x%x\n", 403 "dp: Failed to read DPCD data. CMD 0x%x, Status 0x%x\n",
418 cmd, status); 404 cmd, status);
@@ -427,41 +413,128 @@ static inline u64 tegra_div64(u64 dividend, u32 divisor)
427} 413}
428 414
429 415
430static int tegra_dc_init_max_link_cfg(struct tegra_dc_dp_data *dp, 416#ifdef CONFIG_DEBUG_FS
431 struct tegra_dc_dp_link_config *cfg) 417static int dbg_dp_show(struct seq_file *s, void *unused)
432{ 418{
433 u8 dpcd_data; 419 struct tegra_dc_dp_data *dp = s->private;
434 int ret;
435 420
436 CHECK_RET(tegra_dc_dp_dpcd_read(dp, NV_DPCD_MAX_LANE_COUNT, 421#define DUMP_REG(a) seq_printf(s, "%-32s %03x %08x\n", \
437 &dpcd_data)); 422 #a, a, tegra_dpaux_readl(dp, a))
438 cfg->max_lane_count = dpcd_data & NV_DPCD_MAX_LANE_COUNT_MASK;
439 423
440 cfg->support_enhanced_framing = 424 tegra_dc_io_start(dp->dc);
441 (dpcd_data & NV_DPCD_MAX_LANE_COUNT_ENHANCED_FRAMING_YES) ? 425 clk_prepare_enable(dp->clk);
442 true : false;
443 426
444 CHECK_RET(tegra_dc_dp_dpcd_read(dp, NV_DPCD_MAX_DOWNSPREAD, 427 DUMP_REG(DPAUX_INTR_EN_AUX);
445 &dpcd_data)); 428 DUMP_REG(DPAUX_INTR_AUX);
446 cfg->downspread = (dpcd_data & NV_DPCD_MAX_DOWNSPREAD_VAL_0_5_PCT) ? 429 DUMP_REG(DPAUX_DP_AUXADDR);
447 true : false; 430 DUMP_REG(DPAUX_DP_AUXCTL);
431 DUMP_REG(DPAUX_DP_AUXSTAT);
432 DUMP_REG(DPAUX_HPD_CONFIG);
433 DUMP_REG(DPAUX_HPD_IRQ_CONFIG);
434 DUMP_REG(DPAUX_DP_AUX_CONFIG);
435 DUMP_REG(DPAUX_HYBRID_PADCTL);
436 DUMP_REG(DPAUX_HYBRID_SPARE);
448 437
449 CHECK_RET(tegra_dc_dp_dpcd_read(dp, NV_DPCD_MAX_LINK_BANDWIDTH, 438 clk_disable_unprepare(dp->clk);
450 &cfg->max_link_bw)); 439 tegra_dc_io_end(dp->dc);
451 440
452 cfg->bytes_per_pixel = dp->dc->pdata->fb->bits_per_pixel / 8; 441 return 0;
442}
453 443
454 CHECK_RET(tegra_dc_dp_dpcd_read(dp, NV_DPCD_EDP_CONFIG_CAP, 444static int dbg_dp_open(struct inode *inode, struct file *file)
455 &dpcd_data)); 445{
456 cfg->alt_scramber_reset_cap = 446 return single_open(file, dbg_dp_show, inode->i_private);
457 (dpcd_data & NV_DPCD_EDP_CONFIG_CAP_ASC_RESET_YES) ? 447}
458 true : false;
459 cfg->only_enhanced_framing =
460 (dpcd_data & NV_DPCD_EDP_CONFIG_CAP_FRAMING_CHANGE_YES) ?
461 true : false;
462 448
463 return 0; 449static const struct file_operations dbg_fops = {
450 .open = dbg_dp_open,
451 .read = seq_read,
452 .llseek = seq_lseek,
453 .release = single_release,
454};
455
456static struct dentry *dpdir;
457
458static void tegra_dc_dp_debug_create(struct tegra_dc_dp_data *dp)
459{
460 struct dentry *retval;
461
462 dpdir = debugfs_create_dir("tegra_dp", NULL);
463 if (!dpdir)
464 return;
465 retval = debugfs_create_file("regs", S_IRUGO, dpdir, dp, &dbg_fops);
466 if (!retval)
467 goto free_out;
468 return;
469free_out:
470 debugfs_remove_recursive(dpdir);
471 dpdir = NULL;
472 return;
464} 473}
474#else
475static inline void tegra_dc_dp_debug_create(struct tegra_dc_dp_data *dp)
476{ }
477#endif
478
479static void tegra_dc_dpaux_enable(struct tegra_dc_dp_data *dp)
480{
481 /* clear interrupt */
482 tegra_dpaux_writel(dp, DPAUX_INTR_AUX, 0xffffffff);
483 /* do not enable interrupt for now. Enable them when Isr in place */
484 tegra_dpaux_writel(dp, DPAUX_INTR_EN_AUX, 0x0);
485
486 tegra_dpaux_writel(dp, DPAUX_HYBRID_PADCTL,
487 DPAUX_HYBRID_PADCTL_AUX_DRVZ_OHM_50 |
488 DPAUX_HYBRID_PADCTL_AUX_CMH_V0_70 |
489 0x18 << DPAUX_HYBRID_PADCTL_AUX_DRVI_SHIFT |
490 DPAUX_HYBRID_PADCTL_AUX_INPUT_RCV_ENABLE);
491}
492
493static void tegra_dc_dpaux_disable(struct tegra_dc_dp_data *dp)
494{
495 tegra_dpaux_writel(dp, NV_DPCD_SET_POWER,
496 NV_DPCD_SET_POWER_VAL_D3_PWRDWN);
497
498 /* TODO: power down DPAUX_HYBRID_SPARE too? */
499}
500
501static void tegra_dc_dp_dump_link_cfg(struct tegra_dc_dp_data *dp,
502 const struct tegra_dc_dp_link_config *cfg)
503{
504 BUG_ON(!cfg || !cfg->is_valid);
505
506 dev_info(&dp->dc->ndev->dev, "DP config: cfg_name cfg_value\n");
507 dev_info(&dp->dc->ndev->dev, " Lane Count %d\n",
508 cfg->max_lane_count);
509 dev_info(&dp->dc->ndev->dev, " SupportEnhancedFraming %s\n",
510 cfg->support_enhanced_framing ? "Y" : "N");
511 dev_info(&dp->dc->ndev->dev, " Bandwidth %d\n",
512 cfg->max_link_bw);
513 dev_info(&dp->dc->ndev->dev, " BPP %d\n",
514 cfg->bytes_per_pixel);
515 dev_info(&dp->dc->ndev->dev, " EnhancedFraming %s\n\n",
516 cfg->enhanced_framing ? "Y" : "N");
517 dev_info(&dp->dc->ndev->dev, " Scramble_enabled %s\n",
518 cfg->scramble_ena ? "Y" : "N");
519 dev_info(&dp->dc->ndev->dev, " LinkBW %d\n",
520 cfg->link_bw);
521 dev_info(&dp->dc->ndev->dev, " lane_count %d\n",
522 cfg->lane_count);
523 dev_info(&dp->dc->ndev->dev, " activespolarity %d\n",
524 cfg->activepolarity);
525 dev_info(&dp->dc->ndev->dev, " active_count %d\n",
526 cfg->active_count);
527 dev_info(&dp->dc->ndev->dev, " tu_size %d\n",
528 cfg->tu_size);
529 dev_info(&dp->dc->ndev->dev, " active_frac %d\n",
530 cfg->active_frac);
531 dev_info(&dp->dc->ndev->dev, " watermark %d\n",
532 cfg->watermark);
533 dev_info(&dp->dc->ndev->dev, " hblank_sym %d\n",
534 cfg->hblank_sym);
535 dev_info(&dp->dc->ndev->dev, " vblank_sym %d\n",
536 cfg->vblank_sym);
537};
465 538
466static bool tegra_dc_dp_lower_config(struct tegra_dc_dp_data *dp, 539static bool tegra_dc_dp_lower_config(struct tegra_dc_dp_data *dp,
467 struct tegra_dc_dp_link_config *cfg) 540 struct tegra_dc_dp_link_config *cfg)
@@ -530,7 +603,7 @@ static bool tegra_dc_dp_calc_config(struct tegra_dc_dp_data *dp,
530 (u64)link_rate * mode->h_active, mode->pclk); 603 (u64)link_rate * mode->h_active, mode->pclk);
531 604
532 ratio_f = (u64)mode->pclk * cfg->bytes_per_pixel * f; 605 ratio_f = (u64)mode->pclk * cfg->bytes_per_pixel * f;
533 ratio_f /= 8; 606 /* ratio_f /= 8; */
534 ratio_f = tegra_div64(ratio_f, link_rate * cfg->lane_count); 607 ratio_f = tegra_div64(ratio_f, link_rate * cfg->lane_count);
535 608
536 for (i = 64; i >= 32; --i) { 609 for (i = 64; i >= 32; --i) {
@@ -611,11 +684,11 @@ static bool tegra_dc_dp_calc_config(struct tegra_dc_dp_data *dp,
611 cfg->activepolarity, cfg->active_count, cfg->tu_size, 684 cfg->activepolarity, cfg->active_count, cfg->tu_size,
612 cfg->active_frac); 685 cfg->active_frac);
613 686
614 watermark_f = ratio_f * cfg->tu_size * tegra_div64(f - ratio_f, f); 687 watermark_f = tegra_div64(ratio_f * cfg->tu_size * (f - ratio_f), f);
615 cfg->watermark = 2*((cfg->bytes_per_pixel) * f / 8) + watermark_f + 688 cfg->watermark = (u32)tegra_div64(watermark_f + lowest_neg_error_f,
616 (u32)tegra_div64(lowest_neg_error_f, (u32)f) - 1; 689 f) + 2 * cfg->bytes_per_pixel - 1;
617 num_symbols_per_line = (mode->h_active * cfg->bytes_per_pixel) / 690 num_symbols_per_line = (mode->h_active * cfg->bytes_per_pixel) /
618 (8 * cfg->lane_count); 691 cfg->lane_count;
619 if (cfg->watermark > 30) { 692 if (cfg->watermark > 30) {
620 dev_dbg(&dp->dc->ndev->dev, 693 dev_dbg(&dp->dc->ndev->dev,
621 "dp: sor setting: unable to get a good tusize, " 694 "dp: sor setting: unable to get a good tusize, "
@@ -635,7 +708,7 @@ static bool tegra_dc_dp_calc_config(struct tegra_dc_dp_data *dp,
635 /* SetRasterBlankStart.X - 7) * link_clk / pclk) */ 708 /* SetRasterBlankStart.X - 7) * link_clk / pclk) */
636 /* - 3 * enhanced_framing - Y */ 709 /* - 3 * enhanced_framing - Y */
637 /* where Y = (# lanes == 4) 3 : (# lanes == 2) ? 6 : 12 */ 710 /* where Y = (# lanes == 4) 3 : (# lanes == 2) ? 6 : 12 */
638 cfg->hblank_sym = tegra_div64((u64)(mode->h_back_porch + 711 cfg->hblank_sym = (int)tegra_div64((u64)(mode->h_back_porch +
639 mode->h_front_porch + mode->h_sync_width - 7) 712 mode->h_front_porch + mode->h_sync_width - 7)
640 * link_rate, mode->pclk) 713 * link_rate, mode->pclk)
641 - 3 * cfg->enhanced_framing - (12 / cfg->lane_count); 714 - 3 * cfg->enhanced_framing - (12 / cfg->lane_count);
@@ -645,19 +718,68 @@ static bool tegra_dc_dp_calc_config(struct tegra_dc_dp_data *dp,
645 718
646 719
647 /* Refer to dev_disp.ref for more information. */ 720 /* Refer to dev_disp.ref for more information. */
648 /* # symbols/vblank = ((SetRasterBlankEnd.X + SetRasterSize.Width - */ 721 /* # symbols/vblank = ((SetRasterBlankStart.X - */
649 /* SetRasterBlankStart.X - 7) * link_clk / pclk) */ 722 /* SetRasterBlankEen.X - 25) * link_clk / pclk) */
650 /* - Y - 1; */ 723 /* - Y - 1; */
651 /* where Y = (# lanes == 4) 12 : (# lanes == 2) ? 21 : 39 */ 724 /* where Y = (# lanes == 4) 12 : (# lanes == 2) ? 21 : 39 */
652 cfg->vblank_sym = tegra_div64((u64)(mode->v_back_porch + 725 cfg->vblank_sym = (int)tegra_div64((u64)(mode->h_active - 25)
653 mode->v_front_porch + mode->v_sync_width - 25)
654 * link_rate, mode->pclk) - (36 / cfg->lane_count) - 4; 726 * link_rate, mode->pclk) - (36 / cfg->lane_count) - 4;
655 727
656 if (cfg->vblank_sym < 0) 728 if (cfg->vblank_sym < 0)
657 cfg->vblank_sym = 0; 729 cfg->vblank_sym = 0;
730
731 cfg->is_valid = true;
732 tegra_dc_dp_dump_link_cfg(dp, cfg);
733
658 return true; 734 return true;
659} 735}
660 736
737static int tegra_dc_dp_init_max_link_cfg(struct tegra_dc_dp_data *dp,
738 struct tegra_dc_dp_link_config *cfg)
739{
740 u8 dpcd_data;
741 int ret;
742
743 CHECK_RET(tegra_dc_dp_dpcd_read(dp, NV_DPCD_MAX_LANE_COUNT,
744 &dpcd_data));
745
746 cfg->max_lane_count = dpcd_data & NV_DPCD_MAX_LANE_COUNT_MASK;
747
748 cfg->support_enhanced_framing =
749 (dpcd_data & NV_DPCD_MAX_LANE_COUNT_ENHANCED_FRAMING_YES) ?
750 true : false;
751
752 CHECK_RET(tegra_dc_dp_dpcd_read(dp, NV_DPCD_MAX_DOWNSPREAD,
753 &dpcd_data));
754 cfg->downspread = (dpcd_data & NV_DPCD_MAX_DOWNSPREAD_VAL_0_5_PCT) ?
755 true : false;
756
757 CHECK_RET(tegra_dc_dp_dpcd_read(dp, NV_DPCD_MAX_LINK_BANDWIDTH,
758 &cfg->max_link_bw));
759
760 cfg->bytes_per_pixel = dp->dc->pdata->fb->bits_per_pixel / 8;
761
762 CHECK_RET(tegra_dc_dp_dpcd_read(dp, NV_DPCD_EDP_CONFIG_CAP,
763 &dpcd_data));
764 cfg->alt_scramber_reset_cap =
765 (dpcd_data & NV_DPCD_EDP_CONFIG_CAP_ASC_RESET_YES) ?
766 true : false;
767 cfg->only_enhanced_framing =
768 (dpcd_data & NV_DPCD_EDP_CONFIG_CAP_FRAMING_CHANGE_YES) ?
769 true : false;
770
771 if (tegra_platform_is_fpga()) /* hardcoded to 1.62G on fpga */
772 cfg->max_link_bw = SOR_LINK_SPEED_G1_62;
773 cfg->lane_count = cfg->max_lane_count;
774 cfg->link_bw = cfg->max_link_bw;
775 cfg->enhanced_framing = cfg->support_enhanced_framing;
776
777 tegra_dc_dp_calc_config(dp, dp->mode, cfg);
778 tegra_dc_dp_dump_link_cfg(dp, cfg);
779
780 return 0;
781}
782
661static int tegra_dc_dp_set_assr(struct tegra_dc_dp_data *dp, bool ena) 783static int tegra_dc_dp_set_assr(struct tegra_dc_dp_data *dp, bool ena)
662{ 784{
663 int ret; 785 int ret;
@@ -699,7 +821,6 @@ static int tegra_dp_set_lane_count(struct tegra_dc_dp_data *dp,
699 tegra_dc_sor_set_lane_count(dp->sor, cfg->lane_count); 821 tegra_dc_sor_set_lane_count(dp->sor, cfg->lane_count);
700 822
701 /* Also power down lanes that will not be used */ 823 /* Also power down lanes that will not be used */
702 return tegra_dc_sor_power_dplanes(dp->sor, cfg->lane_count);
703} 824}
704 825
705static int tegra_dc_dp_set_lane_config(struct tegra_dc_dp_data *dp, 826static int tegra_dc_dp_set_lane_config(struct tegra_dc_dp_data *dp,
@@ -1047,7 +1168,7 @@ static int tegra_dc_dp_link_training(struct tegra_dc_dp_data *dp,
1047} 1168}
1048 1169
1049static bool tegra_dc_dp_link_trained(struct tegra_dc_dp_data *dp, 1170static bool tegra_dc_dp_link_trained(struct tegra_dc_dp_data *dp,
1050 struct tegra_dc_dp_link_config *cfg) 1171 const struct tegra_dc_dp_link_config *cfg)
1051{ 1172{
1052 u32 lane; 1173 u32 lane;
1053 u8 mask; 1174 u8 mask;
@@ -1073,34 +1194,40 @@ static bool tegra_dc_dp_link_trained(struct tegra_dc_dp_data *dp,
1073 1194
1074 1195
1075static int tegra_dc_dp_fast_link_training(struct tegra_dc_dp_data *dp, 1196static int tegra_dc_dp_fast_link_training(struct tegra_dc_dp_data *dp,
1076 struct tegra_dc_dp_link_config *cfg) 1197 const struct tegra_dc_dp_link_config *cfg)
1077{ 1198{
1078 struct tegra_dc_sor_data *sor = dp->sor; 1199 struct tegra_dc_sor_data *sor = dp->sor;
1079 int ret; 1200 u8 link_bw;
1201 u8 lane_count;
1080 1202
1203 BUG_ON(!cfg || !cfg->is_valid);
1081 tegra_dc_sor_set_link_bandwidth(sor, cfg->link_bw); 1204 tegra_dc_sor_set_link_bandwidth(sor, cfg->link_bw);
1082 tegra_dc_sor_set_lane_count(sor, cfg->lane_count); 1205 tegra_dc_sor_set_lane_count(sor, cfg->lane_count);
1083 1206
1084 /* Send TP1 */ 1207 /* Send TP1 */
1085 tegra_dc_sor_set_dp_linkctl(sor, true, trainingPattern_1, cfg, 1208 tegra_dc_sor_set_dp_linkctl(sor, true, trainingPattern_1, cfg);
1086 false);
1087 1209
1088 usleep_range(500, 1000); 1210 usleep_range(500, 1000);
1089 /* enable ASSR */ 1211 /* enable ASSR */
1090 tegra_dc_dp_set_assr(dp, true); 1212 tegra_dc_dp_set_assr(dp, true);
1091 tegra_dc_sor_set_dp_linkctl(sor, true, trainingPattern_2, cfg, 1213 tegra_dc_sor_set_dp_linkctl(sor, true, trainingPattern_2, cfg);
1092 true);
1093 1214
1094 usleep_range(500, 1000); 1215 usleep_range(500, 1000);
1095 tegra_dc_sor_set_dp_linkctl(sor, true, trainingPattern_Disabled, 1216 tegra_dc_sor_set_dp_linkctl(sor, true, trainingPattern_Disabled, cfg);
1096 cfg, false); 1217
1218 if (!tegra_dc_dp_link_trained(dp, cfg)) {
1219 tegra_dc_sor_read_link_config(dp->sor, &link_bw,
1220 &lane_count);
1221 dev_info(&dp->dc->ndev->dev,
1222 "Fast link trainging failed, link bw %d, lane # %d\n",
1223 link_bw, lane_count);
1224 return -EFAULT;
1225 } else
1226 dev_dbg(&dp->dc->ndev->dev,
1227 "Fast link trainging succeeded, link bw %d, lane %d\n",
1228 cfg->link_bw, cfg->lane_count);
1097 1229
1098 ret = tegra_dc_dp_link_trained(dp, cfg); 1230 return 0;
1099 if (!ret) {
1100 tegra_dc_sor_read_link_config(dp->sor, &cfg->link_bw,
1101 &cfg->lane_count);
1102 }
1103 return ret;
1104} 1231}
1105 1232
1106static int tegra_dp_link_config(struct tegra_dc_dp_data *dp, 1233static int tegra_dp_link_config(struct tegra_dc_dp_data *dp,
@@ -1125,7 +1252,7 @@ static int tegra_dp_link_config(struct tegra_dc_dp_data *dp,
1125 do { 1252 do {
1126 ret = tegra_dc_dp_dpcd_write(dp, 1253 ret = tegra_dc_dp_dpcd_write(dp,
1127 NV_DPCD_SET_POWER, dpcd_data); 1254 NV_DPCD_SET_POWER, dpcd_data);
1128 } while ((--retry > 0) && (ret != 0)); 1255 } while ((--retry > 0) && ret);
1129 if (ret) { 1256 if (ret) {
1130 dev_err(&dp->dc->ndev->dev, 1257 dev_err(&dp->dc->ndev->dev,
1131 "dp: Failed to set DP panel power\n"); 1258 "dp: Failed to set DP panel power\n");
@@ -1147,13 +1274,13 @@ static int tegra_dp_link_config(struct tegra_dc_dp_data *dp,
1147 dev_err(&dp->dc->ndev->dev, "dp: Failed to set lane count\n"); 1274 dev_err(&dp->dc->ndev->dev, "dp: Failed to set lane count\n");
1148 return ret; 1275 return ret;
1149 } 1276 }
1150 tegra_dc_sor_set_dp_linkctl(dp->sor, true, trainingPattern_Disabled, 1277 tegra_dc_dp_dump_link_cfg(dp, cfg);
1151 cfg, true); 1278 tegra_dc_sor_set_dp_linkctl(dp->sor, true, trainingPattern_None, cfg);
1152 1279
1153 /* Now do the link training */ 1280 /* Now do the fast link training for eDP */
1154 ret = tegra_dc_dp_link_training(dp, cfg); 1281 ret = tegra_dc_dp_fast_link_training(dp, cfg);
1155 if (ret) { 1282 if (ret) {
1156 dev_dbg(&dp->dc->ndev->dev, "dp: link training failed\n"); 1283 dev_err(&dp->dc->ndev->dev, "dp: fast link training failed\n");
1157 return ret; 1284 return ret;
1158 } 1285 }
1159 1286
@@ -1184,7 +1311,7 @@ static int tegra_dc_dp_explore_link_cfg(struct tegra_dc_dp_data *dp,
1184 } 1311 }
1185 1312
1186 cfg->is_valid = false; 1313 cfg->is_valid = false;
1187 memcpy(cfg, &temp_cfg, sizeof(temp_cfg)); 1314 memcpy(&temp_cfg, cfg, sizeof(temp_cfg));
1188 1315
1189 temp_cfg.link_bw = temp_cfg.max_link_bw; 1316 temp_cfg.link_bw = temp_cfg.max_link_bw;
1190 temp_cfg.lane_count = temp_cfg.max_lane_count; 1317 temp_cfg.lane_count = temp_cfg.max_lane_count;
@@ -1192,8 +1319,7 @@ static int tegra_dc_dp_explore_link_cfg(struct tegra_dc_dp_data *dp,
1192 while (tegra_dc_dp_calc_config(dp, mode, &temp_cfg) && 1319 while (tegra_dc_dp_calc_config(dp, mode, &temp_cfg) &&
1193 tegra_dp_link_config(dp, &temp_cfg)) { 1320 tegra_dp_link_config(dp, &temp_cfg)) {
1194 /* current link cfg is doable */ 1321 /* current link cfg is doable */
1195 memcpy(&temp_cfg, cfg, sizeof(temp_cfg)); 1322 memcpy(cfg, &temp_cfg, sizeof(temp_cfg));
1196 cfg->is_valid = true;
1197 1323
1198 /* try to lower the config */ 1324 /* try to lower the config */
1199 if (!tegra_dc_dp_lower_config(dp, &temp_cfg)) 1325 if (!tegra_dc_dp_lower_config(dp, &temp_cfg))
@@ -1211,10 +1337,10 @@ static void tegra_dc_dp_lt_worker(struct work_struct *work)
1211 tegra_dc_disable(dp->dc); 1337 tegra_dc_disable(dp->dc);
1212 1338
1213 if (!dp->link_cfg.is_valid || 1339 if (!dp->link_cfg.is_valid ||
1214 !tegra_dp_link_config(dp, &dp->link_cfg)) { 1340 tegra_dp_link_config(dp, &dp->link_cfg)) {
1215 /* If current config is not valid or cannot be trained, 1341 /* If current config is not valid or cannot be trained,
1216 needs to re-explore the possilbe config */ 1342 needs to re-explore the possilbe config */
1217 if (tegra_dc_init_max_link_cfg(dp, &dp->link_cfg)) 1343 if (tegra_dc_dp_init_max_link_cfg(dp, &dp->link_cfg))
1218 dev_err(&dp->dc->ndev->dev, 1344 dev_err(&dp->dc->ndev->dev,
1219 "dp: failed to init link configuration\n"); 1345 "dp: failed to init link configuration\n");
1220 else if (tegra_dc_dp_explore_link_cfg(dp, &dp->link_cfg, 1346 else if (tegra_dc_dp_explore_link_cfg(dp, &dp->link_cfg,
@@ -1273,7 +1399,7 @@ static int tegra_dc_dp_init(struct tegra_dc *dc)
1273 if (!dp) 1399 if (!dp)
1274 return -ENOMEM; 1400 return -ENOMEM;
1275 1401
1276 res = nvhost_get_resource_byname(dc->ndev, IORESOURCE_MEM, "dpaux"); 1402 res = platform_get_resource_byname(dc->ndev, IORESOURCE_MEM, "dpaux");
1277 if (!res) { 1403 if (!res) {
1278 dev_err(&dc->ndev->dev, "dp: no mem resources for dpaux\n"); 1404 dev_err(&dc->ndev->dev, "dp: no mem resources for dpaux\n");
1279 err = -EFAULT; 1405 err = -EFAULT;
@@ -1295,7 +1421,7 @@ static int tegra_dc_dp_init(struct tegra_dc *dc)
1295 goto err_release_resource_reg; 1421 goto err_release_resource_reg;
1296 } 1422 }
1297 1423
1298 clk = clk_get(&dc->ndev->dev, "edp"); 1424 clk = clk_get_sys("dpaux", NULL);
1299 if (IS_ERR_OR_NULL(clk)) { 1425 if (IS_ERR_OR_NULL(clk)) {
1300 dev_err(&dc->ndev->dev, "dp: dc clock %s.edp unavailable\n", 1426 dev_err(&dc->ndev->dev, "dp: dc clock %s.edp unavailable\n",
1301 dev_name(&dc->ndev->dev)); 1427 dev_name(&dc->ndev->dev));
@@ -1332,6 +1458,7 @@ static int tegra_dc_dp_init(struct tegra_dc *dc)
1332 INIT_WORK(&dp->lt_work, tegra_dc_dp_lt_worker); 1458 INIT_WORK(&dp->lt_work, tegra_dc_dp_lt_worker);
1333 1459
1334 tegra_dc_set_outdata(dc, dp); 1460 tegra_dc_set_outdata(dc, dp);
1461 tegra_dc_dp_debug_create(dp);
1335 1462
1336 return 0; 1463 return 0;
1337 1464
@@ -1354,16 +1481,23 @@ static void tegra_dc_dp_enable(struct tegra_dc *dc)
1354 u32 retry; 1481 u32 retry;
1355 int ret; 1482 int ret;
1356 1483
1484 if (!tegra_is_clk_enabled(dp->clk))
1485 clk_prepare_enable(dp->clk);
1486
1357 tegra_dc_dpaux_enable(dp); 1487 tegra_dc_dpaux_enable(dp);
1358 clk_enable(dp->clk);
1359 1488
1360 /* Power on panel */ 1489 /* Power on panel */
1361 tegra_dc_sor_set_panel_power(dp->sor, true); 1490 tegra_dc_sor_set_panel_power(dp->sor, true);
1362 1491
1363 /* TODO: power on lanes as well? */ 1492 if (tegra_dc_dp_init_max_link_cfg(dp, &dp->link_cfg)) {
1493 dev_err(&dc->ndev->dev,
1494 "dp: failed to init link configuration\n");
1495 goto error_enable;
1496 }
1364 1497
1365 /* Enable backlight -- TODO: need to go through I2C */ 1498 tegra_dc_sor_enable_dp(dp->sor);
1366 1499
1500 /* Enable backlight -- TODO: need to go through I2C */
1367 msleep(DP_LCDVCC_TO_HPD_DELAY_MS); 1501 msleep(DP_LCDVCC_TO_HPD_DELAY_MS);
1368 1502
1369 /* Write power on to DPCD */ 1503 /* Write power on to DPCD */
@@ -1381,39 +1515,30 @@ static void tegra_dc_dp_enable(struct tegra_dc *dc)
1381 } 1515 }
1382 1516
1383 /* Confirm DP is plugging status */ 1517 /* Confirm DP is plugging status */
1384#ifndef CONFIG_TEGRA_SIMULATION_PLATFORM 1518 if (tegra_platform_is_silicon() &&
1385 if (!(tegra_dpaux_readl(dp, DPAUX_DP_AUXSTAT) & 1519 !(tegra_dpaux_readl(dp, DPAUX_DP_AUXSTAT) &
1386 DPAUX_DP_AUXSTAT_HPD_STATUS_PLUGGED)) { 1520 DPAUX_DP_AUXSTAT_HPD_STATUS_PLUGGED)) {
1387 dev_err(&dp->dc->ndev->dev, "dp: could not detect HPD\n"); 1521 dev_err(&dp->dc->ndev->dev, "dp: could not detect HPD\n");
1388 return; 1522 return;
1389 } 1523 }
1390#endif
1391 1524
1392 /* Check DP version */ 1525 /* Check DP version */
1393 if (tegra_dc_dp_dpcd_read(dp, NV_DPCD_REV, &dp->revision)) 1526 if (tegra_dc_dp_dpcd_read(dp, NV_DPCD_REV, &dp->revision))
1394 dev_err(&dp->dc->ndev->dev, 1527 dev_err(&dp->dc->ndev->dev,
1395 "dp: failed to read the revision number from sink\n"); 1528 "dp: failed to read the revision number from sink\n");
1396 1529
1397 if (!dp->link_cfg.is_valid || 1530 if (tegra_dp_link_config(dp, &dp->link_cfg)) {
1398 tegra_dc_dp_fast_link_training(dp, &dp->link_cfg)) { 1531 dev_err(&dp->dc->ndev->dev, "dp: Could not setup link\n");
1399 /* if valid link config is not ready yet, or current 1532 return;
1400 config cannot be link-trained, try to find the
1401 new minimal config */
1402 if (tegra_dc_init_max_link_cfg(dp, &dp->link_cfg)) {
1403 dev_err(&dp->dc->ndev->dev,
1404 "dp: failed to init link configuration\n");
1405 return;
1406 }
1407 if (tegra_dc_dp_explore_link_cfg(dp, &dp->link_cfg, dp->mode) ||
1408 tegra_dc_dp_link_training(dp, &dp->link_cfg)) {
1409 dev_err(&dp->dc->ndev->dev,
1410 "dp: Current mode is not possible\n");
1411 return;
1412 }
1413 } 1533 }
1414 1534
1415 /* enable SOR by programming the watermark/v/hblank_sym etc */ 1535 tegra_dc_dp_explore_link_cfg(dp, &dp->link_cfg, dp->mode);
1416 tegra_dc_sor_enable_dp(dp->sor); 1536
1537 mdelay(100);
1538 tegra_dc_sor_attach(dp->sor);
1539
1540error_enable:
1541 return;
1417} 1542}
1418 1543
1419static void tegra_dc_dp_destroy(struct tegra_dc *dc) 1544static void tegra_dc_dp_destroy(struct tegra_dc *dc)
@@ -1444,24 +1569,55 @@ static void tegra_dc_dp_disable(struct tegra_dc *dc)
1444 /* Make sure the timing meet the eDP specs */ 1569 /* Make sure the timing meet the eDP specs */
1445} 1570}
1446 1571
1572extern struct clk *tegra_get_clock_by_name(const char *name);
1573
1574static long tegra_dc_dp_setup_clk(struct tegra_dc *dc, struct clk *clk)
1575{
1576 struct tegra_dc_dp_data *dp = tegra_dc_get_outdata(dc);
1577 struct clk *sor_clk = dp->sor->sor_clk;
1578 struct clk *parent_clk;
1579
1580 tegra_dc_sor_setup_clk(dp->sor, clk, false);
1581
1582 parent_clk = tegra_get_clock_by_name("pll_dp");
1583
1584 if (clk_get_parent(sor_clk) != parent_clk)
1585 clk_set_parent(sor_clk, parent_clk);
1586 clk_set_rate(parent_clk, 270000000);
1587
1588 if (!tegra_is_clk_enabled(parent_clk))
1589 clk_prepare_enable(parent_clk);
1590
1591 return tegra_dc_pclk_round_rate(dc, dp->sor->dc->mode.pclk);
1592}
1447 1593
1448 1594
1449static void tegra_dc_dp_suspend(struct tegra_dc *dc) 1595static void tegra_dc_dp_suspend(struct tegra_dc *dc)
1450{ 1596{
1451 /* TBD */ 1597 struct tegra_dc_dp_data *dp = tegra_dc_get_outdata(dc);
1598
1599 tegra_dc_dp_disable(dc);
1600 dp->suspended = true;
1452} 1601}
1453 1602
1454 1603
1455static void tegra_dc_dp_resume(struct tegra_dc *dc) 1604static void tegra_dc_dp_resume(struct tegra_dc *dc)
1456{ 1605{
1457 /* TBD */ 1606 struct tegra_dc_dp_data *dp = tegra_dc_get_outdata(dc);
1607
1608 if (!dp->suspended)
1609 return;
1610 tegra_dc_dp_enable(dc);
1458} 1611}
1459 1612
1460struct tegra_dc_out_ops tegra_dc_dp_ops = { 1613struct tegra_dc_out_ops tegra_dc_dp_ops = {
1461 .init = tegra_dc_dp_init, 1614 .init = tegra_dc_dp_init,
1462 .destroy = tegra_dc_dp_destroy, 1615 .destroy = tegra_dc_dp_destroy,
1463 .enable = tegra_dc_dp_enable, 1616 .enable = tegra_dc_dp_enable,
1464 .disable = tegra_dc_dp_disable, 1617 .disable = tegra_dc_dp_disable,
1465 .suspend = tegra_dc_dp_suspend, 1618 .suspend = tegra_dc_dp_suspend,
1466 .resume = tegra_dc_dp_resume, 1619 .resume = tegra_dc_dp_resume,
1620 .setup_clk = tegra_dc_dp_setup_clk,
1467}; 1621};
1622
1623