aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2014-04-05 02:13:08 -0400
committerDave Airlie <airlied@redhat.com>2014-04-05 02:13:08 -0400
commit82c68b6ccd54117a87cb2d9b91c2ee6e1280cf9d (patch)
treef7835f0e4a1884253cbd46bfdb7cbc4fa920b6cc /drivers/gpu
parent243b930f8b228428c2a14ebbb09045041ed0bc70 (diff)
parentd105a6c97e43e35fd4f852928bb8a19df235c6e7 (diff)
Merge tag 'drm/tegra/for-3.15-rc1' of git://anongit.freedesktop.org/tegra/linux into drm-next
drm/tegra: Changes for v3.15-rc1 Implement eDP support for Tegra124 and support the PRIME vmap()/vunmap() operations. A symbol that is required for upcoming V4L2 support is now exported by the host1x driver. Relicense drivers under the GPL v2 for consistency. One exception is the public header file, which is relicensed under MIT to abide by the common rule. * tag 'drm/tegra/for-3.15-rc1' of git://anongit.freedesktop.org/tegra/linux: drm/tegra: Use standard GPL v2 license text drm/tegra: Relicense under GPL v2 drm/tegra: Relicense public header under MIT drm/tegra: Add eDP support gpu: host1x: export host1x_syncpt_incr_max() function drm/tegra: prime: Add vmap support
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/tegra/Makefile2
-rw-r--r--drivers/gpu/drm/tegra/dc.h1
-rw-r--r--drivers/gpu/drm/tegra/dpaux.c544
-rw-r--r--drivers/gpu/drm/tegra/dpaux.h73
-rw-r--r--drivers/gpu/drm/tegra/drm.c19
-rw-r--r--drivers/gpu/drm/tegra/drm.h20
-rw-r--r--drivers/gpu/drm/tegra/dsi.c20
-rw-r--r--drivers/gpu/drm/tegra/dsi.h20
-rw-r--r--drivers/gpu/drm/tegra/gem.c25
-rw-r--r--drivers/gpu/drm/tegra/gem.h14
-rw-r--r--drivers/gpu/drm/tegra/gr2d.c14
-rw-r--r--drivers/gpu/drm/tegra/mipi-phy.c20
-rw-r--r--drivers/gpu/drm/tegra/mipi-phy.h20
-rw-r--r--drivers/gpu/drm/tegra/output.c8
-rw-r--r--drivers/gpu/drm/tegra/sor.c1092
-rw-r--r--drivers/gpu/drm/tegra/sor.h278
-rw-r--r--drivers/gpu/host1x/syncpt.c1
17 files changed, 2071 insertions, 100 deletions
diff --git a/drivers/gpu/drm/tegra/Makefile b/drivers/gpu/drm/tegra/Makefile
index 8d220afbd85f..d43f21bb4596 100644
--- a/drivers/gpu/drm/tegra/Makefile
+++ b/drivers/gpu/drm/tegra/Makefile
@@ -11,6 +11,8 @@ tegra-drm-y := \
11 hdmi.o \ 11 hdmi.o \
12 mipi-phy.o \ 12 mipi-phy.o \
13 dsi.o \ 13 dsi.o \
14 sor.o \
15 dpaux.o \
14 gr2d.o \ 16 gr2d.o \
15 gr3d.o 17 gr3d.o
16 18
diff --git a/drivers/gpu/drm/tegra/dc.h b/drivers/gpu/drm/tegra/dc.h
index 3c2c0ea1cd87..c94101494826 100644
--- a/drivers/gpu/drm/tegra/dc.h
+++ b/drivers/gpu/drm/tegra/dc.h
@@ -118,6 +118,7 @@
118#define DC_DISP_DISP_WIN_OPTIONS 0x402 118#define DC_DISP_DISP_WIN_OPTIONS 0x402
119#define HDMI_ENABLE (1 << 30) 119#define HDMI_ENABLE (1 << 30)
120#define DSI_ENABLE (1 << 29) 120#define DSI_ENABLE (1 << 29)
121#define SOR_ENABLE (1 << 25)
121 122
122#define DC_DISP_DISP_MEM_HIGH_PRIORITY 0x403 123#define DC_DISP_DISP_MEM_HIGH_PRIORITY 0x403
123#define CURSOR_THRESHOLD(x) (((x) & 0x03) << 24) 124#define CURSOR_THRESHOLD(x) (((x) & 0x03) << 24)
diff --git a/drivers/gpu/drm/tegra/dpaux.c b/drivers/gpu/drm/tegra/dpaux.c
new file mode 100644
index 000000000000..d536ed381fbd
--- /dev/null
+++ b/drivers/gpu/drm/tegra/dpaux.c
@@ -0,0 +1,544 @@
1/*
2 * Copyright (C) 2013 NVIDIA Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/clk.h>
10#include <linux/delay.h>
11#include <linux/gpio.h>
12#include <linux/interrupt.h>
13#include <linux/io.h>
14#include <linux/of_gpio.h>
15#include <linux/platform_device.h>
16#include <linux/reset.h>
17#include <linux/regulator/consumer.h>
18
19#include <drm/drm_dp_helper.h>
20#include <drm/drm_panel.h>
21
22#include "dpaux.h"
23#include "drm.h"
24
25static DEFINE_MUTEX(dpaux_lock);
26static LIST_HEAD(dpaux_list);
27
28struct tegra_dpaux {
29 struct drm_dp_aux aux;
30 struct device *dev;
31
32 void __iomem *regs;
33 int irq;
34
35 struct tegra_output *output;
36
37 struct reset_control *rst;
38 struct clk *clk_parent;
39 struct clk *clk;
40
41 struct regulator *vdd;
42
43 struct completion complete;
44 struct list_head list;
45};
46
47static inline struct tegra_dpaux *to_dpaux(struct drm_dp_aux *aux)
48{
49 return container_of(aux, struct tegra_dpaux, aux);
50}
51
52static inline unsigned long tegra_dpaux_readl(struct tegra_dpaux *dpaux,
53 unsigned long offset)
54{
55 return readl(dpaux->regs + (offset << 2));
56}
57
58static inline void tegra_dpaux_writel(struct tegra_dpaux *dpaux,
59 unsigned long value,
60 unsigned long offset)
61{
62 writel(value, dpaux->regs + (offset << 2));
63}
64
65static void tegra_dpaux_write_fifo(struct tegra_dpaux *dpaux, const u8 *buffer,
66 size_t size)
67{
68 unsigned long offset = DPAUX_DP_AUXDATA_WRITE(0);
69 size_t i, j;
70
71 for (i = 0; i < size; i += 4) {
72 size_t num = min_t(size_t, size - i, 4);
73 unsigned long value = 0;
74
75 for (j = 0; j < num; j++)
76 value |= buffer[i + j] << (j * 8);
77
78 tegra_dpaux_writel(dpaux, value, offset++);
79 }
80}
81
82static void tegra_dpaux_read_fifo(struct tegra_dpaux *dpaux, u8 *buffer,
83 size_t size)
84{
85 unsigned long offset = DPAUX_DP_AUXDATA_READ(0);
86 size_t i, j;
87
88 for (i = 0; i < size; i += 4) {
89 size_t num = min_t(size_t, size - i, 4);
90 unsigned long value;
91
92 value = tegra_dpaux_readl(dpaux, offset++);
93
94 for (j = 0; j < num; j++)
95 buffer[i + j] = value >> (j * 8);
96 }
97}
98
99static ssize_t tegra_dpaux_transfer(struct drm_dp_aux *aux,
100 struct drm_dp_aux_msg *msg)
101{
102 unsigned long value = DPAUX_DP_AUXCTL_TRANSACTREQ;
103 unsigned long timeout = msecs_to_jiffies(250);
104 struct tegra_dpaux *dpaux = to_dpaux(aux);
105 unsigned long status;
106 ssize_t ret = 0;
107
108 if (msg->size < 1 || msg->size > 16)
109 return -EINVAL;
110
111 tegra_dpaux_writel(dpaux, msg->address, DPAUX_DP_AUXADDR);
112
113 switch (msg->request & ~DP_AUX_I2C_MOT) {
114 case DP_AUX_I2C_WRITE:
115 if (msg->request & DP_AUX_I2C_MOT)
116 value = DPAUX_DP_AUXCTL_CMD_MOT_WR;
117 else
118 value = DPAUX_DP_AUXCTL_CMD_I2C_WR;
119
120 break;
121
122 case DP_AUX_I2C_READ:
123 if (msg->request & DP_AUX_I2C_MOT)
124 value = DPAUX_DP_AUXCTL_CMD_MOT_RD;
125 else
126 value = DPAUX_DP_AUXCTL_CMD_I2C_RD;
127
128 break;
129
130 case DP_AUX_I2C_STATUS:
131 if (msg->request & DP_AUX_I2C_MOT)
132 value = DPAUX_DP_AUXCTL_CMD_MOT_RQ;
133 else
134 value = DPAUX_DP_AUXCTL_CMD_I2C_RQ;
135
136 break;
137
138 case DP_AUX_NATIVE_WRITE:
139 value = DPAUX_DP_AUXCTL_CMD_AUX_WR;
140 break;
141
142 case DP_AUX_NATIVE_READ:
143 value = DPAUX_DP_AUXCTL_CMD_AUX_RD;
144 break;
145
146 default:
147 return -EINVAL;
148 }
149
150 value |= DPAUX_DP_AUXCTL_CMDLEN(msg->size - 1);
151 tegra_dpaux_writel(dpaux, value, DPAUX_DP_AUXCTL);
152
153 if ((msg->request & DP_AUX_I2C_READ) == 0) {
154 tegra_dpaux_write_fifo(dpaux, msg->buffer, msg->size);
155 ret = msg->size;
156 }
157
158 /* start transaction */
159 value = tegra_dpaux_readl(dpaux, DPAUX_DP_AUXCTL);
160 value |= DPAUX_DP_AUXCTL_TRANSACTREQ;
161 tegra_dpaux_writel(dpaux, value, DPAUX_DP_AUXCTL);
162
163 status = wait_for_completion_timeout(&dpaux->complete, timeout);
164 if (!status)
165 return -ETIMEDOUT;
166
167 /* read status and clear errors */
168 value = tegra_dpaux_readl(dpaux, DPAUX_DP_AUXSTAT);
169 tegra_dpaux_writel(dpaux, 0xf00, DPAUX_DP_AUXSTAT);
170
171 if (value & DPAUX_DP_AUXSTAT_TIMEOUT_ERROR)
172 return -ETIMEDOUT;
173
174 if ((value & DPAUX_DP_AUXSTAT_RX_ERROR) ||
175 (value & DPAUX_DP_AUXSTAT_SINKSTAT_ERROR) ||
176 (value & DPAUX_DP_AUXSTAT_NO_STOP_ERROR))
177 return -EIO;
178
179 switch ((value & DPAUX_DP_AUXSTAT_REPLY_TYPE_MASK) >> 16) {
180 case 0x00:
181 msg->reply = DP_AUX_NATIVE_REPLY_ACK;
182 break;
183
184 case 0x01:
185 msg->reply = DP_AUX_NATIVE_REPLY_NACK;
186 break;
187
188 case 0x02:
189 msg->reply = DP_AUX_NATIVE_REPLY_DEFER;
190 break;
191
192 case 0x04:
193 msg->reply = DP_AUX_I2C_REPLY_NACK;
194 break;
195
196 case 0x08:
197 msg->reply = DP_AUX_I2C_REPLY_DEFER;
198 break;
199 }
200
201 if (msg->reply == DP_AUX_NATIVE_REPLY_ACK) {
202 if (msg->request & DP_AUX_I2C_READ) {
203 size_t count = value & DPAUX_DP_AUXSTAT_REPLY_MASK;
204
205 if (WARN_ON(count != msg->size))
206 count = min_t(size_t, count, msg->size);
207
208 tegra_dpaux_read_fifo(dpaux, msg->buffer, count);
209 ret = count;
210 }
211 }
212
213 return ret;
214}
215
216static irqreturn_t tegra_dpaux_irq(int irq, void *data)
217{
218 struct tegra_dpaux *dpaux = data;
219 irqreturn_t ret = IRQ_HANDLED;
220 unsigned long value;
221
222 /* clear interrupts */
223 value = tegra_dpaux_readl(dpaux, DPAUX_INTR_AUX);
224 tegra_dpaux_writel(dpaux, value, DPAUX_INTR_AUX);
225
226 if (value & DPAUX_INTR_PLUG_EVENT) {
227 if (dpaux->output) {
228 drm_helper_hpd_irq_event(dpaux->output->connector.dev);
229 }
230 }
231
232 if (value & DPAUX_INTR_UNPLUG_EVENT) {
233 if (dpaux->output)
234 drm_helper_hpd_irq_event(dpaux->output->connector.dev);
235 }
236
237 if (value & DPAUX_INTR_IRQ_EVENT) {
238 /* TODO: handle this */
239 }
240
241 if (value & DPAUX_INTR_AUX_DONE)
242 complete(&dpaux->complete);
243
244 return ret;
245}
246
247static int tegra_dpaux_probe(struct platform_device *pdev)
248{
249 struct tegra_dpaux *dpaux;
250 struct resource *regs;
251 unsigned long value;
252 int err;
253
254 dpaux = devm_kzalloc(&pdev->dev, sizeof(*dpaux), GFP_KERNEL);
255 if (!dpaux)
256 return -ENOMEM;
257
258 init_completion(&dpaux->complete);
259 INIT_LIST_HEAD(&dpaux->list);
260 dpaux->dev = &pdev->dev;
261
262 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
263 dpaux->regs = devm_ioremap_resource(&pdev->dev, regs);
264 if (IS_ERR(dpaux->regs))
265 return PTR_ERR(dpaux->regs);
266
267 dpaux->irq = platform_get_irq(pdev, 0);
268 if (dpaux->irq < 0) {
269 dev_err(&pdev->dev, "failed to get IRQ\n");
270 return -ENXIO;
271 }
272
273 dpaux->rst = devm_reset_control_get(&pdev->dev, "dpaux");
274 if (IS_ERR(dpaux->rst))
275 return PTR_ERR(dpaux->rst);
276
277 dpaux->clk = devm_clk_get(&pdev->dev, NULL);
278 if (IS_ERR(dpaux->clk))
279 return PTR_ERR(dpaux->clk);
280
281 err = clk_prepare_enable(dpaux->clk);
282 if (err < 0)
283 return err;
284
285 reset_control_deassert(dpaux->rst);
286
287 dpaux->clk_parent = devm_clk_get(&pdev->dev, "parent");
288 if (IS_ERR(dpaux->clk_parent))
289 return PTR_ERR(dpaux->clk_parent);
290
291 err = clk_prepare_enable(dpaux->clk_parent);
292 if (err < 0)
293 return err;
294
295 err = clk_set_rate(dpaux->clk_parent, 270000000);
296 if (err < 0) {
297 dev_err(&pdev->dev, "failed to set clock to 270 MHz: %d\n",
298 err);
299 return err;
300 }
301
302 dpaux->vdd = devm_regulator_get(&pdev->dev, "vdd");
303 if (IS_ERR(dpaux->vdd))
304 return PTR_ERR(dpaux->vdd);
305
306 err = devm_request_irq(dpaux->dev, dpaux->irq, tegra_dpaux_irq, 0,
307 dev_name(dpaux->dev), dpaux);
308 if (err < 0) {
309 dev_err(dpaux->dev, "failed to request IRQ#%u: %d\n",
310 dpaux->irq, err);
311 return err;
312 }
313
314 dpaux->aux.transfer = tegra_dpaux_transfer;
315 dpaux->aux.dev = &pdev->dev;
316
317 err = drm_dp_aux_register_i2c_bus(&dpaux->aux);
318 if (err < 0)
319 return err;
320
321 /* enable and clear all interrupts */
322 value = DPAUX_INTR_AUX_DONE | DPAUX_INTR_IRQ_EVENT |
323 DPAUX_INTR_UNPLUG_EVENT | DPAUX_INTR_PLUG_EVENT;
324 tegra_dpaux_writel(dpaux, value, DPAUX_INTR_EN_AUX);
325 tegra_dpaux_writel(dpaux, value, DPAUX_INTR_AUX);
326
327 mutex_lock(&dpaux_lock);
328 list_add_tail(&dpaux->list, &dpaux_list);
329 mutex_unlock(&dpaux_lock);
330
331 platform_set_drvdata(pdev, dpaux);
332
333 return 0;
334}
335
336static int tegra_dpaux_remove(struct platform_device *pdev)
337{
338 struct tegra_dpaux *dpaux = platform_get_drvdata(pdev);
339
340 drm_dp_aux_unregister_i2c_bus(&dpaux->aux);
341
342 mutex_lock(&dpaux_lock);
343 list_del(&dpaux->list);
344 mutex_unlock(&dpaux_lock);
345
346 clk_disable_unprepare(dpaux->clk_parent);
347 reset_control_assert(dpaux->rst);
348 clk_disable_unprepare(dpaux->clk);
349
350 return 0;
351}
352
353static const struct of_device_id tegra_dpaux_of_match[] = {
354 { .compatible = "nvidia,tegra124-dpaux", },
355 { },
356};
357
358struct platform_driver tegra_dpaux_driver = {
359 .driver = {
360 .name = "tegra-dpaux",
361 .of_match_table = tegra_dpaux_of_match,
362 },
363 .probe = tegra_dpaux_probe,
364 .remove = tegra_dpaux_remove,
365};
366
367struct tegra_dpaux *tegra_dpaux_find_by_of_node(struct device_node *np)
368{
369 struct tegra_dpaux *dpaux;
370
371 mutex_lock(&dpaux_lock);
372
373 list_for_each_entry(dpaux, &dpaux_list, list)
374 if (np == dpaux->dev->of_node) {
375 mutex_unlock(&dpaux_lock);
376 return dpaux;
377 }
378
379 mutex_unlock(&dpaux_lock);
380
381 return NULL;
382}
383
384int tegra_dpaux_attach(struct tegra_dpaux *dpaux, struct tegra_output *output)
385{
386 unsigned long timeout;
387 int err;
388
389 dpaux->output = output;
390
391 err = regulator_enable(dpaux->vdd);
392 if (err < 0)
393 return err;
394
395 timeout = jiffies + msecs_to_jiffies(250);
396
397 while (time_before(jiffies, timeout)) {
398 enum drm_connector_status status;
399
400 status = tegra_dpaux_detect(dpaux);
401 if (status == connector_status_connected)
402 return 0;
403
404 usleep_range(1000, 2000);
405 }
406
407 return -ETIMEDOUT;
408}
409
410int tegra_dpaux_detach(struct tegra_dpaux *dpaux)
411{
412 unsigned long timeout;
413 int err;
414
415 err = regulator_disable(dpaux->vdd);
416 if (err < 0)
417 return err;
418
419 timeout = jiffies + msecs_to_jiffies(250);
420
421 while (time_before(jiffies, timeout)) {
422 enum drm_connector_status status;
423
424 status = tegra_dpaux_detect(dpaux);
425 if (status == connector_status_disconnected) {
426 dpaux->output = NULL;
427 return 0;
428 }
429
430 usleep_range(1000, 2000);
431 }
432
433 return -ETIMEDOUT;
434}
435
436enum drm_connector_status tegra_dpaux_detect(struct tegra_dpaux *dpaux)
437{
438 unsigned long value;
439
440 value = tegra_dpaux_readl(dpaux, DPAUX_DP_AUXSTAT);
441
442 if (value & DPAUX_DP_AUXSTAT_HPD_STATUS)
443 return connector_status_connected;
444
445 return connector_status_disconnected;
446}
447
448int tegra_dpaux_enable(struct tegra_dpaux *dpaux)
449{
450 unsigned long value;
451
452 value = DPAUX_HYBRID_PADCTL_AUX_CMH(2) |
453 DPAUX_HYBRID_PADCTL_AUX_DRVZ(4) |
454 DPAUX_HYBRID_PADCTL_AUX_DRVI(0x18) |
455 DPAUX_HYBRID_PADCTL_AUX_INPUT_RCV |
456 DPAUX_HYBRID_PADCTL_MODE_AUX;
457 tegra_dpaux_writel(dpaux, value, DPAUX_HYBRID_PADCTL);
458
459 value = tegra_dpaux_readl(dpaux, DPAUX_HYBRID_SPARE);
460 value &= ~DPAUX_HYBRID_SPARE_PAD_POWER_DOWN;
461 tegra_dpaux_writel(dpaux, value, DPAUX_HYBRID_SPARE);
462
463 return 0;
464}
465
466int tegra_dpaux_disable(struct tegra_dpaux *dpaux)
467{
468 unsigned long value;
469
470 value = tegra_dpaux_readl(dpaux, DPAUX_HYBRID_SPARE);
471 value |= DPAUX_HYBRID_SPARE_PAD_POWER_DOWN;
472 tegra_dpaux_writel(dpaux, value, DPAUX_HYBRID_SPARE);
473
474 return 0;
475}
476
477int tegra_dpaux_prepare(struct tegra_dpaux *dpaux, u8 encoding)
478{
479 int err;
480
481 err = drm_dp_dpcd_writeb(&dpaux->aux, DP_MAIN_LINK_CHANNEL_CODING_SET,
482 encoding);
483 if (err < 0)
484 return err;
485
486 return 0;
487}
488
489int tegra_dpaux_train(struct tegra_dpaux *dpaux, struct drm_dp_link *link,
490 u8 pattern)
491{
492 u8 tp = pattern & DP_TRAINING_PATTERN_MASK;
493 u8 status[DP_LINK_STATUS_SIZE], values[4];
494 unsigned int i;
495 int err;
496
497 err = drm_dp_dpcd_writeb(&dpaux->aux, DP_TRAINING_PATTERN_SET, pattern);
498 if (err < 0)
499 return err;
500
501 if (tp == DP_TRAINING_PATTERN_DISABLE)
502 return 0;
503
504 for (i = 0; i < link->num_lanes; i++)
505 values[i] = DP_TRAIN_MAX_PRE_EMPHASIS_REACHED |
506 DP_TRAIN_PRE_EMPHASIS_0 |
507 DP_TRAIN_MAX_SWING_REACHED |
508 DP_TRAIN_VOLTAGE_SWING_400;
509
510 err = drm_dp_dpcd_write(&dpaux->aux, DP_TRAINING_LANE0_SET, values,
511 link->num_lanes);
512 if (err < 0)
513 return err;
514
515 usleep_range(500, 1000);
516
517 err = drm_dp_dpcd_read_link_status(&dpaux->aux, status);
518 if (err < 0)
519 return err;
520
521 switch (tp) {
522 case DP_TRAINING_PATTERN_1:
523 if (!drm_dp_clock_recovery_ok(status, link->num_lanes))
524 return -EAGAIN;
525
526 break;
527
528 case DP_TRAINING_PATTERN_2:
529 if (!drm_dp_channel_eq_ok(status, link->num_lanes))
530 return -EAGAIN;
531
532 break;
533
534 default:
535 dev_err(dpaux->dev, "unsupported training pattern %u\n", tp);
536 return -EINVAL;
537 }
538
539 err = drm_dp_dpcd_writeb(&dpaux->aux, DP_EDP_CONFIGURATION_SET, 0);
540 if (err < 0)
541 return err;
542
543 return 0;
544}
diff --git a/drivers/gpu/drm/tegra/dpaux.h b/drivers/gpu/drm/tegra/dpaux.h
new file mode 100644
index 000000000000..4f5bf10fdff9
--- /dev/null
+++ b/drivers/gpu/drm/tegra/dpaux.h
@@ -0,0 +1,73 @@
1/*
2 * Copyright (C) 2013 NVIDIA Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#ifndef DRM_TEGRA_DPAUX_H
10#define DRM_TEGRA_DPAUX_H
11
12#define DPAUX_CTXSW 0x00
13
14#define DPAUX_INTR_EN_AUX 0x01
15#define DPAUX_INTR_AUX 0x05
16#define DPAUX_INTR_AUX_DONE (1 << 3)
17#define DPAUX_INTR_IRQ_EVENT (1 << 2)
18#define DPAUX_INTR_UNPLUG_EVENT (1 << 1)
19#define DPAUX_INTR_PLUG_EVENT (1 << 0)
20
21#define DPAUX_DP_AUXDATA_WRITE(x) (0x09 + ((x) << 2))
22#define DPAUX_DP_AUXDATA_READ(x) (0x19 + ((x) << 2))
23#define DPAUX_DP_AUXADDR 0x29
24
25#define DPAUX_DP_AUXCTL 0x2d
26#define DPAUX_DP_AUXCTL_TRANSACTREQ (1 << 16)
27#define DPAUX_DP_AUXCTL_CMD_AUX_RD (9 << 12)
28#define DPAUX_DP_AUXCTL_CMD_AUX_WR (8 << 12)
29#define DPAUX_DP_AUXCTL_CMD_MOT_RQ (6 << 12)
30#define DPAUX_DP_AUXCTL_CMD_MOT_RD (5 << 12)
31#define DPAUX_DP_AUXCTL_CMD_MOT_WR (4 << 12)
32#define DPAUX_DP_AUXCTL_CMD_I2C_RQ (2 << 12)
33#define DPAUX_DP_AUXCTL_CMD_I2C_RD (1 << 12)
34#define DPAUX_DP_AUXCTL_CMD_I2C_WR (0 << 12)
35#define DPAUX_DP_AUXCTL_CMDLEN(x) ((x) & 0xff)
36
37#define DPAUX_DP_AUXSTAT 0x31
38#define DPAUX_DP_AUXSTAT_HPD_STATUS (1 << 28)
39#define DPAUX_DP_AUXSTAT_REPLY_TYPE_MASK (0xf0000)
40#define DPAUX_DP_AUXSTAT_NO_STOP_ERROR (1 << 11)
41#define DPAUX_DP_AUXSTAT_SINKSTAT_ERROR (1 << 10)
42#define DPAUX_DP_AUXSTAT_RX_ERROR (1 << 9)
43#define DPAUX_DP_AUXSTAT_TIMEOUT_ERROR (1 << 8)
44#define DPAUX_DP_AUXSTAT_REPLY_MASK (0xff)
45
46#define DPAUX_DP_AUX_SINKSTAT_LO 0x35
47#define DPAUX_DP_AUX_SINKSTAT_HI 0x39
48
49#define DPAUX_HPD_CONFIG 0x3d
50#define DPAUX_HPD_CONFIG_UNPLUG_MIN_TIME(x) (((x) & 0xffff) << 16)
51#define DPAUX_HPD_CONFIG_PLUG_MIN_TIME(x) ((x) & 0xffff)
52
53#define DPAUX_HPD_IRQ_CONFIG 0x41
54#define DPAUX_HPD_IRQ_CONFIG_MIN_LOW_TIME(x) ((x) & 0xffff)
55
56#define DPAUX_DP_AUX_CONFIG 0x45
57
58#define DPAUX_HYBRID_PADCTL 0x49
59#define DPAUX_HYBRID_PADCTL_AUX_CMH(x) (((x) & 0x3) << 12)
60#define DPAUX_HYBRID_PADCTL_AUX_DRVZ(x) (((x) & 0x7) << 8)
61#define DPAUX_HYBRID_PADCTL_AUX_DRVI(x) (((x) & 0x3f) << 2)
62#define DPAUX_HYBRID_PADCTL_AUX_INPUT_RCV (1 << 1)
63#define DPAUX_HYBRID_PADCTL_MODE_I2C (1 << 0)
64#define DPAUX_HYBRID_PADCTL_MODE_AUX (0 << 0)
65
66#define DPAUX_HYBRID_SPARE 0x4d
67#define DPAUX_HYBRID_SPARE_PAD_POWER_DOWN (1 << 0)
68
69#define DPAUX_SCRATCH_REG0 0x51
70#define DPAUX_SCRATCH_REG1 0x55
71#define DPAUX_SCRATCH_REG2 0x59
72
73#endif
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
index c71594754f46..6f5b6e2f552e 100644
--- a/drivers/gpu/drm/tegra/drm.c
+++ b/drivers/gpu/drm/tegra/drm.c
@@ -665,6 +665,7 @@ static const struct of_device_id host1x_drm_subdevs[] = {
665 { .compatible = "nvidia,tegra114-hdmi", }, 665 { .compatible = "nvidia,tegra114-hdmi", },
666 { .compatible = "nvidia,tegra114-gr3d", }, 666 { .compatible = "nvidia,tegra114-gr3d", },
667 { .compatible = "nvidia,tegra124-dc", }, 667 { .compatible = "nvidia,tegra124-dc", },
668 { .compatible = "nvidia,tegra124-sor", },
668 { /* sentinel */ } 669 { /* sentinel */ }
669}; 670};
670 671
@@ -691,14 +692,22 @@ static int __init host1x_drm_init(void)
691 if (err < 0) 692 if (err < 0)
692 goto unregister_dc; 693 goto unregister_dc;
693 694
694 err = platform_driver_register(&tegra_hdmi_driver); 695 err = platform_driver_register(&tegra_sor_driver);
695 if (err < 0) 696 if (err < 0)
696 goto unregister_dsi; 697 goto unregister_dsi;
697 698
698 err = platform_driver_register(&tegra_gr2d_driver); 699 err = platform_driver_register(&tegra_hdmi_driver);
700 if (err < 0)
701 goto unregister_sor;
702
703 err = platform_driver_register(&tegra_dpaux_driver);
699 if (err < 0) 704 if (err < 0)
700 goto unregister_hdmi; 705 goto unregister_hdmi;
701 706
707 err = platform_driver_register(&tegra_gr2d_driver);
708 if (err < 0)
709 goto unregister_dpaux;
710
702 err = platform_driver_register(&tegra_gr3d_driver); 711 err = platform_driver_register(&tegra_gr3d_driver);
703 if (err < 0) 712 if (err < 0)
704 goto unregister_gr2d; 713 goto unregister_gr2d;
@@ -707,8 +716,12 @@ static int __init host1x_drm_init(void)
707 716
708unregister_gr2d: 717unregister_gr2d:
709 platform_driver_unregister(&tegra_gr2d_driver); 718 platform_driver_unregister(&tegra_gr2d_driver);
719unregister_dpaux:
720 platform_driver_unregister(&tegra_dpaux_driver);
710unregister_hdmi: 721unregister_hdmi:
711 platform_driver_unregister(&tegra_hdmi_driver); 722 platform_driver_unregister(&tegra_hdmi_driver);
723unregister_sor:
724 platform_driver_unregister(&tegra_sor_driver);
712unregister_dsi: 725unregister_dsi:
713 platform_driver_unregister(&tegra_dsi_driver); 726 platform_driver_unregister(&tegra_dsi_driver);
714unregister_dc: 727unregister_dc:
@@ -723,7 +736,9 @@ static void __exit host1x_drm_exit(void)
723{ 736{
724 platform_driver_unregister(&tegra_gr3d_driver); 737 platform_driver_unregister(&tegra_gr3d_driver);
725 platform_driver_unregister(&tegra_gr2d_driver); 738 platform_driver_unregister(&tegra_gr2d_driver);
739 platform_driver_unregister(&tegra_dpaux_driver);
726 platform_driver_unregister(&tegra_hdmi_driver); 740 platform_driver_unregister(&tegra_hdmi_driver);
741 platform_driver_unregister(&tegra_sor_driver);
727 platform_driver_unregister(&tegra_dsi_driver); 742 platform_driver_unregister(&tegra_dsi_driver);
728 platform_driver_unregister(&tegra_dc_driver); 743 platform_driver_unregister(&tegra_dc_driver);
729 host1x_driver_unregister(&host1x_drm_driver); 744 host1x_driver_unregister(&host1x_drm_driver);
diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
index bf1cac7658f8..126332c3ecbb 100644
--- a/drivers/gpu/drm/tegra/drm.h
+++ b/drivers/gpu/drm/tegra/drm.h
@@ -179,12 +179,14 @@ struct tegra_output_ops {
179 int (*check_mode)(struct tegra_output *output, 179 int (*check_mode)(struct tegra_output *output,
180 struct drm_display_mode *mode, 180 struct drm_display_mode *mode,
181 enum drm_mode_status *status); 181 enum drm_mode_status *status);
182 enum drm_connector_status (*detect)(struct tegra_output *output);
182}; 183};
183 184
184enum tegra_output_type { 185enum tegra_output_type {
185 TEGRA_OUTPUT_RGB, 186 TEGRA_OUTPUT_RGB,
186 TEGRA_OUTPUT_HDMI, 187 TEGRA_OUTPUT_HDMI,
187 TEGRA_OUTPUT_DSI, 188 TEGRA_OUTPUT_DSI,
189 TEGRA_OUTPUT_EDP,
188}; 190};
189 191
190struct tegra_output { 192struct tegra_output {
@@ -265,6 +267,22 @@ extern int tegra_output_remove(struct tegra_output *output);
265extern int tegra_output_init(struct drm_device *drm, struct tegra_output *output); 267extern int tegra_output_init(struct drm_device *drm, struct tegra_output *output);
266extern int tegra_output_exit(struct tegra_output *output); 268extern int tegra_output_exit(struct tegra_output *output);
267 269
270/* from dpaux.c */
271
272struct tegra_dpaux;
273struct drm_dp_link;
274struct drm_dp_aux;
275
276struct tegra_dpaux *tegra_dpaux_find_by_of_node(struct device_node *np);
277enum drm_connector_status tegra_dpaux_detect(struct tegra_dpaux *dpaux);
278int tegra_dpaux_attach(struct tegra_dpaux *dpaux, struct tegra_output *output);
279int tegra_dpaux_detach(struct tegra_dpaux *dpaux);
280int tegra_dpaux_enable(struct tegra_dpaux *dpaux);
281int tegra_dpaux_disable(struct tegra_dpaux *dpaux);
282int tegra_dpaux_prepare(struct tegra_dpaux *dpaux, u8 encoding);
283int tegra_dpaux_train(struct tegra_dpaux *dpaux, struct drm_dp_link *link,
284 u8 pattern);
285
268/* from fb.c */ 286/* from fb.c */
269struct tegra_bo *tegra_fb_get_plane(struct drm_framebuffer *framebuffer, 287struct tegra_bo *tegra_fb_get_plane(struct drm_framebuffer *framebuffer,
270 unsigned int index); 288 unsigned int index);
@@ -278,7 +296,9 @@ extern void tegra_fbdev_restore_mode(struct tegra_fbdev *fbdev);
278 296
279extern struct platform_driver tegra_dc_driver; 297extern struct platform_driver tegra_dc_driver;
280extern struct platform_driver tegra_dsi_driver; 298extern struct platform_driver tegra_dsi_driver;
299extern struct platform_driver tegra_sor_driver;
281extern struct platform_driver tegra_hdmi_driver; 300extern struct platform_driver tegra_hdmi_driver;
301extern struct platform_driver tegra_dpaux_driver;
282extern struct platform_driver tegra_gr2d_driver; 302extern struct platform_driver tegra_gr2d_driver;
283extern struct platform_driver tegra_gr3d_driver; 303extern struct platform_driver tegra_gr3d_driver;
284 304
diff --git a/drivers/gpu/drm/tegra/dsi.c b/drivers/gpu/drm/tegra/dsi.c
index d452faab0235..0e599f0417c0 100644
--- a/drivers/gpu/drm/tegra/dsi.c
+++ b/drivers/gpu/drm/tegra/dsi.c
@@ -1,23 +1,9 @@
1/* 1/*
2 * Copyright (C) 2013 NVIDIA Corporation 2 * Copyright (C) 2013 NVIDIA Corporation
3 * 3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its 4 * This program is free software; you can redistribute it and/or modify
5 * documentation for any purpose is hereby granted without fee, provided that 5 * it under the terms of the GNU General Public License version 2 as
6 * the above copyright notice appear in all copies and that both that copyright 6 * published by the Free Software Foundation.
7 * notice and this permission notice appear in supporting documentation, and
8 * that the name of the copyright holders not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission. The copyright holders make no representations
11 * about the suitability of this software for any purpose. It is provided "as
12 * is" without express or implied warranty.
13 *
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20 * OF THIS SOFTWARE.
21 */ 7 */
22 8
23#include <linux/clk.h> 9#include <linux/clk.h>
diff --git a/drivers/gpu/drm/tegra/dsi.h b/drivers/gpu/drm/tegra/dsi.h
index 00e79c1f448c..1db5cc24ea91 100644
--- a/drivers/gpu/drm/tegra/dsi.h
+++ b/drivers/gpu/drm/tegra/dsi.h
@@ -1,23 +1,9 @@
1/* 1/*
2 * Copyright (C) 2013 NVIDIA Corporation 2 * Copyright (C) 2013 NVIDIA Corporation
3 * 3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its 4 * This program is free software; you can redistribute it and/or modify
5 * documentation for any purpose is hereby granted without fee, provided that 5 * it under the terms of the GNU General Public License version 2 as
6 * the above copyright notice appear in all copies and that both that copyright 6 * published by the Free Software Foundation.
7 * notice and this permission notice appear in supporting documentation, and
8 * that the name of the copyright holders not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission. The copyright holders make no representations
11 * about the suitability of this software for any purpose. It is provided "as
12 * is" without express or implied warranty.
13 *
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20 * OF THIS SOFTWARE.
21 */ 7 */
22 8
23#ifndef DRM_TEGRA_DSI_H 9#ifndef DRM_TEGRA_DSI_H
diff --git a/drivers/gpu/drm/tegra/gem.c b/drivers/gpu/drm/tegra/gem.c
index ef853e558036..bcf9895cef9f 100644
--- a/drivers/gpu/drm/tegra/gem.c
+++ b/drivers/gpu/drm/tegra/gem.c
@@ -8,14 +8,9 @@
8 * 8 *
9 * Copyright (c) 2011 Samsung Electronics Co., Ltd. 9 * Copyright (c) 2011 Samsung Electronics Co., Ltd.
10 * 10 *
11 * This program is free software; you can redistribute it and/or 11 * This program is free software; you can redistribute it and/or modify
12 * modify it under the terms of the GNU General Public License 12 * it under the terms of the GNU General Public License version 2 as
13 * as published by the Free Software Foundation; either version 2 13 * published by the Free Software Foundation.
14 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 */ 14 */
20 15
21#include <linux/dma-buf.h> 16#include <linux/dma-buf.h>
@@ -394,6 +389,18 @@ static int tegra_gem_prime_mmap(struct dma_buf *buf, struct vm_area_struct *vma)
394 return -EINVAL; 389 return -EINVAL;
395} 390}
396 391
392static void *tegra_gem_prime_vmap(struct dma_buf *buf)
393{
394 struct drm_gem_object *gem = buf->priv;
395 struct tegra_bo *bo = to_tegra_bo(gem);
396
397 return bo->vaddr;
398}
399
400static void tegra_gem_prime_vunmap(struct dma_buf *buf, void *vaddr)
401{
402}
403
397static const struct dma_buf_ops tegra_gem_prime_dmabuf_ops = { 404static const struct dma_buf_ops tegra_gem_prime_dmabuf_ops = {
398 .map_dma_buf = tegra_gem_prime_map_dma_buf, 405 .map_dma_buf = tegra_gem_prime_map_dma_buf,
399 .unmap_dma_buf = tegra_gem_prime_unmap_dma_buf, 406 .unmap_dma_buf = tegra_gem_prime_unmap_dma_buf,
@@ -403,6 +410,8 @@ static const struct dma_buf_ops tegra_gem_prime_dmabuf_ops = {
403 .kmap = tegra_gem_prime_kmap, 410 .kmap = tegra_gem_prime_kmap,
404 .kunmap = tegra_gem_prime_kunmap, 411 .kunmap = tegra_gem_prime_kunmap,
405 .mmap = tegra_gem_prime_mmap, 412 .mmap = tegra_gem_prime_mmap,
413 .vmap = tegra_gem_prime_vmap,
414 .vunmap = tegra_gem_prime_vunmap,
406}; 415};
407 416
408struct dma_buf *tegra_gem_prime_export(struct drm_device *drm, 417struct dma_buf *tegra_gem_prime_export(struct drm_device *drm,
diff --git a/drivers/gpu/drm/tegra/gem.h b/drivers/gpu/drm/tegra/gem.h
index ffd4f792b410..2f3fe96c5154 100644
--- a/drivers/gpu/drm/tegra/gem.h
+++ b/drivers/gpu/drm/tegra/gem.h
@@ -3,17 +3,9 @@
3 * 3 *
4 * Copyright (c) 2012-2013, NVIDIA Corporation. 4 * Copyright (c) 2012-2013, NVIDIA Corporation.
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify it 6 * This program is free software; you can redistribute it and/or modify
7 * under the terms and conditions of the GNU General Public License, 7 * it under the terms of the GNU General Public License version 2 as
8 * version 2, as published by the Free Software Foundation. 8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */ 9 */
18 10
19#ifndef __HOST1X_GEM_H 11#ifndef __HOST1X_GEM_H
diff --git a/drivers/gpu/drm/tegra/gr2d.c b/drivers/gpu/drm/tegra/gr2d.c
index 7ec4259ffded..2c7ca748edf5 100644
--- a/drivers/gpu/drm/tegra/gr2d.c
+++ b/drivers/gpu/drm/tegra/gr2d.c
@@ -1,17 +1,9 @@
1/* 1/*
2 * Copyright (c) 2012-2013, NVIDIA Corporation. 2 * Copyright (c) 2012-2013, NVIDIA Corporation.
3 * 3 *
4 * This program is free software; you can redistribute it and/or modify it 4 * This program is free software; you can redistribute it and/or modify
5 * under the terms and conditions of the GNU General Public License, 5 * it under the terms of the GNU General Public License version 2 as
6 * version 2, as published by the Free Software Foundation. 6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */ 7 */
16 8
17#include <linux/clk.h> 9#include <linux/clk.h>
diff --git a/drivers/gpu/drm/tegra/mipi-phy.c b/drivers/gpu/drm/tegra/mipi-phy.c
index e2c4aedaee78..486d19d589c8 100644
--- a/drivers/gpu/drm/tegra/mipi-phy.c
+++ b/drivers/gpu/drm/tegra/mipi-phy.c
@@ -1,23 +1,9 @@
1/* 1/*
2 * Copyright (C) 2013 NVIDIA Corporation 2 * Copyright (C) 2013 NVIDIA Corporation
3 * 3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its 4 * This program is free software; you can redistribute it and/or modify
5 * documentation for any purpose is hereby granted without fee, provided that 5 * it under the terms of the GNU General Public License version 2 as
6 * the above copyright notice appear in all copies and that both that copyright 6 * published by the Free Software Foundation.
7 * notice and this permission notice appear in supporting documentation, and
8 * that the name of the copyright holders not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission. The copyright holders make no representations
11 * about the suitability of this software for any purpose. It is provided "as
12 * is" without express or implied warranty.
13 *
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20 * OF THIS SOFTWARE.
21 */ 7 */
22 8
23#include <linux/errno.h> 9#include <linux/errno.h>
diff --git a/drivers/gpu/drm/tegra/mipi-phy.h b/drivers/gpu/drm/tegra/mipi-phy.h
index d3591694432d..012ea8ac36d7 100644
--- a/drivers/gpu/drm/tegra/mipi-phy.h
+++ b/drivers/gpu/drm/tegra/mipi-phy.h
@@ -1,23 +1,9 @@
1/* 1/*
2 * Copyright (C) 2013 NVIDIA Corporation 2 * Copyright (C) 2013 NVIDIA Corporation
3 * 3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its 4 * This program is free software; you can redistribute it and/or modify
5 * documentation for any purpose is hereby granted without fee, provided that 5 * it under the terms of the GNU General Public License version 2 as
6 * the above copyright notice appear in all copies and that both that copyright 6 * published by the Free Software Foundation.
7 * notice and this permission notice appear in supporting documentation, and
8 * that the name of the copyright holders not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission. The copyright holders make no representations
11 * about the suitability of this software for any purpose. It is provided "as
12 * is" without express or implied warranty.
13 *
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20 * OF THIS SOFTWARE.
21 */ 7 */
22 8
23#ifndef DRM_TEGRA_MIPI_PHY_H 9#ifndef DRM_TEGRA_MIPI_PHY_H
diff --git a/drivers/gpu/drm/tegra/output.c b/drivers/gpu/drm/tegra/output.c
index 57cecbd18ca8..a3e4f1eca6f7 100644
--- a/drivers/gpu/drm/tegra/output.c
+++ b/drivers/gpu/drm/tegra/output.c
@@ -77,6 +77,9 @@ tegra_connector_detect(struct drm_connector *connector, bool force)
77 struct tegra_output *output = connector_to_output(connector); 77 struct tegra_output *output = connector_to_output(connector);
78 enum drm_connector_status status = connector_status_unknown; 78 enum drm_connector_status status = connector_status_unknown;
79 79
80 if (output->ops->detect)
81 return output->ops->detect(output);
82
80 if (gpio_is_valid(output->hpd_gpio)) { 83 if (gpio_is_valid(output->hpd_gpio)) {
81 if (gpio_get_value(output->hpd_gpio) == 0) 84 if (gpio_get_value(output->hpd_gpio) == 0)
82 status = connector_status_disconnected; 85 status = connector_status_disconnected;
@@ -292,6 +295,11 @@ int tegra_output_init(struct drm_device *drm, struct tegra_output *output)
292 encoder = DRM_MODE_ENCODER_DSI; 295 encoder = DRM_MODE_ENCODER_DSI;
293 break; 296 break;
294 297
298 case TEGRA_OUTPUT_EDP:
299 connector = DRM_MODE_CONNECTOR_eDP;
300 encoder = DRM_MODE_ENCODER_TMDS;
301 break;
302
295 default: 303 default:
296 connector = DRM_MODE_CONNECTOR_Unknown; 304 connector = DRM_MODE_CONNECTOR_Unknown;
297 encoder = DRM_MODE_ENCODER_NONE; 305 encoder = DRM_MODE_ENCODER_NONE;
diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c
new file mode 100644
index 000000000000..49ef5729f435
--- /dev/null
+++ b/drivers/gpu/drm/tegra/sor.c
@@ -0,0 +1,1092 @@
1/*
2 * Copyright (C) 2013 NVIDIA Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/clk.h>
10#include <linux/io.h>
11#include <linux/platform_device.h>
12#include <linux/reset.h>
13#include <linux/tegra-powergate.h>
14
15#include <drm/drm_dp_helper.h>
16
17#include "dc.h"
18#include "drm.h"
19#include "sor.h"
20
21struct tegra_sor {
22 struct host1x_client client;
23 struct tegra_output output;
24 struct device *dev;
25
26 void __iomem *regs;
27
28 struct reset_control *rst;
29 struct clk *clk_parent;
30 struct clk *clk_safe;
31 struct clk *clk_dp;
32 struct clk *clk;
33
34 struct tegra_dpaux *dpaux;
35
36 bool enabled;
37};
38
39static inline struct tegra_sor *
40host1x_client_to_sor(struct host1x_client *client)
41{
42 return container_of(client, struct tegra_sor, client);
43}
44
45static inline struct tegra_sor *to_sor(struct tegra_output *output)
46{
47 return container_of(output, struct tegra_sor, output);
48}
49
50static inline unsigned long tegra_sor_readl(struct tegra_sor *sor,
51 unsigned long offset)
52{
53 return readl(sor->regs + (offset << 2));
54}
55
56static inline void tegra_sor_writel(struct tegra_sor *sor, unsigned long value,
57 unsigned long offset)
58{
59 writel(value, sor->regs + (offset << 2));
60}
61
62static int tegra_sor_dp_train_fast(struct tegra_sor *sor,
63 struct drm_dp_link *link)
64{
65 unsigned long value;
66 unsigned int i;
67 u8 pattern;
68 int err;
69
70 /* setup lane parameters */
71 value = SOR_LANE_DRIVE_CURRENT_LANE3(0x40) |
72 SOR_LANE_DRIVE_CURRENT_LANE2(0x40) |
73 SOR_LANE_DRIVE_CURRENT_LANE1(0x40) |
74 SOR_LANE_DRIVE_CURRENT_LANE0(0x40);
75 tegra_sor_writel(sor, value, SOR_LANE_DRIVE_CURRENT_0);
76
77 value = SOR_LANE_PREEMPHASIS_LANE3(0x0f) |
78 SOR_LANE_PREEMPHASIS_LANE2(0x0f) |
79 SOR_LANE_PREEMPHASIS_LANE1(0x0f) |
80 SOR_LANE_PREEMPHASIS_LANE0(0x0f);
81 tegra_sor_writel(sor, value, SOR_LANE_PREEMPHASIS_0);
82
83 value = SOR_LANE_POST_CURSOR_LANE3(0x00) |
84 SOR_LANE_POST_CURSOR_LANE2(0x00) |
85 SOR_LANE_POST_CURSOR_LANE1(0x00) |
86 SOR_LANE_POST_CURSOR_LANE0(0x00);
87 tegra_sor_writel(sor, value, SOR_LANE_POST_CURSOR_0);
88
89 /* disable LVDS mode */
90 tegra_sor_writel(sor, 0, SOR_LVDS);
91
92 value = tegra_sor_readl(sor, SOR_DP_PADCTL_0);
93 value |= SOR_DP_PADCTL_TX_PU_ENABLE;
94 value &= ~SOR_DP_PADCTL_TX_PU_MASK;
95 value |= SOR_DP_PADCTL_TX_PU(2); /* XXX: don't hardcode? */
96 tegra_sor_writel(sor, value, SOR_DP_PADCTL_0);
97
98 value = tegra_sor_readl(sor, SOR_DP_PADCTL_0);
99 value |= SOR_DP_PADCTL_CM_TXD_3 | SOR_DP_PADCTL_CM_TXD_2 |
100 SOR_DP_PADCTL_CM_TXD_1 | SOR_DP_PADCTL_CM_TXD_0;
101 tegra_sor_writel(sor, value, SOR_DP_PADCTL_0);
102
103 usleep_range(10, 100);
104
105 value = tegra_sor_readl(sor, SOR_DP_PADCTL_0);
106 value &= ~(SOR_DP_PADCTL_CM_TXD_3 | SOR_DP_PADCTL_CM_TXD_2 |
107 SOR_DP_PADCTL_CM_TXD_1 | SOR_DP_PADCTL_CM_TXD_0);
108 tegra_sor_writel(sor, value, SOR_DP_PADCTL_0);
109
110 err = tegra_dpaux_prepare(sor->dpaux, DP_SET_ANSI_8B10B);
111 if (err < 0)
112 return err;
113
114 for (i = 0, value = 0; i < link->num_lanes; i++) {
115 unsigned long lane = SOR_DP_TPG_CHANNEL_CODING |
116 SOR_DP_TPG_SCRAMBLER_NONE |
117 SOR_DP_TPG_PATTERN_TRAIN1;
118 value = (value << 8) | lane;
119 }
120
121 tegra_sor_writel(sor, value, SOR_DP_TPG);
122
123 pattern = DP_TRAINING_PATTERN_1;
124
125 err = tegra_dpaux_train(sor->dpaux, link, pattern);
126 if (err < 0)
127 return err;
128
129 value = tegra_sor_readl(sor, SOR_DP_SPARE_0);
130 value |= SOR_DP_SPARE_SEQ_ENABLE;
131 value &= ~SOR_DP_SPARE_PANEL_INTERNAL;
132 value |= SOR_DP_SPARE_MACRO_SOR_CLK;
133 tegra_sor_writel(sor, value, SOR_DP_SPARE_0);
134
135 for (i = 0, value = 0; i < link->num_lanes; i++) {
136 unsigned long lane = SOR_DP_TPG_CHANNEL_CODING |
137 SOR_DP_TPG_SCRAMBLER_NONE |
138 SOR_DP_TPG_PATTERN_TRAIN2;
139 value = (value << 8) | lane;
140 }
141
142 tegra_sor_writel(sor, value, SOR_DP_TPG);
143
144 pattern = DP_LINK_SCRAMBLING_DISABLE | DP_TRAINING_PATTERN_2;
145
146 err = tegra_dpaux_train(sor->dpaux, link, pattern);
147 if (err < 0)
148 return err;
149
150 for (i = 0, value = 0; i < link->num_lanes; i++) {
151 unsigned long lane = SOR_DP_TPG_CHANNEL_CODING |
152 SOR_DP_TPG_SCRAMBLER_GALIOS |
153 SOR_DP_TPG_PATTERN_NONE;
154 value = (value << 8) | lane;
155 }
156
157 tegra_sor_writel(sor, value, SOR_DP_TPG);
158
159 pattern = DP_TRAINING_PATTERN_DISABLE;
160
161 err = tegra_dpaux_train(sor->dpaux, link, pattern);
162 if (err < 0)
163 return err;
164
165 return 0;
166}
167
168static void tegra_sor_super_update(struct tegra_sor *sor)
169{
170 tegra_sor_writel(sor, 0, SOR_SUPER_STATE_0);
171 tegra_sor_writel(sor, 1, SOR_SUPER_STATE_0);
172 tegra_sor_writel(sor, 0, SOR_SUPER_STATE_0);
173}
174
175static void tegra_sor_update(struct tegra_sor *sor)
176{
177 tegra_sor_writel(sor, 0, SOR_STATE_0);
178 tegra_sor_writel(sor, 1, SOR_STATE_0);
179 tegra_sor_writel(sor, 0, SOR_STATE_0);
180}
181
182static int tegra_sor_setup_pwm(struct tegra_sor *sor, unsigned long timeout)
183{
184 unsigned long value;
185
186 value = tegra_sor_readl(sor, SOR_PWM_DIV);
187 value &= ~SOR_PWM_DIV_MASK;
188 value |= 0x400; /* period */
189 tegra_sor_writel(sor, value, SOR_PWM_DIV);
190
191 value = tegra_sor_readl(sor, SOR_PWM_CTL);
192 value &= ~SOR_PWM_CTL_DUTY_CYCLE_MASK;
193 value |= 0x400; /* duty cycle */
194 value &= ~SOR_PWM_CTL_CLK_SEL; /* clock source: PCLK */
195 value |= SOR_PWM_CTL_TRIGGER;
196 tegra_sor_writel(sor, value, SOR_PWM_CTL);
197
198 timeout = jiffies + msecs_to_jiffies(timeout);
199
200 while (time_before(jiffies, timeout)) {
201 value = tegra_sor_readl(sor, SOR_PWM_CTL);
202 if ((value & SOR_PWM_CTL_TRIGGER) == 0)
203 return 0;
204
205 usleep_range(25, 100);
206 }
207
208 return -ETIMEDOUT;
209}
210
211static int tegra_sor_attach(struct tegra_sor *sor)
212{
213 unsigned long value, timeout;
214
215 /* wake up in normal mode */
216 value = tegra_sor_readl(sor, SOR_SUPER_STATE_1);
217 value |= SOR_SUPER_STATE_HEAD_MODE_AWAKE;
218 value |= SOR_SUPER_STATE_MODE_NORMAL;
219 tegra_sor_writel(sor, value, SOR_SUPER_STATE_1);
220 tegra_sor_super_update(sor);
221
222 /* attach */
223 value = tegra_sor_readl(sor, SOR_SUPER_STATE_1);
224 value |= SOR_SUPER_STATE_ATTACHED;
225 tegra_sor_writel(sor, value, SOR_SUPER_STATE_1);
226 tegra_sor_super_update(sor);
227
228 timeout = jiffies + msecs_to_jiffies(250);
229
230 while (time_before(jiffies, timeout)) {
231 value = tegra_sor_readl(sor, SOR_TEST);
232 if ((value & SOR_TEST_ATTACHED) != 0)
233 return 0;
234
235 usleep_range(25, 100);
236 }
237
238 return -ETIMEDOUT;
239}
240
241static int tegra_sor_wakeup(struct tegra_sor *sor)
242{
243 struct tegra_dc *dc = to_tegra_dc(sor->output.encoder.crtc);
244 unsigned long value, timeout;
245
246 /* enable display controller outputs */
247 value = tegra_dc_readl(dc, DC_CMD_DISPLAY_POWER_CONTROL);
248 value |= PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
249 PW4_ENABLE | PM0_ENABLE | PM1_ENABLE;
250 tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL);
251
252 tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
253 tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
254
255 timeout = jiffies + msecs_to_jiffies(250);
256
257 /* wait for head to wake up */
258 while (time_before(jiffies, timeout)) {
259 value = tegra_sor_readl(sor, SOR_TEST);
260 value &= SOR_TEST_HEAD_MODE_MASK;
261
262 if (value == SOR_TEST_HEAD_MODE_AWAKE)
263 return 0;
264
265 usleep_range(25, 100);
266 }
267
268 return -ETIMEDOUT;
269}
270
271static int tegra_sor_power_up(struct tegra_sor *sor, unsigned long timeout)
272{
273 unsigned long value;
274
275 value = tegra_sor_readl(sor, SOR_PWR);
276 value |= SOR_PWR_TRIGGER | SOR_PWR_NORMAL_STATE_PU;
277 tegra_sor_writel(sor, value, SOR_PWR);
278
279 timeout = jiffies + msecs_to_jiffies(timeout);
280
281 while (time_before(jiffies, timeout)) {
282 value = tegra_sor_readl(sor, SOR_PWR);
283 if ((value & SOR_PWR_TRIGGER) == 0)
284 return 0;
285
286 usleep_range(25, 100);
287 }
288
289 return -ETIMEDOUT;
290}
291
292static int tegra_output_sor_enable(struct tegra_output *output)
293{
294 struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc);
295 struct drm_display_mode *mode = &dc->base.mode;
296 unsigned int vbe, vse, hbe, hse, vbs, hbs, i;
297 struct tegra_sor *sor = to_sor(output);
298 unsigned long value;
299 int err;
300
301 if (sor->enabled)
302 return 0;
303
304 err = clk_prepare_enable(sor->clk);
305 if (err < 0)
306 return err;
307
308 reset_control_deassert(sor->rst);
309
310 if (sor->dpaux) {
311 err = tegra_dpaux_enable(sor->dpaux);
312 if (err < 0)
313 dev_err(sor->dev, "failed to enable DP: %d\n", err);
314 }
315
316 err = clk_set_parent(sor->clk, sor->clk_safe);
317 if (err < 0)
318 dev_err(sor->dev, "failed to set safe parent clock: %d\n", err);
319
320 value = tegra_sor_readl(sor, SOR_CLK_CNTRL);
321 value &= ~SOR_CLK_CNTRL_DP_CLK_SEL_MASK;
322 value |= SOR_CLK_CNTRL_DP_CLK_SEL_SINGLE_DPCLK;
323 tegra_sor_writel(sor, value, SOR_CLK_CNTRL);
324
325 value = tegra_sor_readl(sor, SOR_PLL_2);
326 value &= ~SOR_PLL_2_BANDGAP_POWERDOWN;
327 tegra_sor_writel(sor, value, SOR_PLL_2);
328 usleep_range(20, 100);
329
330 value = tegra_sor_readl(sor, SOR_PLL_3);
331 value |= SOR_PLL_3_PLL_VDD_MODE_V3_3;
332 tegra_sor_writel(sor, value, SOR_PLL_3);
333
334 value = SOR_PLL_0_ICHPMP(0xf) | SOR_PLL_0_VCOCAP_RST |
335 SOR_PLL_0_PLLREG_LEVEL_V45 | SOR_PLL_0_RESISTOR_EXT;
336 tegra_sor_writel(sor, value, SOR_PLL_0);
337
338 value = tegra_sor_readl(sor, SOR_PLL_2);
339 value |= SOR_PLL_2_SEQ_PLLCAPPD;
340 value &= ~SOR_PLL_2_SEQ_PLLCAPPD_ENFORCE;
341 value |= SOR_PLL_2_LVDS_ENABLE;
342 tegra_sor_writel(sor, value, SOR_PLL_2);
343
344 value = SOR_PLL_1_TERM_COMPOUT | SOR_PLL_1_TMDS_TERM;
345 tegra_sor_writel(sor, value, SOR_PLL_1);
346
347 while (true) {
348 value = tegra_sor_readl(sor, SOR_PLL_2);
349 if ((value & SOR_PLL_2_SEQ_PLLCAPPD_ENFORCE) == 0)
350 break;
351
352 usleep_range(250, 1000);
353 }
354
355 value = tegra_sor_readl(sor, SOR_PLL_2);
356 value &= ~SOR_PLL_2_POWERDOWN_OVERRIDE;
357 value &= ~SOR_PLL_2_PORT_POWERDOWN;
358 tegra_sor_writel(sor, value, SOR_PLL_2);
359
360 /*
361 * power up
362 */
363
364 /* set safe link bandwidth (1.62 Gbps) */
365 value = tegra_sor_readl(sor, SOR_CLK_CNTRL);
366 value &= ~SOR_CLK_CNTRL_DP_LINK_SPEED_MASK;
367 value |= SOR_CLK_CNTRL_DP_LINK_SPEED_G1_62;
368 tegra_sor_writel(sor, value, SOR_CLK_CNTRL);
369
370 /* step 1 */
371 value = tegra_sor_readl(sor, SOR_PLL_2);
372 value |= SOR_PLL_2_SEQ_PLLCAPPD_ENFORCE | SOR_PLL_2_PORT_POWERDOWN |
373 SOR_PLL_2_BANDGAP_POWERDOWN;
374 tegra_sor_writel(sor, value, SOR_PLL_2);
375
376 value = tegra_sor_readl(sor, SOR_PLL_0);
377 value |= SOR_PLL_0_VCOPD | SOR_PLL_0_POWER_OFF;
378 tegra_sor_writel(sor, value, SOR_PLL_0);
379
380 value = tegra_sor_readl(sor, SOR_DP_PADCTL_0);
381 value &= ~SOR_DP_PADCTL_PAD_CAL_PD;
382 tegra_sor_writel(sor, value, SOR_DP_PADCTL_0);
383
384 /* step 2 */
385 err = tegra_io_rail_power_on(TEGRA_IO_RAIL_LVDS);
386 if (err < 0) {
387 dev_err(sor->dev, "failed to power on I/O rail: %d\n", err);
388 return err;
389 }
390
391 usleep_range(5, 100);
392
393 /* step 3 */
394 value = tegra_sor_readl(sor, SOR_PLL_2);
395 value &= ~SOR_PLL_2_BANDGAP_POWERDOWN;
396 tegra_sor_writel(sor, value, SOR_PLL_2);
397
398 usleep_range(20, 100);
399
400 /* step 4 */
401 value = tegra_sor_readl(sor, SOR_PLL_0);
402 value &= ~SOR_PLL_0_POWER_OFF;
403 value &= ~SOR_PLL_0_VCOPD;
404 tegra_sor_writel(sor, value, SOR_PLL_0);
405
406 value = tegra_sor_readl(sor, SOR_PLL_2);
407 value &= ~SOR_PLL_2_SEQ_PLLCAPPD_ENFORCE;
408 tegra_sor_writel(sor, value, SOR_PLL_2);
409
410 usleep_range(200, 1000);
411
412 /* step 5 */
413 value = tegra_sor_readl(sor, SOR_PLL_2);
414 value &= ~SOR_PLL_2_PORT_POWERDOWN;
415 tegra_sor_writel(sor, value, SOR_PLL_2);
416
417 /* switch to DP clock */
418 err = clk_set_parent(sor->clk, sor->clk_dp);
419 if (err < 0)
420 dev_err(sor->dev, "failed to set DP parent clock: %d\n", err);
421
422 /* power dplanes (XXX parameterize based on link?) */
423 value = tegra_sor_readl(sor, SOR_DP_PADCTL_0);
424 value |= SOR_DP_PADCTL_PD_TXD_3 | SOR_DP_PADCTL_PD_TXD_0 |
425 SOR_DP_PADCTL_PD_TXD_1 | SOR_DP_PADCTL_PD_TXD_2;
426 tegra_sor_writel(sor, value, SOR_DP_PADCTL_0);
427
428 value = tegra_sor_readl(sor, SOR_DP_LINKCTL_0);
429 value &= ~SOR_DP_LINKCTL_LANE_COUNT_MASK;
430 value |= SOR_DP_LINKCTL_LANE_COUNT(4);
431 tegra_sor_writel(sor, value, SOR_DP_LINKCTL_0);
432
433 /* start lane sequencer */
434 value = SOR_LANE_SEQ_CTL_TRIGGER | SOR_LANE_SEQ_CTL_SEQUENCE_DOWN |
435 SOR_LANE_SEQ_CTL_POWER_STATE_UP;
436 tegra_sor_writel(sor, value, SOR_LANE_SEQ_CTL);
437
438 while (true) {
439 value = tegra_sor_readl(sor, SOR_LANE_SEQ_CTL);
440 if ((value & SOR_LANE_SEQ_CTL_TRIGGER) == 0)
441 break;
442
443 usleep_range(250, 1000);
444 }
445
446 /* set link bandwidth (2.7 GHz, XXX: parameterize based on link?) */
447 value = tegra_sor_readl(sor, SOR_CLK_CNTRL);
448 value &= ~SOR_CLK_CNTRL_DP_LINK_SPEED_MASK;
449 value |= SOR_CLK_CNTRL_DP_LINK_SPEED_G2_70;
450 tegra_sor_writel(sor, value, SOR_CLK_CNTRL);
451
452 /* set linkctl */
453 value = tegra_sor_readl(sor, SOR_DP_LINKCTL_0);
454 value |= SOR_DP_LINKCTL_ENABLE;
455
456 value &= ~SOR_DP_LINKCTL_TU_SIZE_MASK;
457 value |= SOR_DP_LINKCTL_TU_SIZE(59); /* XXX: don't hardcode? */
458
459 value |= SOR_DP_LINKCTL_ENHANCED_FRAME;
460 tegra_sor_writel(sor, value, SOR_DP_LINKCTL_0);
461
462 for (i = 0, value = 0; i < 4; i++) {
463 unsigned long lane = SOR_DP_TPG_CHANNEL_CODING |
464 SOR_DP_TPG_SCRAMBLER_GALIOS |
465 SOR_DP_TPG_PATTERN_NONE;
466 value = (value << 8) | lane;
467 }
468
469 tegra_sor_writel(sor, value, SOR_DP_TPG);
470
471 value = tegra_sor_readl(sor, SOR_DP_CONFIG_0);
472 value &= ~SOR_DP_CONFIG_WATERMARK_MASK;
473 value |= SOR_DP_CONFIG_WATERMARK(14); /* XXX: don't hardcode? */
474
475 value &= ~SOR_DP_CONFIG_ACTIVE_SYM_COUNT_MASK;
476 value |= SOR_DP_CONFIG_ACTIVE_SYM_COUNT(47); /* XXX: don't hardcode? */
477
478 value &= ~SOR_DP_CONFIG_ACTIVE_SYM_FRAC_MASK;
479 value |= SOR_DP_CONFIG_ACTIVE_SYM_FRAC(9); /* XXX: don't hardcode? */
480
481 value &= ~SOR_DP_CONFIG_ACTIVE_SYM_POLARITY; /* XXX: don't hardcode? */
482
483 value |= SOR_DP_CONFIG_ACTIVE_SYM_ENABLE;
484 value |= SOR_DP_CONFIG_DISPARITY_NEGATIVE; /* XXX: don't hardcode? */
485 tegra_sor_writel(sor, value, SOR_DP_CONFIG_0);
486
487 value = tegra_sor_readl(sor, SOR_DP_AUDIO_HBLANK_SYMBOLS);
488 value &= ~SOR_DP_AUDIO_HBLANK_SYMBOLS_MASK;
489 value |= 137; /* XXX: don't hardcode? */
490 tegra_sor_writel(sor, value, SOR_DP_AUDIO_HBLANK_SYMBOLS);
491
492 value = tegra_sor_readl(sor, SOR_DP_AUDIO_VBLANK_SYMBOLS);
493 value &= ~SOR_DP_AUDIO_VBLANK_SYMBOLS_MASK;
494 value |= 2368; /* XXX: don't hardcode? */
495 tegra_sor_writel(sor, value, SOR_DP_AUDIO_VBLANK_SYMBOLS);
496
497 /* enable pad calibration logic */
498 value = tegra_sor_readl(sor, SOR_DP_PADCTL_0);
499 value |= SOR_DP_PADCTL_PAD_CAL_PD;
500 tegra_sor_writel(sor, value, SOR_DP_PADCTL_0);
501
502 if (sor->dpaux) {
503 /* FIXME: properly convert to struct drm_dp_aux */
504 struct drm_dp_aux *aux = (struct drm_dp_aux *)sor->dpaux;
505 struct drm_dp_link link;
506 u8 rate, lanes;
507
508 err = drm_dp_link_probe(aux, &link);
509 if (err < 0) {
510 dev_err(sor->dev, "failed to probe eDP link: %d\n",
511 err);
512 return err;
513 }
514
515 err = drm_dp_link_power_up(aux, &link);
516 if (err < 0) {
517 dev_err(sor->dev, "failed to power up eDP link: %d\n",
518 err);
519 return err;
520 }
521
522 err = drm_dp_link_configure(aux, &link);
523 if (err < 0) {
524 dev_err(sor->dev, "failed to configure eDP link: %d\n",
525 err);
526 return err;
527 }
528
529 rate = drm_dp_link_rate_to_bw_code(link.rate);
530 lanes = link.num_lanes;
531
532 value = tegra_sor_readl(sor, SOR_CLK_CNTRL);
533 value &= ~SOR_CLK_CNTRL_DP_LINK_SPEED_MASK;
534 value |= SOR_CLK_CNTRL_DP_LINK_SPEED(rate);
535 tegra_sor_writel(sor, value, SOR_CLK_CNTRL);
536
537 value = tegra_sor_readl(sor, SOR_DP_LINKCTL_0);
538 value &= ~SOR_DP_LINKCTL_LANE_COUNT_MASK;
539 value |= SOR_DP_LINKCTL_LANE_COUNT(lanes);
540
541 if (link.capabilities & DP_LINK_CAP_ENHANCED_FRAMING)
542 value |= SOR_DP_LINKCTL_ENHANCED_FRAME;
543
544 tegra_sor_writel(sor, value, SOR_DP_LINKCTL_0);
545
546 /* disable training pattern generator */
547
548 for (i = 0; i < link.num_lanes; i++) {
549 unsigned long lane = SOR_DP_TPG_CHANNEL_CODING |
550 SOR_DP_TPG_SCRAMBLER_GALIOS |
551 SOR_DP_TPG_PATTERN_NONE;
552 value = (value << 8) | lane;
553 }
554
555 tegra_sor_writel(sor, value, SOR_DP_TPG);
556
557 err = tegra_sor_dp_train_fast(sor, &link);
558 if (err < 0) {
559 dev_err(sor->dev, "DP fast link training failed: %d\n",
560 err);
561 return err;
562 }
563
564 dev_dbg(sor->dev, "fast link training succeeded\n");
565 }
566
567 err = tegra_sor_power_up(sor, 250);
568 if (err < 0) {
569 dev_err(sor->dev, "failed to power up SOR: %d\n", err);
570 return err;
571 }
572
573 /* start display controller in continuous mode */
574 value = tegra_dc_readl(dc, DC_CMD_STATE_ACCESS);
575 value |= WRITE_MUX;
576 tegra_dc_writel(dc, value, DC_CMD_STATE_ACCESS);
577
578 tegra_dc_writel(dc, VSYNC_H_POSITION(1), DC_DISP_DISP_TIMING_OPTIONS);
579 tegra_dc_writel(dc, DISP_CTRL_MODE_C_DISPLAY, DC_CMD_DISPLAY_COMMAND);
580
581 value = tegra_dc_readl(dc, DC_CMD_STATE_ACCESS);
582 value &= ~WRITE_MUX;
583 tegra_dc_writel(dc, value, DC_CMD_STATE_ACCESS);
584
585 /*
586 * configure panel (24bpp, vsync-, hsync-, DP-A protocol, complete
587 * raster, associate with display controller)
588 */
589 value = SOR_STATE_ASY_PIXELDEPTH_BPP_24_444 |
590 SOR_STATE_ASY_VSYNCPOL |
591 SOR_STATE_ASY_HSYNCPOL |
592 SOR_STATE_ASY_PROTOCOL_DP_A |
593 SOR_STATE_ASY_CRC_MODE_COMPLETE |
594 SOR_STATE_ASY_OWNER(dc->pipe + 1);
595 tegra_sor_writel(sor, value, SOR_STATE_1);
596
597 /*
598 * TODO: The video timing programming below doesn't seem to match the
599 * register definitions.
600 */
601
602 value = ((mode->vtotal & 0x7fff) << 16) | (mode->htotal & 0x7fff);
603 tegra_sor_writel(sor, value, SOR_HEAD_STATE_1(0));
604
605 vse = mode->vsync_end - mode->vsync_start - 1;
606 hse = mode->hsync_end - mode->hsync_start - 1;
607
608 value = ((vse & 0x7fff) << 16) | (hse & 0x7fff);
609 tegra_sor_writel(sor, value, SOR_HEAD_STATE_2(0));
610
611 vbe = vse + (mode->vsync_start - mode->vdisplay);
612 hbe = hse + (mode->hsync_start - mode->hdisplay);
613
614 value = ((vbe & 0x7fff) << 16) | (hbe & 0x7fff);
615 tegra_sor_writel(sor, value, SOR_HEAD_STATE_3(0));
616
617 vbs = vbe + mode->vdisplay;
618 hbs = hbe + mode->hdisplay;
619
620 value = ((vbs & 0x7fff) << 16) | (hbs & 0x7fff);
621 tegra_sor_writel(sor, value, SOR_HEAD_STATE_4(0));
622
623 /* XXX interlaced mode */
624 tegra_sor_writel(sor, 0x00000001, SOR_HEAD_STATE_5(0));
625
626 /* CSTM (LVDS, link A/B, upper) */
627 value = SOR_CSTM_LVDS | SOR_CSTM_LINK_ACT_B | SOR_CSTM_LINK_ACT_B |
628 SOR_CSTM_UPPER;
629 tegra_sor_writel(sor, value, SOR_CSTM);
630
631 /* PWM setup */
632 err = tegra_sor_setup_pwm(sor, 250);
633 if (err < 0) {
634 dev_err(sor->dev, "failed to setup PWM: %d\n", err);
635 return err;
636 }
637
638 value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
639 value |= SOR_ENABLE;
640 tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
641
642 tegra_sor_update(sor);
643
644 err = tegra_sor_attach(sor);
645 if (err < 0) {
646 dev_err(sor->dev, "failed to attach SOR: %d\n", err);
647 return err;
648 }
649
650 err = tegra_sor_wakeup(sor);
651 if (err < 0) {
652 dev_err(sor->dev, "failed to enable DC: %d\n", err);
653 return err;
654 }
655
656 sor->enabled = true;
657
658 return 0;
659}
660
661static int tegra_sor_detach(struct tegra_sor *sor)
662{
663 unsigned long value, timeout;
664
665 /* switch to safe mode */
666 value = tegra_sor_readl(sor, SOR_SUPER_STATE_1);
667 value &= ~SOR_SUPER_STATE_MODE_NORMAL;
668 tegra_sor_writel(sor, value, SOR_SUPER_STATE_1);
669 tegra_sor_super_update(sor);
670
671 timeout = jiffies + msecs_to_jiffies(250);
672
673 while (time_before(jiffies, timeout)) {
674 value = tegra_sor_readl(sor, SOR_PWR);
675 if (value & SOR_PWR_MODE_SAFE)
676 break;
677 }
678
679 if ((value & SOR_PWR_MODE_SAFE) == 0)
680 return -ETIMEDOUT;
681
682 /* go to sleep */
683 value = tegra_sor_readl(sor, SOR_SUPER_STATE_1);
684 value &= ~SOR_SUPER_STATE_HEAD_MODE_MASK;
685 tegra_sor_writel(sor, value, SOR_SUPER_STATE_1);
686 tegra_sor_super_update(sor);
687
688 /* detach */
689 value = tegra_sor_readl(sor, SOR_SUPER_STATE_1);
690 value &= ~SOR_SUPER_STATE_ATTACHED;
691 tegra_sor_writel(sor, value, SOR_SUPER_STATE_1);
692 tegra_sor_super_update(sor);
693
694 timeout = jiffies + msecs_to_jiffies(250);
695
696 while (time_before(jiffies, timeout)) {
697 value = tegra_sor_readl(sor, SOR_TEST);
698 if ((value & SOR_TEST_ATTACHED) == 0)
699 break;
700
701 usleep_range(25, 100);
702 }
703
704 if ((value & SOR_TEST_ATTACHED) != 0)
705 return -ETIMEDOUT;
706
707 return 0;
708}
709
710static int tegra_sor_power_down(struct tegra_sor *sor)
711{
712 unsigned long value, timeout;
713 int err;
714
715 value = tegra_sor_readl(sor, SOR_PWR);
716 value &= ~SOR_PWR_NORMAL_STATE_PU;
717 value |= SOR_PWR_TRIGGER;
718 tegra_sor_writel(sor, value, SOR_PWR);
719
720 timeout = jiffies + msecs_to_jiffies(250);
721
722 while (time_before(jiffies, timeout)) {
723 value = tegra_sor_readl(sor, SOR_PWR);
724 if ((value & SOR_PWR_TRIGGER) == 0)
725 return 0;
726
727 usleep_range(25, 100);
728 }
729
730 if ((value & SOR_PWR_TRIGGER) != 0)
731 return -ETIMEDOUT;
732
733 err = clk_set_parent(sor->clk, sor->clk_safe);
734 if (err < 0)
735 dev_err(sor->dev, "failed to set safe parent clock: %d\n", err);
736
737 value = tegra_sor_readl(sor, SOR_DP_PADCTL_0);
738 value &= ~(SOR_DP_PADCTL_PD_TXD_3 | SOR_DP_PADCTL_PD_TXD_0 |
739 SOR_DP_PADCTL_PD_TXD_1 | SOR_DP_PADCTL_PD_TXD_2);
740 tegra_sor_writel(sor, value, SOR_DP_PADCTL_0);
741
742 /* stop lane sequencer */
743 value = SOR_LANE_SEQ_CTL_TRIGGER | SOR_LANE_SEQ_CTL_SEQUENCE_DOWN |
744 SOR_LANE_SEQ_CTL_POWER_STATE_DOWN;
745 tegra_sor_writel(sor, value, SOR_LANE_SEQ_CTL);
746
747 timeout = jiffies + msecs_to_jiffies(250);
748
749 while (time_before(jiffies, timeout)) {
750 value = tegra_sor_readl(sor, SOR_LANE_SEQ_CTL);
751 if ((value & SOR_LANE_SEQ_CTL_TRIGGER) == 0)
752 break;
753
754 usleep_range(25, 100);
755 }
756
757 if ((value & SOR_LANE_SEQ_CTL_TRIGGER) != 0)
758 return -ETIMEDOUT;
759
760 value = tegra_sor_readl(sor, SOR_PLL_2);
761 value |= SOR_PLL_2_PORT_POWERDOWN;
762 tegra_sor_writel(sor, value, SOR_PLL_2);
763
764 usleep_range(20, 100);
765
766 value = tegra_sor_readl(sor, SOR_PLL_0);
767 value |= SOR_PLL_0_POWER_OFF;
768 value |= SOR_PLL_0_VCOPD;
769 tegra_sor_writel(sor, value, SOR_PLL_0);
770
771 value = tegra_sor_readl(sor, SOR_PLL_2);
772 value |= SOR_PLL_2_SEQ_PLLCAPPD;
773 value |= SOR_PLL_2_SEQ_PLLCAPPD_ENFORCE;
774 tegra_sor_writel(sor, value, SOR_PLL_2);
775
776 usleep_range(20, 100);
777
778 return 0;
779}
780
781static int tegra_output_sor_disable(struct tegra_output *output)
782{
783 struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc);
784 struct tegra_sor *sor = to_sor(output);
785 unsigned long value;
786 int err;
787
788 if (!sor->enabled)
789 return 0;
790
791 err = tegra_sor_detach(sor);
792 if (err < 0) {
793 dev_err(sor->dev, "failed to detach SOR: %d\n", err);
794 return err;
795 }
796
797 tegra_sor_writel(sor, 0, SOR_STATE_1);
798 tegra_sor_update(sor);
799
800 /*
801 * The following accesses registers of the display controller, so make
802 * sure it's only executed when the output is attached to one.
803 */
804 if (dc) {
805 /*
806 * XXX: We can't do this here because it causes the SOR to go
807 * into an erroneous state and the output will look scrambled
808 * the next time it is enabled. Presumably this is because we
809 * should be doing this only on the next VBLANK. A possible
810 * solution would be to queue a "power-off" event to trigger
811 * this code to be run during the next VBLANK.
812 */
813 /*
814 value = tegra_dc_readl(dc, DC_CMD_DISPLAY_POWER_CONTROL);
815 value &= ~(PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
816 PW4_ENABLE | PM0_ENABLE | PM1_ENABLE);
817 tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL);
818 */
819
820 value = tegra_dc_readl(dc, DC_CMD_DISPLAY_COMMAND);
821 value &= ~DISP_CTRL_MODE_MASK;
822 tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND);
823
824 value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
825 value &= ~SOR_ENABLE;
826 tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
827
828 tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
829 tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
830 }
831
832 err = tegra_sor_power_down(sor);
833 if (err < 0) {
834 dev_err(sor->dev, "failed to power down SOR: %d\n", err);
835 return err;
836 }
837
838 if (sor->dpaux) {
839 err = tegra_dpaux_disable(sor->dpaux);
840 if (err < 0) {
841 dev_err(sor->dev, "failed to disable DP: %d\n", err);
842 return err;
843 }
844 }
845
846 err = tegra_io_rail_power_off(TEGRA_IO_RAIL_LVDS);
847 if (err < 0) {
848 dev_err(sor->dev, "failed to power off I/O rail: %d\n", err);
849 return err;
850 }
851
852 reset_control_assert(sor->rst);
853 clk_disable_unprepare(sor->clk);
854
855 sor->enabled = false;
856
857 return 0;
858}
859
860static int tegra_output_sor_setup_clock(struct tegra_output *output,
861 struct clk *clk, unsigned long pclk)
862{
863 struct tegra_sor *sor = to_sor(output);
864 int err;
865
866 /* round to next MHz */
867 pclk = DIV_ROUND_UP(pclk / 2, 1000000) * 1000000;
868
869 err = clk_set_parent(clk, sor->clk_parent);
870 if (err < 0) {
871 dev_err(sor->dev, "failed to set parent clock: %d\n", err);
872 return err;
873 }
874
875 err = clk_set_rate(sor->clk_parent, pclk);
876 if (err < 0) {
877 dev_err(sor->dev, "failed to set base clock rate to %lu Hz\n",
878 pclk * 2);
879 return err;
880 }
881
882 return 0;
883}
884
885static int tegra_output_sor_check_mode(struct tegra_output *output,
886 struct drm_display_mode *mode,
887 enum drm_mode_status *status)
888{
889 /*
890 * FIXME: For now, always assume that the mode is okay.
891 */
892
893 *status = MODE_OK;
894
895 return 0;
896}
897
898static enum drm_connector_status
899tegra_output_sor_detect(struct tegra_output *output)
900{
901 struct tegra_sor *sor = to_sor(output);
902
903 if (sor->dpaux)
904 return tegra_dpaux_detect(sor->dpaux);
905
906 return connector_status_unknown;
907}
908
909static const struct tegra_output_ops sor_ops = {
910 .enable = tegra_output_sor_enable,
911 .disable = tegra_output_sor_disable,
912 .setup_clock = tegra_output_sor_setup_clock,
913 .check_mode = tegra_output_sor_check_mode,
914 .detect = tegra_output_sor_detect,
915};
916
917static int tegra_sor_init(struct host1x_client *client)
918{
919 struct tegra_drm *tegra = dev_get_drvdata(client->parent);
920 struct tegra_sor *sor = host1x_client_to_sor(client);
921 int err;
922
923 if (!sor->dpaux)
924 return -ENODEV;
925
926 sor->output.type = TEGRA_OUTPUT_EDP;
927
928 sor->output.dev = sor->dev;
929 sor->output.ops = &sor_ops;
930
931 err = tegra_output_init(tegra->drm, &sor->output);
932 if (err < 0) {
933 dev_err(sor->dev, "output setup failed: %d\n", err);
934 return err;
935 }
936
937 if (sor->dpaux) {
938 err = tegra_dpaux_attach(sor->dpaux, &sor->output);
939 if (err < 0) {
940 dev_err(sor->dev, "failed to attach DP: %d\n", err);
941 return err;
942 }
943 }
944
945 return 0;
946}
947
948static int tegra_sor_exit(struct host1x_client *client)
949{
950 struct tegra_sor *sor = host1x_client_to_sor(client);
951 int err;
952
953 err = tegra_output_disable(&sor->output);
954 if (err < 0) {
955 dev_err(sor->dev, "output failed to disable: %d\n", err);
956 return err;
957 }
958
959 if (sor->dpaux) {
960 err = tegra_dpaux_detach(sor->dpaux);
961 if (err < 0) {
962 dev_err(sor->dev, "failed to detach DP: %d\n", err);
963 return err;
964 }
965 }
966
967 err = tegra_output_exit(&sor->output);
968 if (err < 0) {
969 dev_err(sor->dev, "output cleanup failed: %d\n", err);
970 return err;
971 }
972
973 return 0;
974}
975
976static const struct host1x_client_ops sor_client_ops = {
977 .init = tegra_sor_init,
978 .exit = tegra_sor_exit,
979};
980
981static int tegra_sor_probe(struct platform_device *pdev)
982{
983 struct device_node *np;
984 struct tegra_sor *sor;
985 struct resource *regs;
986 int err;
987
988 sor = devm_kzalloc(&pdev->dev, sizeof(*sor), GFP_KERNEL);
989 if (!sor)
990 return -ENOMEM;
991
992 sor->output.dev = sor->dev = &pdev->dev;
993
994 np = of_parse_phandle(pdev->dev.of_node, "nvidia,dpaux", 0);
995 if (np) {
996 sor->dpaux = tegra_dpaux_find_by_of_node(np);
997 of_node_put(np);
998
999 if (!sor->dpaux)
1000 return -EPROBE_DEFER;
1001 }
1002
1003 err = tegra_output_probe(&sor->output);
1004 if (err < 0)
1005 return err;
1006
1007 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1008 sor->regs = devm_ioremap_resource(&pdev->dev, regs);
1009 if (IS_ERR(sor->regs))
1010 return PTR_ERR(sor->regs);
1011
1012 sor->rst = devm_reset_control_get(&pdev->dev, "sor");
1013 if (IS_ERR(sor->rst))
1014 return PTR_ERR(sor->rst);
1015
1016 sor->clk = devm_clk_get(&pdev->dev, NULL);
1017 if (IS_ERR(sor->clk))
1018 return PTR_ERR(sor->clk);
1019
1020 sor->clk_parent = devm_clk_get(&pdev->dev, "parent");
1021 if (IS_ERR(sor->clk_parent))
1022 return PTR_ERR(sor->clk_parent);
1023
1024 err = clk_prepare_enable(sor->clk_parent);
1025 if (err < 0)
1026 return err;
1027
1028 sor->clk_safe = devm_clk_get(&pdev->dev, "safe");
1029 if (IS_ERR(sor->clk_safe))
1030 return PTR_ERR(sor->clk_safe);
1031
1032 err = clk_prepare_enable(sor->clk_safe);
1033 if (err < 0)
1034 return err;
1035
1036 sor->clk_dp = devm_clk_get(&pdev->dev, "dp");
1037 if (IS_ERR(sor->clk_dp))
1038 return PTR_ERR(sor->clk_dp);
1039
1040 err = clk_prepare_enable(sor->clk_dp);
1041 if (err < 0)
1042 return err;
1043
1044 INIT_LIST_HEAD(&sor->client.list);
1045 sor->client.ops = &sor_client_ops;
1046 sor->client.dev = &pdev->dev;
1047
1048 err = host1x_client_register(&sor->client);
1049 if (err < 0) {
1050 dev_err(&pdev->dev, "failed to register host1x client: %d\n",
1051 err);
1052 return err;
1053 }
1054
1055 platform_set_drvdata(pdev, sor);
1056
1057 return 0;
1058}
1059
1060static int tegra_sor_remove(struct platform_device *pdev)
1061{
1062 struct tegra_sor *sor = platform_get_drvdata(pdev);
1063 int err;
1064
1065 err = host1x_client_unregister(&sor->client);
1066 if (err < 0) {
1067 dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
1068 err);
1069 return err;
1070 }
1071
1072 clk_disable_unprepare(sor->clk_parent);
1073 clk_disable_unprepare(sor->clk_safe);
1074 clk_disable_unprepare(sor->clk_dp);
1075 clk_disable_unprepare(sor->clk);
1076
1077 return 0;
1078}
1079
1080static const struct of_device_id tegra_sor_of_match[] = {
1081 { .compatible = "nvidia,tegra124-sor", },
1082 { },
1083};
1084
1085struct platform_driver tegra_sor_driver = {
1086 .driver = {
1087 .name = "tegra-sor",
1088 .of_match_table = tegra_sor_of_match,
1089 },
1090 .probe = tegra_sor_probe,
1091 .remove = tegra_sor_remove,
1092};
diff --git a/drivers/gpu/drm/tegra/sor.h b/drivers/gpu/drm/tegra/sor.h
new file mode 100644
index 000000000000..f4156d54cd05
--- /dev/null
+++ b/drivers/gpu/drm/tegra/sor.h
@@ -0,0 +1,278 @@
1/*
2 * Copyright (C) 2013 NVIDIA Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#ifndef DRM_TEGRA_SOR_H
10#define DRM_TEGRA_SOR_H
11
12#define SOR_CTXSW 0x00
13
14#define SOR_SUPER_STATE_0 0x01
15
16#define SOR_SUPER_STATE_1 0x02
17#define SOR_SUPER_STATE_ATTACHED (1 << 3)
18#define SOR_SUPER_STATE_MODE_NORMAL (1 << 2)
19#define SOR_SUPER_STATE_HEAD_MODE_MASK (3 << 0)
20#define SOR_SUPER_STATE_HEAD_MODE_AWAKE (2 << 0)
21#define SOR_SUPER_STATE_HEAD_MODE_SNOOZE (1 << 0)
22#define SOR_SUPER_STATE_HEAD_MODE_SLEEP (0 << 0)
23
24#define SOR_STATE_0 0x03
25
26#define SOR_STATE_1 0x04
27#define SOR_STATE_ASY_PIXELDEPTH_MASK (0xf << 17)
28#define SOR_STATE_ASY_PIXELDEPTH_BPP_18_444 (0x2 << 17)
29#define SOR_STATE_ASY_PIXELDEPTH_BPP_24_444 (0x5 << 17)
30#define SOR_STATE_ASY_VSYNCPOL (1 << 13)
31#define SOR_STATE_ASY_HSYNCPOL (1 << 12)
32#define SOR_STATE_ASY_PROTOCOL_MASK (0xf << 8)
33#define SOR_STATE_ASY_PROTOCOL_CUSTOM (0xf << 8)
34#define SOR_STATE_ASY_PROTOCOL_DP_A (0x8 << 8)
35#define SOR_STATE_ASY_PROTOCOL_DP_B (0x9 << 8)
36#define SOR_STATE_ASY_PROTOCOL_LVDS (0x0 << 8)
37#define SOR_STATE_ASY_CRC_MODE_MASK (0x3 << 6)
38#define SOR_STATE_ASY_CRC_MODE_NON_ACTIVE (0x2 << 6)
39#define SOR_STATE_ASY_CRC_MODE_COMPLETE (0x1 << 6)
40#define SOR_STATE_ASY_CRC_MODE_ACTIVE (0x0 << 6)
41#define SOR_STATE_ASY_OWNER(x) (((x) & 0xf) << 0)
42
43#define SOR_HEAD_STATE_0(x) (0x05 + (x))
44#define SOR_HEAD_STATE_1(x) (0x07 + (x))
45#define SOR_HEAD_STATE_2(x) (0x09 + (x))
46#define SOR_HEAD_STATE_3(x) (0x0b + (x))
47#define SOR_HEAD_STATE_4(x) (0x0d + (x))
48#define SOR_HEAD_STATE_5(x) (0x0f + (x))
49#define SOR_CRC_CNTRL 0x11
50#define SOR_DP_DEBUG_MVID 0x12
51
52#define SOR_CLK_CNTRL 0x13
53#define SOR_CLK_CNTRL_DP_LINK_SPEED_MASK (0x1f << 2)
54#define SOR_CLK_CNTRL_DP_LINK_SPEED(x) (((x) & 0x1f) << 2)
55#define SOR_CLK_CNTRL_DP_LINK_SPEED_G1_62 (0x06 << 2)
56#define SOR_CLK_CNTRL_DP_LINK_SPEED_G2_70 (0x0a << 2)
57#define SOR_CLK_CNTRL_DP_LINK_SPEED_G5_40 (0x14 << 2)
58#define SOR_CLK_CNTRL_DP_CLK_SEL_MASK (3 << 0)
59#define SOR_CLK_CNTRL_DP_CLK_SEL_SINGLE_PCLK (0 << 0)
60#define SOR_CLK_CNTRL_DP_CLK_SEL_DIFF_PCLK (1 << 0)
61#define SOR_CLK_CNTRL_DP_CLK_SEL_SINGLE_DPCLK (2 << 0)
62#define SOR_CLK_CNTRL_DP_CLK_SEL_DIFF_DPCLK (3 << 0)
63
64#define SOR_CAP 0x14
65
66#define SOR_PWR 0x15
67#define SOR_PWR_TRIGGER (1 << 31)
68#define SOR_PWR_MODE_SAFE (1 << 28)
69#define SOR_PWR_NORMAL_STATE_PU (1 << 0)
70
71#define SOR_TEST 0x16
72#define SOR_TEST_ATTACHED (1 << 10)
73#define SOR_TEST_HEAD_MODE_MASK (3 << 8)
74#define SOR_TEST_HEAD_MODE_AWAKE (2 << 8)
75
76#define SOR_PLL_0 0x17
77#define SOR_PLL_0_ICHPMP_MASK (0xf << 24)
78#define SOR_PLL_0_ICHPMP(x) (((x) & 0xf) << 24)
79#define SOR_PLL_0_VCOCAP_MASK (0xf << 8)
80#define SOR_PLL_0_VCOCAP(x) (((x) & 0xf) << 8)
81#define SOR_PLL_0_VCOCAP_RST SOR_PLL_0_VCOCAP(3)
82#define SOR_PLL_0_PLLREG_MASK (0x3 << 6)
83#define SOR_PLL_0_PLLREG_LEVEL(x) (((x) & 0x3) << 6)
84#define SOR_PLL_0_PLLREG_LEVEL_V25 SOR_PLL_0_PLLREG_LEVEL(0)
85#define SOR_PLL_0_PLLREG_LEVEL_V15 SOR_PLL_0_PLLREG_LEVEL(1)
86#define SOR_PLL_0_PLLREG_LEVEL_V35 SOR_PLL_0_PLLREG_LEVEL(2)
87#define SOR_PLL_0_PLLREG_LEVEL_V45 SOR_PLL_0_PLLREG_LEVEL(3)
88#define SOR_PLL_0_PULLDOWN (1 << 5)
89#define SOR_PLL_0_RESISTOR_EXT (1 << 4)
90#define SOR_PLL_0_VCOPD (1 << 2)
91#define SOR_PLL_0_POWER_OFF (1 << 0)
92
93#define SOR_PLL_1 0x18
94/* XXX: read-only bit? */
95#define SOR_PLL_1_TERM_COMPOUT (1 << 15)
96#define SOR_PLL_1_TMDS_TERM (1 << 8)
97
98#define SOR_PLL_2 0x19
99#define SOR_PLL_2_LVDS_ENABLE (1 << 25)
100#define SOR_PLL_2_SEQ_PLLCAPPD_ENFORCE (1 << 24)
101#define SOR_PLL_2_PORT_POWERDOWN (1 << 23)
102#define SOR_PLL_2_BANDGAP_POWERDOWN (1 << 22)
103#define SOR_PLL_2_POWERDOWN_OVERRIDE (1 << 18)
104#define SOR_PLL_2_SEQ_PLLCAPPD (1 << 17)
105
106#define SOR_PLL_3 0x1a
107#define SOR_PLL_3_PLL_VDD_MODE_V1_8 (0 << 13)
108#define SOR_PLL_3_PLL_VDD_MODE_V3_3 (1 << 13)
109
110#define SOR_CSTM 0x1b
111#define SOR_CSTM_LVDS (1 << 16)
112#define SOR_CSTM_LINK_ACT_B (1 << 15)
113#define SOR_CSTM_LINK_ACT_A (1 << 14)
114#define SOR_CSTM_UPPER (1 << 11)
115
116#define SOR_LVDS 0x1c
117#define SOR_CRC_A 0x1d
118#define SOR_CRC_B 0x1e
119#define SOR_BLANK 0x1f
120#define SOR_SEQ_CTL 0x20
121
122#define SOR_LANE_SEQ_CTL 0x21
123#define SOR_LANE_SEQ_CTL_TRIGGER (1 << 31)
124#define SOR_LANE_SEQ_CTL_SEQUENCE_UP (0 << 20)
125#define SOR_LANE_SEQ_CTL_SEQUENCE_DOWN (1 << 20)
126#define SOR_LANE_SEQ_CTL_POWER_STATE_UP (0 << 16)
127#define SOR_LANE_SEQ_CTL_POWER_STATE_DOWN (1 << 16)
128
129#define SOR_SEQ_INST(x) (0x22 + (x))
130
131#define SOR_PWM_DIV 0x32
132#define SOR_PWM_DIV_MASK 0xffffff
133
134#define SOR_PWM_CTL 0x33
135#define SOR_PWM_CTL_TRIGGER (1 << 31)
136#define SOR_PWM_CTL_CLK_SEL (1 << 30)
137#define SOR_PWM_CTL_DUTY_CYCLE_MASK 0xffffff
138
139#define SOR_VCRC_A_0 0x34
140#define SOR_VCRC_A_1 0x35
141#define SOR_VCRC_B_0 0x36
142#define SOR_VCRC_B_1 0x37
143#define SOR_CCRC_A_0 0x38
144#define SOR_CCRC_A_1 0x39
145#define SOR_CCRC_B_0 0x3a
146#define SOR_CCRC_B_1 0x3b
147#define SOR_EDATA_A_0 0x3c
148#define SOR_EDATA_A_1 0x3d
149#define SOR_EDATA_B_0 0x3e
150#define SOR_EDATA_B_1 0x3f
151#define SOR_COUNT_A_0 0x40
152#define SOR_COUNT_A_1 0x41
153#define SOR_COUNT_B_0 0x42
154#define SOR_COUNT_B_1 0x43
155#define SOR_DEBUG_A_0 0x44
156#define SOR_DEBUG_A_1 0x45
157#define SOR_DEBUG_B_0 0x46
158#define SOR_DEBUG_B_1 0x47
159#define SOR_TRIG 0x48
160#define SOR_MSCHECK 0x49
161#define SOR_XBAR_CTRL 0x4a
162#define SOR_XBAR_POL 0x4b
163
164#define SOR_DP_LINKCTL_0 0x4c
165#define SOR_DP_LINKCTL_LANE_COUNT_MASK (0x1f << 16)
166#define SOR_DP_LINKCTL_LANE_COUNT(x) (((1 << (x)) - 1) << 16)
167#define SOR_DP_LINKCTL_ENHANCED_FRAME (1 << 14)
168#define SOR_DP_LINKCTL_TU_SIZE_MASK (0x7f << 2)
169#define SOR_DP_LINKCTL_TU_SIZE(x) (((x) & 0x7f) << 2)
170#define SOR_DP_LINKCTL_ENABLE (1 << 0)
171
172#define SOR_DP_LINKCTL_1 0x4d
173
174#define SOR_LANE_DRIVE_CURRENT_0 0x4e
175#define SOR_LANE_DRIVE_CURRENT_1 0x4f
176#define SOR_LANE4_DRIVE_CURRENT_0 0x50
177#define SOR_LANE4_DRIVE_CURRENT_1 0x51
178#define SOR_LANE_DRIVE_CURRENT_LANE3(x) (((x) & 0xff) << 24)
179#define SOR_LANE_DRIVE_CURRENT_LANE2(x) (((x) & 0xff) << 16)
180#define SOR_LANE_DRIVE_CURRENT_LANE1(x) (((x) & 0xff) << 8)
181#define SOR_LANE_DRIVE_CURRENT_LANE0(x) (((x) & 0xff) << 0)
182
183#define SOR_LANE_PREEMPHASIS_0 0x52
184#define SOR_LANE_PREEMPHASIS_1 0x53
185#define SOR_LANE4_PREEMPHASIS_0 0x54
186#define SOR_LANE4_PREEMPHASIS_1 0x55
187#define SOR_LANE_PREEMPHASIS_LANE3(x) (((x) & 0xff) << 24)
188#define SOR_LANE_PREEMPHASIS_LANE2(x) (((x) & 0xff) << 16)
189#define SOR_LANE_PREEMPHASIS_LANE1(x) (((x) & 0xff) << 8)
190#define SOR_LANE_PREEMPHASIS_LANE0(x) (((x) & 0xff) << 0)
191
192#define SOR_LANE_POST_CURSOR_0 0x56
193#define SOR_LANE_POST_CURSOR_1 0x57
194#define SOR_LANE_POST_CURSOR_LANE3(x) (((x) & 0xff) << 24)
195#define SOR_LANE_POST_CURSOR_LANE2(x) (((x) & 0xff) << 16)
196#define SOR_LANE_POST_CURSOR_LANE1(x) (((x) & 0xff) << 8)
197#define SOR_LANE_POST_CURSOR_LANE0(x) (((x) & 0xff) << 0)
198
199#define SOR_DP_CONFIG_0 0x58
200#define SOR_DP_CONFIG_DISPARITY_NEGATIVE (1 << 31)
201#define SOR_DP_CONFIG_ACTIVE_SYM_ENABLE (1 << 26)
202#define SOR_DP_CONFIG_ACTIVE_SYM_POLARITY (1 << 24)
203#define SOR_DP_CONFIG_ACTIVE_SYM_FRAC_MASK (0xf << 16)
204#define SOR_DP_CONFIG_ACTIVE_SYM_FRAC(x) (((x) & 0xf) << 16)
205#define SOR_DP_CONFIG_ACTIVE_SYM_COUNT_MASK (0x7f << 8)
206#define SOR_DP_CONFIG_ACTIVE_SYM_COUNT(x) (((x) & 0x7f) << 8)
207#define SOR_DP_CONFIG_WATERMARK_MASK (0x3f << 0)
208#define SOR_DP_CONFIG_WATERMARK(x) (((x) & 0x3f) << 0)
209
210#define SOR_DP_CONFIG_1 0x59
211#define SOR_DP_MN_0 0x5a
212#define SOR_DP_MN_1 0x5b
213
214#define SOR_DP_PADCTL_0 0x5c
215#define SOR_DP_PADCTL_PAD_CAL_PD (1 << 23)
216#define SOR_DP_PADCTL_TX_PU_ENABLE (1 << 22)
217#define SOR_DP_PADCTL_TX_PU_MASK (0xff << 8)
218#define SOR_DP_PADCTL_TX_PU(x) (((x) & 0xff) << 8)
219#define SOR_DP_PADCTL_CM_TXD_3 (1 << 7)
220#define SOR_DP_PADCTL_CM_TXD_2 (1 << 6)
221#define SOR_DP_PADCTL_CM_TXD_1 (1 << 5)
222#define SOR_DP_PADCTL_CM_TXD_0 (1 << 4)
223#define SOR_DP_PADCTL_PD_TXD_3 (1 << 3)
224#define SOR_DP_PADCTL_PD_TXD_0 (1 << 2)
225#define SOR_DP_PADCTL_PD_TXD_1 (1 << 1)
226#define SOR_DP_PADCTL_PD_TXD_2 (1 << 0)
227
228#define SOR_DP_PADCTL_1 0x5d
229
230#define SOR_DP_DEBUG_0 0x5e
231#define SOR_DP_DEBUG_1 0x5f
232
233#define SOR_DP_SPARE_0 0x60
234#define SOR_DP_SPARE_MACRO_SOR_CLK (1 << 2)
235#define SOR_DP_SPARE_PANEL_INTERNAL (1 << 1)
236#define SOR_DP_SPARE_SEQ_ENABLE (1 << 0)
237
238#define SOR_DP_SPARE_1 0x61
239#define SOR_DP_AUDIO_CTRL 0x62
240
241#define SOR_DP_AUDIO_HBLANK_SYMBOLS 0x63
242#define SOR_DP_AUDIO_HBLANK_SYMBOLS_MASK (0x01ffff << 0)
243
244#define SOR_DP_AUDIO_VBLANK_SYMBOLS 0x64
245#define SOR_DP_AUDIO_VBLANK_SYMBOLS_MASK (0x1fffff << 0)
246
247#define SOR_DP_GENERIC_INFOFRAME_HEADER 0x65
248#define SOR_DP_GENERIC_INFOFRAME_SUBPACK_0 0x66
249#define SOR_DP_GENERIC_INFOFRAME_SUBPACK_1 0x67
250#define SOR_DP_GENERIC_INFOFRAME_SUBPACK_2 0x68
251#define SOR_DP_GENERIC_INFOFRAME_SUBPACK_3 0x69
252#define SOR_DP_GENERIC_INFOFRAME_SUBPACK_4 0x6a
253#define SOR_DP_GENERIC_INFOFRAME_SUBPACK_5 0x6b
254#define SOR_DP_GENERIC_INFOFRAME_SUBPACK_6 0x6c
255
256#define SOR_DP_TPG 0x6d
257#define SOR_DP_TPG_CHANNEL_CODING (1 << 6)
258#define SOR_DP_TPG_SCRAMBLER_MASK (3 << 4)
259#define SOR_DP_TPG_SCRAMBLER_FIBONACCI (2 << 4)
260#define SOR_DP_TPG_SCRAMBLER_GALIOS (1 << 4)
261#define SOR_DP_TPG_SCRAMBLER_NONE (0 << 4)
262#define SOR_DP_TPG_PATTERN_MASK (0xf << 0)
263#define SOR_DP_TPG_PATTERN_HBR2 (0x8 << 0)
264#define SOR_DP_TPG_PATTERN_CSTM (0x7 << 0)
265#define SOR_DP_TPG_PATTERN_PRBS7 (0x6 << 0)
266#define SOR_DP_TPG_PATTERN_SBLERRRATE (0x5 << 0)
267#define SOR_DP_TPG_PATTERN_D102 (0x4 << 0)
268#define SOR_DP_TPG_PATTERN_TRAIN3 (0x3 << 0)
269#define SOR_DP_TPG_PATTERN_TRAIN2 (0x2 << 0)
270#define SOR_DP_TPG_PATTERN_TRAIN1 (0x1 << 0)
271#define SOR_DP_TPG_PATTERN_NONE (0x0 << 0)
272
273#define SOR_DP_TPG_CONFIG 0x6e
274#define SOR_DP_LQ_CSTM_0 0x6f
275#define SOR_DP_LQ_CSTM_1 0x70
276#define SOR_DP_LQ_CSTM_2 0x71
277
278#endif
diff --git a/drivers/gpu/host1x/syncpt.c b/drivers/gpu/host1x/syncpt.c
index bfb09d802abd..b10550ee1d89 100644
--- a/drivers/gpu/host1x/syncpt.c
+++ b/drivers/gpu/host1x/syncpt.c
@@ -102,6 +102,7 @@ u32 host1x_syncpt_incr_max(struct host1x_syncpt *sp, u32 incrs)
102{ 102{
103 return (u32)atomic_add_return(incrs, &sp->max_val); 103 return (u32)atomic_add_return(incrs, &sp->max_val);
104} 104}
105EXPORT_SYMBOL(host1x_syncpt_incr_max);
105 106
106 /* 107 /*
107 * Write cached syncpoint and waitbase values to hardware. 108 * Write cached syncpoint and waitbase values to hardware.