aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/video/Kconfig3
-rw-r--r--drivers/video/Makefile1
-rw-r--r--drivers/video/hdmi.c308
-rw-r--r--include/linux/hdmi.h231
4 files changed, 543 insertions, 0 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 09f1a18c1adf..b11eeab94151 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -52,6 +52,9 @@ config OF_VIDEOMODE
52 help 52 help
53 helper to get videomodes from the devicetree 53 helper to get videomodes from the devicetree
54 54
55config HDMI
56 bool
57
55menuconfig FB 58menuconfig FB
56 tristate "Support for frame buffer devices" 59 tristate "Support for frame buffer devices"
57 ---help--- 60 ---help---
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index f592f3b32ec7..0b50082635e3 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -5,6 +5,7 @@
5# Each configuration option enables a list of files. 5# Each configuration option enables a list of files.
6 6
7obj-$(CONFIG_VGASTATE) += vgastate.o 7obj-$(CONFIG_VGASTATE) += vgastate.o
8obj-$(CONFIG_HDMI) += hdmi.o
8obj-y += fb_notify.o 9obj-y += fb_notify.o
9obj-$(CONFIG_FB) += fb.o 10obj-$(CONFIG_FB) += fb.o
10fb-y := fbmem.o fbmon.o fbcmap.o fbsysfs.o \ 11fb-y := fbmem.o fbmon.o fbcmap.o fbsysfs.o \
diff --git a/drivers/video/hdmi.c b/drivers/video/hdmi.c
new file mode 100644
index 000000000000..ab23c9b79143
--- /dev/null
+++ b/drivers/video/hdmi.c
@@ -0,0 +1,308 @@
1/*
2 * Copyright (C) 2012 Avionic Design GmbH
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/bitops.h>
10#include <linux/errno.h>
11#include <linux/export.h>
12#include <linux/hdmi.h>
13#include <linux/string.h>
14
15static void hdmi_infoframe_checksum(void *buffer, size_t size)
16{
17 u8 *ptr = buffer;
18 u8 csum = 0;
19 size_t i;
20
21 /* compute checksum */
22 for (i = 0; i < size; i++)
23 csum += ptr[i];
24
25 ptr[3] = 256 - csum;
26}
27
28/**
29 * hdmi_avi_infoframe_init() - initialize an HDMI AVI infoframe
30 * @frame: HDMI AVI infoframe
31 *
32 * Returns 0 on success or a negative error code on failure.
33 */
34int hdmi_avi_infoframe_init(struct hdmi_avi_infoframe *frame)
35{
36 memset(frame, 0, sizeof(*frame));
37
38 frame->type = HDMI_INFOFRAME_TYPE_AVI;
39 frame->version = 2;
40 frame->length = 13;
41
42 return 0;
43}
44EXPORT_SYMBOL(hdmi_avi_infoframe_init);
45
46/**
47 * hdmi_avi_infoframe_pack() - write HDMI AVI infoframe to binary buffer
48 * @frame: HDMI AVI infoframe
49 * @buffer: destination buffer
50 * @size: size of buffer
51 *
52 * Packs the information contained in the @frame structure into a binary
53 * representation that can be written into the corresponding controller
54 * registers. Also computes the checksum as required by section 5.3.5 of
55 * the HDMI 1.4 specification.
56 *
57 * Returns the number of bytes packed into the binary buffer or a negative
58 * error code on failure.
59 */
60ssize_t hdmi_avi_infoframe_pack(struct hdmi_avi_infoframe *frame, void *buffer,
61 size_t size)
62{
63 u8 *ptr = buffer;
64 size_t length;
65
66 length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;
67
68 if (size < length)
69 return -ENOSPC;
70
71 memset(buffer, 0, length);
72
73 ptr[0] = frame->type;
74 ptr[1] = frame->version;
75 ptr[2] = frame->length;
76 ptr[3] = 0; /* checksum */
77
78 /* start infoframe payload */
79 ptr += HDMI_INFOFRAME_HEADER_SIZE;
80
81 ptr[0] = ((frame->colorspace & 0x3) << 5) | (frame->scan_mode & 0x3);
82
83 if (frame->active_info_valid)
84 ptr[0] |= BIT(4);
85
86 if (frame->horizontal_bar_valid)
87 ptr[0] |= BIT(3);
88
89 if (frame->vertical_bar_valid)
90 ptr[0] |= BIT(2);
91
92 ptr[1] = ((frame->colorimetry & 0x3) << 6) |
93 ((frame->picture_aspect & 0x3) << 4) |
94 (frame->active_aspect & 0xf);
95
96 ptr[2] = ((frame->extended_colorimetry & 0x7) << 4) |
97 ((frame->quantization_range & 0x3) << 2) |
98 (frame->nups & 0x3);
99
100 if (frame->itc)
101 ptr[2] |= BIT(7);
102
103 ptr[3] = frame->video_code & 0x7f;
104
105 ptr[4] = ((frame->ycc_quantization_range & 0x3) << 6) |
106 ((frame->content_type & 0x3) << 4) |
107 (frame->pixel_repeat & 0xf);
108
109 ptr[5] = frame->top_bar & 0xff;
110 ptr[6] = (frame->top_bar >> 8) & 0xff;
111 ptr[7] = frame->bottom_bar & 0xff;
112 ptr[8] = (frame->bottom_bar >> 8) & 0xff;
113 ptr[9] = frame->left_bar & 0xff;
114 ptr[10] = (frame->left_bar >> 8) & 0xff;
115 ptr[11] = frame->right_bar & 0xff;
116 ptr[12] = (frame->right_bar >> 8) & 0xff;
117
118 hdmi_infoframe_checksum(buffer, length);
119
120 return length;
121}
122EXPORT_SYMBOL(hdmi_avi_infoframe_pack);
123
124/**
125 * hdmi_spd_infoframe_init() - initialize an HDMI SPD infoframe
126 * @frame: HDMI SPD infoframe
127 * @vendor: vendor string
128 * @product: product string
129 *
130 * Returns 0 on success or a negative error code on failure.
131 */
132int hdmi_spd_infoframe_init(struct hdmi_spd_infoframe *frame,
133 const char *vendor, const char *product)
134{
135 memset(frame, 0, sizeof(*frame));
136
137 frame->type = HDMI_INFOFRAME_TYPE_SPD;
138 frame->version = 1;
139 frame->length = 25;
140
141 strncpy(frame->vendor, vendor, sizeof(frame->vendor));
142 strncpy(frame->product, product, sizeof(frame->product));
143
144 return 0;
145}
146EXPORT_SYMBOL(hdmi_spd_infoframe_init);
147
148/**
149 * hdmi_spd_infoframe_pack() - write HDMI SPD infoframe to binary buffer
150 * @frame: HDMI SPD infoframe
151 * @buffer: destination buffer
152 * @size: size of buffer
153 *
154 * Packs the information contained in the @frame structure into a binary
155 * representation that can be written into the corresponding controller
156 * registers. Also computes the checksum as required by section 5.3.5 of
157 * the HDMI 1.4 specification.
158 *
159 * Returns the number of bytes packed into the binary buffer or a negative
160 * error code on failure.
161 */
162ssize_t hdmi_spd_infoframe_pack(struct hdmi_spd_infoframe *frame, void *buffer,
163 size_t size)
164{
165 u8 *ptr = buffer;
166 size_t length;
167
168 length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;
169
170 if (size < length)
171 return -ENOSPC;
172
173 memset(buffer, 0, length);
174
175 ptr[0] = frame->type;
176 ptr[1] = frame->version;
177 ptr[2] = frame->length;
178 ptr[3] = 0; /* checksum */
179
180 /* start infoframe payload */
181 ptr += HDMI_INFOFRAME_HEADER_SIZE;
182
183 memcpy(ptr, frame->vendor, sizeof(frame->vendor));
184 memcpy(ptr + 8, frame->product, sizeof(frame->product));
185
186 ptr[24] = frame->sdi;
187
188 hdmi_infoframe_checksum(buffer, length);
189
190 return length;
191}
192EXPORT_SYMBOL(hdmi_spd_infoframe_pack);
193
194/**
195 * hdmi_audio_infoframe_init() - initialize an HDMI audio infoframe
196 * @frame: HDMI audio infoframe
197 *
198 * Returns 0 on success or a negative error code on failure.
199 */
200int hdmi_audio_infoframe_init(struct hdmi_audio_infoframe *frame)
201{
202 memset(frame, 0, sizeof(*frame));
203
204 frame->type = HDMI_INFOFRAME_TYPE_AUDIO;
205 frame->version = 1;
206 frame->length = 10;
207
208 return 0;
209}
210EXPORT_SYMBOL(hdmi_audio_infoframe_init);
211
212/**
213 * hdmi_audio_infoframe_pack() - write HDMI audio infoframe to binary buffer
214 * @frame: HDMI audio infoframe
215 * @buffer: destination buffer
216 * @size: size of buffer
217 *
218 * Packs the information contained in the @frame structure into a binary
219 * representation that can be written into the corresponding controller
220 * registers. Also computes the checksum as required by section 5.3.5 of
221 * the HDMI 1.4 specification.
222 *
223 * Returns the number of bytes packed into the binary buffer or a negative
224 * error code on failure.
225 */
226ssize_t hdmi_audio_infoframe_pack(struct hdmi_audio_infoframe *frame,
227 void *buffer, size_t size)
228{
229 unsigned char channels;
230 u8 *ptr = buffer;
231 size_t length;
232
233 length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;
234
235 if (size < length)
236 return -ENOSPC;
237
238 memset(buffer, 0, length);
239
240 if (frame->channels >= 2)
241 channels = frame->channels - 1;
242 else
243 channels = 0;
244
245 ptr[0] = frame->type;
246 ptr[1] = frame->version;
247 ptr[2] = frame->length;
248 ptr[3] = 0; /* checksum */
249
250 /* start infoframe payload */
251 ptr += HDMI_INFOFRAME_HEADER_SIZE;
252
253 ptr[0] = ((frame->coding_type & 0xf) << 4) | (channels & 0x7);
254 ptr[1] = ((frame->sample_frequency & 0x7) << 2) |
255 (frame->sample_size & 0x3);
256 ptr[2] = frame->coding_type_ext & 0x1f;
257 ptr[3] = frame->channel_allocation;
258 ptr[4] = (frame->level_shift_value & 0xf) << 3;
259
260 if (frame->downmix_inhibit)
261 ptr[4] |= BIT(7);
262
263 hdmi_infoframe_checksum(buffer, length);
264
265 return length;
266}
267EXPORT_SYMBOL(hdmi_audio_infoframe_pack);
268
269/**
270 * hdmi_vendor_infoframe_pack() - write a HDMI vendor infoframe to binary
271 * buffer
272 * @frame: HDMI vendor infoframe
273 * @buffer: destination buffer
274 * @size: size of buffer
275 *
276 * Packs the information contained in the @frame structure into a binary
277 * representation that can be written into the corresponding controller
278 * registers. Also computes the checksum as required by section 5.3.5 of
279 * the HDMI 1.4 specification.
280 *
281 * Returns the number of bytes packed into the binary buffer or a negative
282 * error code on failure.
283 */
284ssize_t hdmi_vendor_infoframe_pack(struct hdmi_vendor_infoframe *frame,
285 void *buffer, size_t size)
286{
287 u8 *ptr = buffer;
288 size_t length;
289
290 length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;
291
292 if (size < length)
293 return -ENOSPC;
294
295 memset(buffer, 0, length);
296
297 ptr[0] = frame->type;
298 ptr[1] = frame->version;
299 ptr[2] = frame->length;
300 ptr[3] = 0; /* checksum */
301
302 memcpy(&ptr[HDMI_INFOFRAME_HEADER_SIZE], frame->data, frame->length);
303
304 hdmi_infoframe_checksum(buffer, length);
305
306 return length;
307}
308EXPORT_SYMBOL(hdmi_vendor_infoframe_pack);
diff --git a/include/linux/hdmi.h b/include/linux/hdmi.h
new file mode 100644
index 000000000000..3b589440ecfe
--- /dev/null
+++ b/include/linux/hdmi.h
@@ -0,0 +1,231 @@
1/*
2 * Copyright (C) 2012 Avionic Design GmbH
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#ifndef __LINUX_HDMI_H_
10#define __LINUX_HDMI_H_
11
12#include <linux/types.h>
13
14enum hdmi_infoframe_type {
15 HDMI_INFOFRAME_TYPE_VENDOR = 0x81,
16 HDMI_INFOFRAME_TYPE_AVI = 0x82,
17 HDMI_INFOFRAME_TYPE_SPD = 0x83,
18 HDMI_INFOFRAME_TYPE_AUDIO = 0x84,
19};
20
21#define HDMI_INFOFRAME_HEADER_SIZE 4
22#define HDMI_AVI_INFOFRAME_SIZE 13
23#define HDMI_SPD_INFOFRAME_SIZE 25
24#define HDMI_AUDIO_INFOFRAME_SIZE 10
25
26enum hdmi_colorspace {
27 HDMI_COLORSPACE_RGB,
28 HDMI_COLORSPACE_YUV422,
29 HDMI_COLORSPACE_YUV444,
30};
31
32enum hdmi_scan_mode {
33 HDMI_SCAN_MODE_NONE,
34 HDMI_SCAN_MODE_OVERSCAN,
35 HDMI_SCAN_MODE_UNDERSCAN,
36};
37
38enum hdmi_colorimetry {
39 HDMI_COLORIMETRY_NONE,
40 HDMI_COLORIMETRY_ITU_601,
41 HDMI_COLORIMETRY_ITU_709,
42 HDMI_COLORIMETRY_EXTENDED,
43};
44
45enum hdmi_picture_aspect {
46 HDMI_PICTURE_ASPECT_NONE,
47 HDMI_PICTURE_ASPECT_4_3,
48 HDMI_PICTURE_ASPECT_16_9,
49};
50
51enum hdmi_active_aspect {
52 HDMI_ACTIVE_ASPECT_16_9_TOP = 2,
53 HDMI_ACTIVE_ASPECT_14_9_TOP = 3,
54 HDMI_ACTIVE_ASPECT_16_9_CENTER = 4,
55 HDMI_ACTIVE_ASPECT_PICTURE = 8,
56 HDMI_ACTIVE_ASPECT_4_3 = 9,
57 HDMI_ACTIVE_ASPECT_16_9 = 10,
58 HDMI_ACTIVE_ASPECT_14_9 = 11,
59 HDMI_ACTIVE_ASPECT_4_3_SP_14_9 = 13,
60 HDMI_ACTIVE_ASPECT_16_9_SP_14_9 = 14,
61 HDMI_ACTIVE_ASPECT_16_9_SP_4_3 = 15,
62};
63
64enum hdmi_extended_colorimetry {
65 HDMI_EXTENDED_COLORIMETRY_XV_YCC_601,
66 HDMI_EXTENDED_COLORIMETRY_XV_YCC_709,
67 HDMI_EXTENDED_COLORIMETRY_S_YCC_601,
68 HDMI_EXTENDED_COLORIMETRY_ADOBE_YCC_601,
69 HDMI_EXTENDED_COLORIMETRY_ADOBE_RGB,
70};
71
72enum hdmi_quantization_range {
73 HDMI_QUANTIZATION_RANGE_DEFAULT,
74 HDMI_QUANTIZATION_RANGE_LIMITED,
75 HDMI_QUANTIZATION_RANGE_FULL,
76};
77
78/* non-uniform picture scaling */
79enum hdmi_nups {
80 HDMI_NUPS_UNKNOWN,
81 HDMI_NUPS_HORIZONTAL,
82 HDMI_NUPS_VERTICAL,
83 HDMI_NUPS_BOTH,
84};
85
86enum hdmi_ycc_quantization_range {
87 HDMI_YCC_QUANTIZATION_RANGE_LIMITED,
88 HDMI_YCC_QUANTIZATION_RANGE_FULL,
89};
90
91enum hdmi_content_type {
92 HDMI_CONTENT_TYPE_NONE,
93 HDMI_CONTENT_TYPE_PHOTO,
94 HDMI_CONTENT_TYPE_CINEMA,
95 HDMI_CONTENT_TYPE_GAME,
96};
97
98struct hdmi_avi_infoframe {
99 enum hdmi_infoframe_type type;
100 unsigned char version;
101 unsigned char length;
102 enum hdmi_colorspace colorspace;
103 bool active_info_valid;
104 bool horizontal_bar_valid;
105 bool vertical_bar_valid;
106 enum hdmi_scan_mode scan_mode;
107 enum hdmi_colorimetry colorimetry;
108 enum hdmi_picture_aspect picture_aspect;
109 enum hdmi_active_aspect active_aspect;
110 bool itc;
111 enum hdmi_extended_colorimetry extended_colorimetry;
112 enum hdmi_quantization_range quantization_range;
113 enum hdmi_nups nups;
114 unsigned char video_code;
115 enum hdmi_ycc_quantization_range ycc_quantization_range;
116 enum hdmi_content_type content_type;
117 unsigned char pixel_repeat;
118 unsigned short top_bar;
119 unsigned short bottom_bar;
120 unsigned short left_bar;
121 unsigned short right_bar;
122};
123
124int hdmi_avi_infoframe_init(struct hdmi_avi_infoframe *frame);
125ssize_t hdmi_avi_infoframe_pack(struct hdmi_avi_infoframe *frame, void *buffer,
126 size_t size);
127
128enum hdmi_spd_sdi {
129 HDMI_SPD_SDI_UNKNOWN,
130 HDMI_SPD_SDI_DSTB,
131 HDMI_SPD_SDI_DVDP,
132 HDMI_SPD_SDI_DVHS,
133 HDMI_SPD_SDI_HDDVR,
134 HDMI_SPD_SDI_DVC,
135 HDMI_SPD_SDI_DSC,
136 HDMI_SPD_SDI_VCD,
137 HDMI_SPD_SDI_GAME,
138 HDMI_SPD_SDI_PC,
139 HDMI_SPD_SDI_BD,
140 HDMI_SPD_SDI_SACD,
141 HDMI_SPD_SDI_HDDVD,
142 HDMI_SPD_SDI_PMP,
143};
144
145struct hdmi_spd_infoframe {
146 enum hdmi_infoframe_type type;
147 unsigned char version;
148 unsigned char length;
149 char vendor[8];
150 char product[16];
151 enum hdmi_spd_sdi sdi;
152};
153
154int hdmi_spd_infoframe_init(struct hdmi_spd_infoframe *frame,
155 const char *vendor, const char *product);
156ssize_t hdmi_spd_infoframe_pack(struct hdmi_spd_infoframe *frame, void *buffer,
157 size_t size);
158
159enum hdmi_audio_coding_type {
160 HDMI_AUDIO_CODING_TYPE_STREAM,
161 HDMI_AUDIO_CODING_TYPE_PCM,
162 HDMI_AUDIO_CODING_TYPE_AC3,
163 HDMI_AUDIO_CODING_TYPE_MPEG1,
164 HDMI_AUDIO_CODING_TYPE_MP3,
165 HDMI_AUDIO_CODING_TYPE_MPEG2,
166 HDMI_AUDIO_CODING_TYPE_AAC_LC,
167 HDMI_AUDIO_CODING_TYPE_DTS,
168 HDMI_AUDIO_CODING_TYPE_ATRAC,
169 HDMI_AUDIO_CODING_TYPE_DSD,
170 HDMI_AUDIO_CODING_TYPE_EAC3,
171 HDMI_AUDIO_CODING_TYPE_DTS_HD,
172 HDMI_AUDIO_CODING_TYPE_MLP,
173 HDMI_AUDIO_CODING_TYPE_DST,
174 HDMI_AUDIO_CODING_TYPE_WMA_PRO,
175};
176
177enum hdmi_audio_sample_size {
178 HDMI_AUDIO_SAMPLE_SIZE_STREAM,
179 HDMI_AUDIO_SAMPLE_SIZE_16,
180 HDMI_AUDIO_SAMPLE_SIZE_20,
181 HDMI_AUDIO_SAMPLE_SIZE_24,
182};
183
184enum hdmi_audio_sample_frequency {
185 HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM,
186 HDMI_AUDIO_SAMPLE_FREQUENCY_32000,
187 HDMI_AUDIO_SAMPLE_FREQUENCY_44100,
188 HDMI_AUDIO_SAMPLE_FREQUENCY_48000,
189 HDMI_AUDIO_SAMPLE_FREQUENCY_88200,
190 HDMI_AUDIO_SAMPLE_FREQUENCY_96000,
191 HDMI_AUDIO_SAMPLE_FREQUENCY_176400,
192 HDMI_AUDIO_SAMPLE_FREQUENCY_192000,
193};
194
195enum hdmi_audio_coding_type_ext {
196 HDMI_AUDIO_CODING_TYPE_EXT_STREAM,
197 HDMI_AUDIO_CODING_TYPE_EXT_HE_AAC,
198 HDMI_AUDIO_CODING_TYPE_EXT_HE_AAC_V2,
199 HDMI_AUDIO_CODING_TYPE_EXT_MPEG_SURROUND,
200};
201
202struct hdmi_audio_infoframe {
203 enum hdmi_infoframe_type type;
204 unsigned char version;
205 unsigned char length;
206 unsigned char channels;
207 enum hdmi_audio_coding_type coding_type;
208 enum hdmi_audio_sample_size sample_size;
209 enum hdmi_audio_sample_frequency sample_frequency;
210 enum hdmi_audio_coding_type_ext coding_type_ext;
211 unsigned char channel_allocation;
212 unsigned char level_shift_value;
213 bool downmix_inhibit;
214
215};
216
217int hdmi_audio_infoframe_init(struct hdmi_audio_infoframe *frame);
218ssize_t hdmi_audio_infoframe_pack(struct hdmi_audio_infoframe *frame,
219 void *buffer, size_t size);
220
221struct hdmi_vendor_infoframe {
222 enum hdmi_infoframe_type type;
223 unsigned char version;
224 unsigned char length;
225 u8 data[27];
226};
227
228ssize_t hdmi_vendor_infoframe_pack(struct hdmi_vendor_infoframe *frame,
229 void *buffer, size_t size);
230
231#endif /* _DRM_HDMI_H */