xref: /netbsd-src/sys/external/bsd/drm2/include/linux/hdmi.h (revision 946379e7b37692fc43f68eb0d1c10daa0a7f3b6c)
1 /*	$NetBSD: hdmi.h,v 1.6 2015/11/14 18:04:05 jmcneill Exp $	*/
2 
3 /*-
4  * Copyright (c) 2014 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Taylor R. Campbell.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #ifndef	_LINUX_HDMI_H_
33 #define	_LINUX_HDMI_H_
34 
35 #include <sys/types.h>
36 #include <sys/param.h>
37 #include <sys/errno.h>
38 #include <sys/systm.h>
39 
40 enum hdmi_3d_structure {
41         HDMI_3D_STRUCTURE_INVALID		= -1,
42         HDMI_3D_STRUCTURE_FRAME_PACKING		= 0,
43         HDMI_3D_STRUCTURE_FIELD_ALTERNATIVE	= 1,
44         HDMI_3D_STRUCTURE_LINE_ALTERNATIVE	= 2,
45         HDMI_3D_STRUCTURE_SIDE_BY_SIDE_FULL	= 3,
46         HDMI_3D_STRUCTURE_L_DEPTH		= 4,
47         HDMI_3D_STRUCTURE_L_DEPTH_GFX_GFX_DEPTH	= 5,
48         HDMI_3D_STRUCTURE_TOP_AND_BOTTOM	= 6,
49         HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF	= 8,
50 };
51 
52 enum hdmi_active_aspect {
53         HDMI_ACTIVE_ASPECT_16_9_TOP		= 2,
54         HDMI_ACTIVE_ASPECT_14_9_TOP		= 3,
55         HDMI_ACTIVE_ASPECT_16_9_CENTER		= 4,
56         HDMI_ACTIVE_ASPECT_PICTURE		= 8,
57         HDMI_ACTIVE_ASPECT_4_3			= 9,
58         HDMI_ACTIVE_ASPECT_16_9			= 10,
59         HDMI_ACTIVE_ASPECT_14_9			= 11,
60         HDMI_ACTIVE_ASPECT_4_3_SP_14_9		= 13,
61         HDMI_ACTIVE_ASPECT_16_9_SP_14_9		= 14,
62         HDMI_ACTIVE_ASPECT_16_9_SP_4_3		= 15,
63 };
64 
65 enum hdmi_audio_coding_type {
66 	HDMI_AUDIO_CODING_TYPE_STREAM		= 0,
67 	HDMI_AUDIO_CODING_TYPE_PCM		= 1,
68 	HDMI_AUDIO_CODING_TYPE_AC3		= 2,
69 	HDMI_AUDIO_CODING_TYPE_MPEG1		= 3,
70 	HDMI_AUDIO_CODING_TYPE_MP3		= 4,
71 	HDMI_AUDIO_CODING_TYPE_MPEG2		= 5,
72 	HDMI_AUDIO_CODING_TYPE_AAC_LC		= 6,
73 	HDMI_AUDIO_CODING_TYPE_DTS		= 7,
74 	HDMI_AUDIO_CODING_TYPE_ATRAC		= 8,
75 	HDMI_AUDIO_CODING_TYPE_DSD		= 9,
76 	HDMI_AUDIO_CODING_TYPE_EAC3		= 10,
77 	HDMI_AUDIO_CODING_TYPE_DTS_HD		= 11,
78 	HDMI_AUDIO_CODING_TYPE_MLP		= 12,
79 	HDMI_AUDIO_CODING_TYPE_DST		= 13,
80 	HDMI_AUDIO_CODING_TYPE_WMA_PRO		= 14,
81 };
82 
83 enum hdmi_audio_coding_type_ext {
84 	HDMI_AUDIO_CODING_TYPE_EXT_STREAM	= 0,
85 	HDMI_AUDIO_CODING_TYPE_EXT_HE_AAC	= 1,
86 	HDMI_AUDIO_CODING_TYPE_EXT_HE_AAC_V2	= 2,
87 	HDMI_AUDIO_CODING_TYPE_EXT_MPEG_SURROUND = 3,
88 };
89 
90 enum hdmi_audio_sample_frequency {
91 	HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM	= 0,
92 	HDMI_AUDIO_SAMPLE_FREQUENCY_32000	= 1,
93 	HDMI_AUDIO_SAMPLE_FREQUENCY_44100	= 2,
94 	HDMI_AUDIO_SAMPLE_FREQUENCY_48000	= 3,
95 	HDMI_AUDIO_SAMPLE_FREQUENCY_88200	= 4,
96 	HDMI_AUDIO_SAMPLE_FREQUENCY_96000	= 5,
97 	HDMI_AUDIO_SAMPLE_FREQUENCY_176400	= 6,
98 	HDMI_AUDIO_SAMPLE_FREQUENCY_192000	= 7,
99 };
100 
101 enum hdmi_audio_sample_size {
102 	HDMI_AUDIO_SAMPLE_SIZE_STREAM		= 0,
103 	HDMI_AUDIO_SAMPLE_SIZE_16		= 1,
104 	HDMI_AUDIO_SAMPLE_SIZE_20		= 2,
105 	HDMI_AUDIO_SAMPLE_SIZE_24		= 3,
106 };
107 
108 enum hdmi_colorimetry {
109 	HDMI_COLORIMETRY_NONE			= 0,
110 	HDMI_COLORIMETRY_ITU_601		= 1,
111 	HDMI_COLORIMETRY_ITU_709		= 2,
112 	HDMI_COLORIMETRY_EXTENDED		= 3,
113 };
114 
115 enum hdmi_colorspace {
116 	HDMI_COLORSPACE_RGB			= 0,
117 	HDMI_COLORSPACE_YUV422			= 1,
118 	HDMI_COLORSPACE_YUV444			= 2,
119 };
120 
121 enum hdmi_content_type {
122 	HDMI_CONTENT_TYPE_NONE			= 0,
123 	HDMI_CONTENT_TYPE_PHOTO			= 1,
124 	HDMI_CONTENT_TYPE_CINEMA		= 2,
125 	HDMI_CONTENT_TYPE_GAME			= 3,
126 };
127 
128 enum hdmi_extended_colorimetry {
129 	HDMI_EXTENDED_COLORIMETRY_XV_YCC_601	= 0,
130 	HDMI_EXTENDED_COLORIMETRY_XV_YCC_709	= 1,
131 	HDMI_EXTENDED_COLORIMETRY_S_YCC_601	= 2,
132 	HDMI_EXTENDED_COLORIMETRY_ADOBE_YCC_601	= 3,
133 	HDMI_EXTENDED_COLORIMETRY_ADOBE_RGB	= 4,
134 };
135 
136 enum hdmi_nups {
137 	HDMI_NUPS_UNKNOWN			= 0,
138 	HDMI_NUPS_HORIZONTAL			= 1,
139 	HDMI_NUPS_VERTICAL			= 2,
140 	HDMI_NUPS_BOTH				= 3,
141 };
142 
143 enum hdmi_picture_aspect {
144 	HDMI_PICTURE_ASPECT_NONE		= 0,
145 	HDMI_PICTURE_ASPECT_4_3			= 1,
146 	HDMI_PICTURE_ASPECT_16_9		= 2,
147 };
148 
149 enum hdmi_quantization_range {
150 	HDMI_QUANTIZATION_RANGE_DEFAULT		= 0,
151 	HDMI_QUANTIZATION_RANGE_LIMITED		= 1,
152 	HDMI_QUANTIZATION_RANGE_FULL		= 2,
153 };
154 
155 enum hdmi_scan_mode {
156 	HDMI_SCAN_MODE_NONE			= 0,
157 	HDMI_SCAN_MODE_OVERSCAN			= 1,
158 	HDMI_SCAN_MODE_UNDERSCAN		= 2,
159 };
160 
161 enum hdmi_ycc_quantization_range {
162 	HDMI_YCC_QUANTIZATION_RANGE_LIMITED	= 0,
163 	HDMI_YCC_QUANTIZATION_RANGE_FULL	= 1,
164 };
165 
166 enum hdmi_infoframe_type {
167 	HDMI_INFOFRAME_TYPE_VENDOR		= 0x81,
168 	HDMI_INFOFRAME_TYPE_AVI			= 0x82,
169 	HDMI_INFOFRAME_TYPE_SPD			= 0x83,
170 	HDMI_INFOFRAME_TYPE_AUDIO		= 0x84,
171 };
172 
173 #define	HDMI_INFOFRAME_SIZE(TYPE)					      \
174 	(HDMI_INFOFRAME_HEADER_SIZE + HDMI_##TYPE##_INFOFRAME_SIZE)
175 
176 #define	HDMI_INFOFRAME_HEADER_SIZE	4
177 struct hdmi_infoframe_header {
178 	enum hdmi_infoframe_type	type;
179 	uint8_t				version;
180 	uint8_t				length;
181 	/* checksum */
182 };
183 
184 static inline void
185 hdmi_infoframe_header_init(struct hdmi_infoframe_header *header,
186     enum hdmi_infoframe_type type, uint8_t vers, uint8_t length)
187 {
188 
189 	header->type = type;
190 	header->version = vers;
191 	header->length = length;
192 }
193 
194 static inline int
195 hdmi_infoframe_header_pack(const struct hdmi_infoframe_header *header,
196     uint8_t length, void *buf, size_t size)
197 {
198 	uint8_t *const p = buf;
199 
200 	if (length < HDMI_INFOFRAME_HEADER_SIZE)
201 		return -ENOSPC;
202 	if (size < length)
203 		return -ENOSPC;
204 
205 	p[0] = header->type;
206 	p[1] = header->version;
207 	p[2] = (length - HDMI_INFOFRAME_HEADER_SIZE);
208 	p[3] = 0;		/* checksum */
209 
210 	return HDMI_INFOFRAME_HEADER_SIZE;
211 }
212 
213 static inline void
214 hdmi_infoframe_checksum(void *buf, size_t length)
215 {
216 	uint8_t *p = buf;
217 	uint8_t checksum = 0;
218 
219 	while (length--)
220 		checksum += *p++;
221 
222 	p = buf;
223 	p[3] = (256 - checksum);
224 }
225 
226 #define	HDMI_AUDIO_INFOFRAME_SIZE	10
227 struct hdmi_audio_infoframe {
228 	struct hdmi_infoframe_header	header;
229 	uint8_t				channels;
230 	enum hdmi_audio_coding_type	coding_type;
231 	enum hdmi_audio_sample_size	sample_size;
232 	enum hdmi_audio_sample_frequency sample_frequency;
233 	enum hdmi_audio_coding_type_ext	coding_type_ext;
234 	uint8_t				channel_allocation;
235 	uint8_t				level_shift_value;
236 	bool				downmix_inhibit;
237 };
238 
239 static inline int
240 hdmi_audio_infoframe_init(struct hdmi_audio_infoframe *frame)
241 {
242 	static const struct hdmi_audio_infoframe zero_frame;
243 
244 	*frame = zero_frame;
245 
246 	hdmi_infoframe_header_init(&frame->header, HDMI_INFOFRAME_TYPE_AUDIO,
247 	    1, HDMI_AUDIO_INFOFRAME_SIZE);
248 
249 	return 0;
250 }
251 
252 static inline ssize_t
253 hdmi_audio_infoframe_pack(const struct hdmi_audio_infoframe *frame, void *buf,
254     size_t size)
255 {
256 	const size_t length = HDMI_INFOFRAME_HEADER_SIZE +
257 	    HDMI_AUDIO_INFOFRAME_SIZE;
258 	uint8_t channels = 0;
259 	uint8_t *p = buf;
260 	int ret;
261 
262 	KASSERT(frame->header.length == HDMI_AUDIO_INFOFRAME_SIZE);
263 
264 	ret = hdmi_infoframe_header_pack(&frame->header, length, p, size);
265 	if (ret < 0)
266 		return ret;
267 	KASSERT(ret == HDMI_INFOFRAME_HEADER_SIZE);
268 	p += HDMI_INFOFRAME_HEADER_SIZE;
269 	size -= HDMI_INFOFRAME_HEADER_SIZE;
270 
271 	if (frame->channels >= 2)
272 		channels = frame->channels - 1;
273 
274 	p[0] = __SHIFTIN(frame->coding_type, __BITS(7,4));
275 	p[0] |= __SHIFTIN(channels, __BITS(2,0));
276 
277 	p[1] = __SHIFTIN(frame->sample_frequency, __BITS(4,2));
278 	p[1] |= __SHIFTIN(frame->sample_size, __BITS(1,0));
279 
280 	p[2] = __SHIFTIN(frame->coding_type_ext, __BITS(5,0));
281 
282 	p[3] = __SHIFTIN(frame->level_shift_value, __BITS(6, 3));
283 
284 	p[4] = __SHIFTIN(frame->downmix_inhibit? 1 : 0, __BIT(7));
285 
286 	/* PB6 to PB10 are reserved */
287 	p[5] = 0;
288 	p[6] = 0;
289 	p[7] = 0;
290 	p[8] = 0;
291 	p[9] = 0;
292 
293 	CTASSERT(HDMI_AUDIO_INFOFRAME_SIZE == 10);
294 
295 	hdmi_infoframe_checksum(buf, length);
296 
297 	return length;
298 }
299 
300 #define	HDMI_AVI_INFOFRAME_SIZE		13
301 struct hdmi_avi_infoframe {
302 	struct hdmi_infoframe_header	header;
303 	enum hdmi_colorspace		colorspace;
304 	enum hdmi_scan_mode		scan_mode;
305 	enum hdmi_colorimetry		colorimetry;
306 	enum hdmi_picture_aspect	picture_aspect;
307 	enum hdmi_active_aspect		active_aspect;
308 	bool				itc;
309 	enum hdmi_extended_colorimetry	extended_colorimetry;
310 	enum hdmi_quantization_range	quantization_range;
311 	enum hdmi_nups			nups;
312 	uint8_t				video_code;
313 	enum hdmi_ycc_quantization_range ycc_quantization_range;
314 	enum hdmi_content_type		content_type;
315 	uint8_t				pixel_repeat;
316 	uint16_t			top_bar;
317 	uint16_t			bottom_bar;
318 	uint16_t			left_bar;
319 	uint16_t			right_bar;
320 };
321 
322 static inline int
323 hdmi_avi_infoframe_init(struct hdmi_avi_infoframe *frame)
324 {
325 	static const struct hdmi_avi_infoframe zero_frame;
326 
327 	*frame = zero_frame;
328 
329 	hdmi_infoframe_header_init(&frame->header, HDMI_INFOFRAME_TYPE_AVI, 2,
330 	    HDMI_AVI_INFOFRAME_SIZE);
331 
332 	return 0;
333 }
334 
335 static inline ssize_t
336 hdmi_avi_infoframe_pack(const struct hdmi_avi_infoframe *frame, void *buf,
337     size_t size)
338 {
339 	const size_t length = HDMI_INFOFRAME_HEADER_SIZE +
340 	    HDMI_AVI_INFOFRAME_SIZE;
341 	uint8_t *p = buf;
342 	int ret;
343 
344 	KASSERT(frame->header.length == HDMI_AVI_INFOFRAME_SIZE);
345 
346 	ret = hdmi_infoframe_header_pack(&frame->header, length, p, size);
347 	if (ret < 0)
348 		return ret;
349 	KASSERT(ret == HDMI_INFOFRAME_HEADER_SIZE);
350 	p += HDMI_INFOFRAME_HEADER_SIZE;
351 	size -= HDMI_INFOFRAME_HEADER_SIZE;
352 
353 	p[0] = __SHIFTIN(frame->colorspace, __BITS(6,5));
354 	p[0] |= __SHIFTIN(frame->active_aspect & 0xf? 1 : 0, __BIT(4));
355 	p[0] |= __SHIFTIN(frame->top_bar || frame->bottom_bar, __BIT(3));
356 	p[0] |= __SHIFTIN(frame->left_bar || frame->right_bar, __BIT(2));
357 	p[0] |= __SHIFTIN(frame->scan_mode, __BITS(1,0));
358 
359 	p[1] = __SHIFTIN(frame->colorimetry, __BITS(7,6));
360 	p[1] |= __SHIFTIN(frame->picture_aspect, __BITS(5,4));
361 	p[1] |= __SHIFTIN(frame->active_aspect, __BITS(3,0));
362 
363 	p[2] = __SHIFTIN(frame->itc? 1 : 0, __BIT(7));
364 	p[2] |= __SHIFTIN(frame->extended_colorimetry, __BITS(6,4));
365 	p[2] |= __SHIFTIN(frame->quantization_range, __BITS(3,2));
366 	p[2] |= __SHIFTIN(frame->nups, __BITS(1,0));
367 
368 	p[3] = frame->video_code;
369 
370 	p[4] = __SHIFTIN(frame->ycc_quantization_range, __BITS(7,6));
371 	p[4] |= __SHIFTIN(frame->content_type, __BITS(5,4));
372 	p[4] |= __SHIFTIN(frame->pixel_repeat, __BITS(3,0));
373 
374 	le16enc(&p[5], frame->top_bar);
375 	le16enc(&p[7], frame->bottom_bar);
376 	le16enc(&p[9], frame->left_bar);
377 	le16enc(&p[11], frame->right_bar);
378 	CTASSERT(HDMI_AVI_INFOFRAME_SIZE == 13);
379 
380 	hdmi_infoframe_checksum(buf, length);
381 
382 	return length;
383 }
384 
385 #define	HDMI_SPD_INFOFRAME_SIZE		25
386 struct hdmi_spd_infoframe {
387 	struct hdmi_infoframe_header	header;
388 	char				vendor[8];
389 	char				product[16];
390 	enum hdmi_spd_sdi {
391 	        HDMI_SPD_SDI_UNKNOWN	= 0,
392 		HDMI_SPD_SDI_DSTB	= 1,
393 		HDMI_SPD_SDI_DVDP	= 2,
394 		HDMI_SPD_SDI_DVHS	= 3,
395 		HDMI_SPD_SDI_HDDVR	= 4,
396 		HDMI_SPD_SDI_DVC	= 5,
397 		HDMI_SPD_SDI_DSC	= 6,
398 		HDMI_SPD_SDI_VCD	= 7,
399 		HDMI_SPD_SDI_GAME	= 8,
400 		HDMI_SPD_SDI_PC		= 9,
401 		HDMI_SPD_SDI_BD		= 10,
402 		HDMI_SPD_SDI_SACD	= 11,
403 		HDMI_SPD_SDI_HDDVD	= 12,
404 		HDMI_SPD_SDI_PMP	= 13,
405 	}				sdi;
406 };
407 
408 static inline int
409 hdmi_spd_infoframe_init(struct hdmi_spd_infoframe *frame, const char *vendor,
410     const char *product)
411 {
412 	static const struct hdmi_spd_infoframe zero_frame;
413 
414 	*frame = zero_frame;
415 
416 	hdmi_infoframe_header_init(&frame->header, HDMI_INFOFRAME_TYPE_SPD,
417 	    1, HDMI_SPD_INFOFRAME_SIZE);
418 
419 	(void)strlcpy(frame->vendor, vendor, sizeof(frame->vendor));
420 	(void)strlcpy(frame->product, product, sizeof(frame->product));
421 
422 	return 0;
423 }
424 
425 static inline ssize_t
426 hdmi_spd_infoframe_pack(struct hdmi_spd_infoframe *frame, void *buf,
427     size_t size)
428 {
429 	const size_t length = HDMI_INFOFRAME_HEADER_SIZE +
430 	    HDMI_SPD_INFOFRAME_SIZE;
431 	uint8_t *p = buf;
432 	int ret;
433 
434 	KASSERT(frame->header.length == HDMI_SPD_INFOFRAME_SIZE);
435 
436 	ret = hdmi_infoframe_header_pack(&frame->header, length, p, size);
437 	if (ret < 0)
438 		return ret;
439 	KASSERT(ret == HDMI_INFOFRAME_HEADER_SIZE);
440 	p += HDMI_INFOFRAME_HEADER_SIZE;
441 	size -= HDMI_INFOFRAME_HEADER_SIZE;
442 
443 	(void)memcpy(&p[0], frame->vendor, 8);
444 	(void)memcpy(&p[8], frame->product, 16);
445 	p[24] = frame->sdi;
446 
447 	hdmi_infoframe_checksum(buf, length);
448 
449 	return length;
450 }
451 
452 #define	HDMI_IEEE_OUI	0x000c03
453 
454 struct hdmi_vendor_infoframe {
455 	struct hdmi_infoframe_header	header;
456 	uint32_t			oui;
457 	uint8_t				vic;
458 	enum hdmi_3d_structure		s3d_struct;
459 	unsigned			s3d_ext_data;
460 };
461 
462 union hdmi_vendor_any_infoframe {
463 	struct {
464 		struct hdmi_infoframe_header	header;
465 		uint32_t			oui;
466 	}				any;
467 	struct hdmi_vendor_infoframe	hdmi;
468 };
469 
470 static inline int
471 hdmi_vendor_infoframe_init(struct hdmi_vendor_infoframe *frame)
472 {
473 	static const struct hdmi_vendor_infoframe zero_frame;
474 
475 	*frame = zero_frame;
476 
477 	hdmi_infoframe_header_init(&frame->header, HDMI_INFOFRAME_TYPE_VENDOR,
478 	    1, 0 /* depends on s3d_struct */);
479 
480 	frame->oui = HDMI_IEEE_OUI;
481 	frame->s3d_struct = HDMI_3D_STRUCTURE_INVALID;
482 
483 	return 0;
484 }
485 
486 static inline int
487 hdmi_vendor_infoframe_pack(const struct hdmi_vendor_infoframe *frame,
488     void *buf, size_t size)
489 {
490 	uint8_t *p = buf;
491 	size_t length;
492 	int ret;
493 
494 	/* Exactly one must be supplied.  */
495 	if ((frame->vic == 0) ==
496 	    (frame->s3d_struct == HDMI_3D_STRUCTURE_INVALID))
497 		return -EINVAL;
498 
499 	length = HDMI_INFOFRAME_HEADER_SIZE + 6;
500 	if (frame->s3d_struct >= HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF)
501 		length += 1;
502 
503 	ret = hdmi_infoframe_header_pack(&frame->header, length, p, size);
504 	if (ret < 0)
505 		return ret;
506 	KASSERT(ret == HDMI_INFOFRAME_HEADER_SIZE);
507 	p += HDMI_INFOFRAME_HEADER_SIZE;
508 	size -= HDMI_INFOFRAME_HEADER_SIZE;
509 
510 	p[0] = 0x03;
511 	p[1] = 0x0c;
512 	p[2] = 0x00;
513 
514 	if (frame->vic == 0) {
515 		p[3] = __SHIFTIN(0x2, __BITS(6,5));
516 		p[4] = __SHIFTIN(frame->s3d_struct, __BITS(7,4));
517 		if (frame->s3d_struct >= HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF)
518 			p[9] = __SHIFTIN(frame->s3d_ext_data, __BITS(7,4));
519 	} else {
520 		p[3] = __SHIFTIN(0x1, __BITS(6,5));
521 		p[4] = frame->vic;
522 	}
523 
524 	hdmi_infoframe_checksum(buf, length);
525 
526 	return length;
527 }
528 
529 union hdmi_infoframe {
530 	struct hdmi_infoframe_header	any;
531 	struct hdmi_avi_infoframe	avi;
532 	struct hdmi_spd_infoframe	spd;
533 	union hdmi_vendor_any_infoframe	vendor;
534 };
535 
536 static inline ssize_t
537 hdmi_infoframe_pack(union hdmi_infoframe *frame, void *buf, size_t size)
538 {
539 
540 	switch (frame->any.type) {
541 	case HDMI_INFOFRAME_TYPE_AVI:
542 		return hdmi_avi_infoframe_pack(&frame->avi, buf, size);
543 	case HDMI_INFOFRAME_TYPE_SPD:
544 		return hdmi_spd_infoframe_pack(&frame->spd, buf, size);
545 	case HDMI_INFOFRAME_TYPE_VENDOR:
546 		return hdmi_vendor_infoframe_pack(&frame->vendor.hdmi, buf,
547 		    size);
548 	default:
549 		return -EINVAL;
550 	}
551 }
552 
553 #endif	/* _LINUX_HDMI_H_ */
554