aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/tegra
diff options
context:
space:
mode:
authorThierry Reding <thierry.reding@avionic-design.de>2012-11-23 09:14:00 -0500
committerThierry Reding <thierry.reding@avionic-design.de>2013-02-22 02:20:18 -0500
commitac24c2204a76e5b42aa103bf963ae0eda1b827f3 (patch)
tree73d668aaaebdc49e1b0a064715d9a21733559d9c /drivers/gpu/drm/tegra
parent5e308591a887604ed4fca7e7fcd8fb18d8bdc459 (diff)
drm/tegra: Use generic HDMI infoframe helpers
Use the generic HDMI infoframe helpers to get rid of the NVIDIA Tegra reimplementation. Signed-off-by: Thierry Reding <thierry.reding@avionic-design.de> Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/tegra')
-rw-r--r--drivers/gpu/drm/tegra/Kconfig1
-rw-r--r--drivers/gpu/drm/tegra/hdmi.c226
-rw-r--r--drivers/gpu/drm/tegra/hdmi.h189
3 files changed, 110 insertions, 306 deletions
diff --git a/drivers/gpu/drm/tegra/Kconfig b/drivers/gpu/drm/tegra/Kconfig
index be1daf7344d3..c92955df0658 100644
--- a/drivers/gpu/drm/tegra/Kconfig
+++ b/drivers/gpu/drm/tegra/Kconfig
@@ -4,6 +4,7 @@ config DRM_TEGRA
4 select DRM_KMS_HELPER 4 select DRM_KMS_HELPER
5 select DRM_GEM_CMA_HELPER 5 select DRM_GEM_CMA_HELPER
6 select DRM_KMS_CMA_HELPER 6 select DRM_KMS_CMA_HELPER
7 select DRM_HDMI
7 select FB_CFB_FILLRECT 8 select FB_CFB_FILLRECT
8 select FB_CFB_COPYAREA 9 select FB_CFB_COPYAREA
9 select FB_CFB_IMAGEBLIT 10 select FB_CFB_IMAGEBLIT
diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c
index e060c7e6434d..0daee8e2578b 100644
--- a/drivers/gpu/drm/tegra/hdmi.c
+++ b/drivers/gpu/drm/tegra/hdmi.c
@@ -10,6 +10,7 @@
10#include <linux/clk.h> 10#include <linux/clk.h>
11#include <linux/debugfs.h> 11#include <linux/debugfs.h>
12#include <linux/gpio.h> 12#include <linux/gpio.h>
13#include <linux/hdmi.h>
13#include <linux/module.h> 14#include <linux/module.h>
14#include <linux/of.h> 15#include <linux/of.h>
15#include <linux/platform_device.h> 16#include <linux/platform_device.h>
@@ -17,6 +18,8 @@
17 18
18#include <mach/clk.h> 19#include <mach/clk.h>
19 20
21#include <drm/drm_edid.h>
22
20#include "hdmi.h" 23#include "hdmi.h"
21#include "drm.h" 24#include "drm.h"
22#include "dc.h" 25#include "dc.h"
@@ -401,54 +404,65 @@ static int tegra_hdmi_setup_audio(struct tegra_hdmi *hdmi, unsigned int pclk)
401 return 0; 404 return 0;
402} 405}
403 406
404static void tegra_hdmi_write_infopack(struct tegra_hdmi *hdmi, 407static inline unsigned long tegra_hdmi_subpack(const u8 *ptr, size_t size)
405 unsigned int offset, u8 type,
406 u8 version, void *data, size_t size)
407{ 408{
408 unsigned long value; 409 unsigned long value = 0;
409 u8 *ptr = data;
410 u32 subpack[2];
411 size_t i; 410 size_t i;
412 u8 csum;
413 411
414 /* first byte of data is the checksum */ 412 for (i = size; i > 0; i--)
415 csum = type + version + size - 1; 413 value = (value << 8) | ptr[i - 1];
416 414
417 for (i = 1; i < size; i++) 415 return value;
418 csum += ptr[i]; 416}
419 417
420 ptr[0] = 0x100 - csum; 418static void tegra_hdmi_write_infopack(struct tegra_hdmi *hdmi, const void *data,
419 size_t size)
420{
421 const u8 *ptr = data;
422 unsigned long offset;
423 unsigned long value;
424 size_t i, j;
421 425
422 value = INFOFRAME_HEADER_TYPE(type) | 426 switch (ptr[0]) {
423 INFOFRAME_HEADER_VERSION(version) | 427 case HDMI_INFOFRAME_TYPE_AVI:
424 INFOFRAME_HEADER_LEN(size - 1); 428 offset = HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_HEADER;
425 tegra_hdmi_writel(hdmi, value, offset); 429 break;
426 430
427 /* The audio inforame only has one set of subpack registers. The hdmi 431 case HDMI_INFOFRAME_TYPE_AUDIO:
428 * block pads the rest of the data as per the spec so we have to fixup 432 offset = HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_HEADER;
429 * the length before filling in the subpacks. 433 break;
430 */
431 if (offset == HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_HEADER)
432 size = 6;
433 434
434 /* each subpack 7 bytes devided into: 435 case HDMI_INFOFRAME_TYPE_VENDOR:
435 * subpack_low - bytes 0 - 3 436 offset = HDMI_NV_PDISP_HDMI_GENERIC_HEADER;
436 * subpack_high - bytes 4 - 6 (with byte 7 padded to 0x00) 437 break;
437 */ 438
438 for (i = 0; i < size; i++) { 439 default:
439 size_t index = i % 7; 440 dev_err(hdmi->dev, "unsupported infoframe type: %02x\n",
441 ptr[0]);
442 return;
443 }
444
445 value = INFOFRAME_HEADER_TYPE(ptr[0]) |
446 INFOFRAME_HEADER_VERSION(ptr[1]) |
447 INFOFRAME_HEADER_LEN(ptr[2]);
448 tegra_hdmi_writel(hdmi, value, offset);
449 offset++;
440 450
441 if (index == 0) 451 /*
442 memset(subpack, 0x0, sizeof(subpack)); 452 * Each subpack contains 7 bytes, divided into:
453 * - subpack_low: bytes 0 - 3
454 * - subpack_high: bytes 4 - 6 (with byte 7 padded to 0x00)
455 */
456 for (i = 3, j = 0; i < size; i += 7, j += 8) {
457 size_t rem = size - i, num = min_t(size_t, rem, 4);
443 458
444 ((u8 *)subpack)[index] = ptr[i]; 459 value = tegra_hdmi_subpack(&ptr[i], num);
460 tegra_hdmi_writel(hdmi, value, offset++);
445 461
446 if (index == 6 || (i + 1 == size)) { 462 num = min_t(size_t, rem - num, 3);
447 unsigned int reg = offset + 1 + (i / 7) * 2;
448 463
449 tegra_hdmi_writel(hdmi, subpack[0], reg); 464 value = tegra_hdmi_subpack(&ptr[i + 4], num);
450 tegra_hdmi_writel(hdmi, subpack[1], reg + 1); 465 tegra_hdmi_writel(hdmi, value, offset++);
451 }
452 } 466 }
453} 467}
454 468
@@ -456,9 +470,8 @@ static void tegra_hdmi_setup_avi_infoframe(struct tegra_hdmi *hdmi,
456 struct drm_display_mode *mode) 470 struct drm_display_mode *mode)
457{ 471{
458 struct hdmi_avi_infoframe frame; 472 struct hdmi_avi_infoframe frame;
459 unsigned int h_front_porch; 473 u8 buffer[17];
460 unsigned int hsize = 16; 474 ssize_t err;
461 unsigned int vsize = 9;
462 475
463 if (hdmi->dvi) { 476 if (hdmi->dvi) {
464 tegra_hdmi_writel(hdmi, 0, 477 tegra_hdmi_writel(hdmi, 0,
@@ -466,69 +479,19 @@ static void tegra_hdmi_setup_avi_infoframe(struct tegra_hdmi *hdmi,
466 return; 479 return;
467 } 480 }
468 481
469 h_front_porch = mode->hsync_start - mode->hdisplay; 482 err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
470 memset(&frame, 0, sizeof(frame)); 483 if (err < 0) {
471 frame.r = HDMI_AVI_R_SAME; 484 dev_err(hdmi->dev, "failed to setup AVI infoframe: %zd\n", err);
472 485 return;
473 switch (mode->vdisplay) { 486 }
474 case 480:
475 if (mode->hdisplay == 640) {
476 frame.m = HDMI_AVI_M_4_3;
477 frame.vic = 1;
478 } else {
479 frame.m = HDMI_AVI_M_16_9;
480 frame.vic = 3;
481 }
482 break;
483
484 case 576:
485 if (((hsize * 10) / vsize) > 14) {
486 frame.m = HDMI_AVI_M_16_9;
487 frame.vic = 18;
488 } else {
489 frame.m = HDMI_AVI_M_4_3;
490 frame.vic = 17;
491 }
492 break;
493
494 case 720:
495 case 1470: /* stereo mode */
496 frame.m = HDMI_AVI_M_16_9;
497
498 if (h_front_porch == 110)
499 frame.vic = 4;
500 else
501 frame.vic = 19;
502 break;
503
504 case 1080:
505 case 2205: /* stereo mode */
506 frame.m = HDMI_AVI_M_16_9;
507
508 switch (h_front_porch) {
509 case 88:
510 frame.vic = 16;
511 break;
512
513 case 528:
514 frame.vic = 31;
515 break;
516
517 default:
518 frame.vic = 32;
519 break;
520 }
521 break;
522 487
523 default: 488 err = hdmi_avi_infoframe_pack(&frame, buffer, sizeof(buffer));
524 frame.m = HDMI_AVI_M_16_9; 489 if (err < 0) {
525 frame.vic = 0; 490 dev_err(hdmi->dev, "failed to pack AVI infoframe: %zd\n", err);
526 break; 491 return;
527 } 492 }
528 493
529 tegra_hdmi_write_infopack(hdmi, HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_HEADER, 494 tegra_hdmi_write_infopack(hdmi, buffer, err);
530 HDMI_INFOFRAME_TYPE_AVI, HDMI_AVI_VERSION,
531 &frame, sizeof(frame));
532 495
533 tegra_hdmi_writel(hdmi, INFOFRAME_CTRL_ENABLE, 496 tegra_hdmi_writel(hdmi, INFOFRAME_CTRL_ENABLE,
534 HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_CTRL); 497 HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_CTRL);
@@ -537,6 +500,8 @@ static void tegra_hdmi_setup_avi_infoframe(struct tegra_hdmi *hdmi,
537static void tegra_hdmi_setup_audio_infoframe(struct tegra_hdmi *hdmi) 500static void tegra_hdmi_setup_audio_infoframe(struct tegra_hdmi *hdmi)
538{ 501{
539 struct hdmi_audio_infoframe frame; 502 struct hdmi_audio_infoframe frame;
503 u8 buffer[14];
504 ssize_t err;
540 505
541 if (hdmi->dvi) { 506 if (hdmi->dvi) {
542 tegra_hdmi_writel(hdmi, 0, 507 tegra_hdmi_writel(hdmi, 0,
@@ -544,14 +509,29 @@ static void tegra_hdmi_setup_audio_infoframe(struct tegra_hdmi *hdmi)
544 return; 509 return;
545 } 510 }
546 511
547 memset(&frame, 0, sizeof(frame)); 512 err = hdmi_audio_infoframe_init(&frame);
548 frame.cc = HDMI_AUDIO_CC_2; 513 if (err < 0) {
514 dev_err(hdmi->dev, "failed to initialize audio infoframe: %d\n",
515 err);
516 return;
517 }
518
519 frame.channels = 2;
520
521 err = hdmi_audio_infoframe_pack(&frame, buffer, sizeof(buffer));
522 if (err < 0) {
523 dev_err(hdmi->dev, "failed to pack audio infoframe: %zd\n",
524 err);
525 return;
526 }
549 527
550 tegra_hdmi_write_infopack(hdmi, 528 /*
551 HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_HEADER, 529 * The audio infoframe has only one set of subpack registers, so the
552 HDMI_INFOFRAME_TYPE_AUDIO, 530 * infoframe needs to be truncated. One set of subpack registers can
553 HDMI_AUDIO_VERSION, 531 * contain 7 bytes. Including the 3 byte header only the first 10
554 &frame, sizeof(frame)); 532 * bytes can be programmed.
533 */
534 tegra_hdmi_write_infopack(hdmi, buffer, min(10, err));
555 535
556 tegra_hdmi_writel(hdmi, INFOFRAME_CTRL_ENABLE, 536 tegra_hdmi_writel(hdmi, INFOFRAME_CTRL_ENABLE,
557 HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_CTRL); 537 HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_CTRL);
@@ -559,8 +539,10 @@ static void tegra_hdmi_setup_audio_infoframe(struct tegra_hdmi *hdmi)
559 539
560static void tegra_hdmi_setup_stereo_infoframe(struct tegra_hdmi *hdmi) 540static void tegra_hdmi_setup_stereo_infoframe(struct tegra_hdmi *hdmi)
561{ 541{
562 struct hdmi_stereo_infoframe frame; 542 struct hdmi_vendor_infoframe frame;
563 unsigned long value; 543 unsigned long value;
544 u8 buffer[10];
545 ssize_t err;
564 546
565 if (!hdmi->stereo) { 547 if (!hdmi->stereo) {
566 value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_HDMI_GENERIC_CTRL); 548 value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
@@ -570,22 +552,32 @@ static void tegra_hdmi_setup_stereo_infoframe(struct tegra_hdmi *hdmi)
570 } 552 }
571 553
572 memset(&frame, 0, sizeof(frame)); 554 memset(&frame, 0, sizeof(frame));
573 frame.regid0 = 0x03; 555
574 frame.regid1 = 0x0c; 556 frame.type = HDMI_INFOFRAME_TYPE_VENDOR;
575 frame.regid2 = 0x00; 557 frame.version = 0x01;
576 frame.hdmi_video_format = 2; 558 frame.length = 6;
559
560 frame.data[0] = 0x03; /* regid0 */
561 frame.data[1] = 0x0c; /* regid1 */
562 frame.data[2] = 0x00; /* regid2 */
563 frame.data[3] = 0x02 << 5; /* video format */
577 564
578 /* TODO: 74 MHz limit? */ 565 /* TODO: 74 MHz limit? */
579 if (1) { 566 if (1) {
580 frame._3d_structure = 0; 567 frame.data[4] = 0x00 << 4; /* 3D structure */
581 } else { 568 } else {
582 frame._3d_structure = 8; 569 frame.data[4] = 0x08 << 4; /* 3D structure */
583 frame._3d_ext_data = 0; 570 frame.data[5] = 0x00 << 4; /* 3D ext. data */
571 }
572
573 err = hdmi_vendor_infoframe_pack(&frame, buffer, sizeof(buffer));
574 if (err < 0) {
575 dev_err(hdmi->dev, "failed to pack vendor infoframe: %zd\n",
576 err);
577 return;
584 } 578 }
585 579
586 tegra_hdmi_write_infopack(hdmi, HDMI_NV_PDISP_HDMI_GENERIC_HEADER, 580 tegra_hdmi_write_infopack(hdmi, buffer, err);
587 HDMI_INFOFRAME_TYPE_VENDOR,
588 HDMI_VENDOR_VERSION, &frame, 6);
589 581
590 value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_HDMI_GENERIC_CTRL); 582 value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
591 value |= GENERIC_CTRL_ENABLE; 583 value |= GENERIC_CTRL_ENABLE;
diff --git a/drivers/gpu/drm/tegra/hdmi.h b/drivers/gpu/drm/tegra/hdmi.h
index 1477f36eb45a..52ac36e08ccb 100644
--- a/drivers/gpu/drm/tegra/hdmi.h
+++ b/drivers/gpu/drm/tegra/hdmi.h
@@ -10,195 +10,6 @@
10#ifndef TEGRA_HDMI_H 10#ifndef TEGRA_HDMI_H
11#define TEGRA_HDMI_H 1 11#define TEGRA_HDMI_H 1
12 12
13#define HDMI_INFOFRAME_TYPE_VENDOR 0x81
14#define HDMI_INFOFRAME_TYPE_AVI 0x82
15#define HDMI_INFOFRAME_TYPE_SPD 0x83
16#define HDMI_INFOFRAME_TYPE_AUDIO 0x84
17#define HDMI_INFOFRAME_TYPE_MPEG_SRC 0x85
18#define HDMI_INFOFRAME_TYPE_NTSC_VBI 0x86
19
20/* all fields little endian */
21struct hdmi_avi_infoframe {
22 /* PB0 */
23 u8 csum;
24
25 /* PB1 */
26 unsigned s:2; /* scan information */
27 unsigned b:2; /* bar info data valid */
28 unsigned a:1; /* active info present */
29 unsigned y:2; /* RGB or YCbCr */
30 unsigned res1:1;
31
32 /* PB2 */
33 unsigned r:4; /* active format aspect ratio */
34 unsigned m:2; /* picture aspect ratio */
35 unsigned c:2; /* colorimetry */
36
37 /* PB3 */
38 unsigned sc:2; /* scan information */
39 unsigned q:2; /* quantization range */
40 unsigned ec:3; /* extended colorimetry */
41 unsigned itc:1; /* it content */
42
43 /* PB4 */
44 unsigned vic:7; /* video format id code */
45 unsigned res4:1;
46
47 /* PB5 */
48 unsigned pr:4; /* pixel repetition factor */
49 unsigned cn:2; /* it content type*/
50 unsigned yq:2; /* ycc quantization range */
51
52 /* PB6-7 */
53 u16 top_bar_end_line;
54
55 /* PB8-9 */
56 u16 bot_bar_start_line;
57
58 /* PB10-11 */
59 u16 left_bar_end_pixel;
60
61 /* PB12-13 */
62 u16 right_bar_start_pixel;
63} __packed;
64
65#define HDMI_AVI_VERSION 0x02
66
67#define HDMI_AVI_Y_RGB 0x0
68#define HDMI_AVI_Y_YCBCR_422 0x1
69#define HDMI_AVI_Y_YCBCR_444 0x2
70
71#define HDMI_AVI_B_VERT 0x1
72#define HDMI_AVI_B_HORIZ 0x2
73
74#define HDMI_AVI_S_NONE 0x0
75#define HDMI_AVI_S_OVERSCAN 0x1
76#define HDMI_AVI_S_UNDERSCAN 0x2
77
78#define HDMI_AVI_C_NONE 0x0
79#define HDMI_AVI_C_SMPTE 0x1
80#define HDMI_AVI_C_ITU_R 0x2
81#define HDMI_AVI_C_EXTENDED 0x4
82
83#define HDMI_AVI_M_4_3 0x1
84#define HDMI_AVI_M_16_9 0x2
85
86#define HDMI_AVI_R_SAME 0x8
87#define HDMI_AVI_R_4_3_CENTER 0x9
88#define HDMI_AVI_R_16_9_CENTER 0xa
89#define HDMI_AVI_R_14_9_CENTER 0xb
90
91/* all fields little endian */
92struct hdmi_audio_infoframe {
93 /* PB0 */
94 u8 csum;
95
96 /* PB1 */
97 unsigned cc:3; /* channel count */
98 unsigned res1:1;
99 unsigned ct:4; /* coding type */
100
101 /* PB2 */
102 unsigned ss:2; /* sample size */
103 unsigned sf:3; /* sample frequency */
104 unsigned res2:3;
105
106 /* PB3 */
107 unsigned cxt:5; /* coding extention type */
108 unsigned res3:3;
109
110 /* PB4 */
111 u8 ca; /* channel/speaker allocation */
112
113 /* PB5 */
114 unsigned res5:3;
115 unsigned lsv:4; /* level shift value */
116 unsigned dm_inh:1; /* downmix inhibit */
117
118 /* PB6-10 reserved */
119 u8 res6;
120 u8 res7;
121 u8 res8;
122 u8 res9;
123 u8 res10;
124} __packed;
125
126#define HDMI_AUDIO_VERSION 0x01
127
128#define HDMI_AUDIO_CC_STREAM 0x0 /* specified by audio stream */
129#define HDMI_AUDIO_CC_2 0x1
130#define HDMI_AUDIO_CC_3 0x2
131#define HDMI_AUDIO_CC_4 0x3
132#define HDMI_AUDIO_CC_5 0x4
133#define HDMI_AUDIO_CC_6 0x5
134#define HDMI_AUDIO_CC_7 0x6
135#define HDMI_AUDIO_CC_8 0x7
136
137#define HDMI_AUDIO_CT_STREAM 0x0 /* specified by audio stream */
138#define HDMI_AUDIO_CT_PCM 0x1
139#define HDMI_AUDIO_CT_AC3 0x2
140#define HDMI_AUDIO_CT_MPEG1 0x3
141#define HDMI_AUDIO_CT_MP3 0x4
142#define HDMI_AUDIO_CT_MPEG2 0x5
143#define HDMI_AUDIO_CT_AAC_LC 0x6
144#define HDMI_AUDIO_CT_DTS 0x7
145#define HDMI_AUDIO_CT_ATRAC 0x8
146#define HDMI_AUDIO_CT_DSD 0x9
147#define HDMI_AUDIO_CT_E_AC3 0xa
148#define HDMI_AUDIO_CT_DTS_HD 0xb
149#define HDMI_AUDIO_CT_MLP 0xc
150#define HDMI_AUDIO_CT_DST 0xd
151#define HDMI_AUDIO_CT_WMA_PRO 0xe
152#define HDMI_AUDIO_CT_CXT 0xf
153
154#define HDMI_AUDIO_SF_STREAM 0x0 /* specified by audio stream */
155#define HDMI_AUIDO_SF_32K 0x1
156#define HDMI_AUDIO_SF_44_1K 0x2
157#define HDMI_AUDIO_SF_48K 0x3
158#define HDMI_AUDIO_SF_88_2K 0x4
159#define HDMI_AUDIO_SF_96K 0x5
160#define HDMI_AUDIO_SF_176_4K 0x6
161#define HDMI_AUDIO_SF_192K 0x7
162
163#define HDMI_AUDIO_SS_STREAM 0x0 /* specified by audio stream */
164#define HDMI_AUDIO_SS_16BIT 0x1
165#define HDMI_AUDIO_SS_20BIT 0x2
166#define HDMI_AUDIO_SS_24BIT 0x3
167
168#define HDMI_AUDIO_CXT_CT 0x0 /* refer to coding in CT */
169#define HDMI_AUDIO_CXT_HE_AAC 0x1
170#define HDMI_AUDIO_CXT_HE_AAC_V2 0x2
171#define HDMI_AUDIO_CXT_MPEG_SURROUND 0x3
172
173/* all fields little endian */
174struct hdmi_stereo_infoframe {
175 /* PB0 */
176 u8 csum;
177
178 /* PB1 */
179 u8 regid0;
180
181 /* PB2 */
182 u8 regid1;
183
184 /* PB3 */
185 u8 regid2;
186
187 /* PB4 */
188 unsigned res1:5;
189 unsigned hdmi_video_format:3;
190
191 /* PB5 */
192 unsigned res2:4;
193 unsigned _3d_structure:4;
194
195 /* PB6*/
196 unsigned res3:4;
197 unsigned _3d_ext_data:4;
198} __packed;
199
200#define HDMI_VENDOR_VERSION 0x01
201
202/* register definitions */ 13/* register definitions */
203#define HDMI_CTXSW 0x00 14#define HDMI_CTXSW 0x00
204 15