aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/tegra/hdmi.c
diff options
context:
space:
mode:
authorThierry Reding <thierry.reding@avionic-design.de>2012-11-15 16:28:23 -0500
committerDave Airlie <airlied@redhat.com>2012-11-20 00:43:53 -0500
commitedec4af4c3d6d225578290a9acc38c78147df55b (patch)
tree1435e5f1b6d5c30861acefe33f379bc678658b41 /drivers/gpu/drm/tegra/hdmi.c
parentd8f4a9eda006788d8054b8500d9eb5b6efcd8755 (diff)
drm: tegra: Add HDMI support
This commit adds support for the HDMI output on the Tegra20 SoC. Only one such output is available, but it can be driven by either of the two display controllers. A lot of work on this patch has been contributed by NVIDIA's Mark Zhang <markz@nvidia.com> and many other people at NVIDIA were very helpful in getting the HDMI support and surrounding infrastructure to work. Signed-off-by: Thierry Reding <thierry.reding@avionic-design.de> Tested-by: Stephen Warren <swarren@nvidia.com> Acked-by: Mark Zhang <markz@nvidia.com> Reviewed-by: Mark Zhang <markz@nvidia.com> Tested-by: Mark Zhang <markz@nvidia.com> Tested-and-acked-by: Alexandre Courbot <acourbot@nvidia.com> Acked-by: Terje Bergstrom <tbergstrom@nvidia.com> Tested-by: Terje Bergstrom <tbergstrom@nvidia.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/tegra/hdmi.c')
-rw-r--r--drivers/gpu/drm/tegra/hdmi.c1334
1 files changed, 1334 insertions, 0 deletions
diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c
new file mode 100644
index 000000000000..58f55dc6d59d
--- /dev/null
+++ b/drivers/gpu/drm/tegra/hdmi.c
@@ -0,0 +1,1334 @@
1/*
2 * Copyright (C) 2012 Avionic Design GmbH
3 * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 */
9
10#include <linux/clk.h>
11#include <linux/debugfs.h>
12#include <linux/gpio.h>
13#include <linux/module.h>
14#include <linux/of.h>
15#include <linux/platform_device.h>
16#include <linux/regulator/consumer.h>
17
18#include <mach/clk.h>
19
20#include "hdmi.h"
21#include "drm.h"
22#include "dc.h"
23
24struct tegra_hdmi {
25 struct host1x_client client;
26 struct tegra_output output;
27 struct device *dev;
28
29 struct regulator *vdd;
30 struct regulator *pll;
31
32 void __iomem *regs;
33 unsigned int irq;
34
35 struct clk *clk_parent;
36 struct clk *clk;
37
38 unsigned int audio_source;
39 unsigned int audio_freq;
40 bool stereo;
41 bool dvi;
42
43 struct drm_info_list *debugfs_files;
44 struct drm_minor *minor;
45 struct dentry *debugfs;
46};
47
48static inline struct tegra_hdmi *
49host1x_client_to_hdmi(struct host1x_client *client)
50{
51 return container_of(client, struct tegra_hdmi, client);
52}
53
54static inline struct tegra_hdmi *to_hdmi(struct tegra_output *output)
55{
56 return container_of(output, struct tegra_hdmi, output);
57}
58
59#define HDMI_AUDIOCLK_FREQ 216000000
60#define HDMI_REKEY_DEFAULT 56
61
62enum {
63 AUTO = 0,
64 SPDIF,
65 HDA,
66};
67
68static inline unsigned long tegra_hdmi_readl(struct tegra_hdmi *hdmi,
69 unsigned long reg)
70{
71 return readl(hdmi->regs + (reg << 2));
72}
73
74static inline void tegra_hdmi_writel(struct tegra_hdmi *hdmi, unsigned long val,
75 unsigned long reg)
76{
77 writel(val, hdmi->regs + (reg << 2));
78}
79
80struct tegra_hdmi_audio_config {
81 unsigned int pclk;
82 unsigned int n;
83 unsigned int cts;
84 unsigned int aval;
85};
86
87static const struct tegra_hdmi_audio_config tegra_hdmi_audio_32k[] = {
88 { 25200000, 4096, 25200, 24000 },
89 { 27000000, 4096, 27000, 24000 },
90 { 74250000, 4096, 74250, 24000 },
91 { 148500000, 4096, 148500, 24000 },
92 { 0, 0, 0, 0 },
93};
94
95static const struct tegra_hdmi_audio_config tegra_hdmi_audio_44_1k[] = {
96 { 25200000, 5880, 26250, 25000 },
97 { 27000000, 5880, 28125, 25000 },
98 { 74250000, 4704, 61875, 20000 },
99 { 148500000, 4704, 123750, 20000 },
100 { 0, 0, 0, 0 },
101};
102
103static const struct tegra_hdmi_audio_config tegra_hdmi_audio_48k[] = {
104 { 25200000, 6144, 25200, 24000 },
105 { 27000000, 6144, 27000, 24000 },
106 { 74250000, 6144, 74250, 24000 },
107 { 148500000, 6144, 148500, 24000 },
108 { 0, 0, 0, 0 },
109};
110
111static const struct tegra_hdmi_audio_config tegra_hdmi_audio_88_2k[] = {
112 { 25200000, 11760, 26250, 25000 },
113 { 27000000, 11760, 28125, 25000 },
114 { 74250000, 9408, 61875, 20000 },
115 { 148500000, 9408, 123750, 20000 },
116 { 0, 0, 0, 0 },
117};
118
119static const struct tegra_hdmi_audio_config tegra_hdmi_audio_96k[] = {
120 { 25200000, 12288, 25200, 24000 },
121 { 27000000, 12288, 27000, 24000 },
122 { 74250000, 12288, 74250, 24000 },
123 { 148500000, 12288, 148500, 24000 },
124 { 0, 0, 0, 0 },
125};
126
127static const struct tegra_hdmi_audio_config tegra_hdmi_audio_176_4k[] = {
128 { 25200000, 23520, 26250, 25000 },
129 { 27000000, 23520, 28125, 25000 },
130 { 74250000, 18816, 61875, 20000 },
131 { 148500000, 18816, 123750, 20000 },
132 { 0, 0, 0, 0 },
133};
134
135static const struct tegra_hdmi_audio_config tegra_hdmi_audio_192k[] = {
136 { 25200000, 24576, 25200, 24000 },
137 { 27000000, 24576, 27000, 24000 },
138 { 74250000, 24576, 74250, 24000 },
139 { 148500000, 24576, 148500, 24000 },
140 { 0, 0, 0, 0 },
141};
142
143struct tmds_config {
144 unsigned int pclk;
145 u32 pll0;
146 u32 pll1;
147 u32 pe_current;
148 u32 drive_current;
149};
150
151static const struct tmds_config tegra2_tmds_config[] = {
152 { /* 480p modes */
153 .pclk = 27000000,
154 .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) |
155 SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(0) |
156 SOR_PLL_TX_REG_LOAD(3),
157 .pll1 = SOR_PLL_TMDS_TERM_ENABLE,
158 .pe_current = PE_CURRENT0(PE_CURRENT_0_0_mA) |
159 PE_CURRENT1(PE_CURRENT_0_0_mA) |
160 PE_CURRENT2(PE_CURRENT_0_0_mA) |
161 PE_CURRENT3(PE_CURRENT_0_0_mA),
162 .drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_7_125_mA) |
163 DRIVE_CURRENT_LANE1(DRIVE_CURRENT_7_125_mA) |
164 DRIVE_CURRENT_LANE2(DRIVE_CURRENT_7_125_mA) |
165 DRIVE_CURRENT_LANE3(DRIVE_CURRENT_7_125_mA),
166 }, { /* 720p modes */
167 .pclk = 74250000,
168 .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) |
169 SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(1) |
170 SOR_PLL_TX_REG_LOAD(3),
171 .pll1 = SOR_PLL_TMDS_TERM_ENABLE | SOR_PLL_PE_EN,
172 .pe_current = PE_CURRENT0(PE_CURRENT_6_0_mA) |
173 PE_CURRENT1(PE_CURRENT_6_0_mA) |
174 PE_CURRENT2(PE_CURRENT_6_0_mA) |
175 PE_CURRENT3(PE_CURRENT_6_0_mA),
176 .drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_7_125_mA) |
177 DRIVE_CURRENT_LANE1(DRIVE_CURRENT_7_125_mA) |
178 DRIVE_CURRENT_LANE2(DRIVE_CURRENT_7_125_mA) |
179 DRIVE_CURRENT_LANE3(DRIVE_CURRENT_7_125_mA),
180 }, { /* 1080p modes */
181 .pclk = UINT_MAX,
182 .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) |
183 SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(1) |
184 SOR_PLL_TX_REG_LOAD(3),
185 .pll1 = SOR_PLL_TMDS_TERM_ENABLE | SOR_PLL_PE_EN,
186 .pe_current = PE_CURRENT0(PE_CURRENT_6_0_mA) |
187 PE_CURRENT1(PE_CURRENT_6_0_mA) |
188 PE_CURRENT2(PE_CURRENT_6_0_mA) |
189 PE_CURRENT3(PE_CURRENT_6_0_mA),
190 .drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_7_125_mA) |
191 DRIVE_CURRENT_LANE1(DRIVE_CURRENT_7_125_mA) |
192 DRIVE_CURRENT_LANE2(DRIVE_CURRENT_7_125_mA) |
193 DRIVE_CURRENT_LANE3(DRIVE_CURRENT_7_125_mA),
194 },
195};
196
197static const struct tmds_config tegra3_tmds_config[] = {
198 { /* 480p modes */
199 .pclk = 27000000,
200 .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) |
201 SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(0) |
202 SOR_PLL_TX_REG_LOAD(0),
203 .pll1 = SOR_PLL_TMDS_TERM_ENABLE,
204 .pe_current = PE_CURRENT0(PE_CURRENT_0_0_mA) |
205 PE_CURRENT1(PE_CURRENT_0_0_mA) |
206 PE_CURRENT2(PE_CURRENT_0_0_mA) |
207 PE_CURRENT3(PE_CURRENT_0_0_mA),
208 .drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_5_250_mA) |
209 DRIVE_CURRENT_LANE1(DRIVE_CURRENT_5_250_mA) |
210 DRIVE_CURRENT_LANE2(DRIVE_CURRENT_5_250_mA) |
211 DRIVE_CURRENT_LANE3(DRIVE_CURRENT_5_250_mA),
212 }, { /* 720p modes */
213 .pclk = 74250000,
214 .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) |
215 SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(1) |
216 SOR_PLL_TX_REG_LOAD(0),
217 .pll1 = SOR_PLL_TMDS_TERM_ENABLE | SOR_PLL_PE_EN,
218 .pe_current = PE_CURRENT0(PE_CURRENT_5_0_mA) |
219 PE_CURRENT1(PE_CURRENT_5_0_mA) |
220 PE_CURRENT2(PE_CURRENT_5_0_mA) |
221 PE_CURRENT3(PE_CURRENT_5_0_mA),
222 .drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_5_250_mA) |
223 DRIVE_CURRENT_LANE1(DRIVE_CURRENT_5_250_mA) |
224 DRIVE_CURRENT_LANE2(DRIVE_CURRENT_5_250_mA) |
225 DRIVE_CURRENT_LANE3(DRIVE_CURRENT_5_250_mA),
226 }, { /* 1080p modes */
227 .pclk = UINT_MAX,
228 .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) |
229 SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(3) |
230 SOR_PLL_TX_REG_LOAD(0),
231 .pll1 = SOR_PLL_TMDS_TERM_ENABLE | SOR_PLL_PE_EN,
232 .pe_current = PE_CURRENT0(PE_CURRENT_5_0_mA) |
233 PE_CURRENT1(PE_CURRENT_5_0_mA) |
234 PE_CURRENT2(PE_CURRENT_5_0_mA) |
235 PE_CURRENT3(PE_CURRENT_5_0_mA),
236 .drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_5_250_mA) |
237 DRIVE_CURRENT_LANE1(DRIVE_CURRENT_5_250_mA) |
238 DRIVE_CURRENT_LANE2(DRIVE_CURRENT_5_250_mA) |
239 DRIVE_CURRENT_LANE3(DRIVE_CURRENT_5_250_mA),
240 },
241};
242
243static const struct tegra_hdmi_audio_config *
244tegra_hdmi_get_audio_config(unsigned int audio_freq, unsigned int pclk)
245{
246 const struct tegra_hdmi_audio_config *table;
247
248 switch (audio_freq) {
249 case 32000:
250 table = tegra_hdmi_audio_32k;
251 break;
252
253 case 44100:
254 table = tegra_hdmi_audio_44_1k;
255 break;
256
257 case 48000:
258 table = tegra_hdmi_audio_48k;
259 break;
260
261 case 88200:
262 table = tegra_hdmi_audio_88_2k;
263 break;
264
265 case 96000:
266 table = tegra_hdmi_audio_96k;
267 break;
268
269 case 176400:
270 table = tegra_hdmi_audio_176_4k;
271 break;
272
273 case 192000:
274 table = tegra_hdmi_audio_192k;
275 break;
276
277 default:
278 return NULL;
279 }
280
281 while (table->pclk) {
282 if (table->pclk == pclk)
283 return table;
284
285 table++;
286 }
287
288 return NULL;
289}
290
291static void tegra_hdmi_setup_audio_fs_tables(struct tegra_hdmi *hdmi)
292{
293 const unsigned int freqs[] = {
294 32000, 44100, 48000, 88200, 96000, 176400, 192000
295 };
296 unsigned int i;
297
298 for (i = 0; i < ARRAY_SIZE(freqs); i++) {
299 unsigned int f = freqs[i];
300 unsigned int eight_half;
301 unsigned long value;
302 unsigned int delta;
303
304 if (f > 96000)
305 delta = 2;
306 else if (f > 480000)
307 delta = 6;
308 else
309 delta = 9;
310
311 eight_half = (8 * HDMI_AUDIOCLK_FREQ) / (f * 128);
312 value = AUDIO_FS_LOW(eight_half - delta) |
313 AUDIO_FS_HIGH(eight_half + delta);
314 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_AUDIO_FS(i));
315 }
316}
317
318static int tegra_hdmi_setup_audio(struct tegra_hdmi *hdmi, unsigned int pclk)
319{
320 struct device_node *node = hdmi->dev->of_node;
321 const struct tegra_hdmi_audio_config *config;
322 unsigned int offset = 0;
323 unsigned long value;
324
325 switch (hdmi->audio_source) {
326 case HDA:
327 value = AUDIO_CNTRL0_SOURCE_SELECT_HDAL;
328 break;
329
330 case SPDIF:
331 value = AUDIO_CNTRL0_SOURCE_SELECT_SPDIF;
332 break;
333
334 default:
335 value = AUDIO_CNTRL0_SOURCE_SELECT_AUTO;
336 break;
337 }
338
339 if (of_device_is_compatible(node, "nvidia,tegra30-hdmi")) {
340 value |= AUDIO_CNTRL0_ERROR_TOLERANCE(6) |
341 AUDIO_CNTRL0_FRAMES_PER_BLOCK(0xc0);
342 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_AUDIO_CNTRL0);
343 } else {
344 value |= AUDIO_CNTRL0_INJECT_NULLSMPL;
345 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_AUDIO_CNTRL0);
346
347 value = AUDIO_CNTRL0_ERROR_TOLERANCE(6) |
348 AUDIO_CNTRL0_FRAMES_PER_BLOCK(0xc0);
349 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_AUDIO_CNTRL0);
350 }
351
352 config = tegra_hdmi_get_audio_config(hdmi->audio_freq, pclk);
353 if (!config) {
354 dev_err(hdmi->dev, "cannot set audio to %u at %u pclk\n",
355 hdmi->audio_freq, pclk);
356 return -EINVAL;
357 }
358
359 tegra_hdmi_writel(hdmi, 0, HDMI_NV_PDISP_HDMI_ACR_CTRL);
360
361 value = AUDIO_N_RESETF | AUDIO_N_GENERATE_ALTERNATE |
362 AUDIO_N_VALUE(config->n - 1);
363 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_AUDIO_N);
364
365 tegra_hdmi_writel(hdmi, ACR_SUBPACK_N(config->n) | ACR_ENABLE,
366 HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_HIGH);
367
368 value = ACR_SUBPACK_CTS(config->cts);
369 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_LOW);
370
371 value = SPARE_HW_CTS | SPARE_FORCE_SW_CTS | SPARE_CTS_RESET_VAL(1);
372 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_SPARE);
373
374 value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_AUDIO_N);
375 value &= ~AUDIO_N_RESETF;
376 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_AUDIO_N);
377
378 if (of_device_is_compatible(node, "nvidia,tegra30-hdmi")) {
379 switch (hdmi->audio_freq) {
380 case 32000:
381 offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_0320;
382 break;
383
384 case 44100:
385 offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_0441;
386 break;
387
388 case 48000:
389 offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_0480;
390 break;
391
392 case 88200:
393 offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_0882;
394 break;
395
396 case 96000:
397 offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_0960;
398 break;
399
400 case 176400:
401 offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_1764;
402 break;
403
404 case 192000:
405 offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_1920;
406 break;
407 }
408
409 tegra_hdmi_writel(hdmi, config->aval, offset);
410 }
411
412 tegra_hdmi_setup_audio_fs_tables(hdmi);
413
414 return 0;
415}
416
417static void tegra_hdmi_write_infopack(struct tegra_hdmi *hdmi,
418 unsigned int offset, u8 type,
419 u8 version, void *data, size_t size)
420{
421 unsigned long value;
422 u8 *ptr = data;
423 u32 subpack[2];
424 size_t i;
425 u8 csum;
426
427 /* first byte of data is the checksum */
428 csum = type + version + size - 1;
429
430 for (i = 1; i < size; i++)
431 csum += ptr[i];
432
433 ptr[0] = 0x100 - csum;
434
435 value = INFOFRAME_HEADER_TYPE(type) |
436 INFOFRAME_HEADER_VERSION(version) |
437 INFOFRAME_HEADER_LEN(size - 1);
438 tegra_hdmi_writel(hdmi, value, offset);
439
440 /* The audio inforame only has one set of subpack registers. The hdmi
441 * block pads the rest of the data as per the spec so we have to fixup
442 * the length before filling in the subpacks.
443 */
444 if (offset == HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_HEADER)
445 size = 6;
446
447 /* each subpack 7 bytes devided into:
448 * subpack_low - bytes 0 - 3
449 * subpack_high - bytes 4 - 6 (with byte 7 padded to 0x00)
450 */
451 for (i = 0; i < size; i++) {
452 size_t index = i % 7;
453
454 if (index == 0)
455 memset(subpack, 0x0, sizeof(subpack));
456
457 ((u8 *)subpack)[index] = ptr[i];
458
459 if (index == 6 || (i + 1 == size)) {
460 unsigned int reg = offset + 1 + (i / 7) * 2;
461
462 tegra_hdmi_writel(hdmi, subpack[0], reg);
463 tegra_hdmi_writel(hdmi, subpack[1], reg + 1);
464 }
465 }
466}
467
468static void tegra_hdmi_setup_avi_infoframe(struct tegra_hdmi *hdmi,
469 struct drm_display_mode *mode)
470{
471 struct hdmi_avi_infoframe frame;
472 unsigned int h_front_porch;
473 unsigned int hsize = 16;
474 unsigned int vsize = 9;
475
476 if (hdmi->dvi) {
477 tegra_hdmi_writel(hdmi, 0,
478 HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_CTRL);
479 return;
480 }
481
482 h_front_porch = mode->htotal - mode->hsync_end;
483 memset(&frame, 0, sizeof(frame));
484 frame.r = HDMI_AVI_R_SAME;
485
486 switch (mode->vdisplay) {
487 case 480:
488 if (mode->hdisplay == 640) {
489 frame.m = HDMI_AVI_M_4_3;
490 frame.vic = 1;
491 } else {
492 frame.m = HDMI_AVI_M_16_9;
493 frame.vic = 3;
494 }
495 break;
496
497 case 576:
498 if (((hsize * 10) / vsize) > 14) {
499 frame.m = HDMI_AVI_M_16_9;
500 frame.vic = 18;
501 } else {
502 frame.m = HDMI_AVI_M_4_3;
503 frame.vic = 17;
504 }
505 break;
506
507 case 720:
508 case 1470: /* stereo mode */
509 frame.m = HDMI_AVI_M_16_9;
510
511 if (h_front_porch == 110)
512 frame.vic = 4;
513 else
514 frame.vic = 19;
515 break;
516
517 case 1080:
518 case 2205: /* stereo mode */
519 frame.m = HDMI_AVI_M_16_9;
520
521 switch (h_front_porch) {
522 case 88:
523 frame.vic = 16;
524 break;
525
526 case 528:
527 frame.vic = 31;
528 break;
529
530 default:
531 frame.vic = 32;
532 break;
533 }
534 break;
535
536 default:
537 frame.m = HDMI_AVI_M_16_9;
538 frame.vic = 0;
539 break;
540 }
541
542 tegra_hdmi_write_infopack(hdmi, HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_HEADER,
543 HDMI_INFOFRAME_TYPE_AVI, HDMI_AVI_VERSION,
544 &frame, sizeof(frame));
545
546 tegra_hdmi_writel(hdmi, INFOFRAME_CTRL_ENABLE,
547 HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_CTRL);
548}
549
550static void tegra_hdmi_setup_audio_infoframe(struct tegra_hdmi *hdmi)
551{
552 struct hdmi_audio_infoframe frame;
553
554 if (hdmi->dvi) {
555 tegra_hdmi_writel(hdmi, 0,
556 HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_CTRL);
557 return;
558 }
559
560 memset(&frame, 0, sizeof(frame));
561 frame.cc = HDMI_AUDIO_CC_2;
562
563 tegra_hdmi_write_infopack(hdmi,
564 HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_HEADER,
565 HDMI_INFOFRAME_TYPE_AUDIO,
566 HDMI_AUDIO_VERSION,
567 &frame, sizeof(frame));
568
569 tegra_hdmi_writel(hdmi, INFOFRAME_CTRL_ENABLE,
570 HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_CTRL);
571}
572
573static void tegra_hdmi_setup_stereo_infoframe(struct tegra_hdmi *hdmi)
574{
575 struct hdmi_stereo_infoframe frame;
576 unsigned long value;
577
578 if (!hdmi->stereo) {
579 value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
580 value &= ~GENERIC_CTRL_ENABLE;
581 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
582 return;
583 }
584
585 memset(&frame, 0, sizeof(frame));
586 frame.regid0 = 0x03;
587 frame.regid1 = 0x0c;
588 frame.regid2 = 0x00;
589 frame.hdmi_video_format = 2;
590
591 /* TODO: 74 MHz limit? */
592 if (1) {
593 frame._3d_structure = 0;
594 } else {
595 frame._3d_structure = 8;
596 frame._3d_ext_data = 0;
597 }
598
599 tegra_hdmi_write_infopack(hdmi, HDMI_NV_PDISP_HDMI_GENERIC_HEADER,
600 HDMI_INFOFRAME_TYPE_VENDOR,
601 HDMI_VENDOR_VERSION, &frame, 6);
602
603 value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
604 value |= GENERIC_CTRL_ENABLE;
605 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
606}
607
608static void tegra_hdmi_setup_tmds(struct tegra_hdmi *hdmi,
609 const struct tmds_config *tmds)
610{
611 unsigned long value;
612
613 tegra_hdmi_writel(hdmi, tmds->pll0, HDMI_NV_PDISP_SOR_PLL0);
614 tegra_hdmi_writel(hdmi, tmds->pll1, HDMI_NV_PDISP_SOR_PLL1);
615 tegra_hdmi_writel(hdmi, tmds->pe_current, HDMI_NV_PDISP_PE_CURRENT);
616
617 value = tmds->drive_current | DRIVE_CURRENT_FUSE_OVERRIDE;
618 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_LANE_DRIVE_CURRENT);
619}
620
621static int tegra_output_hdmi_enable(struct tegra_output *output)
622{
623 unsigned int h_sync_width, h_front_porch, h_back_porch, i, rekey;
624 struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc);
625 struct drm_display_mode *mode = &dc->base.mode;
626 struct tegra_hdmi *hdmi = to_hdmi(output);
627 struct device_node *node = hdmi->dev->of_node;
628 unsigned int pulse_start, div82, pclk;
629 const struct tmds_config *tmds;
630 unsigned int num_tmds;
631 unsigned long value;
632 int retries = 1000;
633 int err;
634
635 pclk = mode->clock * 1000;
636 h_sync_width = mode->hsync_end - mode->hsync_start;
637 h_front_porch = mode->htotal - mode->hsync_end;
638 h_back_porch = mode->hsync_start - mode->hdisplay;
639
640 err = regulator_enable(hdmi->vdd);
641 if (err < 0) {
642 dev_err(hdmi->dev, "failed to enable VDD regulator: %d\n", err);
643 return err;
644 }
645
646 err = regulator_enable(hdmi->pll);
647 if (err < 0) {
648 dev_err(hdmi->dev, "failed to enable PLL regulator: %d\n", err);
649 return err;
650 }
651
652 /*
653 * This assumes that the display controller will divide its parent
654 * clock by 2 to generate the pixel clock.
655 */
656 err = tegra_output_setup_clock(output, hdmi->clk, pclk * 2);
657 if (err < 0) {
658 dev_err(hdmi->dev, "failed to setup clock: %d\n", err);
659 return err;
660 }
661
662 err = clk_set_rate(hdmi->clk, pclk);
663 if (err < 0)
664 return err;
665
666 err = clk_enable(hdmi->clk);
667 if (err < 0) {
668 dev_err(hdmi->dev, "failed to enable clock: %d\n", err);
669 return err;
670 }
671
672 tegra_periph_reset_assert(hdmi->clk);
673 usleep_range(1000, 2000);
674 tegra_periph_reset_deassert(hdmi->clk);
675
676 tegra_dc_writel(dc, VSYNC_H_POSITION(1),
677 DC_DISP_DISP_TIMING_OPTIONS);
678 tegra_dc_writel(dc, DITHER_CONTROL_DISABLE | BASE_COLOR_SIZE888,
679 DC_DISP_DISP_COLOR_CONTROL);
680
681 /* video_preamble uses h_pulse2 */
682 pulse_start = 1 + h_sync_width + h_back_porch - 10;
683
684 tegra_dc_writel(dc, H_PULSE_2_ENABLE, DC_DISP_DISP_SIGNAL_OPTIONS0);
685
686 value = PULSE_MODE_NORMAL | PULSE_POLARITY_HIGH | PULSE_QUAL_VACTIVE |
687 PULSE_LAST_END_A;
688 tegra_dc_writel(dc, value, DC_DISP_H_PULSE2_CONTROL);
689
690 value = PULSE_START(pulse_start) | PULSE_END(pulse_start + 8);
691 tegra_dc_writel(dc, value, DC_DISP_H_PULSE2_POSITION_A);
692
693 value = VSYNC_WINDOW_END(0x210) | VSYNC_WINDOW_START(0x200) |
694 VSYNC_WINDOW_ENABLE;
695 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_VSYNC_WINDOW);
696
697 if (dc->pipe)
698 value = HDMI_SRC_DISPLAYB;
699 else
700 value = HDMI_SRC_DISPLAYA;
701
702 if ((mode->hdisplay == 720) && ((mode->vdisplay == 480) ||
703 (mode->vdisplay == 576)))
704 tegra_hdmi_writel(hdmi,
705 value | ARM_VIDEO_RANGE_FULL,
706 HDMI_NV_PDISP_INPUT_CONTROL);
707 else
708 tegra_hdmi_writel(hdmi,
709 value | ARM_VIDEO_RANGE_LIMITED,
710 HDMI_NV_PDISP_INPUT_CONTROL);
711
712 div82 = clk_get_rate(hdmi->clk) / 1000000 * 4;
713 value = SOR_REFCLK_DIV_INT(div82 >> 2) | SOR_REFCLK_DIV_FRAC(div82);
714 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_REFCLK);
715
716 if (!hdmi->dvi) {
717 err = tegra_hdmi_setup_audio(hdmi, pclk);
718 if (err < 0)
719 hdmi->dvi = true;
720 }
721
722 if (of_device_is_compatible(node, "nvidia,tegra20-hdmi")) {
723 /*
724 * TODO: add ELD support
725 */
726 }
727
728 rekey = HDMI_REKEY_DEFAULT;
729 value = HDMI_CTRL_REKEY(rekey);
730 value |= HDMI_CTRL_MAX_AC_PACKET((h_sync_width + h_back_porch +
731 h_front_porch - rekey - 18) / 32);
732
733 if (!hdmi->dvi)
734 value |= HDMI_CTRL_ENABLE;
735
736 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_CTRL);
737
738 if (hdmi->dvi)
739 tegra_hdmi_writel(hdmi, 0x0,
740 HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
741 else
742 tegra_hdmi_writel(hdmi, GENERIC_CTRL_AUDIO,
743 HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
744
745 tegra_hdmi_setup_avi_infoframe(hdmi, mode);
746 tegra_hdmi_setup_audio_infoframe(hdmi);
747 tegra_hdmi_setup_stereo_infoframe(hdmi);
748
749 /* TMDS CONFIG */
750 if (of_device_is_compatible(node, "nvidia,tegra30-hdmi")) {
751 num_tmds = ARRAY_SIZE(tegra3_tmds_config);
752 tmds = tegra3_tmds_config;
753 } else {
754 num_tmds = ARRAY_SIZE(tegra2_tmds_config);
755 tmds = tegra2_tmds_config;
756 }
757
758 for (i = 0; i < num_tmds; i++) {
759 if (pclk <= tmds[i].pclk) {
760 tegra_hdmi_setup_tmds(hdmi, &tmds[i]);
761 break;
762 }
763 }
764
765 tegra_hdmi_writel(hdmi,
766 SOR_SEQ_CTL_PU_PC(0) |
767 SOR_SEQ_PU_PC_ALT(0) |
768 SOR_SEQ_PD_PC(8) |
769 SOR_SEQ_PD_PC_ALT(8),
770 HDMI_NV_PDISP_SOR_SEQ_CTL);
771
772 value = SOR_SEQ_INST_WAIT_TIME(1) |
773 SOR_SEQ_INST_WAIT_UNITS_VSYNC |
774 SOR_SEQ_INST_HALT |
775 SOR_SEQ_INST_PIN_A_LOW |
776 SOR_SEQ_INST_PIN_B_LOW |
777 SOR_SEQ_INST_DRIVE_PWM_OUT_LO;
778
779 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_SEQ_INST(0));
780 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_SEQ_INST(8));
781
782 value = 0x1c800;
783 value &= ~SOR_CSTM_ROTCLK(~0);
784 value |= SOR_CSTM_ROTCLK(2);
785 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_CSTM);
786
787 tegra_dc_writel(dc, DISP_CTRL_MODE_STOP, DC_CMD_DISPLAY_COMMAND);
788 tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
789 tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
790
791 /* start SOR */
792 tegra_hdmi_writel(hdmi,
793 SOR_PWR_NORMAL_STATE_PU |
794 SOR_PWR_NORMAL_START_NORMAL |
795 SOR_PWR_SAFE_STATE_PD |
796 SOR_PWR_SETTING_NEW_TRIGGER,
797 HDMI_NV_PDISP_SOR_PWR);
798 tegra_hdmi_writel(hdmi,
799 SOR_PWR_NORMAL_STATE_PU |
800 SOR_PWR_NORMAL_START_NORMAL |
801 SOR_PWR_SAFE_STATE_PD |
802 SOR_PWR_SETTING_NEW_DONE,
803 HDMI_NV_PDISP_SOR_PWR);
804
805 do {
806 BUG_ON(--retries < 0);
807 value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_SOR_PWR);
808 } while (value & SOR_PWR_SETTING_NEW_PENDING);
809
810 value = SOR_STATE_ASY_CRCMODE_COMPLETE |
811 SOR_STATE_ASY_OWNER_HEAD0 |
812 SOR_STATE_ASY_SUBOWNER_BOTH |
813 SOR_STATE_ASY_PROTOCOL_SINGLE_TMDS_A |
814 SOR_STATE_ASY_DEPOL_POS;
815
816 /* setup sync polarities */
817 if (mode->flags & DRM_MODE_FLAG_PHSYNC)
818 value |= SOR_STATE_ASY_HSYNCPOL_POS;
819
820 if (mode->flags & DRM_MODE_FLAG_NHSYNC)
821 value |= SOR_STATE_ASY_HSYNCPOL_NEG;
822
823 if (mode->flags & DRM_MODE_FLAG_PVSYNC)
824 value |= SOR_STATE_ASY_VSYNCPOL_POS;
825
826 if (mode->flags & DRM_MODE_FLAG_NVSYNC)
827 value |= SOR_STATE_ASY_VSYNCPOL_NEG;
828
829 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_STATE2);
830
831 value = SOR_STATE_ASY_HEAD_OPMODE_AWAKE | SOR_STATE_ASY_ORMODE_NORMAL;
832 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_STATE1);
833
834 tegra_hdmi_writel(hdmi, 0, HDMI_NV_PDISP_SOR_STATE0);
835 tegra_hdmi_writel(hdmi, SOR_STATE_UPDATE, HDMI_NV_PDISP_SOR_STATE0);
836 tegra_hdmi_writel(hdmi, value | SOR_STATE_ATTACHED,
837 HDMI_NV_PDISP_SOR_STATE1);
838 tegra_hdmi_writel(hdmi, 0, HDMI_NV_PDISP_SOR_STATE0);
839
840 tegra_dc_writel(dc, HDMI_ENABLE, DC_DISP_DISP_WIN_OPTIONS);
841
842 value = PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
843 PW4_ENABLE | PM0_ENABLE | PM1_ENABLE;
844 tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL);
845
846 value = DISP_CTRL_MODE_C_DISPLAY;
847 tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND);
848
849 tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
850 tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
851
852 /* TODO: add HDCP support */
853
854 return 0;
855}
856
857static int tegra_output_hdmi_disable(struct tegra_output *output)
858{
859 struct tegra_hdmi *hdmi = to_hdmi(output);
860
861 tegra_periph_reset_assert(hdmi->clk);
862 clk_disable(hdmi->clk);
863 regulator_disable(hdmi->pll);
864 regulator_disable(hdmi->vdd);
865
866 return 0;
867}
868
869static int tegra_output_hdmi_setup_clock(struct tegra_output *output,
870 struct clk *clk, unsigned long pclk)
871{
872 struct tegra_hdmi *hdmi = to_hdmi(output);
873 struct clk *base;
874 int err;
875
876 err = clk_set_parent(clk, hdmi->clk_parent);
877 if (err < 0) {
878 dev_err(output->dev, "failed to set parent: %d\n", err);
879 return err;
880 }
881
882 base = clk_get_parent(hdmi->clk_parent);
883
884 /*
885 * This assumes that the parent clock is pll_d_out0 or pll_d2_out
886 * respectively, each of which divides the base pll_d by 2.
887 */
888 err = clk_set_rate(base, pclk * 2);
889 if (err < 0)
890 dev_err(output->dev,
891 "failed to set base clock rate to %lu Hz\n",
892 pclk * 2);
893
894 return 0;
895}
896
897static int tegra_output_hdmi_check_mode(struct tegra_output *output,
898 struct drm_display_mode *mode,
899 enum drm_mode_status *status)
900{
901 struct tegra_hdmi *hdmi = to_hdmi(output);
902 unsigned long pclk = mode->clock * 1000;
903 struct clk *parent;
904 long err;
905
906 parent = clk_get_parent(hdmi->clk_parent);
907
908 err = clk_round_rate(parent, pclk * 4);
909 if (err < 0)
910 *status = MODE_NOCLOCK;
911 else
912 *status = MODE_OK;
913
914 return 0;
915}
916
917static const struct tegra_output_ops hdmi_ops = {
918 .enable = tegra_output_hdmi_enable,
919 .disable = tegra_output_hdmi_disable,
920 .setup_clock = tegra_output_hdmi_setup_clock,
921 .check_mode = tegra_output_hdmi_check_mode,
922};
923
924static int tegra_hdmi_show_regs(struct seq_file *s, void *data)
925{
926 struct drm_info_node *node = s->private;
927 struct tegra_hdmi *hdmi = node->info_ent->data;
928
929#define DUMP_REG(name) \
930 seq_printf(s, "%-56s %#05x %08lx\n", #name, name, \
931 tegra_hdmi_readl(hdmi, name))
932
933 DUMP_REG(HDMI_CTXSW);
934 DUMP_REG(HDMI_NV_PDISP_SOR_STATE0);
935 DUMP_REG(HDMI_NV_PDISP_SOR_STATE1);
936 DUMP_REG(HDMI_NV_PDISP_SOR_STATE2);
937 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_AN_MSB);
938 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_AN_LSB);
939 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CN_MSB);
940 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CN_LSB);
941 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_AKSV_MSB);
942 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_AKSV_LSB);
943 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_BKSV_MSB);
944 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_BKSV_LSB);
945 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CKSV_MSB);
946 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CKSV_LSB);
947 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_DKSV_MSB);
948 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_DKSV_LSB);
949 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CTRL);
950 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CMODE);
951 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_MPRIME_MSB);
952 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_MPRIME_LSB);
953 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_SPRIME_MSB);
954 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_SPRIME_LSB2);
955 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_SPRIME_LSB1);
956 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_RI);
957 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CS_MSB);
958 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CS_LSB);
959 DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_EMU0);
960 DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_EMU_RDATA0);
961 DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_EMU1);
962 DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_EMU2);
963 DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_CTRL);
964 DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_STATUS);
965 DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_HEADER);
966 DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_SUBPACK0_LOW);
967 DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_SUBPACK0_HIGH);
968 DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_CTRL);
969 DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_STATUS);
970 DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_HEADER);
971 DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK0_LOW);
972 DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK0_HIGH);
973 DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK1_LOW);
974 DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK1_HIGH);
975 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
976 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_STATUS);
977 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_HEADER);
978 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK0_LOW);
979 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK0_HIGH);
980 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK1_LOW);
981 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK1_HIGH);
982 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK2_LOW);
983 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK2_HIGH);
984 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK3_LOW);
985 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK3_HIGH);
986 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_CTRL);
987 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0320_SUBPACK_LOW);
988 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0320_SUBPACK_HIGH);
989 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_LOW);
990 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_HIGH);
991 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0882_SUBPACK_LOW);
992 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0882_SUBPACK_HIGH);
993 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_1764_SUBPACK_LOW);
994 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_1764_SUBPACK_HIGH);
995 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0480_SUBPACK_LOW);
996 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0480_SUBPACK_HIGH);
997 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0960_SUBPACK_LOW);
998 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0960_SUBPACK_HIGH);
999 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_1920_SUBPACK_LOW);
1000 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_1920_SUBPACK_HIGH);
1001 DUMP_REG(HDMI_NV_PDISP_HDMI_CTRL);
1002 DUMP_REG(HDMI_NV_PDISP_HDMI_VSYNC_KEEPOUT);
1003 DUMP_REG(HDMI_NV_PDISP_HDMI_VSYNC_WINDOW);
1004 DUMP_REG(HDMI_NV_PDISP_HDMI_GCP_CTRL);
1005 DUMP_REG(HDMI_NV_PDISP_HDMI_GCP_STATUS);
1006 DUMP_REG(HDMI_NV_PDISP_HDMI_GCP_SUBPACK);
1007 DUMP_REG(HDMI_NV_PDISP_HDMI_CHANNEL_STATUS1);
1008 DUMP_REG(HDMI_NV_PDISP_HDMI_CHANNEL_STATUS2);
1009 DUMP_REG(HDMI_NV_PDISP_HDMI_EMU0);
1010 DUMP_REG(HDMI_NV_PDISP_HDMI_EMU1);
1011 DUMP_REG(HDMI_NV_PDISP_HDMI_EMU1_RDATA);
1012 DUMP_REG(HDMI_NV_PDISP_HDMI_SPARE);
1013 DUMP_REG(HDMI_NV_PDISP_HDMI_SPDIF_CHN_STATUS1);
1014 DUMP_REG(HDMI_NV_PDISP_HDMI_SPDIF_CHN_STATUS2);
1015 DUMP_REG(HDMI_NV_PDISP_HDMI_HDCPRIF_ROM_CTRL);
1016 DUMP_REG(HDMI_NV_PDISP_SOR_CAP);
1017 DUMP_REG(HDMI_NV_PDISP_SOR_PWR);
1018 DUMP_REG(HDMI_NV_PDISP_SOR_TEST);
1019 DUMP_REG(HDMI_NV_PDISP_SOR_PLL0);
1020 DUMP_REG(HDMI_NV_PDISP_SOR_PLL1);
1021 DUMP_REG(HDMI_NV_PDISP_SOR_PLL2);
1022 DUMP_REG(HDMI_NV_PDISP_SOR_CSTM);
1023 DUMP_REG(HDMI_NV_PDISP_SOR_LVDS);
1024 DUMP_REG(HDMI_NV_PDISP_SOR_CRCA);
1025 DUMP_REG(HDMI_NV_PDISP_SOR_CRCB);
1026 DUMP_REG(HDMI_NV_PDISP_SOR_BLANK);
1027 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_CTL);
1028 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(0));
1029 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(1));
1030 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(2));
1031 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(3));
1032 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(4));
1033 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(5));
1034 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(6));
1035 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(7));
1036 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(8));
1037 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(9));
1038 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(10));
1039 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(11));
1040 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(12));
1041 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(13));
1042 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(14));
1043 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(15));
1044 DUMP_REG(HDMI_NV_PDISP_SOR_VCRCA0);
1045 DUMP_REG(HDMI_NV_PDISP_SOR_VCRCA1);
1046 DUMP_REG(HDMI_NV_PDISP_SOR_CCRCA0);
1047 DUMP_REG(HDMI_NV_PDISP_SOR_CCRCA1);
1048 DUMP_REG(HDMI_NV_PDISP_SOR_EDATAA0);
1049 DUMP_REG(HDMI_NV_PDISP_SOR_EDATAA1);
1050 DUMP_REG(HDMI_NV_PDISP_SOR_COUNTA0);
1051 DUMP_REG(HDMI_NV_PDISP_SOR_COUNTA1);
1052 DUMP_REG(HDMI_NV_PDISP_SOR_DEBUGA0);
1053 DUMP_REG(HDMI_NV_PDISP_SOR_DEBUGA1);
1054 DUMP_REG(HDMI_NV_PDISP_SOR_TRIG);
1055 DUMP_REG(HDMI_NV_PDISP_SOR_MSCHECK);
1056 DUMP_REG(HDMI_NV_PDISP_SOR_LANE_DRIVE_CURRENT);
1057 DUMP_REG(HDMI_NV_PDISP_AUDIO_DEBUG0);
1058 DUMP_REG(HDMI_NV_PDISP_AUDIO_DEBUG1);
1059 DUMP_REG(HDMI_NV_PDISP_AUDIO_DEBUG2);
1060 DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(0));
1061 DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(1));
1062 DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(2));
1063 DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(3));
1064 DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(4));
1065 DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(5));
1066 DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(6));
1067 DUMP_REG(HDMI_NV_PDISP_AUDIO_PULSE_WIDTH);
1068 DUMP_REG(HDMI_NV_PDISP_AUDIO_THRESHOLD);
1069 DUMP_REG(HDMI_NV_PDISP_AUDIO_CNTRL0);
1070 DUMP_REG(HDMI_NV_PDISP_AUDIO_N);
1071 DUMP_REG(HDMI_NV_PDISP_HDCPRIF_ROM_TIMING);
1072 DUMP_REG(HDMI_NV_PDISP_SOR_REFCLK);
1073 DUMP_REG(HDMI_NV_PDISP_CRC_CONTROL);
1074 DUMP_REG(HDMI_NV_PDISP_INPUT_CONTROL);
1075 DUMP_REG(HDMI_NV_PDISP_SCRATCH);
1076 DUMP_REG(HDMI_NV_PDISP_PE_CURRENT);
1077 DUMP_REG(HDMI_NV_PDISP_KEY_CTRL);
1078 DUMP_REG(HDMI_NV_PDISP_KEY_DEBUG0);
1079 DUMP_REG(HDMI_NV_PDISP_KEY_DEBUG1);
1080 DUMP_REG(HDMI_NV_PDISP_KEY_DEBUG2);
1081 DUMP_REG(HDMI_NV_PDISP_KEY_HDCP_KEY_0);
1082 DUMP_REG(HDMI_NV_PDISP_KEY_HDCP_KEY_1);
1083 DUMP_REG(HDMI_NV_PDISP_KEY_HDCP_KEY_2);
1084 DUMP_REG(HDMI_NV_PDISP_KEY_HDCP_KEY_3);
1085 DUMP_REG(HDMI_NV_PDISP_KEY_HDCP_KEY_TRIG);
1086 DUMP_REG(HDMI_NV_PDISP_KEY_SKEY_INDEX);
1087 DUMP_REG(HDMI_NV_PDISP_SOR_AUDIO_CNTRL0);
1088 DUMP_REG(HDMI_NV_PDISP_SOR_AUDIO_HDA_ELD_BUFWR);
1089 DUMP_REG(HDMI_NV_PDISP_SOR_AUDIO_HDA_PRESENSE);
1090
1091#undef DUMP_REG
1092
1093 return 0;
1094}
1095
1096static struct drm_info_list debugfs_files[] = {
1097 { "regs", tegra_hdmi_show_regs, 0, NULL },
1098};
1099
1100static int tegra_hdmi_debugfs_init(struct tegra_hdmi *hdmi,
1101 struct drm_minor *minor)
1102{
1103 unsigned int i;
1104 int err;
1105
1106 hdmi->debugfs = debugfs_create_dir("hdmi", minor->debugfs_root);
1107 if (!hdmi->debugfs)
1108 return -ENOMEM;
1109
1110 hdmi->debugfs_files = kmemdup(debugfs_files, sizeof(debugfs_files),
1111 GFP_KERNEL);
1112 if (!hdmi->debugfs_files) {
1113 err = -ENOMEM;
1114 goto remove;
1115 }
1116
1117 for (i = 0; i < ARRAY_SIZE(debugfs_files); i++)
1118 hdmi->debugfs_files[i].data = hdmi;
1119
1120 err = drm_debugfs_create_files(hdmi->debugfs_files,
1121 ARRAY_SIZE(debugfs_files),
1122 hdmi->debugfs, minor);
1123 if (err < 0)
1124 goto free;
1125
1126 hdmi->minor = minor;
1127
1128 return 0;
1129
1130free:
1131 kfree(hdmi->debugfs_files);
1132 hdmi->debugfs_files = NULL;
1133remove:
1134 debugfs_remove(hdmi->debugfs);
1135 hdmi->debugfs = NULL;
1136
1137 return err;
1138}
1139
1140static int tegra_hdmi_debugfs_exit(struct tegra_hdmi *hdmi)
1141{
1142 drm_debugfs_remove_files(hdmi->debugfs_files, ARRAY_SIZE(debugfs_files),
1143 hdmi->minor);
1144 hdmi->minor = NULL;
1145
1146 kfree(hdmi->debugfs_files);
1147 hdmi->debugfs_files = NULL;
1148
1149 debugfs_remove(hdmi->debugfs);
1150 hdmi->debugfs = NULL;
1151
1152 return 0;
1153}
1154
1155static int tegra_hdmi_drm_init(struct host1x_client *client,
1156 struct drm_device *drm)
1157{
1158 struct tegra_hdmi *hdmi = host1x_client_to_hdmi(client);
1159 int err;
1160
1161 hdmi->output.type = TEGRA_OUTPUT_HDMI;
1162 hdmi->output.dev = client->dev;
1163 hdmi->output.ops = &hdmi_ops;
1164
1165 err = tegra_output_init(drm, &hdmi->output);
1166 if (err < 0) {
1167 dev_err(client->dev, "output setup failed: %d\n", err);
1168 return err;
1169 }
1170
1171 if (IS_ENABLED(CONFIG_DEBUG_FS)) {
1172 err = tegra_hdmi_debugfs_init(hdmi, drm->primary);
1173 if (err < 0)
1174 dev_err(client->dev, "debugfs setup failed: %d\n", err);
1175 }
1176
1177 return 0;
1178}
1179
1180static int tegra_hdmi_drm_exit(struct host1x_client *client)
1181{
1182 struct tegra_hdmi *hdmi = host1x_client_to_hdmi(client);
1183 int err;
1184
1185 if (IS_ENABLED(CONFIG_DEBUG_FS)) {
1186 err = tegra_hdmi_debugfs_exit(hdmi);
1187 if (err < 0)
1188 dev_err(client->dev, "debugfs cleanup failed: %d\n",
1189 err);
1190 }
1191
1192 err = tegra_output_disable(&hdmi->output);
1193 if (err < 0) {
1194 dev_err(client->dev, "output failed to disable: %d\n", err);
1195 return err;
1196 }
1197
1198 err = tegra_output_exit(&hdmi->output);
1199 if (err < 0) {
1200 dev_err(client->dev, "output cleanup failed: %d\n", err);
1201 return err;
1202 }
1203
1204 return 0;
1205}
1206
1207static const struct host1x_client_ops hdmi_client_ops = {
1208 .drm_init = tegra_hdmi_drm_init,
1209 .drm_exit = tegra_hdmi_drm_exit,
1210};
1211
1212static int tegra_hdmi_probe(struct platform_device *pdev)
1213{
1214 struct host1x *host1x = dev_get_drvdata(pdev->dev.parent);
1215 struct tegra_hdmi *hdmi;
1216 struct resource *regs;
1217 int err;
1218
1219 hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL);
1220 if (!hdmi)
1221 return -ENOMEM;
1222
1223 hdmi->dev = &pdev->dev;
1224 hdmi->audio_source = AUTO;
1225 hdmi->audio_freq = 44100;
1226 hdmi->stereo = false;
1227 hdmi->dvi = false;
1228
1229 hdmi->clk = devm_clk_get(&pdev->dev, NULL);
1230 if (IS_ERR(hdmi->clk)) {
1231 dev_err(&pdev->dev, "failed to get clock\n");
1232 return PTR_ERR(hdmi->clk);
1233 }
1234
1235 err = clk_prepare(hdmi->clk);
1236 if (err < 0)
1237 return err;
1238
1239 hdmi->clk_parent = devm_clk_get(&pdev->dev, "parent");
1240 if (IS_ERR(hdmi->clk_parent))
1241 return PTR_ERR(hdmi->clk_parent);
1242
1243 err = clk_prepare(hdmi->clk_parent);
1244 if (err < 0)
1245 return err;
1246
1247 err = clk_set_parent(hdmi->clk, hdmi->clk_parent);
1248 if (err < 0) {
1249 dev_err(&pdev->dev, "failed to setup clocks: %d\n", err);
1250 return err;
1251 }
1252
1253 hdmi->vdd = devm_regulator_get(&pdev->dev, "vdd");
1254 if (IS_ERR(hdmi->vdd)) {
1255 dev_err(&pdev->dev, "failed to get VDD regulator\n");
1256 return PTR_ERR(hdmi->vdd);
1257 }
1258
1259 hdmi->pll = devm_regulator_get(&pdev->dev, "pll");
1260 if (IS_ERR(hdmi->pll)) {
1261 dev_err(&pdev->dev, "failed to get PLL regulator\n");
1262 return PTR_ERR(hdmi->pll);
1263 }
1264
1265 hdmi->output.dev = &pdev->dev;
1266
1267 err = tegra_output_parse_dt(&hdmi->output);
1268 if (err < 0)
1269 return err;
1270
1271 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1272 if (!regs)
1273 return -ENXIO;
1274
1275 hdmi->regs = devm_request_and_ioremap(&pdev->dev, regs);
1276 if (!hdmi->regs)
1277 return -EADDRNOTAVAIL;
1278
1279 err = platform_get_irq(pdev, 0);
1280 if (err < 0)
1281 return err;
1282
1283 hdmi->irq = err;
1284
1285 hdmi->client.ops = &hdmi_client_ops;
1286 INIT_LIST_HEAD(&hdmi->client.list);
1287 hdmi->client.dev = &pdev->dev;
1288
1289 err = host1x_register_client(host1x, &hdmi->client);
1290 if (err < 0) {
1291 dev_err(&pdev->dev, "failed to register host1x client: %d\n",
1292 err);
1293 return err;
1294 }
1295
1296 platform_set_drvdata(pdev, hdmi);
1297
1298 return 0;
1299}
1300
1301static int tegra_hdmi_remove(struct platform_device *pdev)
1302{
1303 struct host1x *host1x = dev_get_drvdata(pdev->dev.parent);
1304 struct tegra_hdmi *hdmi = platform_get_drvdata(pdev);
1305 int err;
1306
1307 err = host1x_unregister_client(host1x, &hdmi->client);
1308 if (err < 0) {
1309 dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
1310 err);
1311 return err;
1312 }
1313
1314 clk_unprepare(hdmi->clk_parent);
1315 clk_unprepare(hdmi->clk);
1316
1317 return 0;
1318}
1319
1320static struct of_device_id tegra_hdmi_of_match[] = {
1321 { .compatible = "nvidia,tegra20-hdmi", },
1322 { .compatible = "nvidia,tegra30-hdmi", },
1323 { },
1324};
1325
1326struct platform_driver tegra_hdmi_driver = {
1327 .driver = {
1328 .name = "tegra-hdmi",
1329 .owner = THIS_MODULE,
1330 .of_match_table = tegra_hdmi_of_match,
1331 },
1332 .probe = tegra_hdmi_probe,
1333 .remove = tegra_hdmi_remove,
1334};