]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/gpu/drm/tegra/sor.c
drm/tegra: sor: Add Tegra210 eDP support
[mirror_ubuntu-artful-kernel.git] / drivers / gpu / drm / tegra / sor.c
CommitLineData
6b6b6042
TR
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>
a82752e1 10#include <linux/debugfs.h>
6fad8f66 11#include <linux/gpio.h>
6b6b6042
TR
12#include <linux/io.h>
13#include <linux/platform_device.h>
14#include <linux/reset.h>
306a7f91 15
7232398a 16#include <soc/tegra/pmc.h>
6b6b6042 17
4aa3df71 18#include <drm/drm_atomic_helper.h>
6b6b6042 19#include <drm/drm_dp_helper.h>
6fad8f66 20#include <drm/drm_panel.h>
6b6b6042
TR
21
22#include "dc.h"
23#include "drm.h"
24#include "sor.h"
25
26struct tegra_sor {
27 struct host1x_client client;
28 struct tegra_output output;
29 struct device *dev;
30
31 void __iomem *regs;
32
33 struct reset_control *rst;
34 struct clk *clk_parent;
35 struct clk *clk_safe;
36 struct clk *clk_dp;
37 struct clk *clk;
38
39 struct tegra_dpaux *dpaux;
40
dab16336
TR
41 struct drm_info_list *debugfs_files;
42 struct drm_minor *minor;
a82752e1 43 struct dentry *debugfs;
6b6b6042
TR
44};
45
34fa183b
TR
46struct tegra_sor_config {
47 u32 bits_per_pixel;
48
49 u32 active_polarity;
50 u32 active_count;
51 u32 tu_size;
52 u32 active_frac;
53 u32 watermark;
7890b576
TR
54
55 u32 hblank_symbols;
56 u32 vblank_symbols;
34fa183b
TR
57};
58
6b6b6042
TR
59static inline struct tegra_sor *
60host1x_client_to_sor(struct host1x_client *client)
61{
62 return container_of(client, struct tegra_sor, client);
63}
64
65static inline struct tegra_sor *to_sor(struct tegra_output *output)
66{
67 return container_of(output, struct tegra_sor, output);
68}
69
28fe2076 70static inline u32 tegra_sor_readl(struct tegra_sor *sor, unsigned long offset)
6b6b6042
TR
71{
72 return readl(sor->regs + (offset << 2));
73}
74
28fe2076 75static inline void tegra_sor_writel(struct tegra_sor *sor, u32 value,
6b6b6042
TR
76 unsigned long offset)
77{
78 writel(value, sor->regs + (offset << 2));
79}
80
81static int tegra_sor_dp_train_fast(struct tegra_sor *sor,
82 struct drm_dp_link *link)
83{
6b6b6042
TR
84 unsigned int i;
85 u8 pattern;
28fe2076 86 u32 value;
6b6b6042
TR
87 int err;
88
89 /* setup lane parameters */
90 value = SOR_LANE_DRIVE_CURRENT_LANE3(0x40) |
91 SOR_LANE_DRIVE_CURRENT_LANE2(0x40) |
92 SOR_LANE_DRIVE_CURRENT_LANE1(0x40) |
93 SOR_LANE_DRIVE_CURRENT_LANE0(0x40);
a9a9e4fd 94 tegra_sor_writel(sor, value, SOR_LANE_DRIVE_CURRENT0);
6b6b6042
TR
95
96 value = SOR_LANE_PREEMPHASIS_LANE3(0x0f) |
97 SOR_LANE_PREEMPHASIS_LANE2(0x0f) |
98 SOR_LANE_PREEMPHASIS_LANE1(0x0f) |
99 SOR_LANE_PREEMPHASIS_LANE0(0x0f);
a9a9e4fd 100 tegra_sor_writel(sor, value, SOR_LANE_PREEMPHASIS0);
6b6b6042 101
a9a9e4fd
TR
102 value = SOR_LANE_POSTCURSOR_LANE3(0x00) |
103 SOR_LANE_POSTCURSOR_LANE2(0x00) |
104 SOR_LANE_POSTCURSOR_LANE1(0x00) |
105 SOR_LANE_POSTCURSOR_LANE0(0x00);
106 tegra_sor_writel(sor, value, SOR_LANE_POSTCURSOR0);
6b6b6042
TR
107
108 /* disable LVDS mode */
109 tegra_sor_writel(sor, 0, SOR_LVDS);
110
a9a9e4fd 111 value = tegra_sor_readl(sor, SOR_DP_PADCTL0);
6b6b6042
TR
112 value |= SOR_DP_PADCTL_TX_PU_ENABLE;
113 value &= ~SOR_DP_PADCTL_TX_PU_MASK;
114 value |= SOR_DP_PADCTL_TX_PU(2); /* XXX: don't hardcode? */
a9a9e4fd 115 tegra_sor_writel(sor, value, SOR_DP_PADCTL0);
6b6b6042 116
a9a9e4fd 117 value = tegra_sor_readl(sor, SOR_DP_PADCTL0);
6b6b6042
TR
118 value |= SOR_DP_PADCTL_CM_TXD_3 | SOR_DP_PADCTL_CM_TXD_2 |
119 SOR_DP_PADCTL_CM_TXD_1 | SOR_DP_PADCTL_CM_TXD_0;
a9a9e4fd 120 tegra_sor_writel(sor, value, SOR_DP_PADCTL0);
6b6b6042
TR
121
122 usleep_range(10, 100);
123
a9a9e4fd 124 value = tegra_sor_readl(sor, SOR_DP_PADCTL0);
6b6b6042
TR
125 value &= ~(SOR_DP_PADCTL_CM_TXD_3 | SOR_DP_PADCTL_CM_TXD_2 |
126 SOR_DP_PADCTL_CM_TXD_1 | SOR_DP_PADCTL_CM_TXD_0);
a9a9e4fd 127 tegra_sor_writel(sor, value, SOR_DP_PADCTL0);
6b6b6042
TR
128
129 err = tegra_dpaux_prepare(sor->dpaux, DP_SET_ANSI_8B10B);
130 if (err < 0)
131 return err;
132
133 for (i = 0, value = 0; i < link->num_lanes; i++) {
134 unsigned long lane = SOR_DP_TPG_CHANNEL_CODING |
135 SOR_DP_TPG_SCRAMBLER_NONE |
136 SOR_DP_TPG_PATTERN_TRAIN1;
137 value = (value << 8) | lane;
138 }
139
140 tegra_sor_writel(sor, value, SOR_DP_TPG);
141
142 pattern = DP_TRAINING_PATTERN_1;
143
144 err = tegra_dpaux_train(sor->dpaux, link, pattern);
145 if (err < 0)
146 return err;
147
a9a9e4fd 148 value = tegra_sor_readl(sor, SOR_DP_SPARE0);
6b6b6042
TR
149 value |= SOR_DP_SPARE_SEQ_ENABLE;
150 value &= ~SOR_DP_SPARE_PANEL_INTERNAL;
151 value |= SOR_DP_SPARE_MACRO_SOR_CLK;
a9a9e4fd 152 tegra_sor_writel(sor, value, SOR_DP_SPARE0);
6b6b6042
TR
153
154 for (i = 0, value = 0; i < link->num_lanes; i++) {
155 unsigned long lane = SOR_DP_TPG_CHANNEL_CODING |
156 SOR_DP_TPG_SCRAMBLER_NONE |
157 SOR_DP_TPG_PATTERN_TRAIN2;
158 value = (value << 8) | lane;
159 }
160
161 tegra_sor_writel(sor, value, SOR_DP_TPG);
162
163 pattern = DP_LINK_SCRAMBLING_DISABLE | DP_TRAINING_PATTERN_2;
164
165 err = tegra_dpaux_train(sor->dpaux, link, pattern);
166 if (err < 0)
167 return err;
168
169 for (i = 0, value = 0; i < link->num_lanes; i++) {
170 unsigned long lane = SOR_DP_TPG_CHANNEL_CODING |
171 SOR_DP_TPG_SCRAMBLER_GALIOS |
172 SOR_DP_TPG_PATTERN_NONE;
173 value = (value << 8) | lane;
174 }
175
176 tegra_sor_writel(sor, value, SOR_DP_TPG);
177
178 pattern = DP_TRAINING_PATTERN_DISABLE;
179
180 err = tegra_dpaux_train(sor->dpaux, link, pattern);
181 if (err < 0)
182 return err;
183
184 return 0;
185}
186
187static void tegra_sor_super_update(struct tegra_sor *sor)
188{
a9a9e4fd
TR
189 tegra_sor_writel(sor, 0, SOR_SUPER_STATE0);
190 tegra_sor_writel(sor, 1, SOR_SUPER_STATE0);
191 tegra_sor_writel(sor, 0, SOR_SUPER_STATE0);
6b6b6042
TR
192}
193
194static void tegra_sor_update(struct tegra_sor *sor)
195{
a9a9e4fd
TR
196 tegra_sor_writel(sor, 0, SOR_STATE0);
197 tegra_sor_writel(sor, 1, SOR_STATE0);
198 tegra_sor_writel(sor, 0, SOR_STATE0);
6b6b6042
TR
199}
200
201static int tegra_sor_setup_pwm(struct tegra_sor *sor, unsigned long timeout)
202{
28fe2076 203 u32 value;
6b6b6042
TR
204
205 value = tegra_sor_readl(sor, SOR_PWM_DIV);
206 value &= ~SOR_PWM_DIV_MASK;
207 value |= 0x400; /* period */
208 tegra_sor_writel(sor, value, SOR_PWM_DIV);
209
210 value = tegra_sor_readl(sor, SOR_PWM_CTL);
211 value &= ~SOR_PWM_CTL_DUTY_CYCLE_MASK;
212 value |= 0x400; /* duty cycle */
213 value &= ~SOR_PWM_CTL_CLK_SEL; /* clock source: PCLK */
214 value |= SOR_PWM_CTL_TRIGGER;
215 tegra_sor_writel(sor, value, SOR_PWM_CTL);
216
217 timeout = jiffies + msecs_to_jiffies(timeout);
218
219 while (time_before(jiffies, timeout)) {
220 value = tegra_sor_readl(sor, SOR_PWM_CTL);
221 if ((value & SOR_PWM_CTL_TRIGGER) == 0)
222 return 0;
223
224 usleep_range(25, 100);
225 }
226
227 return -ETIMEDOUT;
228}
229
230static int tegra_sor_attach(struct tegra_sor *sor)
231{
232 unsigned long value, timeout;
233
234 /* wake up in normal mode */
a9a9e4fd 235 value = tegra_sor_readl(sor, SOR_SUPER_STATE1);
6b6b6042
TR
236 value |= SOR_SUPER_STATE_HEAD_MODE_AWAKE;
237 value |= SOR_SUPER_STATE_MODE_NORMAL;
a9a9e4fd 238 tegra_sor_writel(sor, value, SOR_SUPER_STATE1);
6b6b6042
TR
239 tegra_sor_super_update(sor);
240
241 /* attach */
a9a9e4fd 242 value = tegra_sor_readl(sor, SOR_SUPER_STATE1);
6b6b6042 243 value |= SOR_SUPER_STATE_ATTACHED;
a9a9e4fd 244 tegra_sor_writel(sor, value, SOR_SUPER_STATE1);
6b6b6042
TR
245 tegra_sor_super_update(sor);
246
247 timeout = jiffies + msecs_to_jiffies(250);
248
249 while (time_before(jiffies, timeout)) {
250 value = tegra_sor_readl(sor, SOR_TEST);
251 if ((value & SOR_TEST_ATTACHED) != 0)
252 return 0;
253
254 usleep_range(25, 100);
255 }
256
257 return -ETIMEDOUT;
258}
259
260static int tegra_sor_wakeup(struct tegra_sor *sor)
261{
6b6b6042
TR
262 unsigned long value, timeout;
263
6b6b6042
TR
264 timeout = jiffies + msecs_to_jiffies(250);
265
266 /* wait for head to wake up */
267 while (time_before(jiffies, timeout)) {
268 value = tegra_sor_readl(sor, SOR_TEST);
269 value &= SOR_TEST_HEAD_MODE_MASK;
270
271 if (value == SOR_TEST_HEAD_MODE_AWAKE)
272 return 0;
273
274 usleep_range(25, 100);
275 }
276
277 return -ETIMEDOUT;
278}
279
280static int tegra_sor_power_up(struct tegra_sor *sor, unsigned long timeout)
281{
28fe2076 282 u32 value;
6b6b6042
TR
283
284 value = tegra_sor_readl(sor, SOR_PWR);
285 value |= SOR_PWR_TRIGGER | SOR_PWR_NORMAL_STATE_PU;
286 tegra_sor_writel(sor, value, SOR_PWR);
287
288 timeout = jiffies + msecs_to_jiffies(timeout);
289
290 while (time_before(jiffies, timeout)) {
291 value = tegra_sor_readl(sor, SOR_PWR);
292 if ((value & SOR_PWR_TRIGGER) == 0)
293 return 0;
294
295 usleep_range(25, 100);
296 }
297
298 return -ETIMEDOUT;
299}
300
34fa183b
TR
301struct tegra_sor_params {
302 /* number of link clocks per line */
303 unsigned int num_clocks;
304 /* ratio between input and output */
305 u64 ratio;
306 /* precision factor */
307 u64 precision;
308
309 unsigned int active_polarity;
310 unsigned int active_count;
311 unsigned int active_frac;
312 unsigned int tu_size;
313 unsigned int error;
314};
315
316static int tegra_sor_compute_params(struct tegra_sor *sor,
317 struct tegra_sor_params *params,
318 unsigned int tu_size)
319{
320 u64 active_sym, active_count, frac, approx;
321 u32 active_polarity, active_frac = 0;
322 const u64 f = params->precision;
323 s64 error;
324
325 active_sym = params->ratio * tu_size;
326 active_count = div_u64(active_sym, f) * f;
327 frac = active_sym - active_count;
328
329 /* fraction < 0.5 */
330 if (frac >= (f / 2)) {
331 active_polarity = 1;
332 frac = f - frac;
333 } else {
334 active_polarity = 0;
335 }
336
337 if (frac != 0) {
338 frac = div_u64(f * f, frac); /* 1/fraction */
339 if (frac <= (15 * f)) {
340 active_frac = div_u64(frac, f);
341
342 /* round up */
343 if (active_polarity)
344 active_frac++;
345 } else {
346 active_frac = active_polarity ? 1 : 15;
347 }
348 }
349
350 if (active_frac == 1)
351 active_polarity = 0;
352
353 if (active_polarity == 1) {
354 if (active_frac) {
355 approx = active_count + (active_frac * (f - 1)) * f;
356 approx = div_u64(approx, active_frac * f);
357 } else {
358 approx = active_count + f;
359 }
360 } else {
361 if (active_frac)
362 approx = active_count + div_u64(f, active_frac);
363 else
364 approx = active_count;
365 }
366
367 error = div_s64(active_sym - approx, tu_size);
368 error *= params->num_clocks;
369
370 if (error <= 0 && abs64(error) < params->error) {
371 params->active_count = div_u64(active_count, f);
372 params->active_polarity = active_polarity;
373 params->active_frac = active_frac;
374 params->error = abs64(error);
375 params->tu_size = tu_size;
376
377 if (error == 0)
378 return true;
379 }
380
381 return false;
382}
383
384static int tegra_sor_calc_config(struct tegra_sor *sor,
80444495 385 const struct drm_display_mode *mode,
34fa183b
TR
386 struct tegra_sor_config *config,
387 struct drm_dp_link *link)
388{
389 const u64 f = 100000, link_rate = link->rate * 1000;
390 const u64 pclk = mode->clock * 1000;
7890b576 391 u64 input, output, watermark, num;
34fa183b 392 struct tegra_sor_params params;
34fa183b
TR
393 u32 num_syms_per_line;
394 unsigned int i;
395
396 if (!link_rate || !link->num_lanes || !pclk || !config->bits_per_pixel)
397 return -EINVAL;
398
399 output = link_rate * 8 * link->num_lanes;
400 input = pclk * config->bits_per_pixel;
401
402 if (input >= output)
403 return -ERANGE;
404
405 memset(&params, 0, sizeof(params));
406 params.ratio = div64_u64(input * f, output);
407 params.num_clocks = div_u64(link_rate * mode->hdisplay, pclk);
408 params.precision = f;
409 params.error = 64 * f;
410 params.tu_size = 64;
411
412 for (i = params.tu_size; i >= 32; i--)
413 if (tegra_sor_compute_params(sor, &params, i))
414 break;
415
416 if (params.active_frac == 0) {
417 config->active_polarity = 0;
418 config->active_count = params.active_count;
419
420 if (!params.active_polarity)
421 config->active_count--;
422
423 config->tu_size = params.tu_size;
424 config->active_frac = 1;
425 } else {
426 config->active_polarity = params.active_polarity;
427 config->active_count = params.active_count;
428 config->active_frac = params.active_frac;
429 config->tu_size = params.tu_size;
430 }
431
432 dev_dbg(sor->dev,
433 "polarity: %d active count: %d tu size: %d active frac: %d\n",
434 config->active_polarity, config->active_count,
435 config->tu_size, config->active_frac);
436
437 watermark = params.ratio * config->tu_size * (f - params.ratio);
438 watermark = div_u64(watermark, f);
439
440 watermark = div_u64(watermark + params.error, f);
441 config->watermark = watermark + (config->bits_per_pixel / 8) + 2;
442 num_syms_per_line = (mode->hdisplay * config->bits_per_pixel) *
443 (link->num_lanes * 8);
444
445 if (config->watermark > 30) {
446 config->watermark = 30;
447 dev_err(sor->dev,
448 "unable to compute TU size, forcing watermark to %u\n",
449 config->watermark);
450 } else if (config->watermark > num_syms_per_line) {
451 config->watermark = num_syms_per_line;
452 dev_err(sor->dev, "watermark too high, forcing to %u\n",
453 config->watermark);
454 }
455
7890b576
TR
456 /* compute the number of symbols per horizontal blanking interval */
457 num = ((mode->htotal - mode->hdisplay) - 7) * link_rate;
458 config->hblank_symbols = div_u64(num, pclk);
459
460 if (link->capabilities & DP_LINK_CAP_ENHANCED_FRAMING)
461 config->hblank_symbols -= 3;
462
463 config->hblank_symbols -= 12 / link->num_lanes;
464
465 /* compute the number of symbols per vertical blanking interval */
466 num = (mode->hdisplay - 25) * link_rate;
467 config->vblank_symbols = div_u64(num, pclk);
468 config->vblank_symbols -= 36 / link->num_lanes + 4;
469
470 dev_dbg(sor->dev, "blank symbols: H:%u V:%u\n", config->hblank_symbols,
471 config->vblank_symbols);
472
34fa183b
TR
473 return 0;
474}
475
6fad8f66
TR
476static int tegra_sor_detach(struct tegra_sor *sor)
477{
478 unsigned long value, timeout;
479
480 /* switch to safe mode */
a9a9e4fd 481 value = tegra_sor_readl(sor, SOR_SUPER_STATE1);
6fad8f66 482 value &= ~SOR_SUPER_STATE_MODE_NORMAL;
a9a9e4fd 483 tegra_sor_writel(sor, value, SOR_SUPER_STATE1);
6fad8f66
TR
484 tegra_sor_super_update(sor);
485
486 timeout = jiffies + msecs_to_jiffies(250);
487
488 while (time_before(jiffies, timeout)) {
489 value = tegra_sor_readl(sor, SOR_PWR);
490 if (value & SOR_PWR_MODE_SAFE)
491 break;
492 }
493
494 if ((value & SOR_PWR_MODE_SAFE) == 0)
495 return -ETIMEDOUT;
496
497 /* go to sleep */
a9a9e4fd 498 value = tegra_sor_readl(sor, SOR_SUPER_STATE1);
6fad8f66 499 value &= ~SOR_SUPER_STATE_HEAD_MODE_MASK;
a9a9e4fd 500 tegra_sor_writel(sor, value, SOR_SUPER_STATE1);
6fad8f66
TR
501 tegra_sor_super_update(sor);
502
503 /* detach */
a9a9e4fd 504 value = tegra_sor_readl(sor, SOR_SUPER_STATE1);
6fad8f66 505 value &= ~SOR_SUPER_STATE_ATTACHED;
a9a9e4fd 506 tegra_sor_writel(sor, value, SOR_SUPER_STATE1);
6fad8f66
TR
507 tegra_sor_super_update(sor);
508
509 timeout = jiffies + msecs_to_jiffies(250);
510
511 while (time_before(jiffies, timeout)) {
512 value = tegra_sor_readl(sor, SOR_TEST);
513 if ((value & SOR_TEST_ATTACHED) == 0)
514 break;
515
516 usleep_range(25, 100);
517 }
518
519 if ((value & SOR_TEST_ATTACHED) != 0)
520 return -ETIMEDOUT;
521
522 return 0;
523}
524
525static int tegra_sor_power_down(struct tegra_sor *sor)
526{
527 unsigned long value, timeout;
528 int err;
529
530 value = tegra_sor_readl(sor, SOR_PWR);
531 value &= ~SOR_PWR_NORMAL_STATE_PU;
532 value |= SOR_PWR_TRIGGER;
533 tegra_sor_writel(sor, value, SOR_PWR);
534
535 timeout = jiffies + msecs_to_jiffies(250);
536
537 while (time_before(jiffies, timeout)) {
538 value = tegra_sor_readl(sor, SOR_PWR);
539 if ((value & SOR_PWR_TRIGGER) == 0)
540 return 0;
541
542 usleep_range(25, 100);
543 }
544
545 if ((value & SOR_PWR_TRIGGER) != 0)
546 return -ETIMEDOUT;
547
548 err = clk_set_parent(sor->clk, sor->clk_safe);
549 if (err < 0)
550 dev_err(sor->dev, "failed to set safe parent clock: %d\n", err);
551
a9a9e4fd 552 value = tegra_sor_readl(sor, SOR_DP_PADCTL0);
6fad8f66
TR
553 value &= ~(SOR_DP_PADCTL_PD_TXD_3 | SOR_DP_PADCTL_PD_TXD_0 |
554 SOR_DP_PADCTL_PD_TXD_1 | SOR_DP_PADCTL_PD_TXD_2);
a9a9e4fd 555 tegra_sor_writel(sor, value, SOR_DP_PADCTL0);
6fad8f66
TR
556
557 /* stop lane sequencer */
558 value = SOR_LANE_SEQ_CTL_TRIGGER | SOR_LANE_SEQ_CTL_SEQUENCE_UP |
559 SOR_LANE_SEQ_CTL_POWER_STATE_DOWN;
560 tegra_sor_writel(sor, value, SOR_LANE_SEQ_CTL);
561
562 timeout = jiffies + msecs_to_jiffies(250);
563
564 while (time_before(jiffies, timeout)) {
565 value = tegra_sor_readl(sor, SOR_LANE_SEQ_CTL);
566 if ((value & SOR_LANE_SEQ_CTL_TRIGGER) == 0)
567 break;
568
569 usleep_range(25, 100);
570 }
571
572 if ((value & SOR_LANE_SEQ_CTL_TRIGGER) != 0)
573 return -ETIMEDOUT;
574
a9a9e4fd
TR
575 value = tegra_sor_readl(sor, SOR_PLL2);
576 value |= SOR_PLL2_PORT_POWERDOWN;
577 tegra_sor_writel(sor, value, SOR_PLL2);
6fad8f66
TR
578
579 usleep_range(20, 100);
580
a9a9e4fd
TR
581 value = tegra_sor_readl(sor, SOR_PLL0);
582 value |= SOR_PLL0_VCOPD | SOR_PLL0_PWR;
583 tegra_sor_writel(sor, value, SOR_PLL0);
6fad8f66 584
a9a9e4fd
TR
585 value = tegra_sor_readl(sor, SOR_PLL2);
586 value |= SOR_PLL2_SEQ_PLLCAPPD;
587 value |= SOR_PLL2_SEQ_PLLCAPPD_ENFORCE;
588 tegra_sor_writel(sor, value, SOR_PLL2);
6fad8f66
TR
589
590 usleep_range(20, 100);
591
592 return 0;
593}
594
6fad8f66
TR
595static int tegra_sor_crc_wait(struct tegra_sor *sor, unsigned long timeout)
596{
597 u32 value;
598
599 timeout = jiffies + msecs_to_jiffies(timeout);
600
601 while (time_before(jiffies, timeout)) {
a9a9e4fd
TR
602 value = tegra_sor_readl(sor, SOR_CRCA);
603 if (value & SOR_CRCA_VALID)
6fad8f66
TR
604 return 0;
605
606 usleep_range(100, 200);
607 }
608
609 return -ETIMEDOUT;
610}
611
530239a8 612static int tegra_sor_show_crc(struct seq_file *s, void *data)
6fad8f66 613{
530239a8
TR
614 struct drm_info_node *node = s->private;
615 struct tegra_sor *sor = node->info_ent->data;
850bab44
TR
616 struct drm_crtc *crtc = sor->output.encoder.crtc;
617 struct drm_device *drm = node->minor->dev;
530239a8 618 int err = 0;
6fad8f66
TR
619 u32 value;
620
850bab44 621 drm_modeset_lock_all(drm);
6fad8f66 622
850bab44
TR
623 if (!crtc || !crtc->state->active) {
624 err = -EBUSY;
6fad8f66
TR
625 goto unlock;
626 }
627
a9a9e4fd 628 value = tegra_sor_readl(sor, SOR_STATE1);
6fad8f66 629 value &= ~SOR_STATE_ASY_CRC_MODE_MASK;
a9a9e4fd 630 tegra_sor_writel(sor, value, SOR_STATE1);
6fad8f66
TR
631
632 value = tegra_sor_readl(sor, SOR_CRC_CNTRL);
633 value |= SOR_CRC_CNTRL_ENABLE;
634 tegra_sor_writel(sor, value, SOR_CRC_CNTRL);
635
636 value = tegra_sor_readl(sor, SOR_TEST);
637 value &= ~SOR_TEST_CRC_POST_SERIALIZE;
638 tegra_sor_writel(sor, value, SOR_TEST);
639
640 err = tegra_sor_crc_wait(sor, 100);
641 if (err < 0)
642 goto unlock;
643
a9a9e4fd
TR
644 tegra_sor_writel(sor, SOR_CRCA_RESET, SOR_CRCA);
645 value = tegra_sor_readl(sor, SOR_CRCB);
6fad8f66 646
530239a8 647 seq_printf(s, "%08x\n", value);
6fad8f66
TR
648
649unlock:
850bab44 650 drm_modeset_unlock_all(drm);
6fad8f66
TR
651 return err;
652}
653
dab16336
TR
654static int tegra_sor_show_regs(struct seq_file *s, void *data)
655{
656 struct drm_info_node *node = s->private;
657 struct tegra_sor *sor = node->info_ent->data;
850bab44
TR
658 struct drm_crtc *crtc = sor->output.encoder.crtc;
659 struct drm_device *drm = node->minor->dev;
660 int err = 0;
661
662 drm_modeset_lock_all(drm);
663
664 if (!crtc || !crtc->state->active) {
665 err = -EBUSY;
666 goto unlock;
667 }
dab16336
TR
668
669#define DUMP_REG(name) \
670 seq_printf(s, "%-38s %#05x %08x\n", #name, name, \
671 tegra_sor_readl(sor, name))
672
673 DUMP_REG(SOR_CTXSW);
a9a9e4fd
TR
674 DUMP_REG(SOR_SUPER_STATE0);
675 DUMP_REG(SOR_SUPER_STATE1);
676 DUMP_REG(SOR_STATE0);
677 DUMP_REG(SOR_STATE1);
678 DUMP_REG(SOR_HEAD_STATE0(0));
679 DUMP_REG(SOR_HEAD_STATE0(1));
680 DUMP_REG(SOR_HEAD_STATE1(0));
681 DUMP_REG(SOR_HEAD_STATE1(1));
682 DUMP_REG(SOR_HEAD_STATE2(0));
683 DUMP_REG(SOR_HEAD_STATE2(1));
684 DUMP_REG(SOR_HEAD_STATE3(0));
685 DUMP_REG(SOR_HEAD_STATE3(1));
686 DUMP_REG(SOR_HEAD_STATE4(0));
687 DUMP_REG(SOR_HEAD_STATE4(1));
688 DUMP_REG(SOR_HEAD_STATE5(0));
689 DUMP_REG(SOR_HEAD_STATE5(1));
dab16336
TR
690 DUMP_REG(SOR_CRC_CNTRL);
691 DUMP_REG(SOR_DP_DEBUG_MVID);
692 DUMP_REG(SOR_CLK_CNTRL);
693 DUMP_REG(SOR_CAP);
694 DUMP_REG(SOR_PWR);
695 DUMP_REG(SOR_TEST);
a9a9e4fd
TR
696 DUMP_REG(SOR_PLL0);
697 DUMP_REG(SOR_PLL1);
698 DUMP_REG(SOR_PLL2);
699 DUMP_REG(SOR_PLL3);
dab16336
TR
700 DUMP_REG(SOR_CSTM);
701 DUMP_REG(SOR_LVDS);
a9a9e4fd
TR
702 DUMP_REG(SOR_CRCA);
703 DUMP_REG(SOR_CRCB);
dab16336
TR
704 DUMP_REG(SOR_BLANK);
705 DUMP_REG(SOR_SEQ_CTL);
706 DUMP_REG(SOR_LANE_SEQ_CTL);
707 DUMP_REG(SOR_SEQ_INST(0));
708 DUMP_REG(SOR_SEQ_INST(1));
709 DUMP_REG(SOR_SEQ_INST(2));
710 DUMP_REG(SOR_SEQ_INST(3));
711 DUMP_REG(SOR_SEQ_INST(4));
712 DUMP_REG(SOR_SEQ_INST(5));
713 DUMP_REG(SOR_SEQ_INST(6));
714 DUMP_REG(SOR_SEQ_INST(7));
715 DUMP_REG(SOR_SEQ_INST(8));
716 DUMP_REG(SOR_SEQ_INST(9));
717 DUMP_REG(SOR_SEQ_INST(10));
718 DUMP_REG(SOR_SEQ_INST(11));
719 DUMP_REG(SOR_SEQ_INST(12));
720 DUMP_REG(SOR_SEQ_INST(13));
721 DUMP_REG(SOR_SEQ_INST(14));
722 DUMP_REG(SOR_SEQ_INST(15));
723 DUMP_REG(SOR_PWM_DIV);
724 DUMP_REG(SOR_PWM_CTL);
a9a9e4fd
TR
725 DUMP_REG(SOR_VCRC_A0);
726 DUMP_REG(SOR_VCRC_A1);
727 DUMP_REG(SOR_VCRC_B0);
728 DUMP_REG(SOR_VCRC_B1);
729 DUMP_REG(SOR_CCRC_A0);
730 DUMP_REG(SOR_CCRC_A1);
731 DUMP_REG(SOR_CCRC_B0);
732 DUMP_REG(SOR_CCRC_B1);
733 DUMP_REG(SOR_EDATA_A0);
734 DUMP_REG(SOR_EDATA_A1);
735 DUMP_REG(SOR_EDATA_B0);
736 DUMP_REG(SOR_EDATA_B1);
737 DUMP_REG(SOR_COUNT_A0);
738 DUMP_REG(SOR_COUNT_A1);
739 DUMP_REG(SOR_COUNT_B0);
740 DUMP_REG(SOR_COUNT_B1);
741 DUMP_REG(SOR_DEBUG_A0);
742 DUMP_REG(SOR_DEBUG_A1);
743 DUMP_REG(SOR_DEBUG_B0);
744 DUMP_REG(SOR_DEBUG_B1);
dab16336
TR
745 DUMP_REG(SOR_TRIG);
746 DUMP_REG(SOR_MSCHECK);
747 DUMP_REG(SOR_XBAR_CTRL);
748 DUMP_REG(SOR_XBAR_POL);
a9a9e4fd
TR
749 DUMP_REG(SOR_DP_LINKCTL0);
750 DUMP_REG(SOR_DP_LINKCTL1);
751 DUMP_REG(SOR_LANE_DRIVE_CURRENT0);
752 DUMP_REG(SOR_LANE_DRIVE_CURRENT1);
753 DUMP_REG(SOR_LANE4_DRIVE_CURRENT0);
754 DUMP_REG(SOR_LANE4_DRIVE_CURRENT1);
755 DUMP_REG(SOR_LANE_PREEMPHASIS0);
756 DUMP_REG(SOR_LANE_PREEMPHASIS1);
757 DUMP_REG(SOR_LANE4_PREEMPHASIS0);
758 DUMP_REG(SOR_LANE4_PREEMPHASIS1);
759 DUMP_REG(SOR_LANE_POSTCURSOR0);
760 DUMP_REG(SOR_LANE_POSTCURSOR1);
761 DUMP_REG(SOR_DP_CONFIG0);
762 DUMP_REG(SOR_DP_CONFIG1);
763 DUMP_REG(SOR_DP_MN0);
764 DUMP_REG(SOR_DP_MN1);
765 DUMP_REG(SOR_DP_PADCTL0);
766 DUMP_REG(SOR_DP_PADCTL1);
767 DUMP_REG(SOR_DP_DEBUG0);
768 DUMP_REG(SOR_DP_DEBUG1);
769 DUMP_REG(SOR_DP_SPARE0);
770 DUMP_REG(SOR_DP_SPARE1);
dab16336
TR
771 DUMP_REG(SOR_DP_AUDIO_CTRL);
772 DUMP_REG(SOR_DP_AUDIO_HBLANK_SYMBOLS);
773 DUMP_REG(SOR_DP_AUDIO_VBLANK_SYMBOLS);
774 DUMP_REG(SOR_DP_GENERIC_INFOFRAME_HEADER);
a9a9e4fd
TR
775 DUMP_REG(SOR_DP_GENERIC_INFOFRAME_SUBPACK0);
776 DUMP_REG(SOR_DP_GENERIC_INFOFRAME_SUBPACK1);
777 DUMP_REG(SOR_DP_GENERIC_INFOFRAME_SUBPACK2);
778 DUMP_REG(SOR_DP_GENERIC_INFOFRAME_SUBPACK3);
779 DUMP_REG(SOR_DP_GENERIC_INFOFRAME_SUBPACK4);
780 DUMP_REG(SOR_DP_GENERIC_INFOFRAME_SUBPACK5);
781 DUMP_REG(SOR_DP_GENERIC_INFOFRAME_SUBPACK6);
dab16336
TR
782 DUMP_REG(SOR_DP_TPG);
783 DUMP_REG(SOR_DP_TPG_CONFIG);
a9a9e4fd
TR
784 DUMP_REG(SOR_DP_LQ_CSTM0);
785 DUMP_REG(SOR_DP_LQ_CSTM1);
786 DUMP_REG(SOR_DP_LQ_CSTM2);
dab16336
TR
787
788#undef DUMP_REG
789
850bab44
TR
790unlock:
791 drm_modeset_unlock_all(drm);
792 return err;
dab16336
TR
793}
794
795static const struct drm_info_list debugfs_files[] = {
530239a8 796 { "crc", tegra_sor_show_crc, 0, NULL },
dab16336
TR
797 { "regs", tegra_sor_show_regs, 0, NULL },
798};
799
6fad8f66
TR
800static int tegra_sor_debugfs_init(struct tegra_sor *sor,
801 struct drm_minor *minor)
6b6b6042 802{
dab16336 803 unsigned int i;
530239a8 804 int err;
6fad8f66
TR
805
806 sor->debugfs = debugfs_create_dir("sor", minor->debugfs_root);
807 if (!sor->debugfs)
808 return -ENOMEM;
809
dab16336
TR
810 sor->debugfs_files = kmemdup(debugfs_files, sizeof(debugfs_files),
811 GFP_KERNEL);
812 if (!sor->debugfs_files) {
813 err = -ENOMEM;
814 goto remove;
815 }
816
817 for (i = 0; i < ARRAY_SIZE(debugfs_files); i++)
818 sor->debugfs_files[i].data = sor;
819
820 err = drm_debugfs_create_files(sor->debugfs_files,
821 ARRAY_SIZE(debugfs_files),
822 sor->debugfs, minor);
823 if (err < 0)
824 goto free;
825
3ff1f22c
TR
826 sor->minor = minor;
827
530239a8 828 return 0;
6fad8f66 829
dab16336
TR
830free:
831 kfree(sor->debugfs_files);
832 sor->debugfs_files = NULL;
6fad8f66 833remove:
dab16336 834 debugfs_remove_recursive(sor->debugfs);
6fad8f66
TR
835 sor->debugfs = NULL;
836 return err;
837}
838
4009c224 839static void tegra_sor_debugfs_exit(struct tegra_sor *sor)
6fad8f66 840{
dab16336
TR
841 drm_debugfs_remove_files(sor->debugfs_files, ARRAY_SIZE(debugfs_files),
842 sor->minor);
843 sor->minor = NULL;
844
845 kfree(sor->debugfs_files);
066d30f8 846 sor->debugfs_files = NULL;
dab16336
TR
847
848 debugfs_remove_recursive(sor->debugfs);
066d30f8 849 sor->debugfs = NULL;
6fad8f66
TR
850}
851
6fad8f66
TR
852static enum drm_connector_status
853tegra_sor_connector_detect(struct drm_connector *connector, bool force)
854{
855 struct tegra_output *output = connector_to_output(connector);
856 struct tegra_sor *sor = to_sor(output);
857
858 if (sor->dpaux)
859 return tegra_dpaux_detect(sor->dpaux);
860
861 return connector_status_unknown;
862}
863
864static const struct drm_connector_funcs tegra_sor_connector_funcs = {
850bab44 865 .dpms = drm_atomic_helper_connector_dpms,
9d44189f 866 .reset = drm_atomic_helper_connector_reset,
6fad8f66
TR
867 .detect = tegra_sor_connector_detect,
868 .fill_modes = drm_helper_probe_single_connector_modes,
869 .destroy = tegra_output_connector_destroy,
9d44189f 870 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
4aa3df71 871 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
6fad8f66
TR
872};
873
874static int tegra_sor_connector_get_modes(struct drm_connector *connector)
875{
876 struct tegra_output *output = connector_to_output(connector);
877 struct tegra_sor *sor = to_sor(output);
878 int err;
879
880 if (sor->dpaux)
881 tegra_dpaux_enable(sor->dpaux);
882
883 err = tegra_output_connector_get_modes(connector);
884
885 if (sor->dpaux)
886 tegra_dpaux_disable(sor->dpaux);
887
888 return err;
889}
890
891static enum drm_mode_status
892tegra_sor_connector_mode_valid(struct drm_connector *connector,
893 struct drm_display_mode *mode)
894{
895 return MODE_OK;
896}
897
898static const struct drm_connector_helper_funcs tegra_sor_connector_helper_funcs = {
899 .get_modes = tegra_sor_connector_get_modes,
900 .mode_valid = tegra_sor_connector_mode_valid,
901 .best_encoder = tegra_output_connector_best_encoder,
902};
903
904static const struct drm_encoder_funcs tegra_sor_encoder_funcs = {
905 .destroy = tegra_output_encoder_destroy,
906};
907
850bab44 908static void tegra_sor_edp_disable(struct drm_encoder *encoder)
6fad8f66 909{
850bab44
TR
910 struct tegra_output *output = encoder_to_output(encoder);
911 struct tegra_dc *dc = to_tegra_dc(encoder->crtc);
912 struct tegra_sor *sor = to_sor(output);
913 u32 value;
914 int err;
6fad8f66 915
850bab44
TR
916 if (output->panel)
917 drm_panel_disable(output->panel);
6fad8f66 918
850bab44
TR
919 err = tegra_sor_detach(sor);
920 if (err < 0)
921 dev_err(sor->dev, "failed to detach SOR: %d\n", err);
922
923 tegra_sor_writel(sor, 0, SOR_STATE1);
924 tegra_sor_update(sor);
925
926 /*
927 * The following accesses registers of the display controller, so make
928 * sure it's only executed when the output is attached to one.
929 */
930 if (dc) {
931 value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
932 value &= ~SOR_ENABLE;
933 tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
934
935 tegra_dc_commit(dc);
936 }
937
938 err = tegra_sor_power_down(sor);
939 if (err < 0)
940 dev_err(sor->dev, "failed to power down SOR: %d\n", err);
941
942 if (sor->dpaux) {
943 err = tegra_dpaux_disable(sor->dpaux);
944 if (err < 0)
945 dev_err(sor->dev, "failed to disable DP: %d\n", err);
946 }
947
948 err = tegra_io_rail_power_off(TEGRA_IO_RAIL_LVDS);
949 if (err < 0)
950 dev_err(sor->dev, "failed to power off I/O rail: %d\n", err);
951
952 if (output->panel)
953 drm_panel_unprepare(output->panel);
954
955 reset_control_assert(sor->rst);
956 clk_disable_unprepare(sor->clk);
6fad8f66
TR
957}
958
850bab44 959static void tegra_sor_edp_enable(struct drm_encoder *encoder)
6fad8f66 960{
850bab44 961 struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
6fad8f66
TR
962 struct tegra_output *output = encoder_to_output(encoder);
963 struct tegra_dc *dc = to_tegra_dc(encoder->crtc);
6b6b6042
TR
964 unsigned int vbe, vse, hbe, hse, vbs, hbs, i;
965 struct tegra_sor *sor = to_sor(output);
34fa183b
TR
966 struct tegra_sor_config config;
967 struct drm_dp_link link;
968 struct drm_dp_aux *aux;
86f5c52d 969 int err = 0;
28fe2076 970 u32 value;
86f5c52d 971
6b6b6042
TR
972 err = clk_prepare_enable(sor->clk);
973 if (err < 0)
850bab44 974 dev_err(sor->dev, "failed to enable clock: %d\n", err);
6b6b6042
TR
975
976 reset_control_deassert(sor->rst);
977
6fad8f66
TR
978 if (output->panel)
979 drm_panel_prepare(output->panel);
980
34fa183b
TR
981 /* FIXME: properly convert to struct drm_dp_aux */
982 aux = (struct drm_dp_aux *)sor->dpaux;
983
6b6b6042
TR
984 if (sor->dpaux) {
985 err = tegra_dpaux_enable(sor->dpaux);
986 if (err < 0)
987 dev_err(sor->dev, "failed to enable DP: %d\n", err);
34fa183b
TR
988
989 err = drm_dp_link_probe(aux, &link);
990 if (err < 0) {
991 dev_err(sor->dev, "failed to probe eDP link: %d\n",
992 err);
850bab44 993 return;
34fa183b 994 }
6b6b6042
TR
995 }
996
997 err = clk_set_parent(sor->clk, sor->clk_safe);
998 if (err < 0)
999 dev_err(sor->dev, "failed to set safe parent clock: %d\n", err);
1000
34fa183b 1001 memset(&config, 0, sizeof(config));
054b1bd1 1002 config.bits_per_pixel = output->connector.display_info.bpc * 3;
34fa183b
TR
1003
1004 err = tegra_sor_calc_config(sor, mode, &config, &link);
1005 if (err < 0)
1006 dev_err(sor->dev, "failed to compute link configuration: %d\n",
1007 err);
1008
6b6b6042
TR
1009 value = tegra_sor_readl(sor, SOR_CLK_CNTRL);
1010 value &= ~SOR_CLK_CNTRL_DP_CLK_SEL_MASK;
1011 value |= SOR_CLK_CNTRL_DP_CLK_SEL_SINGLE_DPCLK;
1012 tegra_sor_writel(sor, value, SOR_CLK_CNTRL);
1013
a9a9e4fd
TR
1014 value = tegra_sor_readl(sor, SOR_PLL2);
1015 value &= ~SOR_PLL2_BANDGAP_POWERDOWN;
1016 tegra_sor_writel(sor, value, SOR_PLL2);
6b6b6042
TR
1017 usleep_range(20, 100);
1018
a9a9e4fd
TR
1019 value = tegra_sor_readl(sor, SOR_PLL3);
1020 value |= SOR_PLL3_PLL_VDD_MODE_3V3;
1021 tegra_sor_writel(sor, value, SOR_PLL3);
6b6b6042 1022
a9a9e4fd
TR
1023 value = SOR_PLL0_ICHPMP(0xf) | SOR_PLL0_VCOCAP_RST |
1024 SOR_PLL0_PLLREG_LEVEL_V45 | SOR_PLL0_RESISTOR_EXT;
1025 tegra_sor_writel(sor, value, SOR_PLL0);
6b6b6042 1026
a9a9e4fd
TR
1027 value = tegra_sor_readl(sor, SOR_PLL2);
1028 value |= SOR_PLL2_SEQ_PLLCAPPD;
1029 value &= ~SOR_PLL2_SEQ_PLLCAPPD_ENFORCE;
1030 value |= SOR_PLL2_LVDS_ENABLE;
1031 tegra_sor_writel(sor, value, SOR_PLL2);
6b6b6042 1032
a9a9e4fd
TR
1033 value = SOR_PLL1_TERM_COMPOUT | SOR_PLL1_TMDS_TERM;
1034 tegra_sor_writel(sor, value, SOR_PLL1);
6b6b6042
TR
1035
1036 while (true) {
a9a9e4fd
TR
1037 value = tegra_sor_readl(sor, SOR_PLL2);
1038 if ((value & SOR_PLL2_SEQ_PLLCAPPD_ENFORCE) == 0)
6b6b6042
TR
1039 break;
1040
1041 usleep_range(250, 1000);
1042 }
1043
a9a9e4fd
TR
1044 value = tegra_sor_readl(sor, SOR_PLL2);
1045 value &= ~SOR_PLL2_POWERDOWN_OVERRIDE;
1046 value &= ~SOR_PLL2_PORT_POWERDOWN;
1047 tegra_sor_writel(sor, value, SOR_PLL2);
6b6b6042
TR
1048
1049 /*
1050 * power up
1051 */
1052
1053 /* set safe link bandwidth (1.62 Gbps) */
1054 value = tegra_sor_readl(sor, SOR_CLK_CNTRL);
1055 value &= ~SOR_CLK_CNTRL_DP_LINK_SPEED_MASK;
1056 value |= SOR_CLK_CNTRL_DP_LINK_SPEED_G1_62;
1057 tegra_sor_writel(sor, value, SOR_CLK_CNTRL);
1058
1059 /* step 1 */
a9a9e4fd
TR
1060 value = tegra_sor_readl(sor, SOR_PLL2);
1061 value |= SOR_PLL2_SEQ_PLLCAPPD_ENFORCE | SOR_PLL2_PORT_POWERDOWN |
1062 SOR_PLL2_BANDGAP_POWERDOWN;
1063 tegra_sor_writel(sor, value, SOR_PLL2);
6b6b6042 1064
a9a9e4fd
TR
1065 value = tegra_sor_readl(sor, SOR_PLL0);
1066 value |= SOR_PLL0_VCOPD | SOR_PLL0_PWR;
1067 tegra_sor_writel(sor, value, SOR_PLL0);
6b6b6042 1068
a9a9e4fd 1069 value = tegra_sor_readl(sor, SOR_DP_PADCTL0);
6b6b6042 1070 value &= ~SOR_DP_PADCTL_PAD_CAL_PD;
a9a9e4fd 1071 tegra_sor_writel(sor, value, SOR_DP_PADCTL0);
6b6b6042
TR
1072
1073 /* step 2 */
1074 err = tegra_io_rail_power_on(TEGRA_IO_RAIL_LVDS);
850bab44 1075 if (err < 0)
6b6b6042 1076 dev_err(sor->dev, "failed to power on I/O rail: %d\n", err);
6b6b6042
TR
1077
1078 usleep_range(5, 100);
1079
1080 /* step 3 */
a9a9e4fd
TR
1081 value = tegra_sor_readl(sor, SOR_PLL2);
1082 value &= ~SOR_PLL2_BANDGAP_POWERDOWN;
1083 tegra_sor_writel(sor, value, SOR_PLL2);
6b6b6042
TR
1084
1085 usleep_range(20, 100);
1086
1087 /* step 4 */
a9a9e4fd
TR
1088 value = tegra_sor_readl(sor, SOR_PLL0);
1089 value &= ~SOR_PLL0_VCOPD;
1090 value &= ~SOR_PLL0_PWR;
1091 tegra_sor_writel(sor, value, SOR_PLL0);
6b6b6042 1092
a9a9e4fd
TR
1093 value = tegra_sor_readl(sor, SOR_PLL2);
1094 value &= ~SOR_PLL2_SEQ_PLLCAPPD_ENFORCE;
1095 tegra_sor_writel(sor, value, SOR_PLL2);
6b6b6042
TR
1096
1097 usleep_range(200, 1000);
1098
1099 /* step 5 */
a9a9e4fd
TR
1100 value = tegra_sor_readl(sor, SOR_PLL2);
1101 value &= ~SOR_PLL2_PORT_POWERDOWN;
1102 tegra_sor_writel(sor, value, SOR_PLL2);
6b6b6042
TR
1103
1104 /* switch to DP clock */
1105 err = clk_set_parent(sor->clk, sor->clk_dp);
1106 if (err < 0)
1107 dev_err(sor->dev, "failed to set DP parent clock: %d\n", err);
1108
899451b7 1109 /* power DP lanes */
a9a9e4fd 1110 value = tegra_sor_readl(sor, SOR_DP_PADCTL0);
899451b7
TR
1111
1112 if (link.num_lanes <= 2)
1113 value &= ~(SOR_DP_PADCTL_PD_TXD_3 | SOR_DP_PADCTL_PD_TXD_2);
1114 else
1115 value |= SOR_DP_PADCTL_PD_TXD_3 | SOR_DP_PADCTL_PD_TXD_2;
1116
1117 if (link.num_lanes <= 1)
1118 value &= ~SOR_DP_PADCTL_PD_TXD_1;
1119 else
1120 value |= SOR_DP_PADCTL_PD_TXD_1;
1121
1122 if (link.num_lanes == 0)
1123 value &= ~SOR_DP_PADCTL_PD_TXD_0;
1124 else
1125 value |= SOR_DP_PADCTL_PD_TXD_0;
1126
a9a9e4fd 1127 tegra_sor_writel(sor, value, SOR_DP_PADCTL0);
6b6b6042 1128
a9a9e4fd 1129 value = tegra_sor_readl(sor, SOR_DP_LINKCTL0);
6b6b6042 1130 value &= ~SOR_DP_LINKCTL_LANE_COUNT_MASK;
0c90a184 1131 value |= SOR_DP_LINKCTL_LANE_COUNT(link.num_lanes);
a9a9e4fd 1132 tegra_sor_writel(sor, value, SOR_DP_LINKCTL0);
6b6b6042
TR
1133
1134 /* start lane sequencer */
1135 value = SOR_LANE_SEQ_CTL_TRIGGER | SOR_LANE_SEQ_CTL_SEQUENCE_DOWN |
1136 SOR_LANE_SEQ_CTL_POWER_STATE_UP;
1137 tegra_sor_writel(sor, value, SOR_LANE_SEQ_CTL);
1138
1139 while (true) {
1140 value = tegra_sor_readl(sor, SOR_LANE_SEQ_CTL);
1141 if ((value & SOR_LANE_SEQ_CTL_TRIGGER) == 0)
1142 break;
1143
1144 usleep_range(250, 1000);
1145 }
1146
a4263fed 1147 /* set link bandwidth */
6b6b6042
TR
1148 value = tegra_sor_readl(sor, SOR_CLK_CNTRL);
1149 value &= ~SOR_CLK_CNTRL_DP_LINK_SPEED_MASK;
a4263fed 1150 value |= drm_dp_link_rate_to_bw_code(link.rate) << 2;
6b6b6042
TR
1151 tegra_sor_writel(sor, value, SOR_CLK_CNTRL);
1152
1153 /* set linkctl */
a9a9e4fd 1154 value = tegra_sor_readl(sor, SOR_DP_LINKCTL0);
6b6b6042
TR
1155 value |= SOR_DP_LINKCTL_ENABLE;
1156
1157 value &= ~SOR_DP_LINKCTL_TU_SIZE_MASK;
34fa183b 1158 value |= SOR_DP_LINKCTL_TU_SIZE(config.tu_size);
6b6b6042
TR
1159
1160 value |= SOR_DP_LINKCTL_ENHANCED_FRAME;
a9a9e4fd 1161 tegra_sor_writel(sor, value, SOR_DP_LINKCTL0);
6b6b6042
TR
1162
1163 for (i = 0, value = 0; i < 4; i++) {
1164 unsigned long lane = SOR_DP_TPG_CHANNEL_CODING |
1165 SOR_DP_TPG_SCRAMBLER_GALIOS |
1166 SOR_DP_TPG_PATTERN_NONE;
1167 value = (value << 8) | lane;
1168 }
1169
1170 tegra_sor_writel(sor, value, SOR_DP_TPG);
1171
a9a9e4fd 1172 value = tegra_sor_readl(sor, SOR_DP_CONFIG0);
6b6b6042 1173 value &= ~SOR_DP_CONFIG_WATERMARK_MASK;
34fa183b 1174 value |= SOR_DP_CONFIG_WATERMARK(config.watermark);
6b6b6042
TR
1175
1176 value &= ~SOR_DP_CONFIG_ACTIVE_SYM_COUNT_MASK;
34fa183b 1177 value |= SOR_DP_CONFIG_ACTIVE_SYM_COUNT(config.active_count);
6b6b6042
TR
1178
1179 value &= ~SOR_DP_CONFIG_ACTIVE_SYM_FRAC_MASK;
34fa183b 1180 value |= SOR_DP_CONFIG_ACTIVE_SYM_FRAC(config.active_frac);
6b6b6042 1181
34fa183b
TR
1182 if (config.active_polarity)
1183 value |= SOR_DP_CONFIG_ACTIVE_SYM_POLARITY;
1184 else
1185 value &= ~SOR_DP_CONFIG_ACTIVE_SYM_POLARITY;
6b6b6042
TR
1186
1187 value |= SOR_DP_CONFIG_ACTIVE_SYM_ENABLE;
1f64ae7c 1188 value |= SOR_DP_CONFIG_DISPARITY_NEGATIVE;
a9a9e4fd 1189 tegra_sor_writel(sor, value, SOR_DP_CONFIG0);
6b6b6042
TR
1190
1191 value = tegra_sor_readl(sor, SOR_DP_AUDIO_HBLANK_SYMBOLS);
1192 value &= ~SOR_DP_AUDIO_HBLANK_SYMBOLS_MASK;
7890b576 1193 value |= config.hblank_symbols & 0xffff;
6b6b6042
TR
1194 tegra_sor_writel(sor, value, SOR_DP_AUDIO_HBLANK_SYMBOLS);
1195
1196 value = tegra_sor_readl(sor, SOR_DP_AUDIO_VBLANK_SYMBOLS);
1197 value &= ~SOR_DP_AUDIO_VBLANK_SYMBOLS_MASK;
7890b576 1198 value |= config.vblank_symbols & 0xffff;
6b6b6042
TR
1199 tegra_sor_writel(sor, value, SOR_DP_AUDIO_VBLANK_SYMBOLS);
1200
1201 /* enable pad calibration logic */
a9a9e4fd 1202 value = tegra_sor_readl(sor, SOR_DP_PADCTL0);
6b6b6042 1203 value |= SOR_DP_PADCTL_PAD_CAL_PD;
a9a9e4fd 1204 tegra_sor_writel(sor, value, SOR_DP_PADCTL0);
6b6b6042
TR
1205
1206 if (sor->dpaux) {
6b6b6042
TR
1207 u8 rate, lanes;
1208
1209 err = drm_dp_link_probe(aux, &link);
850bab44 1210 if (err < 0)
6b6b6042
TR
1211 dev_err(sor->dev, "failed to probe eDP link: %d\n",
1212 err);
6b6b6042
TR
1213
1214 err = drm_dp_link_power_up(aux, &link);
850bab44 1215 if (err < 0)
6b6b6042
TR
1216 dev_err(sor->dev, "failed to power up eDP link: %d\n",
1217 err);
6b6b6042
TR
1218
1219 err = drm_dp_link_configure(aux, &link);
850bab44 1220 if (err < 0)
6b6b6042
TR
1221 dev_err(sor->dev, "failed to configure eDP link: %d\n",
1222 err);
6b6b6042
TR
1223
1224 rate = drm_dp_link_rate_to_bw_code(link.rate);
1225 lanes = link.num_lanes;
1226
1227 value = tegra_sor_readl(sor, SOR_CLK_CNTRL);
1228 value &= ~SOR_CLK_CNTRL_DP_LINK_SPEED_MASK;
1229 value |= SOR_CLK_CNTRL_DP_LINK_SPEED(rate);
1230 tegra_sor_writel(sor, value, SOR_CLK_CNTRL);
1231
a9a9e4fd 1232 value = tegra_sor_readl(sor, SOR_DP_LINKCTL0);
6b6b6042
TR
1233 value &= ~SOR_DP_LINKCTL_LANE_COUNT_MASK;
1234 value |= SOR_DP_LINKCTL_LANE_COUNT(lanes);
1235
1236 if (link.capabilities & DP_LINK_CAP_ENHANCED_FRAMING)
1237 value |= SOR_DP_LINKCTL_ENHANCED_FRAME;
1238
a9a9e4fd 1239 tegra_sor_writel(sor, value, SOR_DP_LINKCTL0);
6b6b6042
TR
1240
1241 /* disable training pattern generator */
1242
1243 for (i = 0; i < link.num_lanes; i++) {
1244 unsigned long lane = SOR_DP_TPG_CHANNEL_CODING |
1245 SOR_DP_TPG_SCRAMBLER_GALIOS |
1246 SOR_DP_TPG_PATTERN_NONE;
1247 value = (value << 8) | lane;
1248 }
1249
1250 tegra_sor_writel(sor, value, SOR_DP_TPG);
1251
1252 err = tegra_sor_dp_train_fast(sor, &link);
1253 if (err < 0) {
1254 dev_err(sor->dev, "DP fast link training failed: %d\n",
1255 err);
6b6b6042
TR
1256 }
1257
1258 dev_dbg(sor->dev, "fast link training succeeded\n");
1259 }
1260
1261 err = tegra_sor_power_up(sor, 250);
850bab44 1262 if (err < 0)
6b6b6042 1263 dev_err(sor->dev, "failed to power up SOR: %d\n", err);
6b6b6042 1264
6b6b6042
TR
1265 /*
1266 * configure panel (24bpp, vsync-, hsync-, DP-A protocol, complete
1267 * raster, associate with display controller)
1268 */
3f4f3b5f 1269 value = SOR_STATE_ASY_PROTOCOL_DP_A |
6b6b6042
TR
1270 SOR_STATE_ASY_CRC_MODE_COMPLETE |
1271 SOR_STATE_ASY_OWNER(dc->pipe + 1);
34fa183b 1272
3f4f3b5f
TR
1273 if (mode->flags & DRM_MODE_FLAG_PHSYNC)
1274 value &= ~SOR_STATE_ASY_HSYNCPOL;
1275
1276 if (mode->flags & DRM_MODE_FLAG_NHSYNC)
1277 value |= SOR_STATE_ASY_HSYNCPOL;
1278
1279 if (mode->flags & DRM_MODE_FLAG_PVSYNC)
1280 value &= ~SOR_STATE_ASY_VSYNCPOL;
1281
1282 if (mode->flags & DRM_MODE_FLAG_NVSYNC)
1283 value |= SOR_STATE_ASY_VSYNCPOL;
1284
34fa183b
TR
1285 switch (config.bits_per_pixel) {
1286 case 24:
1287 value |= SOR_STATE_ASY_PIXELDEPTH_BPP_24_444;
1288 break;
1289
1290 case 18:
1291 value |= SOR_STATE_ASY_PIXELDEPTH_BPP_18_444;
1292 break;
1293
1294 default:
1295 BUG();
1296 break;
1297 }
1298
a9a9e4fd 1299 tegra_sor_writel(sor, value, SOR_STATE1);
6b6b6042
TR
1300
1301 /*
1302 * TODO: The video timing programming below doesn't seem to match the
1303 * register definitions.
1304 */
1305
1306 value = ((mode->vtotal & 0x7fff) << 16) | (mode->htotal & 0x7fff);
51511d05 1307 tegra_sor_writel(sor, value, SOR_HEAD_STATE1(dc->pipe));
6b6b6042
TR
1308
1309 vse = mode->vsync_end - mode->vsync_start - 1;
1310 hse = mode->hsync_end - mode->hsync_start - 1;
1311
1312 value = ((vse & 0x7fff) << 16) | (hse & 0x7fff);
51511d05 1313 tegra_sor_writel(sor, value, SOR_HEAD_STATE2(dc->pipe));
6b6b6042
TR
1314
1315 vbe = vse + (mode->vsync_start - mode->vdisplay);
1316 hbe = hse + (mode->hsync_start - mode->hdisplay);
1317
1318 value = ((vbe & 0x7fff) << 16) | (hbe & 0x7fff);
51511d05 1319 tegra_sor_writel(sor, value, SOR_HEAD_STATE3(dc->pipe));
6b6b6042
TR
1320
1321 vbs = vbe + mode->vdisplay;
1322 hbs = hbe + mode->hdisplay;
1323
1324 value = ((vbs & 0x7fff) << 16) | (hbs & 0x7fff);
51511d05
TR
1325 tegra_sor_writel(sor, value, SOR_HEAD_STATE4(dc->pipe));
1326
1327 tegra_sor_writel(sor, 0x1, SOR_HEAD_STATE5(dc->pipe));
6b6b6042 1328
6fad8f66
TR
1329 /* CSTM (LVDS, link A/B, upper) */
1330 value = SOR_CSTM_LVDS | SOR_CSTM_LINK_ACT_A | SOR_CSTM_LINK_ACT_B |
1331 SOR_CSTM_UPPER;
1332 tegra_sor_writel(sor, value, SOR_CSTM);
1333
1334 /* PWM setup */
1335 err = tegra_sor_setup_pwm(sor, 250);
850bab44 1336 if (err < 0)
6fad8f66 1337 dev_err(sor->dev, "failed to setup PWM: %d\n", err);
6b6b6042 1338
666cb873
TR
1339 tegra_sor_update(sor);
1340
6fad8f66
TR
1341 value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
1342 value |= SOR_ENABLE;
1343 tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
6b6b6042 1344
666cb873 1345 tegra_dc_commit(dc);
6b6b6042 1346
6fad8f66 1347 err = tegra_sor_attach(sor);
850bab44 1348 if (err < 0)
6fad8f66 1349 dev_err(sor->dev, "failed to attach SOR: %d\n", err);
6b6b6042 1350
6fad8f66 1351 err = tegra_sor_wakeup(sor);
850bab44 1352 if (err < 0)
6fad8f66 1353 dev_err(sor->dev, "failed to enable DC: %d\n", err);
6b6b6042 1354
6fad8f66
TR
1355 if (output->panel)
1356 drm_panel_enable(output->panel);
a82752e1
TR
1357}
1358
82f1511c
TR
1359static int
1360tegra_sor_encoder_atomic_check(struct drm_encoder *encoder,
1361 struct drm_crtc_state *crtc_state,
1362 struct drm_connector_state *conn_state)
1363{
1364 struct tegra_output *output = encoder_to_output(encoder);
1365 struct tegra_dc *dc = to_tegra_dc(conn_state->crtc);
1366 unsigned long pclk = crtc_state->mode.clock * 1000;
1367 struct tegra_sor *sor = to_sor(output);
1368 int err;
1369
1370 err = tegra_dc_state_setup_clock(dc, crtc_state, sor->clk_parent,
1371 pclk, 0);
1372 if (err < 0) {
1373 dev_err(output->dev, "failed to setup CRTC state: %d\n", err);
1374 return err;
1375 }
1376
1377 return 0;
1378}
1379
850bab44
TR
1380static const struct drm_encoder_helper_funcs tegra_sor_edp_helper_funcs = {
1381 .disable = tegra_sor_edp_disable,
1382 .enable = tegra_sor_edp_enable,
82f1511c 1383 .atomic_check = tegra_sor_encoder_atomic_check,
a82752e1
TR
1384};
1385
6b6b6042
TR
1386static int tegra_sor_init(struct host1x_client *client)
1387{
9910f5c4 1388 struct drm_device *drm = dev_get_drvdata(client->parent);
6b6b6042
TR
1389 struct tegra_sor *sor = host1x_client_to_sor(client);
1390 int err;
1391
1392 if (!sor->dpaux)
1393 return -ENODEV;
1394
6b6b6042 1395 sor->output.dev = sor->dev;
6b6b6042 1396
6fad8f66
TR
1397 drm_connector_init(drm, &sor->output.connector,
1398 &tegra_sor_connector_funcs,
1399 DRM_MODE_CONNECTOR_eDP);
1400 drm_connector_helper_add(&sor->output.connector,
1401 &tegra_sor_connector_helper_funcs);
1402 sor->output.connector.dpms = DRM_MODE_DPMS_OFF;
1403
6fad8f66
TR
1404 drm_encoder_init(drm, &sor->output.encoder, &tegra_sor_encoder_funcs,
1405 DRM_MODE_ENCODER_TMDS);
1406 drm_encoder_helper_add(&sor->output.encoder,
850bab44 1407 &tegra_sor_edp_helper_funcs);
6fad8f66
TR
1408
1409 drm_mode_connector_attach_encoder(&sor->output.connector,
1410 &sor->output.encoder);
1411 drm_connector_register(&sor->output.connector);
1412
ea130b24
TR
1413 err = tegra_output_init(drm, &sor->output);
1414 if (err < 0) {
1415 dev_err(client->dev, "failed to initialize output: %d\n", err);
1416 return err;
1417 }
6fad8f66 1418
ea130b24 1419 sor->output.encoder.possible_crtcs = 0x3;
6b6b6042 1420
a82752e1 1421 if (IS_ENABLED(CONFIG_DEBUG_FS)) {
1b0c7b48 1422 err = tegra_sor_debugfs_init(sor, drm->primary);
a82752e1
TR
1423 if (err < 0)
1424 dev_err(sor->dev, "debugfs setup failed: %d\n", err);
1425 }
1426
6b6b6042
TR
1427 if (sor->dpaux) {
1428 err = tegra_dpaux_attach(sor->dpaux, &sor->output);
1429 if (err < 0) {
1430 dev_err(sor->dev, "failed to attach DP: %d\n", err);
1431 return err;
1432 }
1433 }
1434
535a65db
TV
1435 /*
1436 * XXX: Remove this reset once proper hand-over from firmware to
1437 * kernel is possible.
1438 */
1439 err = reset_control_assert(sor->rst);
1440 if (err < 0) {
1441 dev_err(sor->dev, "failed to assert SOR reset: %d\n", err);
1442 return err;
1443 }
1444
6fad8f66
TR
1445 err = clk_prepare_enable(sor->clk);
1446 if (err < 0) {
1447 dev_err(sor->dev, "failed to enable clock: %d\n", err);
1448 return err;
1449 }
1450
535a65db
TV
1451 usleep_range(1000, 3000);
1452
1453 err = reset_control_deassert(sor->rst);
1454 if (err < 0) {
1455 dev_err(sor->dev, "failed to deassert SOR reset: %d\n", err);
1456 return err;
1457 }
1458
6fad8f66
TR
1459 err = clk_prepare_enable(sor->clk_safe);
1460 if (err < 0)
1461 return err;
1462
1463 err = clk_prepare_enable(sor->clk_dp);
1464 if (err < 0)
1465 return err;
1466
6b6b6042
TR
1467 return 0;
1468}
1469
1470static int tegra_sor_exit(struct host1x_client *client)
1471{
1472 struct tegra_sor *sor = host1x_client_to_sor(client);
1473 int err;
1474
328ec69e
TR
1475 tegra_output_exit(&sor->output);
1476
6b6b6042
TR
1477 if (sor->dpaux) {
1478 err = tegra_dpaux_detach(sor->dpaux);
1479 if (err < 0) {
1480 dev_err(sor->dev, "failed to detach DP: %d\n", err);
1481 return err;
1482 }
1483 }
1484
6fad8f66
TR
1485 clk_disable_unprepare(sor->clk_safe);
1486 clk_disable_unprepare(sor->clk_dp);
1487 clk_disable_unprepare(sor->clk);
1488
4009c224
TR
1489 if (IS_ENABLED(CONFIG_DEBUG_FS))
1490 tegra_sor_debugfs_exit(sor);
a82752e1 1491
6b6b6042
TR
1492 return 0;
1493}
1494
1495static const struct host1x_client_ops sor_client_ops = {
1496 .init = tegra_sor_init,
1497 .exit = tegra_sor_exit,
1498};
1499
1500static int tegra_sor_probe(struct platform_device *pdev)
1501{
1502 struct device_node *np;
1503 struct tegra_sor *sor;
1504 struct resource *regs;
1505 int err;
1506
1507 sor = devm_kzalloc(&pdev->dev, sizeof(*sor), GFP_KERNEL);
1508 if (!sor)
1509 return -ENOMEM;
1510
1511 sor->output.dev = sor->dev = &pdev->dev;
1512
1513 np = of_parse_phandle(pdev->dev.of_node, "nvidia,dpaux", 0);
1514 if (np) {
1515 sor->dpaux = tegra_dpaux_find_by_of_node(np);
1516 of_node_put(np);
1517
1518 if (!sor->dpaux)
1519 return -EPROBE_DEFER;
1520 }
1521
1522 err = tegra_output_probe(&sor->output);
4dbdc740
TR
1523 if (err < 0) {
1524 dev_err(&pdev->dev, "failed to probe output: %d\n", err);
6b6b6042 1525 return err;
4dbdc740 1526 }
6b6b6042
TR
1527
1528 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1529 sor->regs = devm_ioremap_resource(&pdev->dev, regs);
1530 if (IS_ERR(sor->regs))
1531 return PTR_ERR(sor->regs);
1532
1533 sor->rst = devm_reset_control_get(&pdev->dev, "sor");
4dbdc740
TR
1534 if (IS_ERR(sor->rst)) {
1535 dev_err(&pdev->dev, "failed to get reset control: %ld\n",
1536 PTR_ERR(sor->rst));
6b6b6042 1537 return PTR_ERR(sor->rst);
4dbdc740 1538 }
6b6b6042
TR
1539
1540 sor->clk = devm_clk_get(&pdev->dev, NULL);
4dbdc740
TR
1541 if (IS_ERR(sor->clk)) {
1542 dev_err(&pdev->dev, "failed to get module clock: %ld\n",
1543 PTR_ERR(sor->clk));
6b6b6042 1544 return PTR_ERR(sor->clk);
4dbdc740 1545 }
6b6b6042
TR
1546
1547 sor->clk_parent = devm_clk_get(&pdev->dev, "parent");
4dbdc740
TR
1548 if (IS_ERR(sor->clk_parent)) {
1549 dev_err(&pdev->dev, "failed to get parent clock: %ld\n",
1550 PTR_ERR(sor->clk_parent));
6b6b6042 1551 return PTR_ERR(sor->clk_parent);
4dbdc740 1552 }
6b6b6042 1553
6b6b6042 1554 sor->clk_safe = devm_clk_get(&pdev->dev, "safe");
4dbdc740
TR
1555 if (IS_ERR(sor->clk_safe)) {
1556 dev_err(&pdev->dev, "failed to get safe clock: %ld\n",
1557 PTR_ERR(sor->clk_safe));
6b6b6042 1558 return PTR_ERR(sor->clk_safe);
4dbdc740 1559 }
6b6b6042 1560
6b6b6042 1561 sor->clk_dp = devm_clk_get(&pdev->dev, "dp");
4dbdc740
TR
1562 if (IS_ERR(sor->clk_dp)) {
1563 dev_err(&pdev->dev, "failed to get DP clock: %ld\n",
1564 PTR_ERR(sor->clk_dp));
6b6b6042 1565 return PTR_ERR(sor->clk_dp);
4dbdc740 1566 }
6b6b6042 1567
6b6b6042
TR
1568 INIT_LIST_HEAD(&sor->client.list);
1569 sor->client.ops = &sor_client_ops;
1570 sor->client.dev = &pdev->dev;
1571
1572 err = host1x_client_register(&sor->client);
1573 if (err < 0) {
1574 dev_err(&pdev->dev, "failed to register host1x client: %d\n",
1575 err);
1576 return err;
1577 }
1578
1579 platform_set_drvdata(pdev, sor);
1580
1581 return 0;
1582}
1583
1584static int tegra_sor_remove(struct platform_device *pdev)
1585{
1586 struct tegra_sor *sor = platform_get_drvdata(pdev);
1587 int err;
1588
1589 err = host1x_client_unregister(&sor->client);
1590 if (err < 0) {
1591 dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
1592 err);
1593 return err;
1594 }
1595
328ec69e 1596 tegra_output_remove(&sor->output);
6b6b6042
TR
1597
1598 return 0;
1599}
1600
1601static const struct of_device_id tegra_sor_of_match[] = {
1602 { .compatible = "nvidia,tegra124-sor", },
3309ac83 1603 { .compatible = "nvidia,tegra210-sor", },
6b6b6042
TR
1604 { },
1605};
ef70728c 1606MODULE_DEVICE_TABLE(of, tegra_sor_of_match);
6b6b6042
TR
1607
1608struct platform_driver tegra_sor_driver = {
1609 .driver = {
1610 .name = "tegra-sor",
1611 .of_match_table = tegra_sor_of_match,
1612 },
1613 .probe = tegra_sor_probe,
1614 .remove = tegra_sor_remove,
1615};