blob: f5663d15670b5310bbb1d428199757c7b0468400 [file] [log] [blame]
Thierry Redingedec4af2012-11-15 21:28:23 +00001/*
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>
Prashant Gaikwad61fd2902013-01-11 13:16:26 +053011#include <linux/clk/tegra.h>
Thierry Reding9eb9b222013-09-24 16:32:47 +020012#include <linux/debugfs.h>
13#include <linux/hdmi.h>
14#include <linux/regulator/consumer.h>
Thierry Redingac24c222012-11-23 15:14:00 +010015
Thierry Redingedec4af2012-11-15 21:28:23 +000016#include "hdmi.h"
17#include "drm.h"
18#include "dc.h"
19
20struct tegra_hdmi {
Thierry Reding776dc382013-10-14 14:43:22 +020021 struct host1x_client client;
Thierry Redingedec4af2012-11-15 21:28:23 +000022 struct tegra_output output;
23 struct device *dev;
24
25 struct regulator *vdd;
26 struct regulator *pll;
27
28 void __iomem *regs;
29 unsigned int irq;
30
31 struct clk *clk_parent;
32 struct clk *clk;
33
34 unsigned int audio_source;
35 unsigned int audio_freq;
36 bool stereo;
37 bool dvi;
38
39 struct drm_info_list *debugfs_files;
40 struct drm_minor *minor;
41 struct dentry *debugfs;
42};
43
44static inline struct tegra_hdmi *
Thierry Reding776dc382013-10-14 14:43:22 +020045host1x_client_to_hdmi(struct host1x_client *client)
Thierry Redingedec4af2012-11-15 21:28:23 +000046{
47 return container_of(client, struct tegra_hdmi, client);
48}
49
50static inline struct tegra_hdmi *to_hdmi(struct tegra_output *output)
51{
52 return container_of(output, struct tegra_hdmi, output);
53}
54
55#define HDMI_AUDIOCLK_FREQ 216000000
56#define HDMI_REKEY_DEFAULT 56
57
58enum {
59 AUTO = 0,
60 SPDIF,
61 HDA,
62};
63
64static inline unsigned long tegra_hdmi_readl(struct tegra_hdmi *hdmi,
65 unsigned long reg)
66{
67 return readl(hdmi->regs + (reg << 2));
68}
69
70static inline void tegra_hdmi_writel(struct tegra_hdmi *hdmi, unsigned long val,
71 unsigned long reg)
72{
73 writel(val, hdmi->regs + (reg << 2));
74}
75
76struct tegra_hdmi_audio_config {
77 unsigned int pclk;
78 unsigned int n;
79 unsigned int cts;
80 unsigned int aval;
81};
82
83static const struct tegra_hdmi_audio_config tegra_hdmi_audio_32k[] = {
84 { 25200000, 4096, 25200, 24000 },
85 { 27000000, 4096, 27000, 24000 },
86 { 74250000, 4096, 74250, 24000 },
87 { 148500000, 4096, 148500, 24000 },
88 { 0, 0, 0, 0 },
89};
90
91static const struct tegra_hdmi_audio_config tegra_hdmi_audio_44_1k[] = {
92 { 25200000, 5880, 26250, 25000 },
93 { 27000000, 5880, 28125, 25000 },
94 { 74250000, 4704, 61875, 20000 },
95 { 148500000, 4704, 123750, 20000 },
96 { 0, 0, 0, 0 },
97};
98
99static const struct tegra_hdmi_audio_config tegra_hdmi_audio_48k[] = {
100 { 25200000, 6144, 25200, 24000 },
101 { 27000000, 6144, 27000, 24000 },
102 { 74250000, 6144, 74250, 24000 },
103 { 148500000, 6144, 148500, 24000 },
104 { 0, 0, 0, 0 },
105};
106
107static const struct tegra_hdmi_audio_config tegra_hdmi_audio_88_2k[] = {
108 { 25200000, 11760, 26250, 25000 },
109 { 27000000, 11760, 28125, 25000 },
110 { 74250000, 9408, 61875, 20000 },
111 { 148500000, 9408, 123750, 20000 },
112 { 0, 0, 0, 0 },
113};
114
115static const struct tegra_hdmi_audio_config tegra_hdmi_audio_96k[] = {
116 { 25200000, 12288, 25200, 24000 },
117 { 27000000, 12288, 27000, 24000 },
118 { 74250000, 12288, 74250, 24000 },
119 { 148500000, 12288, 148500, 24000 },
120 { 0, 0, 0, 0 },
121};
122
123static const struct tegra_hdmi_audio_config tegra_hdmi_audio_176_4k[] = {
124 { 25200000, 23520, 26250, 25000 },
125 { 27000000, 23520, 28125, 25000 },
126 { 74250000, 18816, 61875, 20000 },
127 { 148500000, 18816, 123750, 20000 },
128 { 0, 0, 0, 0 },
129};
130
131static const struct tegra_hdmi_audio_config tegra_hdmi_audio_192k[] = {
132 { 25200000, 24576, 25200, 24000 },
133 { 27000000, 24576, 27000, 24000 },
134 { 74250000, 24576, 74250, 24000 },
135 { 148500000, 24576, 148500, 24000 },
136 { 0, 0, 0, 0 },
137};
138
139struct tmds_config {
140 unsigned int pclk;
141 u32 pll0;
142 u32 pll1;
143 u32 pe_current;
144 u32 drive_current;
145};
146
147static const struct tmds_config tegra2_tmds_config[] = {
Lucas Stachfa416dd2012-12-19 21:38:55 +0000148 { /* slow pixel clock modes */
Thierry Redingedec4af2012-11-15 21:28:23 +0000149 .pclk = 27000000,
150 .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) |
151 SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(0) |
152 SOR_PLL_TX_REG_LOAD(3),
153 .pll1 = SOR_PLL_TMDS_TERM_ENABLE,
154 .pe_current = PE_CURRENT0(PE_CURRENT_0_0_mA) |
155 PE_CURRENT1(PE_CURRENT_0_0_mA) |
156 PE_CURRENT2(PE_CURRENT_0_0_mA) |
157 PE_CURRENT3(PE_CURRENT_0_0_mA),
158 .drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_7_125_mA) |
159 DRIVE_CURRENT_LANE1(DRIVE_CURRENT_7_125_mA) |
160 DRIVE_CURRENT_LANE2(DRIVE_CURRENT_7_125_mA) |
161 DRIVE_CURRENT_LANE3(DRIVE_CURRENT_7_125_mA),
Lucas Stachfa416dd2012-12-19 21:38:55 +0000162 },
163 { /* high pixel clock modes */
Thierry Redingedec4af2012-11-15 21:28:23 +0000164 .pclk = UINT_MAX,
165 .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) |
166 SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(1) |
167 SOR_PLL_TX_REG_LOAD(3),
168 .pll1 = SOR_PLL_TMDS_TERM_ENABLE | SOR_PLL_PE_EN,
169 .pe_current = PE_CURRENT0(PE_CURRENT_6_0_mA) |
170 PE_CURRENT1(PE_CURRENT_6_0_mA) |
171 PE_CURRENT2(PE_CURRENT_6_0_mA) |
172 PE_CURRENT3(PE_CURRENT_6_0_mA),
173 .drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_7_125_mA) |
174 DRIVE_CURRENT_LANE1(DRIVE_CURRENT_7_125_mA) |
175 DRIVE_CURRENT_LANE2(DRIVE_CURRENT_7_125_mA) |
176 DRIVE_CURRENT_LANE3(DRIVE_CURRENT_7_125_mA),
177 },
178};
179
180static const struct tmds_config tegra3_tmds_config[] = {
181 { /* 480p modes */
182 .pclk = 27000000,
183 .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) |
184 SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(0) |
185 SOR_PLL_TX_REG_LOAD(0),
186 .pll1 = SOR_PLL_TMDS_TERM_ENABLE,
187 .pe_current = PE_CURRENT0(PE_CURRENT_0_0_mA) |
188 PE_CURRENT1(PE_CURRENT_0_0_mA) |
189 PE_CURRENT2(PE_CURRENT_0_0_mA) |
190 PE_CURRENT3(PE_CURRENT_0_0_mA),
191 .drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_5_250_mA) |
192 DRIVE_CURRENT_LANE1(DRIVE_CURRENT_5_250_mA) |
193 DRIVE_CURRENT_LANE2(DRIVE_CURRENT_5_250_mA) |
194 DRIVE_CURRENT_LANE3(DRIVE_CURRENT_5_250_mA),
195 }, { /* 720p modes */
196 .pclk = 74250000,
197 .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) |
198 SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(1) |
199 SOR_PLL_TX_REG_LOAD(0),
200 .pll1 = SOR_PLL_TMDS_TERM_ENABLE | SOR_PLL_PE_EN,
201 .pe_current = PE_CURRENT0(PE_CURRENT_5_0_mA) |
202 PE_CURRENT1(PE_CURRENT_5_0_mA) |
203 PE_CURRENT2(PE_CURRENT_5_0_mA) |
204 PE_CURRENT3(PE_CURRENT_5_0_mA),
205 .drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_5_250_mA) |
206 DRIVE_CURRENT_LANE1(DRIVE_CURRENT_5_250_mA) |
207 DRIVE_CURRENT_LANE2(DRIVE_CURRENT_5_250_mA) |
208 DRIVE_CURRENT_LANE3(DRIVE_CURRENT_5_250_mA),
209 }, { /* 1080p modes */
210 .pclk = UINT_MAX,
211 .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) |
212 SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(3) |
213 SOR_PLL_TX_REG_LOAD(0),
214 .pll1 = SOR_PLL_TMDS_TERM_ENABLE | SOR_PLL_PE_EN,
215 .pe_current = PE_CURRENT0(PE_CURRENT_5_0_mA) |
216 PE_CURRENT1(PE_CURRENT_5_0_mA) |
217 PE_CURRENT2(PE_CURRENT_5_0_mA) |
218 PE_CURRENT3(PE_CURRENT_5_0_mA),
219 .drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_5_250_mA) |
220 DRIVE_CURRENT_LANE1(DRIVE_CURRENT_5_250_mA) |
221 DRIVE_CURRENT_LANE2(DRIVE_CURRENT_5_250_mA) |
222 DRIVE_CURRENT_LANE3(DRIVE_CURRENT_5_250_mA),
223 },
224};
225
226static const struct tegra_hdmi_audio_config *
227tegra_hdmi_get_audio_config(unsigned int audio_freq, unsigned int pclk)
228{
229 const struct tegra_hdmi_audio_config *table;
230
231 switch (audio_freq) {
232 case 32000:
233 table = tegra_hdmi_audio_32k;
234 break;
235
236 case 44100:
237 table = tegra_hdmi_audio_44_1k;
238 break;
239
240 case 48000:
241 table = tegra_hdmi_audio_48k;
242 break;
243
244 case 88200:
245 table = tegra_hdmi_audio_88_2k;
246 break;
247
248 case 96000:
249 table = tegra_hdmi_audio_96k;
250 break;
251
252 case 176400:
253 table = tegra_hdmi_audio_176_4k;
254 break;
255
256 case 192000:
257 table = tegra_hdmi_audio_192k;
258 break;
259
260 default:
261 return NULL;
262 }
263
264 while (table->pclk) {
265 if (table->pclk == pclk)
266 return table;
267
268 table++;
269 }
270
271 return NULL;
272}
273
274static void tegra_hdmi_setup_audio_fs_tables(struct tegra_hdmi *hdmi)
275{
276 const unsigned int freqs[] = {
277 32000, 44100, 48000, 88200, 96000, 176400, 192000
278 };
279 unsigned int i;
280
281 for (i = 0; i < ARRAY_SIZE(freqs); i++) {
282 unsigned int f = freqs[i];
283 unsigned int eight_half;
284 unsigned long value;
285 unsigned int delta;
286
287 if (f > 96000)
288 delta = 2;
289 else if (f > 480000)
290 delta = 6;
291 else
292 delta = 9;
293
294 eight_half = (8 * HDMI_AUDIOCLK_FREQ) / (f * 128);
295 value = AUDIO_FS_LOW(eight_half - delta) |
296 AUDIO_FS_HIGH(eight_half + delta);
297 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_AUDIO_FS(i));
298 }
299}
300
301static int tegra_hdmi_setup_audio(struct tegra_hdmi *hdmi, unsigned int pclk)
302{
303 struct device_node *node = hdmi->dev->of_node;
304 const struct tegra_hdmi_audio_config *config;
305 unsigned int offset = 0;
306 unsigned long value;
307
308 switch (hdmi->audio_source) {
309 case HDA:
310 value = AUDIO_CNTRL0_SOURCE_SELECT_HDAL;
311 break;
312
313 case SPDIF:
314 value = AUDIO_CNTRL0_SOURCE_SELECT_SPDIF;
315 break;
316
317 default:
318 value = AUDIO_CNTRL0_SOURCE_SELECT_AUTO;
319 break;
320 }
321
322 if (of_device_is_compatible(node, "nvidia,tegra30-hdmi")) {
323 value |= AUDIO_CNTRL0_ERROR_TOLERANCE(6) |
324 AUDIO_CNTRL0_FRAMES_PER_BLOCK(0xc0);
325 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_AUDIO_CNTRL0);
326 } else {
327 value |= AUDIO_CNTRL0_INJECT_NULLSMPL;
328 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_AUDIO_CNTRL0);
329
330 value = AUDIO_CNTRL0_ERROR_TOLERANCE(6) |
331 AUDIO_CNTRL0_FRAMES_PER_BLOCK(0xc0);
332 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_AUDIO_CNTRL0);
333 }
334
335 config = tegra_hdmi_get_audio_config(hdmi->audio_freq, pclk);
336 if (!config) {
337 dev_err(hdmi->dev, "cannot set audio to %u at %u pclk\n",
338 hdmi->audio_freq, pclk);
339 return -EINVAL;
340 }
341
342 tegra_hdmi_writel(hdmi, 0, HDMI_NV_PDISP_HDMI_ACR_CTRL);
343
344 value = AUDIO_N_RESETF | AUDIO_N_GENERATE_ALTERNATE |
345 AUDIO_N_VALUE(config->n - 1);
346 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_AUDIO_N);
347
348 tegra_hdmi_writel(hdmi, ACR_SUBPACK_N(config->n) | ACR_ENABLE,
349 HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_HIGH);
350
351 value = ACR_SUBPACK_CTS(config->cts);
352 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_LOW);
353
354 value = SPARE_HW_CTS | SPARE_FORCE_SW_CTS | SPARE_CTS_RESET_VAL(1);
355 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_SPARE);
356
357 value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_AUDIO_N);
358 value &= ~AUDIO_N_RESETF;
359 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_AUDIO_N);
360
361 if (of_device_is_compatible(node, "nvidia,tegra30-hdmi")) {
362 switch (hdmi->audio_freq) {
363 case 32000:
364 offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_0320;
365 break;
366
367 case 44100:
368 offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_0441;
369 break;
370
371 case 48000:
372 offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_0480;
373 break;
374
375 case 88200:
376 offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_0882;
377 break;
378
379 case 96000:
380 offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_0960;
381 break;
382
383 case 176400:
384 offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_1764;
385 break;
386
387 case 192000:
388 offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_1920;
389 break;
390 }
391
392 tegra_hdmi_writel(hdmi, config->aval, offset);
393 }
394
395 tegra_hdmi_setup_audio_fs_tables(hdmi);
396
397 return 0;
398}
399
Thierry Redingac24c222012-11-23 15:14:00 +0100400static inline unsigned long tegra_hdmi_subpack(const u8 *ptr, size_t size)
Thierry Redingedec4af2012-11-15 21:28:23 +0000401{
Thierry Redingac24c222012-11-23 15:14:00 +0100402 unsigned long value = 0;
Thierry Redingedec4af2012-11-15 21:28:23 +0000403 size_t i;
Thierry Redingedec4af2012-11-15 21:28:23 +0000404
Thierry Redingac24c222012-11-23 15:14:00 +0100405 for (i = size; i > 0; i--)
406 value = (value << 8) | ptr[i - 1];
Thierry Redingedec4af2012-11-15 21:28:23 +0000407
Thierry Redingac24c222012-11-23 15:14:00 +0100408 return value;
409}
Thierry Redingedec4af2012-11-15 21:28:23 +0000410
Thierry Redingac24c222012-11-23 15:14:00 +0100411static void tegra_hdmi_write_infopack(struct tegra_hdmi *hdmi, const void *data,
412 size_t size)
413{
414 const u8 *ptr = data;
415 unsigned long offset;
416 unsigned long value;
417 size_t i, j;
Thierry Redingedec4af2012-11-15 21:28:23 +0000418
Thierry Redingac24c222012-11-23 15:14:00 +0100419 switch (ptr[0]) {
420 case HDMI_INFOFRAME_TYPE_AVI:
421 offset = HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_HEADER;
422 break;
423
424 case HDMI_INFOFRAME_TYPE_AUDIO:
425 offset = HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_HEADER;
426 break;
427
428 case HDMI_INFOFRAME_TYPE_VENDOR:
429 offset = HDMI_NV_PDISP_HDMI_GENERIC_HEADER;
430 break;
431
432 default:
433 dev_err(hdmi->dev, "unsupported infoframe type: %02x\n",
434 ptr[0]);
435 return;
436 }
437
438 value = INFOFRAME_HEADER_TYPE(ptr[0]) |
439 INFOFRAME_HEADER_VERSION(ptr[1]) |
440 INFOFRAME_HEADER_LEN(ptr[2]);
Thierry Redingedec4af2012-11-15 21:28:23 +0000441 tegra_hdmi_writel(hdmi, value, offset);
Thierry Redingac24c222012-11-23 15:14:00 +0100442 offset++;
Thierry Redingedec4af2012-11-15 21:28:23 +0000443
Thierry Redingac24c222012-11-23 15:14:00 +0100444 /*
445 * Each subpack contains 7 bytes, divided into:
446 * - subpack_low: bytes 0 - 3
447 * - subpack_high: bytes 4 - 6 (with byte 7 padded to 0x00)
Thierry Redingedec4af2012-11-15 21:28:23 +0000448 */
Thierry Redingac24c222012-11-23 15:14:00 +0100449 for (i = 3, j = 0; i < size; i += 7, j += 8) {
450 size_t rem = size - i, num = min_t(size_t, rem, 4);
Thierry Redingedec4af2012-11-15 21:28:23 +0000451
Thierry Redingac24c222012-11-23 15:14:00 +0100452 value = tegra_hdmi_subpack(&ptr[i], num);
453 tegra_hdmi_writel(hdmi, value, offset++);
Thierry Redingedec4af2012-11-15 21:28:23 +0000454
Thierry Redingac24c222012-11-23 15:14:00 +0100455 num = min_t(size_t, rem - num, 3);
Thierry Redingedec4af2012-11-15 21:28:23 +0000456
Thierry Redingac24c222012-11-23 15:14:00 +0100457 value = tegra_hdmi_subpack(&ptr[i + 4], num);
458 tegra_hdmi_writel(hdmi, value, offset++);
Thierry Redingedec4af2012-11-15 21:28:23 +0000459 }
460}
461
462static void tegra_hdmi_setup_avi_infoframe(struct tegra_hdmi *hdmi,
463 struct drm_display_mode *mode)
464{
465 struct hdmi_avi_infoframe frame;
Thierry Redingac24c222012-11-23 15:14:00 +0100466 u8 buffer[17];
467 ssize_t err;
Thierry Redingedec4af2012-11-15 21:28:23 +0000468
469 if (hdmi->dvi) {
470 tegra_hdmi_writel(hdmi, 0,
471 HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_CTRL);
472 return;
473 }
474
Thierry Redingac24c222012-11-23 15:14:00 +0100475 err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
476 if (err < 0) {
477 dev_err(hdmi->dev, "failed to setup AVI infoframe: %zd\n", err);
478 return;
Thierry Redingedec4af2012-11-15 21:28:23 +0000479 }
480
Thierry Redingac24c222012-11-23 15:14:00 +0100481 err = hdmi_avi_infoframe_pack(&frame, buffer, sizeof(buffer));
482 if (err < 0) {
483 dev_err(hdmi->dev, "failed to pack AVI infoframe: %zd\n", err);
484 return;
485 }
486
487 tegra_hdmi_write_infopack(hdmi, buffer, err);
Thierry Redingedec4af2012-11-15 21:28:23 +0000488
489 tegra_hdmi_writel(hdmi, INFOFRAME_CTRL_ENABLE,
490 HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_CTRL);
491}
492
493static void tegra_hdmi_setup_audio_infoframe(struct tegra_hdmi *hdmi)
494{
495 struct hdmi_audio_infoframe frame;
Thierry Redingac24c222012-11-23 15:14:00 +0100496 u8 buffer[14];
497 ssize_t err;
Thierry Redingedec4af2012-11-15 21:28:23 +0000498
499 if (hdmi->dvi) {
500 tegra_hdmi_writel(hdmi, 0,
501 HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_CTRL);
502 return;
503 }
504
Thierry Redingac24c222012-11-23 15:14:00 +0100505 err = hdmi_audio_infoframe_init(&frame);
506 if (err < 0) {
507 dev_err(hdmi->dev, "failed to initialize audio infoframe: %d\n",
508 err);
509 return;
510 }
Thierry Redingedec4af2012-11-15 21:28:23 +0000511
Thierry Redingac24c222012-11-23 15:14:00 +0100512 frame.channels = 2;
513
514 err = hdmi_audio_infoframe_pack(&frame, buffer, sizeof(buffer));
515 if (err < 0) {
516 dev_err(hdmi->dev, "failed to pack audio infoframe: %zd\n",
517 err);
518 return;
519 }
520
521 /*
522 * The audio infoframe has only one set of subpack registers, so the
523 * infoframe needs to be truncated. One set of subpack registers can
524 * contain 7 bytes. Including the 3 byte header only the first 10
525 * bytes can be programmed.
526 */
527 tegra_hdmi_write_infopack(hdmi, buffer, min(10, err));
Thierry Redingedec4af2012-11-15 21:28:23 +0000528
529 tegra_hdmi_writel(hdmi, INFOFRAME_CTRL_ENABLE,
530 HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_CTRL);
531}
532
533static void tegra_hdmi_setup_stereo_infoframe(struct tegra_hdmi *hdmi)
534{
Lespiau, Damienae84b902013-08-19 16:59:02 +0100535 struct hdmi_vendor_infoframe frame;
Thierry Redingedec4af2012-11-15 21:28:23 +0000536 unsigned long value;
Thierry Redingac24c222012-11-23 15:14:00 +0100537 u8 buffer[10];
538 ssize_t err;
Thierry Redingedec4af2012-11-15 21:28:23 +0000539
540 if (!hdmi->stereo) {
541 value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
542 value &= ~GENERIC_CTRL_ENABLE;
543 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
544 return;
545 }
546
Lespiau, Damienae84b902013-08-19 16:59:02 +0100547 hdmi_vendor_infoframe_init(&frame);
Lespiau, Damiena26a58e82013-08-19 16:58:59 +0100548 frame.s3d_struct = HDMI_3D_STRUCTURE_FRAME_PACKING;
Thierry Redingac24c222012-11-23 15:14:00 +0100549
Lespiau, Damienae84b902013-08-19 16:59:02 +0100550 err = hdmi_vendor_infoframe_pack(&frame, buffer, sizeof(buffer));
Thierry Redingac24c222012-11-23 15:14:00 +0100551 if (err < 0) {
552 dev_err(hdmi->dev, "failed to pack vendor infoframe: %zd\n",
553 err);
554 return;
555 }
556
557 tegra_hdmi_write_infopack(hdmi, buffer, err);
Thierry Redingedec4af2012-11-15 21:28:23 +0000558
559 value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
560 value |= GENERIC_CTRL_ENABLE;
561 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
562}
563
564static void tegra_hdmi_setup_tmds(struct tegra_hdmi *hdmi,
565 const struct tmds_config *tmds)
566{
567 unsigned long value;
568
569 tegra_hdmi_writel(hdmi, tmds->pll0, HDMI_NV_PDISP_SOR_PLL0);
570 tegra_hdmi_writel(hdmi, tmds->pll1, HDMI_NV_PDISP_SOR_PLL1);
571 tegra_hdmi_writel(hdmi, tmds->pe_current, HDMI_NV_PDISP_PE_CURRENT);
572
573 value = tmds->drive_current | DRIVE_CURRENT_FUSE_OVERRIDE;
574 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_LANE_DRIVE_CURRENT);
575}
576
577static int tegra_output_hdmi_enable(struct tegra_output *output)
578{
579 unsigned int h_sync_width, h_front_porch, h_back_porch, i, rekey;
580 struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc);
581 struct drm_display_mode *mode = &dc->base.mode;
582 struct tegra_hdmi *hdmi = to_hdmi(output);
583 struct device_node *node = hdmi->dev->of_node;
584 unsigned int pulse_start, div82, pclk;
585 const struct tmds_config *tmds;
586 unsigned int num_tmds;
587 unsigned long value;
588 int retries = 1000;
589 int err;
590
591 pclk = mode->clock * 1000;
592 h_sync_width = mode->hsync_end - mode->hsync_start;
Lucas Stach40495082012-12-19 21:38:52 +0000593 h_back_porch = mode->htotal - mode->hsync_end;
594 h_front_porch = mode->hsync_start - mode->hdisplay;
Thierry Redingedec4af2012-11-15 21:28:23 +0000595
596 err = regulator_enable(hdmi->vdd);
597 if (err < 0) {
598 dev_err(hdmi->dev, "failed to enable VDD regulator: %d\n", err);
599 return err;
600 }
601
602 err = regulator_enable(hdmi->pll);
603 if (err < 0) {
604 dev_err(hdmi->dev, "failed to enable PLL regulator: %d\n", err);
605 return err;
606 }
607
608 /*
609 * This assumes that the display controller will divide its parent
610 * clock by 2 to generate the pixel clock.
611 */
612 err = tegra_output_setup_clock(output, hdmi->clk, pclk * 2);
613 if (err < 0) {
614 dev_err(hdmi->dev, "failed to setup clock: %d\n", err);
615 return err;
616 }
617
618 err = clk_set_rate(hdmi->clk, pclk);
619 if (err < 0)
620 return err;
621
622 err = clk_enable(hdmi->clk);
623 if (err < 0) {
624 dev_err(hdmi->dev, "failed to enable clock: %d\n", err);
625 return err;
626 }
627
628 tegra_periph_reset_assert(hdmi->clk);
629 usleep_range(1000, 2000);
630 tegra_periph_reset_deassert(hdmi->clk);
631
632 tegra_dc_writel(dc, VSYNC_H_POSITION(1),
633 DC_DISP_DISP_TIMING_OPTIONS);
634 tegra_dc_writel(dc, DITHER_CONTROL_DISABLE | BASE_COLOR_SIZE888,
635 DC_DISP_DISP_COLOR_CONTROL);
636
637 /* video_preamble uses h_pulse2 */
638 pulse_start = 1 + h_sync_width + h_back_porch - 10;
639
640 tegra_dc_writel(dc, H_PULSE_2_ENABLE, DC_DISP_DISP_SIGNAL_OPTIONS0);
641
642 value = PULSE_MODE_NORMAL | PULSE_POLARITY_HIGH | PULSE_QUAL_VACTIVE |
643 PULSE_LAST_END_A;
644 tegra_dc_writel(dc, value, DC_DISP_H_PULSE2_CONTROL);
645
646 value = PULSE_START(pulse_start) | PULSE_END(pulse_start + 8);
647 tegra_dc_writel(dc, value, DC_DISP_H_PULSE2_POSITION_A);
648
649 value = VSYNC_WINDOW_END(0x210) | VSYNC_WINDOW_START(0x200) |
650 VSYNC_WINDOW_ENABLE;
651 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_VSYNC_WINDOW);
652
653 if (dc->pipe)
654 value = HDMI_SRC_DISPLAYB;
655 else
656 value = HDMI_SRC_DISPLAYA;
657
658 if ((mode->hdisplay == 720) && ((mode->vdisplay == 480) ||
659 (mode->vdisplay == 576)))
660 tegra_hdmi_writel(hdmi,
661 value | ARM_VIDEO_RANGE_FULL,
662 HDMI_NV_PDISP_INPUT_CONTROL);
663 else
664 tegra_hdmi_writel(hdmi,
665 value | ARM_VIDEO_RANGE_LIMITED,
666 HDMI_NV_PDISP_INPUT_CONTROL);
667
668 div82 = clk_get_rate(hdmi->clk) / 1000000 * 4;
669 value = SOR_REFCLK_DIV_INT(div82 >> 2) | SOR_REFCLK_DIV_FRAC(div82);
670 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_REFCLK);
671
672 if (!hdmi->dvi) {
673 err = tegra_hdmi_setup_audio(hdmi, pclk);
674 if (err < 0)
675 hdmi->dvi = true;
676 }
677
678 if (of_device_is_compatible(node, "nvidia,tegra20-hdmi")) {
679 /*
680 * TODO: add ELD support
681 */
682 }
683
684 rekey = HDMI_REKEY_DEFAULT;
685 value = HDMI_CTRL_REKEY(rekey);
686 value |= HDMI_CTRL_MAX_AC_PACKET((h_sync_width + h_back_porch +
687 h_front_porch - rekey - 18) / 32);
688
689 if (!hdmi->dvi)
690 value |= HDMI_CTRL_ENABLE;
691
692 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_CTRL);
693
694 if (hdmi->dvi)
695 tegra_hdmi_writel(hdmi, 0x0,
696 HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
697 else
698 tegra_hdmi_writel(hdmi, GENERIC_CTRL_AUDIO,
699 HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
700
701 tegra_hdmi_setup_avi_infoframe(hdmi, mode);
702 tegra_hdmi_setup_audio_infoframe(hdmi);
703 tegra_hdmi_setup_stereo_infoframe(hdmi);
704
705 /* TMDS CONFIG */
706 if (of_device_is_compatible(node, "nvidia,tegra30-hdmi")) {
707 num_tmds = ARRAY_SIZE(tegra3_tmds_config);
708 tmds = tegra3_tmds_config;
709 } else {
710 num_tmds = ARRAY_SIZE(tegra2_tmds_config);
711 tmds = tegra2_tmds_config;
712 }
713
714 for (i = 0; i < num_tmds; i++) {
715 if (pclk <= tmds[i].pclk) {
716 tegra_hdmi_setup_tmds(hdmi, &tmds[i]);
717 break;
718 }
719 }
720
721 tegra_hdmi_writel(hdmi,
722 SOR_SEQ_CTL_PU_PC(0) |
723 SOR_SEQ_PU_PC_ALT(0) |
724 SOR_SEQ_PD_PC(8) |
725 SOR_SEQ_PD_PC_ALT(8),
726 HDMI_NV_PDISP_SOR_SEQ_CTL);
727
728 value = SOR_SEQ_INST_WAIT_TIME(1) |
729 SOR_SEQ_INST_WAIT_UNITS_VSYNC |
730 SOR_SEQ_INST_HALT |
731 SOR_SEQ_INST_PIN_A_LOW |
732 SOR_SEQ_INST_PIN_B_LOW |
733 SOR_SEQ_INST_DRIVE_PWM_OUT_LO;
734
735 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_SEQ_INST(0));
736 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_SEQ_INST(8));
737
738 value = 0x1c800;
739 value &= ~SOR_CSTM_ROTCLK(~0);
740 value |= SOR_CSTM_ROTCLK(2);
741 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_CSTM);
742
743 tegra_dc_writel(dc, DISP_CTRL_MODE_STOP, DC_CMD_DISPLAY_COMMAND);
744 tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
745 tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
746
747 /* start SOR */
748 tegra_hdmi_writel(hdmi,
749 SOR_PWR_NORMAL_STATE_PU |
750 SOR_PWR_NORMAL_START_NORMAL |
751 SOR_PWR_SAFE_STATE_PD |
752 SOR_PWR_SETTING_NEW_TRIGGER,
753 HDMI_NV_PDISP_SOR_PWR);
754 tegra_hdmi_writel(hdmi,
755 SOR_PWR_NORMAL_STATE_PU |
756 SOR_PWR_NORMAL_START_NORMAL |
757 SOR_PWR_SAFE_STATE_PD |
758 SOR_PWR_SETTING_NEW_DONE,
759 HDMI_NV_PDISP_SOR_PWR);
760
761 do {
762 BUG_ON(--retries < 0);
763 value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_SOR_PWR);
764 } while (value & SOR_PWR_SETTING_NEW_PENDING);
765
766 value = SOR_STATE_ASY_CRCMODE_COMPLETE |
767 SOR_STATE_ASY_OWNER_HEAD0 |
768 SOR_STATE_ASY_SUBOWNER_BOTH |
769 SOR_STATE_ASY_PROTOCOL_SINGLE_TMDS_A |
770 SOR_STATE_ASY_DEPOL_POS;
771
772 /* setup sync polarities */
773 if (mode->flags & DRM_MODE_FLAG_PHSYNC)
774 value |= SOR_STATE_ASY_HSYNCPOL_POS;
775
776 if (mode->flags & DRM_MODE_FLAG_NHSYNC)
777 value |= SOR_STATE_ASY_HSYNCPOL_NEG;
778
779 if (mode->flags & DRM_MODE_FLAG_PVSYNC)
780 value |= SOR_STATE_ASY_VSYNCPOL_POS;
781
782 if (mode->flags & DRM_MODE_FLAG_NVSYNC)
783 value |= SOR_STATE_ASY_VSYNCPOL_NEG;
784
785 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_STATE2);
786
787 value = SOR_STATE_ASY_HEAD_OPMODE_AWAKE | SOR_STATE_ASY_ORMODE_NORMAL;
788 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_STATE1);
789
790 tegra_hdmi_writel(hdmi, 0, HDMI_NV_PDISP_SOR_STATE0);
791 tegra_hdmi_writel(hdmi, SOR_STATE_UPDATE, HDMI_NV_PDISP_SOR_STATE0);
792 tegra_hdmi_writel(hdmi, value | SOR_STATE_ATTACHED,
793 HDMI_NV_PDISP_SOR_STATE1);
794 tegra_hdmi_writel(hdmi, 0, HDMI_NV_PDISP_SOR_STATE0);
795
796 tegra_dc_writel(dc, HDMI_ENABLE, DC_DISP_DISP_WIN_OPTIONS);
797
798 value = PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
799 PW4_ENABLE | PM0_ENABLE | PM1_ENABLE;
800 tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL);
801
802 value = DISP_CTRL_MODE_C_DISPLAY;
803 tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND);
804
805 tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
806 tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
807
808 /* TODO: add HDCP support */
809
810 return 0;
811}
812
813static int tegra_output_hdmi_disable(struct tegra_output *output)
814{
815 struct tegra_hdmi *hdmi = to_hdmi(output);
816
817 tegra_periph_reset_assert(hdmi->clk);
818 clk_disable(hdmi->clk);
819 regulator_disable(hdmi->pll);
820 regulator_disable(hdmi->vdd);
821
822 return 0;
823}
824
825static int tegra_output_hdmi_setup_clock(struct tegra_output *output,
826 struct clk *clk, unsigned long pclk)
827{
828 struct tegra_hdmi *hdmi = to_hdmi(output);
829 struct clk *base;
830 int err;
831
832 err = clk_set_parent(clk, hdmi->clk_parent);
833 if (err < 0) {
834 dev_err(output->dev, "failed to set parent: %d\n", err);
835 return err;
836 }
837
838 base = clk_get_parent(hdmi->clk_parent);
839
840 /*
841 * This assumes that the parent clock is pll_d_out0 or pll_d2_out
842 * respectively, each of which divides the base pll_d by 2.
843 */
844 err = clk_set_rate(base, pclk * 2);
845 if (err < 0)
846 dev_err(output->dev,
847 "failed to set base clock rate to %lu Hz\n",
848 pclk * 2);
849
850 return 0;
851}
852
853static int tegra_output_hdmi_check_mode(struct tegra_output *output,
854 struct drm_display_mode *mode,
855 enum drm_mode_status *status)
856{
857 struct tegra_hdmi *hdmi = to_hdmi(output);
858 unsigned long pclk = mode->clock * 1000;
859 struct clk *parent;
860 long err;
861
862 parent = clk_get_parent(hdmi->clk_parent);
863
864 err = clk_round_rate(parent, pclk * 4);
865 if (err < 0)
866 *status = MODE_NOCLOCK;
867 else
868 *status = MODE_OK;
869
870 return 0;
871}
872
873static const struct tegra_output_ops hdmi_ops = {
874 .enable = tegra_output_hdmi_enable,
875 .disable = tegra_output_hdmi_disable,
876 .setup_clock = tegra_output_hdmi_setup_clock,
877 .check_mode = tegra_output_hdmi_check_mode,
878};
879
880static int tegra_hdmi_show_regs(struct seq_file *s, void *data)
881{
882 struct drm_info_node *node = s->private;
883 struct tegra_hdmi *hdmi = node->info_ent->data;
Mikko Perttunenccaddfe2013-07-30 11:35:03 +0300884 int err;
885
886 err = clk_enable(hdmi->clk);
887 if (err)
888 return err;
Thierry Redingedec4af2012-11-15 21:28:23 +0000889
890#define DUMP_REG(name) \
891 seq_printf(s, "%-56s %#05x %08lx\n", #name, name, \
892 tegra_hdmi_readl(hdmi, name))
893
894 DUMP_REG(HDMI_CTXSW);
895 DUMP_REG(HDMI_NV_PDISP_SOR_STATE0);
896 DUMP_REG(HDMI_NV_PDISP_SOR_STATE1);
897 DUMP_REG(HDMI_NV_PDISP_SOR_STATE2);
898 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_AN_MSB);
899 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_AN_LSB);
900 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CN_MSB);
901 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CN_LSB);
902 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_AKSV_MSB);
903 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_AKSV_LSB);
904 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_BKSV_MSB);
905 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_BKSV_LSB);
906 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CKSV_MSB);
907 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CKSV_LSB);
908 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_DKSV_MSB);
909 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_DKSV_LSB);
910 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CTRL);
911 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CMODE);
912 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_MPRIME_MSB);
913 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_MPRIME_LSB);
914 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_SPRIME_MSB);
915 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_SPRIME_LSB2);
916 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_SPRIME_LSB1);
917 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_RI);
918 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CS_MSB);
919 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CS_LSB);
920 DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_EMU0);
921 DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_EMU_RDATA0);
922 DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_EMU1);
923 DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_EMU2);
924 DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_CTRL);
925 DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_STATUS);
926 DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_HEADER);
927 DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_SUBPACK0_LOW);
928 DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_SUBPACK0_HIGH);
929 DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_CTRL);
930 DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_STATUS);
931 DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_HEADER);
932 DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK0_LOW);
933 DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK0_HIGH);
934 DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK1_LOW);
935 DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK1_HIGH);
936 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
937 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_STATUS);
938 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_HEADER);
939 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK0_LOW);
940 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK0_HIGH);
941 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK1_LOW);
942 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK1_HIGH);
943 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK2_LOW);
944 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK2_HIGH);
945 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK3_LOW);
946 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK3_HIGH);
947 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_CTRL);
948 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0320_SUBPACK_LOW);
949 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0320_SUBPACK_HIGH);
950 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_LOW);
951 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_HIGH);
952 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0882_SUBPACK_LOW);
953 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0882_SUBPACK_HIGH);
954 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_1764_SUBPACK_LOW);
955 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_1764_SUBPACK_HIGH);
956 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0480_SUBPACK_LOW);
957 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0480_SUBPACK_HIGH);
958 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0960_SUBPACK_LOW);
959 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0960_SUBPACK_HIGH);
960 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_1920_SUBPACK_LOW);
961 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_1920_SUBPACK_HIGH);
962 DUMP_REG(HDMI_NV_PDISP_HDMI_CTRL);
963 DUMP_REG(HDMI_NV_PDISP_HDMI_VSYNC_KEEPOUT);
964 DUMP_REG(HDMI_NV_PDISP_HDMI_VSYNC_WINDOW);
965 DUMP_REG(HDMI_NV_PDISP_HDMI_GCP_CTRL);
966 DUMP_REG(HDMI_NV_PDISP_HDMI_GCP_STATUS);
967 DUMP_REG(HDMI_NV_PDISP_HDMI_GCP_SUBPACK);
968 DUMP_REG(HDMI_NV_PDISP_HDMI_CHANNEL_STATUS1);
969 DUMP_REG(HDMI_NV_PDISP_HDMI_CHANNEL_STATUS2);
970 DUMP_REG(HDMI_NV_PDISP_HDMI_EMU0);
971 DUMP_REG(HDMI_NV_PDISP_HDMI_EMU1);
972 DUMP_REG(HDMI_NV_PDISP_HDMI_EMU1_RDATA);
973 DUMP_REG(HDMI_NV_PDISP_HDMI_SPARE);
974 DUMP_REG(HDMI_NV_PDISP_HDMI_SPDIF_CHN_STATUS1);
975 DUMP_REG(HDMI_NV_PDISP_HDMI_SPDIF_CHN_STATUS2);
976 DUMP_REG(HDMI_NV_PDISP_HDMI_HDCPRIF_ROM_CTRL);
977 DUMP_REG(HDMI_NV_PDISP_SOR_CAP);
978 DUMP_REG(HDMI_NV_PDISP_SOR_PWR);
979 DUMP_REG(HDMI_NV_PDISP_SOR_TEST);
980 DUMP_REG(HDMI_NV_PDISP_SOR_PLL0);
981 DUMP_REG(HDMI_NV_PDISP_SOR_PLL1);
982 DUMP_REG(HDMI_NV_PDISP_SOR_PLL2);
983 DUMP_REG(HDMI_NV_PDISP_SOR_CSTM);
984 DUMP_REG(HDMI_NV_PDISP_SOR_LVDS);
985 DUMP_REG(HDMI_NV_PDISP_SOR_CRCA);
986 DUMP_REG(HDMI_NV_PDISP_SOR_CRCB);
987 DUMP_REG(HDMI_NV_PDISP_SOR_BLANK);
988 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_CTL);
989 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(0));
990 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(1));
991 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(2));
992 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(3));
993 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(4));
994 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(5));
995 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(6));
996 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(7));
997 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(8));
998 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(9));
999 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(10));
1000 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(11));
1001 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(12));
1002 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(13));
1003 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(14));
1004 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(15));
1005 DUMP_REG(HDMI_NV_PDISP_SOR_VCRCA0);
1006 DUMP_REG(HDMI_NV_PDISP_SOR_VCRCA1);
1007 DUMP_REG(HDMI_NV_PDISP_SOR_CCRCA0);
1008 DUMP_REG(HDMI_NV_PDISP_SOR_CCRCA1);
1009 DUMP_REG(HDMI_NV_PDISP_SOR_EDATAA0);
1010 DUMP_REG(HDMI_NV_PDISP_SOR_EDATAA1);
1011 DUMP_REG(HDMI_NV_PDISP_SOR_COUNTA0);
1012 DUMP_REG(HDMI_NV_PDISP_SOR_COUNTA1);
1013 DUMP_REG(HDMI_NV_PDISP_SOR_DEBUGA0);
1014 DUMP_REG(HDMI_NV_PDISP_SOR_DEBUGA1);
1015 DUMP_REG(HDMI_NV_PDISP_SOR_TRIG);
1016 DUMP_REG(HDMI_NV_PDISP_SOR_MSCHECK);
1017 DUMP_REG(HDMI_NV_PDISP_SOR_LANE_DRIVE_CURRENT);
1018 DUMP_REG(HDMI_NV_PDISP_AUDIO_DEBUG0);
1019 DUMP_REG(HDMI_NV_PDISP_AUDIO_DEBUG1);
1020 DUMP_REG(HDMI_NV_PDISP_AUDIO_DEBUG2);
1021 DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(0));
1022 DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(1));
1023 DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(2));
1024 DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(3));
1025 DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(4));
1026 DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(5));
1027 DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(6));
1028 DUMP_REG(HDMI_NV_PDISP_AUDIO_PULSE_WIDTH);
1029 DUMP_REG(HDMI_NV_PDISP_AUDIO_THRESHOLD);
1030 DUMP_REG(HDMI_NV_PDISP_AUDIO_CNTRL0);
1031 DUMP_REG(HDMI_NV_PDISP_AUDIO_N);
1032 DUMP_REG(HDMI_NV_PDISP_HDCPRIF_ROM_TIMING);
1033 DUMP_REG(HDMI_NV_PDISP_SOR_REFCLK);
1034 DUMP_REG(HDMI_NV_PDISP_CRC_CONTROL);
1035 DUMP_REG(HDMI_NV_PDISP_INPUT_CONTROL);
1036 DUMP_REG(HDMI_NV_PDISP_SCRATCH);
1037 DUMP_REG(HDMI_NV_PDISP_PE_CURRENT);
1038 DUMP_REG(HDMI_NV_PDISP_KEY_CTRL);
1039 DUMP_REG(HDMI_NV_PDISP_KEY_DEBUG0);
1040 DUMP_REG(HDMI_NV_PDISP_KEY_DEBUG1);
1041 DUMP_REG(HDMI_NV_PDISP_KEY_DEBUG2);
1042 DUMP_REG(HDMI_NV_PDISP_KEY_HDCP_KEY_0);
1043 DUMP_REG(HDMI_NV_PDISP_KEY_HDCP_KEY_1);
1044 DUMP_REG(HDMI_NV_PDISP_KEY_HDCP_KEY_2);
1045 DUMP_REG(HDMI_NV_PDISP_KEY_HDCP_KEY_3);
1046 DUMP_REG(HDMI_NV_PDISP_KEY_HDCP_KEY_TRIG);
1047 DUMP_REG(HDMI_NV_PDISP_KEY_SKEY_INDEX);
1048 DUMP_REG(HDMI_NV_PDISP_SOR_AUDIO_CNTRL0);
1049 DUMP_REG(HDMI_NV_PDISP_SOR_AUDIO_HDA_ELD_BUFWR);
1050 DUMP_REG(HDMI_NV_PDISP_SOR_AUDIO_HDA_PRESENSE);
1051
1052#undef DUMP_REG
1053
Mikko Perttunenccaddfe2013-07-30 11:35:03 +03001054 clk_disable(hdmi->clk);
1055
Thierry Redingedec4af2012-11-15 21:28:23 +00001056 return 0;
1057}
1058
1059static struct drm_info_list debugfs_files[] = {
1060 { "regs", tegra_hdmi_show_regs, 0, NULL },
1061};
1062
1063static int tegra_hdmi_debugfs_init(struct tegra_hdmi *hdmi,
1064 struct drm_minor *minor)
1065{
1066 unsigned int i;
1067 int err;
1068
1069 hdmi->debugfs = debugfs_create_dir("hdmi", minor->debugfs_root);
1070 if (!hdmi->debugfs)
1071 return -ENOMEM;
1072
1073 hdmi->debugfs_files = kmemdup(debugfs_files, sizeof(debugfs_files),
1074 GFP_KERNEL);
1075 if (!hdmi->debugfs_files) {
1076 err = -ENOMEM;
1077 goto remove;
1078 }
1079
1080 for (i = 0; i < ARRAY_SIZE(debugfs_files); i++)
1081 hdmi->debugfs_files[i].data = hdmi;
1082
1083 err = drm_debugfs_create_files(hdmi->debugfs_files,
1084 ARRAY_SIZE(debugfs_files),
1085 hdmi->debugfs, minor);
1086 if (err < 0)
1087 goto free;
1088
1089 hdmi->minor = minor;
1090
1091 return 0;
1092
1093free:
1094 kfree(hdmi->debugfs_files);
1095 hdmi->debugfs_files = NULL;
1096remove:
1097 debugfs_remove(hdmi->debugfs);
1098 hdmi->debugfs = NULL;
1099
1100 return err;
1101}
1102
1103static int tegra_hdmi_debugfs_exit(struct tegra_hdmi *hdmi)
1104{
1105 drm_debugfs_remove_files(hdmi->debugfs_files, ARRAY_SIZE(debugfs_files),
1106 hdmi->minor);
1107 hdmi->minor = NULL;
1108
1109 kfree(hdmi->debugfs_files);
1110 hdmi->debugfs_files = NULL;
1111
1112 debugfs_remove(hdmi->debugfs);
1113 hdmi->debugfs = NULL;
1114
1115 return 0;
1116}
1117
Thierry Reding53fa7f72013-09-24 15:35:40 +02001118static int tegra_hdmi_init(struct host1x_client *client)
Thierry Redingedec4af2012-11-15 21:28:23 +00001119{
Thierry Reding776dc382013-10-14 14:43:22 +02001120 struct tegra_drm *tegra = dev_get_drvdata(client->parent);
1121 struct tegra_hdmi *hdmi = host1x_client_to_hdmi(client);
Thierry Redingedec4af2012-11-15 21:28:23 +00001122 int err;
1123
1124 hdmi->output.type = TEGRA_OUTPUT_HDMI;
1125 hdmi->output.dev = client->dev;
1126 hdmi->output.ops = &hdmi_ops;
1127
Thierry Reding776dc382013-10-14 14:43:22 +02001128 err = tegra_output_init(tegra->drm, &hdmi->output);
Thierry Redingedec4af2012-11-15 21:28:23 +00001129 if (err < 0) {
1130 dev_err(client->dev, "output setup failed: %d\n", err);
1131 return err;
1132 }
1133
1134 if (IS_ENABLED(CONFIG_DEBUG_FS)) {
Thierry Reding776dc382013-10-14 14:43:22 +02001135 err = tegra_hdmi_debugfs_init(hdmi, tegra->drm->primary);
Thierry Redingedec4af2012-11-15 21:28:23 +00001136 if (err < 0)
1137 dev_err(client->dev, "debugfs setup failed: %d\n", err);
1138 }
1139
1140 return 0;
1141}
1142
Thierry Reding53fa7f72013-09-24 15:35:40 +02001143static int tegra_hdmi_exit(struct host1x_client *client)
Thierry Redingedec4af2012-11-15 21:28:23 +00001144{
Thierry Reding776dc382013-10-14 14:43:22 +02001145 struct tegra_hdmi *hdmi = host1x_client_to_hdmi(client);
Thierry Redingedec4af2012-11-15 21:28:23 +00001146 int err;
1147
1148 if (IS_ENABLED(CONFIG_DEBUG_FS)) {
1149 err = tegra_hdmi_debugfs_exit(hdmi);
1150 if (err < 0)
1151 dev_err(client->dev, "debugfs cleanup failed: %d\n",
1152 err);
1153 }
1154
1155 err = tegra_output_disable(&hdmi->output);
1156 if (err < 0) {
1157 dev_err(client->dev, "output failed to disable: %d\n", err);
1158 return err;
1159 }
1160
1161 err = tegra_output_exit(&hdmi->output);
1162 if (err < 0) {
1163 dev_err(client->dev, "output cleanup failed: %d\n", err);
1164 return err;
1165 }
1166
1167 return 0;
1168}
1169
1170static const struct host1x_client_ops hdmi_client_ops = {
Thierry Reding53fa7f72013-09-24 15:35:40 +02001171 .init = tegra_hdmi_init,
1172 .exit = tegra_hdmi_exit,
Thierry Redingedec4af2012-11-15 21:28:23 +00001173};
1174
1175static int tegra_hdmi_probe(struct platform_device *pdev)
1176{
Thierry Redingedec4af2012-11-15 21:28:23 +00001177 struct tegra_hdmi *hdmi;
1178 struct resource *regs;
1179 int err;
1180
1181 hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL);
1182 if (!hdmi)
1183 return -ENOMEM;
1184
1185 hdmi->dev = &pdev->dev;
1186 hdmi->audio_source = AUTO;
1187 hdmi->audio_freq = 44100;
1188 hdmi->stereo = false;
1189 hdmi->dvi = false;
1190
1191 hdmi->clk = devm_clk_get(&pdev->dev, NULL);
1192 if (IS_ERR(hdmi->clk)) {
1193 dev_err(&pdev->dev, "failed to get clock\n");
1194 return PTR_ERR(hdmi->clk);
1195 }
1196
1197 err = clk_prepare(hdmi->clk);
1198 if (err < 0)
1199 return err;
1200
1201 hdmi->clk_parent = devm_clk_get(&pdev->dev, "parent");
1202 if (IS_ERR(hdmi->clk_parent))
1203 return PTR_ERR(hdmi->clk_parent);
1204
1205 err = clk_prepare(hdmi->clk_parent);
1206 if (err < 0)
1207 return err;
1208
1209 err = clk_set_parent(hdmi->clk, hdmi->clk_parent);
1210 if (err < 0) {
1211 dev_err(&pdev->dev, "failed to setup clocks: %d\n", err);
1212 return err;
1213 }
1214
1215 hdmi->vdd = devm_regulator_get(&pdev->dev, "vdd");
1216 if (IS_ERR(hdmi->vdd)) {
1217 dev_err(&pdev->dev, "failed to get VDD regulator\n");
1218 return PTR_ERR(hdmi->vdd);
1219 }
1220
1221 hdmi->pll = devm_regulator_get(&pdev->dev, "pll");
1222 if (IS_ERR(hdmi->pll)) {
1223 dev_err(&pdev->dev, "failed to get PLL regulator\n");
1224 return PTR_ERR(hdmi->pll);
1225 }
1226
1227 hdmi->output.dev = &pdev->dev;
1228
1229 err = tegra_output_parse_dt(&hdmi->output);
1230 if (err < 0)
1231 return err;
1232
1233 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1234 if (!regs)
1235 return -ENXIO;
1236
Thierry Redingd4ed6022013-01-21 11:09:02 +01001237 hdmi->regs = devm_ioremap_resource(&pdev->dev, regs);
1238 if (IS_ERR(hdmi->regs))
1239 return PTR_ERR(hdmi->regs);
Thierry Redingedec4af2012-11-15 21:28:23 +00001240
1241 err = platform_get_irq(pdev, 0);
1242 if (err < 0)
1243 return err;
1244
1245 hdmi->irq = err;
1246
Thierry Reding776dc382013-10-14 14:43:22 +02001247 INIT_LIST_HEAD(&hdmi->client.list);
1248 hdmi->client.ops = &hdmi_client_ops;
1249 hdmi->client.dev = &pdev->dev;
Thierry Redingedec4af2012-11-15 21:28:23 +00001250
Thierry Reding776dc382013-10-14 14:43:22 +02001251 err = host1x_client_register(&hdmi->client);
Thierry Redingedec4af2012-11-15 21:28:23 +00001252 if (err < 0) {
1253 dev_err(&pdev->dev, "failed to register host1x client: %d\n",
1254 err);
1255 return err;
1256 }
1257
1258 platform_set_drvdata(pdev, hdmi);
1259
1260 return 0;
1261}
1262
1263static int tegra_hdmi_remove(struct platform_device *pdev)
1264{
Thierry Redingedec4af2012-11-15 21:28:23 +00001265 struct tegra_hdmi *hdmi = platform_get_drvdata(pdev);
1266 int err;
1267
Thierry Reding776dc382013-10-14 14:43:22 +02001268 err = host1x_client_unregister(&hdmi->client);
Thierry Redingedec4af2012-11-15 21:28:23 +00001269 if (err < 0) {
1270 dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
1271 err);
1272 return err;
1273 }
1274
1275 clk_unprepare(hdmi->clk_parent);
1276 clk_unprepare(hdmi->clk);
1277
1278 return 0;
1279}
1280
1281static struct of_device_id tegra_hdmi_of_match[] = {
Thierry Redingedec4af2012-11-15 21:28:23 +00001282 { .compatible = "nvidia,tegra30-hdmi", },
Thierry Reding219e8152012-11-21 09:50:41 +01001283 { .compatible = "nvidia,tegra20-hdmi", },
Thierry Redingedec4af2012-11-15 21:28:23 +00001284 { },
1285};
1286
1287struct platform_driver tegra_hdmi_driver = {
1288 .driver = {
1289 .name = "tegra-hdmi",
1290 .owner = THIS_MODULE,
1291 .of_match_table = tegra_hdmi_of_match,
1292 },
1293 .probe = tegra_hdmi_probe,
1294 .remove = tegra_hdmi_remove,
1295};