xref: /freebsd/sys/compat/linuxkpi/common/src/linux_hdmi.c (revision c89d94ad5d95fd15e891b2723caae8a6104ee153)
1f1d7ae31SEmmanuel Vadot /*
2f1d7ae31SEmmanuel Vadot  * Copyright (C) 2012 Avionic Design GmbH
3f1d7ae31SEmmanuel Vadot  *
4f1d7ae31SEmmanuel Vadot  * Permission is hereby granted, free of charge, to any person obtaining a
5f1d7ae31SEmmanuel Vadot  * copy of this software and associated documentation files (the "Software"),
6f1d7ae31SEmmanuel Vadot  * to deal in the Software without restriction, including without limitation
7f1d7ae31SEmmanuel Vadot  * the rights to use, copy, modify, merge, publish, distribute, sub license,
8f1d7ae31SEmmanuel Vadot  * and/or sell copies of the Software, and to permit persons to whom the
9f1d7ae31SEmmanuel Vadot  * Software is furnished to do so, subject to the following conditions:
10f1d7ae31SEmmanuel Vadot  *
11f1d7ae31SEmmanuel Vadot  * The above copyright notice and this permission notice (including the
12f1d7ae31SEmmanuel Vadot  * next paragraph) shall be included in all copies or substantial portions
13f1d7ae31SEmmanuel Vadot  * of the Software.
14f1d7ae31SEmmanuel Vadot  *
15f1d7ae31SEmmanuel Vadot  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16f1d7ae31SEmmanuel Vadot  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17f1d7ae31SEmmanuel Vadot  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18f1d7ae31SEmmanuel Vadot  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19f1d7ae31SEmmanuel Vadot  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20f1d7ae31SEmmanuel Vadot  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21f1d7ae31SEmmanuel Vadot  * DEALINGS IN THE SOFTWARE.
22f1d7ae31SEmmanuel Vadot  */
23f1d7ae31SEmmanuel Vadot 
24*c89d94adSVladimir Kondratyev #ifdef __linux__
25*c89d94adSVladimir Kondratyev #include <drm/display/drm_dp.h>
26*c89d94adSVladimir Kondratyev #endif
27f1d7ae31SEmmanuel Vadot #include <linux/bitops.h>
28f1d7ae31SEmmanuel Vadot #include <linux/bug.h>
29f1d7ae31SEmmanuel Vadot #include <linux/errno.h>
30f1d7ae31SEmmanuel Vadot #include <linux/export.h>
31f1d7ae31SEmmanuel Vadot #include <linux/hdmi.h>
32f1d7ae31SEmmanuel Vadot #include <linux/string.h>
33f1d7ae31SEmmanuel Vadot #include <linux/device.h>
34f1d7ae31SEmmanuel Vadot 
35f1d7ae31SEmmanuel Vadot #define hdmi_log(fmt, ...) dev_printk(level, dev, fmt, ##__VA_ARGS__)
36f1d7ae31SEmmanuel Vadot 
hdmi_infoframe_checksum(const u8 * ptr,size_t size)37f1d7ae31SEmmanuel Vadot static u8 hdmi_infoframe_checksum(const u8 *ptr, size_t size)
38f1d7ae31SEmmanuel Vadot {
39f1d7ae31SEmmanuel Vadot 	u8 csum = 0;
40f1d7ae31SEmmanuel Vadot 	size_t i;
41f1d7ae31SEmmanuel Vadot 
42f1d7ae31SEmmanuel Vadot 	/* compute checksum */
43f1d7ae31SEmmanuel Vadot 	for (i = 0; i < size; i++)
44f1d7ae31SEmmanuel Vadot 		csum += ptr[i];
45f1d7ae31SEmmanuel Vadot 
46f1d7ae31SEmmanuel Vadot 	return 256 - csum;
47f1d7ae31SEmmanuel Vadot }
48f1d7ae31SEmmanuel Vadot 
hdmi_infoframe_set_checksum(void * buffer,size_t size)49f1d7ae31SEmmanuel Vadot static void hdmi_infoframe_set_checksum(void *buffer, size_t size)
50f1d7ae31SEmmanuel Vadot {
51f1d7ae31SEmmanuel Vadot 	u8 *ptr = buffer;
52f1d7ae31SEmmanuel Vadot 
53f1d7ae31SEmmanuel Vadot 	ptr[3] = hdmi_infoframe_checksum(buffer, size);
54f1d7ae31SEmmanuel Vadot }
55f1d7ae31SEmmanuel Vadot 
56f1d7ae31SEmmanuel Vadot /**
57f1d7ae31SEmmanuel Vadot  * hdmi_avi_infoframe_init() - initialize an HDMI AVI infoframe
58f1d7ae31SEmmanuel Vadot  * @frame: HDMI AVI infoframe
59f1d7ae31SEmmanuel Vadot  */
hdmi_avi_infoframe_init(struct hdmi_avi_infoframe * frame)60f1d7ae31SEmmanuel Vadot void hdmi_avi_infoframe_init(struct hdmi_avi_infoframe *frame)
61f1d7ae31SEmmanuel Vadot {
62f1d7ae31SEmmanuel Vadot 	memset(frame, 0, sizeof(*frame));
63f1d7ae31SEmmanuel Vadot 
64f1d7ae31SEmmanuel Vadot 	frame->type = HDMI_INFOFRAME_TYPE_AVI;
65f1d7ae31SEmmanuel Vadot 	frame->version = 2;
66f1d7ae31SEmmanuel Vadot 	frame->length = HDMI_AVI_INFOFRAME_SIZE;
67f1d7ae31SEmmanuel Vadot }
68f1d7ae31SEmmanuel Vadot EXPORT_SYMBOL(hdmi_avi_infoframe_init);
69f1d7ae31SEmmanuel Vadot 
hdmi_avi_infoframe_check_only(const struct hdmi_avi_infoframe * frame)70f1d7ae31SEmmanuel Vadot static int hdmi_avi_infoframe_check_only(const struct hdmi_avi_infoframe *frame)
71f1d7ae31SEmmanuel Vadot {
72f1d7ae31SEmmanuel Vadot 	if (frame->type != HDMI_INFOFRAME_TYPE_AVI ||
73f1d7ae31SEmmanuel Vadot 	    frame->version != 2 ||
74f1d7ae31SEmmanuel Vadot 	    frame->length != HDMI_AVI_INFOFRAME_SIZE)
75f1d7ae31SEmmanuel Vadot 		return -EINVAL;
76f1d7ae31SEmmanuel Vadot 
77f1d7ae31SEmmanuel Vadot 	if (frame->picture_aspect > HDMI_PICTURE_ASPECT_16_9)
78f1d7ae31SEmmanuel Vadot 		return -EINVAL;
79f1d7ae31SEmmanuel Vadot 
80f1d7ae31SEmmanuel Vadot 	return 0;
81f1d7ae31SEmmanuel Vadot }
82f1d7ae31SEmmanuel Vadot 
83f1d7ae31SEmmanuel Vadot /**
84f1d7ae31SEmmanuel Vadot  * hdmi_avi_infoframe_check() - check a HDMI AVI infoframe
85f1d7ae31SEmmanuel Vadot  * @frame: HDMI AVI infoframe
86f1d7ae31SEmmanuel Vadot  *
87f1d7ae31SEmmanuel Vadot  * Validates that the infoframe is consistent and updates derived fields
88f1d7ae31SEmmanuel Vadot  * (eg. length) based on other fields.
89f1d7ae31SEmmanuel Vadot  *
90f1d7ae31SEmmanuel Vadot  * Returns 0 on success or a negative error code on failure.
91f1d7ae31SEmmanuel Vadot  */
hdmi_avi_infoframe_check(struct hdmi_avi_infoframe * frame)92f1d7ae31SEmmanuel Vadot int hdmi_avi_infoframe_check(struct hdmi_avi_infoframe *frame)
93f1d7ae31SEmmanuel Vadot {
94f1d7ae31SEmmanuel Vadot 	return hdmi_avi_infoframe_check_only(frame);
95f1d7ae31SEmmanuel Vadot }
96f1d7ae31SEmmanuel Vadot EXPORT_SYMBOL(hdmi_avi_infoframe_check);
97f1d7ae31SEmmanuel Vadot 
98f1d7ae31SEmmanuel Vadot /**
99f1d7ae31SEmmanuel Vadot  * hdmi_avi_infoframe_pack_only() - write HDMI AVI infoframe to binary buffer
100f1d7ae31SEmmanuel Vadot  * @frame: HDMI AVI infoframe
101f1d7ae31SEmmanuel Vadot  * @buffer: destination buffer
102f1d7ae31SEmmanuel Vadot  * @size: size of buffer
103f1d7ae31SEmmanuel Vadot  *
104f1d7ae31SEmmanuel Vadot  * Packs the information contained in the @frame structure into a binary
105f1d7ae31SEmmanuel Vadot  * representation that can be written into the corresponding controller
106f1d7ae31SEmmanuel Vadot  * registers. Also computes the checksum as required by section 5.3.5 of
107f1d7ae31SEmmanuel Vadot  * the HDMI 1.4 specification.
108f1d7ae31SEmmanuel Vadot  *
109f1d7ae31SEmmanuel Vadot  * Returns the number of bytes packed into the binary buffer or a negative
110f1d7ae31SEmmanuel Vadot  * error code on failure.
111f1d7ae31SEmmanuel Vadot  */
hdmi_avi_infoframe_pack_only(const struct hdmi_avi_infoframe * frame,void * buffer,size_t size)112f1d7ae31SEmmanuel Vadot ssize_t hdmi_avi_infoframe_pack_only(const struct hdmi_avi_infoframe *frame,
113f1d7ae31SEmmanuel Vadot 				     void *buffer, size_t size)
114f1d7ae31SEmmanuel Vadot {
115f1d7ae31SEmmanuel Vadot 	u8 *ptr = buffer;
116f1d7ae31SEmmanuel Vadot 	size_t length;
117f1d7ae31SEmmanuel Vadot 	int ret;
118f1d7ae31SEmmanuel Vadot 
119f1d7ae31SEmmanuel Vadot 	ret = hdmi_avi_infoframe_check_only(frame);
120f1d7ae31SEmmanuel Vadot 	if (ret)
121f1d7ae31SEmmanuel Vadot 		return ret;
122f1d7ae31SEmmanuel Vadot 
123f1d7ae31SEmmanuel Vadot 	length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;
124f1d7ae31SEmmanuel Vadot 
125f1d7ae31SEmmanuel Vadot 	if (size < length)
126f1d7ae31SEmmanuel Vadot 		return -ENOSPC;
127f1d7ae31SEmmanuel Vadot 
128f1d7ae31SEmmanuel Vadot 	memset(buffer, 0, size);
129f1d7ae31SEmmanuel Vadot 
130f1d7ae31SEmmanuel Vadot 	ptr[0] = frame->type;
131f1d7ae31SEmmanuel Vadot 	ptr[1] = frame->version;
132f1d7ae31SEmmanuel Vadot 	ptr[2] = frame->length;
133f1d7ae31SEmmanuel Vadot 	ptr[3] = 0; /* checksum */
134f1d7ae31SEmmanuel Vadot 
135f1d7ae31SEmmanuel Vadot 	/* start infoframe payload */
136f1d7ae31SEmmanuel Vadot 	ptr += HDMI_INFOFRAME_HEADER_SIZE;
137f1d7ae31SEmmanuel Vadot 
138f1d7ae31SEmmanuel Vadot 	ptr[0] = ((frame->colorspace & 0x3) << 5) | (frame->scan_mode & 0x3);
139f1d7ae31SEmmanuel Vadot 
140f1d7ae31SEmmanuel Vadot 	/*
141f1d7ae31SEmmanuel Vadot 	 * Data byte 1, bit 4 has to be set if we provide the active format
142f1d7ae31SEmmanuel Vadot 	 * aspect ratio
143f1d7ae31SEmmanuel Vadot 	 */
144f1d7ae31SEmmanuel Vadot 	if (frame->active_aspect & 0xf)
145f1d7ae31SEmmanuel Vadot 		ptr[0] |= BIT(4);
146f1d7ae31SEmmanuel Vadot 
147f1d7ae31SEmmanuel Vadot 	/* Bit 3 and 2 indicate if we transmit horizontal/vertical bar data */
148f1d7ae31SEmmanuel Vadot 	if (frame->top_bar || frame->bottom_bar)
149f1d7ae31SEmmanuel Vadot 		ptr[0] |= BIT(3);
150f1d7ae31SEmmanuel Vadot 
151f1d7ae31SEmmanuel Vadot 	if (frame->left_bar || frame->right_bar)
152f1d7ae31SEmmanuel Vadot 		ptr[0] |= BIT(2);
153f1d7ae31SEmmanuel Vadot 
154f1d7ae31SEmmanuel Vadot 	ptr[1] = ((frame->colorimetry & 0x3) << 6) |
155f1d7ae31SEmmanuel Vadot 		 ((frame->picture_aspect & 0x3) << 4) |
156f1d7ae31SEmmanuel Vadot 		 (frame->active_aspect & 0xf);
157f1d7ae31SEmmanuel Vadot 
158f1d7ae31SEmmanuel Vadot 	ptr[2] = ((frame->extended_colorimetry & 0x7) << 4) |
159f1d7ae31SEmmanuel Vadot 		 ((frame->quantization_range & 0x3) << 2) |
160f1d7ae31SEmmanuel Vadot 		 (frame->nups & 0x3);
161f1d7ae31SEmmanuel Vadot 
162f1d7ae31SEmmanuel Vadot 	if (frame->itc)
163f1d7ae31SEmmanuel Vadot 		ptr[2] |= BIT(7);
164f1d7ae31SEmmanuel Vadot 
165f1d7ae31SEmmanuel Vadot 	ptr[3] = frame->video_code & 0x7f;
166f1d7ae31SEmmanuel Vadot 
167f1d7ae31SEmmanuel Vadot 	ptr[4] = ((frame->ycc_quantization_range & 0x3) << 6) |
168f1d7ae31SEmmanuel Vadot 		 ((frame->content_type & 0x3) << 4) |
169f1d7ae31SEmmanuel Vadot 		 (frame->pixel_repeat & 0xf);
170f1d7ae31SEmmanuel Vadot 
171f1d7ae31SEmmanuel Vadot 	ptr[5] = frame->top_bar & 0xff;
172f1d7ae31SEmmanuel Vadot 	ptr[6] = (frame->top_bar >> 8) & 0xff;
173f1d7ae31SEmmanuel Vadot 	ptr[7] = frame->bottom_bar & 0xff;
174f1d7ae31SEmmanuel Vadot 	ptr[8] = (frame->bottom_bar >> 8) & 0xff;
175f1d7ae31SEmmanuel Vadot 	ptr[9] = frame->left_bar & 0xff;
176f1d7ae31SEmmanuel Vadot 	ptr[10] = (frame->left_bar >> 8) & 0xff;
177f1d7ae31SEmmanuel Vadot 	ptr[11] = frame->right_bar & 0xff;
178f1d7ae31SEmmanuel Vadot 	ptr[12] = (frame->right_bar >> 8) & 0xff;
179f1d7ae31SEmmanuel Vadot 
180f1d7ae31SEmmanuel Vadot 	hdmi_infoframe_set_checksum(buffer, length);
181f1d7ae31SEmmanuel Vadot 
182f1d7ae31SEmmanuel Vadot 	return length;
183f1d7ae31SEmmanuel Vadot }
184f1d7ae31SEmmanuel Vadot EXPORT_SYMBOL(hdmi_avi_infoframe_pack_only);
185f1d7ae31SEmmanuel Vadot 
186f1d7ae31SEmmanuel Vadot /**
187f1d7ae31SEmmanuel Vadot  * hdmi_avi_infoframe_pack() - check a HDMI AVI infoframe,
188f1d7ae31SEmmanuel Vadot  *                             and write it to binary buffer
189f1d7ae31SEmmanuel Vadot  * @frame: HDMI AVI infoframe
190f1d7ae31SEmmanuel Vadot  * @buffer: destination buffer
191f1d7ae31SEmmanuel Vadot  * @size: size of buffer
192f1d7ae31SEmmanuel Vadot  *
193f1d7ae31SEmmanuel Vadot  * Validates that the infoframe is consistent and updates derived fields
194f1d7ae31SEmmanuel Vadot  * (eg. length) based on other fields, after which it packs the information
195f1d7ae31SEmmanuel Vadot  * contained in the @frame structure into a binary representation that
196f1d7ae31SEmmanuel Vadot  * can be written into the corresponding controller registers. This function
197f1d7ae31SEmmanuel Vadot  * also computes the checksum as required by section 5.3.5 of the HDMI 1.4
198f1d7ae31SEmmanuel Vadot  * specification.
199f1d7ae31SEmmanuel Vadot  *
200f1d7ae31SEmmanuel Vadot  * Returns the number of bytes packed into the binary buffer or a negative
201f1d7ae31SEmmanuel Vadot  * error code on failure.
202f1d7ae31SEmmanuel Vadot  */
hdmi_avi_infoframe_pack(struct hdmi_avi_infoframe * frame,void * buffer,size_t size)203f1d7ae31SEmmanuel Vadot ssize_t hdmi_avi_infoframe_pack(struct hdmi_avi_infoframe *frame,
204f1d7ae31SEmmanuel Vadot 				void *buffer, size_t size)
205f1d7ae31SEmmanuel Vadot {
206f1d7ae31SEmmanuel Vadot 	int ret;
207f1d7ae31SEmmanuel Vadot 
208f1d7ae31SEmmanuel Vadot 	ret = hdmi_avi_infoframe_check(frame);
209f1d7ae31SEmmanuel Vadot 	if (ret)
210f1d7ae31SEmmanuel Vadot 		return ret;
211f1d7ae31SEmmanuel Vadot 
212f1d7ae31SEmmanuel Vadot 	return hdmi_avi_infoframe_pack_only(frame, buffer, size);
213f1d7ae31SEmmanuel Vadot }
214f1d7ae31SEmmanuel Vadot EXPORT_SYMBOL(hdmi_avi_infoframe_pack);
215f1d7ae31SEmmanuel Vadot 
216f1d7ae31SEmmanuel Vadot /**
217f1d7ae31SEmmanuel Vadot  * hdmi_spd_infoframe_init() - initialize an HDMI SPD infoframe
218f1d7ae31SEmmanuel Vadot  * @frame: HDMI SPD infoframe
219f1d7ae31SEmmanuel Vadot  * @vendor: vendor string
220f1d7ae31SEmmanuel Vadot  * @product: product string
221f1d7ae31SEmmanuel Vadot  *
222f1d7ae31SEmmanuel Vadot  * Returns 0 on success or a negative error code on failure.
223f1d7ae31SEmmanuel Vadot  */
hdmi_spd_infoframe_init(struct hdmi_spd_infoframe * frame,const char * vendor,const char * product)224f1d7ae31SEmmanuel Vadot int hdmi_spd_infoframe_init(struct hdmi_spd_infoframe *frame,
225f1d7ae31SEmmanuel Vadot 			    const char *vendor, const char *product)
226f1d7ae31SEmmanuel Vadot {
227f1d7ae31SEmmanuel Vadot 	size_t len;
228f1d7ae31SEmmanuel Vadot 
229f1d7ae31SEmmanuel Vadot 	memset(frame, 0, sizeof(*frame));
230f1d7ae31SEmmanuel Vadot 
231f1d7ae31SEmmanuel Vadot 	frame->type = HDMI_INFOFRAME_TYPE_SPD;
232f1d7ae31SEmmanuel Vadot 	frame->version = 1;
233f1d7ae31SEmmanuel Vadot 	frame->length = HDMI_SPD_INFOFRAME_SIZE;
234f1d7ae31SEmmanuel Vadot 
235f1d7ae31SEmmanuel Vadot 	len = strlen(vendor);
236f1d7ae31SEmmanuel Vadot 	memcpy(frame->vendor, vendor, min(len, sizeof(frame->vendor)));
237f1d7ae31SEmmanuel Vadot 	len = strlen(product);
238f1d7ae31SEmmanuel Vadot 	memcpy(frame->product, product, min(len, sizeof(frame->product)));
239f1d7ae31SEmmanuel Vadot 
240f1d7ae31SEmmanuel Vadot 	return 0;
241f1d7ae31SEmmanuel Vadot }
242f1d7ae31SEmmanuel Vadot EXPORT_SYMBOL(hdmi_spd_infoframe_init);
243f1d7ae31SEmmanuel Vadot 
hdmi_spd_infoframe_check_only(const struct hdmi_spd_infoframe * frame)244f1d7ae31SEmmanuel Vadot static int hdmi_spd_infoframe_check_only(const struct hdmi_spd_infoframe *frame)
245f1d7ae31SEmmanuel Vadot {
246f1d7ae31SEmmanuel Vadot 	if (frame->type != HDMI_INFOFRAME_TYPE_SPD ||
247f1d7ae31SEmmanuel Vadot 	    frame->version != 1 ||
248f1d7ae31SEmmanuel Vadot 	    frame->length != HDMI_SPD_INFOFRAME_SIZE)
249f1d7ae31SEmmanuel Vadot 		return -EINVAL;
250f1d7ae31SEmmanuel Vadot 
251f1d7ae31SEmmanuel Vadot 	return 0;
252f1d7ae31SEmmanuel Vadot }
253f1d7ae31SEmmanuel Vadot 
254f1d7ae31SEmmanuel Vadot /**
255f1d7ae31SEmmanuel Vadot  * hdmi_spd_infoframe_check() - check a HDMI SPD infoframe
256f1d7ae31SEmmanuel Vadot  * @frame: HDMI SPD infoframe
257f1d7ae31SEmmanuel Vadot  *
258f1d7ae31SEmmanuel Vadot  * Validates that the infoframe is consistent and updates derived fields
259f1d7ae31SEmmanuel Vadot  * (eg. length) based on other fields.
260f1d7ae31SEmmanuel Vadot  *
261f1d7ae31SEmmanuel Vadot  * Returns 0 on success or a negative error code on failure.
262f1d7ae31SEmmanuel Vadot  */
hdmi_spd_infoframe_check(struct hdmi_spd_infoframe * frame)263f1d7ae31SEmmanuel Vadot int hdmi_spd_infoframe_check(struct hdmi_spd_infoframe *frame)
264f1d7ae31SEmmanuel Vadot {
265f1d7ae31SEmmanuel Vadot 	return hdmi_spd_infoframe_check_only(frame);
266f1d7ae31SEmmanuel Vadot }
267f1d7ae31SEmmanuel Vadot EXPORT_SYMBOL(hdmi_spd_infoframe_check);
268f1d7ae31SEmmanuel Vadot 
269f1d7ae31SEmmanuel Vadot /**
270f1d7ae31SEmmanuel Vadot  * hdmi_spd_infoframe_pack_only() - write HDMI SPD infoframe to binary buffer
271f1d7ae31SEmmanuel Vadot  * @frame: HDMI SPD infoframe
272f1d7ae31SEmmanuel Vadot  * @buffer: destination buffer
273f1d7ae31SEmmanuel Vadot  * @size: size of buffer
274f1d7ae31SEmmanuel Vadot  *
275f1d7ae31SEmmanuel Vadot  * Packs the information contained in the @frame structure into a binary
276f1d7ae31SEmmanuel Vadot  * representation that can be written into the corresponding controller
277f1d7ae31SEmmanuel Vadot  * registers. Also computes the checksum as required by section 5.3.5 of
278f1d7ae31SEmmanuel Vadot  * the HDMI 1.4 specification.
279f1d7ae31SEmmanuel Vadot  *
280f1d7ae31SEmmanuel Vadot  * Returns the number of bytes packed into the binary buffer or a negative
281f1d7ae31SEmmanuel Vadot  * error code on failure.
282f1d7ae31SEmmanuel Vadot  */
hdmi_spd_infoframe_pack_only(const struct hdmi_spd_infoframe * frame,void * buffer,size_t size)283f1d7ae31SEmmanuel Vadot ssize_t hdmi_spd_infoframe_pack_only(const struct hdmi_spd_infoframe *frame,
284f1d7ae31SEmmanuel Vadot 				     void *buffer, size_t size)
285f1d7ae31SEmmanuel Vadot {
286f1d7ae31SEmmanuel Vadot 	u8 *ptr = buffer;
287f1d7ae31SEmmanuel Vadot 	size_t length;
288f1d7ae31SEmmanuel Vadot 	int ret;
289f1d7ae31SEmmanuel Vadot 
290f1d7ae31SEmmanuel Vadot 	ret = hdmi_spd_infoframe_check_only(frame);
291f1d7ae31SEmmanuel Vadot 	if (ret)
292f1d7ae31SEmmanuel Vadot 		return ret;
293f1d7ae31SEmmanuel Vadot 
294f1d7ae31SEmmanuel Vadot 	length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;
295f1d7ae31SEmmanuel Vadot 
296f1d7ae31SEmmanuel Vadot 	if (size < length)
297f1d7ae31SEmmanuel Vadot 		return -ENOSPC;
298f1d7ae31SEmmanuel Vadot 
299f1d7ae31SEmmanuel Vadot 	memset(buffer, 0, size);
300f1d7ae31SEmmanuel Vadot 
301f1d7ae31SEmmanuel Vadot 	ptr[0] = frame->type;
302f1d7ae31SEmmanuel Vadot 	ptr[1] = frame->version;
303f1d7ae31SEmmanuel Vadot 	ptr[2] = frame->length;
304f1d7ae31SEmmanuel Vadot 	ptr[3] = 0; /* checksum */
305f1d7ae31SEmmanuel Vadot 
306f1d7ae31SEmmanuel Vadot 	/* start infoframe payload */
307f1d7ae31SEmmanuel Vadot 	ptr += HDMI_INFOFRAME_HEADER_SIZE;
308f1d7ae31SEmmanuel Vadot 
309f1d7ae31SEmmanuel Vadot 	memcpy(ptr, frame->vendor, sizeof(frame->vendor));
310f1d7ae31SEmmanuel Vadot 	memcpy(ptr + 8, frame->product, sizeof(frame->product));
311f1d7ae31SEmmanuel Vadot 
312f1d7ae31SEmmanuel Vadot 	ptr[24] = frame->sdi;
313f1d7ae31SEmmanuel Vadot 
314f1d7ae31SEmmanuel Vadot 	hdmi_infoframe_set_checksum(buffer, length);
315f1d7ae31SEmmanuel Vadot 
316f1d7ae31SEmmanuel Vadot 	return length;
317f1d7ae31SEmmanuel Vadot }
318f1d7ae31SEmmanuel Vadot EXPORT_SYMBOL(hdmi_spd_infoframe_pack_only);
319f1d7ae31SEmmanuel Vadot 
320f1d7ae31SEmmanuel Vadot /**
321f1d7ae31SEmmanuel Vadot  * hdmi_spd_infoframe_pack() - check a HDMI SPD infoframe,
322f1d7ae31SEmmanuel Vadot  *                             and write it to binary buffer
323f1d7ae31SEmmanuel Vadot  * @frame: HDMI SPD infoframe
324f1d7ae31SEmmanuel Vadot  * @buffer: destination buffer
325f1d7ae31SEmmanuel Vadot  * @size: size of buffer
326f1d7ae31SEmmanuel Vadot  *
327f1d7ae31SEmmanuel Vadot  * Validates that the infoframe is consistent and updates derived fields
328f1d7ae31SEmmanuel Vadot  * (eg. length) based on other fields, after which it packs the information
329f1d7ae31SEmmanuel Vadot  * contained in the @frame structure into a binary representation that
330f1d7ae31SEmmanuel Vadot  * can be written into the corresponding controller registers. This function
331f1d7ae31SEmmanuel Vadot  * also computes the checksum as required by section 5.3.5 of the HDMI 1.4
332f1d7ae31SEmmanuel Vadot  * specification.
333f1d7ae31SEmmanuel Vadot  *
334f1d7ae31SEmmanuel Vadot  * Returns the number of bytes packed into the binary buffer or a negative
335f1d7ae31SEmmanuel Vadot  * error code on failure.
336f1d7ae31SEmmanuel Vadot  */
hdmi_spd_infoframe_pack(struct hdmi_spd_infoframe * frame,void * buffer,size_t size)337f1d7ae31SEmmanuel Vadot ssize_t hdmi_spd_infoframe_pack(struct hdmi_spd_infoframe *frame,
338f1d7ae31SEmmanuel Vadot 				void *buffer, size_t size)
339f1d7ae31SEmmanuel Vadot {
340f1d7ae31SEmmanuel Vadot 	int ret;
341f1d7ae31SEmmanuel Vadot 
342f1d7ae31SEmmanuel Vadot 	ret = hdmi_spd_infoframe_check(frame);
343f1d7ae31SEmmanuel Vadot 	if (ret)
344f1d7ae31SEmmanuel Vadot 		return ret;
345f1d7ae31SEmmanuel Vadot 
346f1d7ae31SEmmanuel Vadot 	return hdmi_spd_infoframe_pack_only(frame, buffer, size);
347f1d7ae31SEmmanuel Vadot }
348f1d7ae31SEmmanuel Vadot EXPORT_SYMBOL(hdmi_spd_infoframe_pack);
349f1d7ae31SEmmanuel Vadot 
350f1d7ae31SEmmanuel Vadot /**
351f1d7ae31SEmmanuel Vadot  * hdmi_audio_infoframe_init() - initialize an HDMI audio infoframe
352f1d7ae31SEmmanuel Vadot  * @frame: HDMI audio infoframe
353f1d7ae31SEmmanuel Vadot  *
354f1d7ae31SEmmanuel Vadot  * Returns 0 on success or a negative error code on failure.
355f1d7ae31SEmmanuel Vadot  */
hdmi_audio_infoframe_init(struct hdmi_audio_infoframe * frame)356f1d7ae31SEmmanuel Vadot int hdmi_audio_infoframe_init(struct hdmi_audio_infoframe *frame)
357f1d7ae31SEmmanuel Vadot {
358f1d7ae31SEmmanuel Vadot 	memset(frame, 0, sizeof(*frame));
359f1d7ae31SEmmanuel Vadot 
360f1d7ae31SEmmanuel Vadot 	frame->type = HDMI_INFOFRAME_TYPE_AUDIO;
361f1d7ae31SEmmanuel Vadot 	frame->version = 1;
362f1d7ae31SEmmanuel Vadot 	frame->length = HDMI_AUDIO_INFOFRAME_SIZE;
363f1d7ae31SEmmanuel Vadot 
364f1d7ae31SEmmanuel Vadot 	return 0;
365f1d7ae31SEmmanuel Vadot }
366f1d7ae31SEmmanuel Vadot EXPORT_SYMBOL(hdmi_audio_infoframe_init);
367f1d7ae31SEmmanuel Vadot 
hdmi_audio_infoframe_check_only(const struct hdmi_audio_infoframe * frame)368f1d7ae31SEmmanuel Vadot static int hdmi_audio_infoframe_check_only(const struct hdmi_audio_infoframe *frame)
369f1d7ae31SEmmanuel Vadot {
370f1d7ae31SEmmanuel Vadot 	if (frame->type != HDMI_INFOFRAME_TYPE_AUDIO ||
371f1d7ae31SEmmanuel Vadot 	    frame->version != 1 ||
372f1d7ae31SEmmanuel Vadot 	    frame->length != HDMI_AUDIO_INFOFRAME_SIZE)
373f1d7ae31SEmmanuel Vadot 		return -EINVAL;
374f1d7ae31SEmmanuel Vadot 
375f1d7ae31SEmmanuel Vadot 	return 0;
376f1d7ae31SEmmanuel Vadot }
377f1d7ae31SEmmanuel Vadot 
378f1d7ae31SEmmanuel Vadot /**
379f1d7ae31SEmmanuel Vadot  * hdmi_audio_infoframe_check() - check a HDMI audio infoframe
380f1d7ae31SEmmanuel Vadot  * @frame: HDMI audio infoframe
381f1d7ae31SEmmanuel Vadot  *
382f1d7ae31SEmmanuel Vadot  * Validates that the infoframe is consistent and updates derived fields
383f1d7ae31SEmmanuel Vadot  * (eg. length) based on other fields.
384f1d7ae31SEmmanuel Vadot  *
385f1d7ae31SEmmanuel Vadot  * Returns 0 on success or a negative error code on failure.
386f1d7ae31SEmmanuel Vadot  */
hdmi_audio_infoframe_check(const struct hdmi_audio_infoframe * frame)387*c89d94adSVladimir Kondratyev int hdmi_audio_infoframe_check(const struct hdmi_audio_infoframe *frame)
388f1d7ae31SEmmanuel Vadot {
389f1d7ae31SEmmanuel Vadot 	return hdmi_audio_infoframe_check_only(frame);
390f1d7ae31SEmmanuel Vadot }
391f1d7ae31SEmmanuel Vadot EXPORT_SYMBOL(hdmi_audio_infoframe_check);
392f1d7ae31SEmmanuel Vadot 
393*c89d94adSVladimir Kondratyev static void
hdmi_audio_infoframe_pack_payload(const struct hdmi_audio_infoframe * frame,u8 * buffer)394*c89d94adSVladimir Kondratyev hdmi_audio_infoframe_pack_payload(const struct hdmi_audio_infoframe *frame,
395*c89d94adSVladimir Kondratyev 				  u8 *buffer)
396*c89d94adSVladimir Kondratyev {
397*c89d94adSVladimir Kondratyev 	u8 channels;
398*c89d94adSVladimir Kondratyev 
399*c89d94adSVladimir Kondratyev 	if (frame->channels >= 2)
400*c89d94adSVladimir Kondratyev 		channels = frame->channels - 1;
401*c89d94adSVladimir Kondratyev 	else
402*c89d94adSVladimir Kondratyev 		channels = 0;
403*c89d94adSVladimir Kondratyev 
404*c89d94adSVladimir Kondratyev 	buffer[0] = ((frame->coding_type & 0xf) << 4) | (channels & 0x7);
405*c89d94adSVladimir Kondratyev 	buffer[1] = ((frame->sample_frequency & 0x7) << 2) |
406*c89d94adSVladimir Kondratyev 		 (frame->sample_size & 0x3);
407*c89d94adSVladimir Kondratyev 	buffer[2] = frame->coding_type_ext & 0x1f;
408*c89d94adSVladimir Kondratyev 	buffer[3] = frame->channel_allocation;
409*c89d94adSVladimir Kondratyev 	buffer[4] = (frame->level_shift_value & 0xf) << 3;
410*c89d94adSVladimir Kondratyev 
411*c89d94adSVladimir Kondratyev 	if (frame->downmix_inhibit)
412*c89d94adSVladimir Kondratyev 		buffer[4] |= BIT(7);
413*c89d94adSVladimir Kondratyev }
414*c89d94adSVladimir Kondratyev 
415f1d7ae31SEmmanuel Vadot /**
416f1d7ae31SEmmanuel Vadot  * hdmi_audio_infoframe_pack_only() - write HDMI audio infoframe to binary buffer
417f1d7ae31SEmmanuel Vadot  * @frame: HDMI audio infoframe
418f1d7ae31SEmmanuel Vadot  * @buffer: destination buffer
419f1d7ae31SEmmanuel Vadot  * @size: size of buffer
420f1d7ae31SEmmanuel Vadot  *
421f1d7ae31SEmmanuel Vadot  * Packs the information contained in the @frame structure into a binary
422f1d7ae31SEmmanuel Vadot  * representation that can be written into the corresponding controller
423f1d7ae31SEmmanuel Vadot  * registers. Also computes the checksum as required by section 5.3.5 of
424f1d7ae31SEmmanuel Vadot  * the HDMI 1.4 specification.
425f1d7ae31SEmmanuel Vadot  *
426f1d7ae31SEmmanuel Vadot  * Returns the number of bytes packed into the binary buffer or a negative
427f1d7ae31SEmmanuel Vadot  * error code on failure.
428f1d7ae31SEmmanuel Vadot  */
hdmi_audio_infoframe_pack_only(const struct hdmi_audio_infoframe * frame,void * buffer,size_t size)429f1d7ae31SEmmanuel Vadot ssize_t hdmi_audio_infoframe_pack_only(const struct hdmi_audio_infoframe *frame,
430f1d7ae31SEmmanuel Vadot 				       void *buffer, size_t size)
431f1d7ae31SEmmanuel Vadot {
432f1d7ae31SEmmanuel Vadot 	u8 *ptr = buffer;
433f1d7ae31SEmmanuel Vadot 	size_t length;
434f1d7ae31SEmmanuel Vadot 	int ret;
435f1d7ae31SEmmanuel Vadot 
436f1d7ae31SEmmanuel Vadot 	ret = hdmi_audio_infoframe_check_only(frame);
437f1d7ae31SEmmanuel Vadot 	if (ret)
438f1d7ae31SEmmanuel Vadot 		return ret;
439f1d7ae31SEmmanuel Vadot 
440f1d7ae31SEmmanuel Vadot 	length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;
441f1d7ae31SEmmanuel Vadot 
442f1d7ae31SEmmanuel Vadot 	if (size < length)
443f1d7ae31SEmmanuel Vadot 		return -ENOSPC;
444f1d7ae31SEmmanuel Vadot 
445f1d7ae31SEmmanuel Vadot 	memset(buffer, 0, size);
446f1d7ae31SEmmanuel Vadot 
447f1d7ae31SEmmanuel Vadot 	ptr[0] = frame->type;
448f1d7ae31SEmmanuel Vadot 	ptr[1] = frame->version;
449f1d7ae31SEmmanuel Vadot 	ptr[2] = frame->length;
450f1d7ae31SEmmanuel Vadot 	ptr[3] = 0; /* checksum */
451f1d7ae31SEmmanuel Vadot 
452*c89d94adSVladimir Kondratyev 	hdmi_audio_infoframe_pack_payload(frame,
453*c89d94adSVladimir Kondratyev 					  ptr + HDMI_INFOFRAME_HEADER_SIZE);
454f1d7ae31SEmmanuel Vadot 
455f1d7ae31SEmmanuel Vadot 	hdmi_infoframe_set_checksum(buffer, length);
456f1d7ae31SEmmanuel Vadot 
457f1d7ae31SEmmanuel Vadot 	return length;
458f1d7ae31SEmmanuel Vadot }
459f1d7ae31SEmmanuel Vadot EXPORT_SYMBOL(hdmi_audio_infoframe_pack_only);
460f1d7ae31SEmmanuel Vadot 
461f1d7ae31SEmmanuel Vadot /**
462f1d7ae31SEmmanuel Vadot  * hdmi_audio_infoframe_pack() - check a HDMI Audio infoframe,
463f1d7ae31SEmmanuel Vadot  *                               and write it to binary buffer
464f1d7ae31SEmmanuel Vadot  * @frame: HDMI Audio infoframe
465f1d7ae31SEmmanuel Vadot  * @buffer: destination buffer
466f1d7ae31SEmmanuel Vadot  * @size: size of buffer
467f1d7ae31SEmmanuel Vadot  *
468f1d7ae31SEmmanuel Vadot  * Validates that the infoframe is consistent and updates derived fields
469f1d7ae31SEmmanuel Vadot  * (eg. length) based on other fields, after which it packs the information
470f1d7ae31SEmmanuel Vadot  * contained in the @frame structure into a binary representation that
471f1d7ae31SEmmanuel Vadot  * can be written into the corresponding controller registers. This function
472f1d7ae31SEmmanuel Vadot  * also computes the checksum as required by section 5.3.5 of the HDMI 1.4
473f1d7ae31SEmmanuel Vadot  * specification.
474f1d7ae31SEmmanuel Vadot  *
475f1d7ae31SEmmanuel Vadot  * Returns the number of bytes packed into the binary buffer or a negative
476f1d7ae31SEmmanuel Vadot  * error code on failure.
477f1d7ae31SEmmanuel Vadot  */
hdmi_audio_infoframe_pack(struct hdmi_audio_infoframe * frame,void * buffer,size_t size)478f1d7ae31SEmmanuel Vadot ssize_t hdmi_audio_infoframe_pack(struct hdmi_audio_infoframe *frame,
479f1d7ae31SEmmanuel Vadot 				  void *buffer, size_t size)
480f1d7ae31SEmmanuel Vadot {
481f1d7ae31SEmmanuel Vadot 	int ret;
482f1d7ae31SEmmanuel Vadot 
483f1d7ae31SEmmanuel Vadot 	ret = hdmi_audio_infoframe_check(frame);
484f1d7ae31SEmmanuel Vadot 	if (ret)
485f1d7ae31SEmmanuel Vadot 		return ret;
486f1d7ae31SEmmanuel Vadot 
487f1d7ae31SEmmanuel Vadot 	return hdmi_audio_infoframe_pack_only(frame, buffer, size);
488f1d7ae31SEmmanuel Vadot }
489f1d7ae31SEmmanuel Vadot EXPORT_SYMBOL(hdmi_audio_infoframe_pack);
490f1d7ae31SEmmanuel Vadot 
491*c89d94adSVladimir Kondratyev #ifdef __linux__
492*c89d94adSVladimir Kondratyev /**
493*c89d94adSVladimir Kondratyev  * hdmi_audio_infoframe_pack_for_dp - Pack a HDMI Audio infoframe for DisplayPort
494*c89d94adSVladimir Kondratyev  *
495*c89d94adSVladimir Kondratyev  * @frame:      HDMI Audio infoframe
496*c89d94adSVladimir Kondratyev  * @sdp:        Secondary data packet for DisplayPort.
497*c89d94adSVladimir Kondratyev  * @dp_version: DisplayPort version to be encoded in the header
498*c89d94adSVladimir Kondratyev  *
499*c89d94adSVladimir Kondratyev  * Packs a HDMI Audio Infoframe to be sent over DisplayPort. This function
500*c89d94adSVladimir Kondratyev  * fills the secondary data packet to be used for DisplayPort.
501*c89d94adSVladimir Kondratyev  *
502*c89d94adSVladimir Kondratyev  * Return: Number of total written bytes or a negative errno on failure.
503*c89d94adSVladimir Kondratyev  */
504*c89d94adSVladimir Kondratyev ssize_t
hdmi_audio_infoframe_pack_for_dp(const struct hdmi_audio_infoframe * frame,struct dp_sdp * sdp,u8 dp_version)505*c89d94adSVladimir Kondratyev hdmi_audio_infoframe_pack_for_dp(const struct hdmi_audio_infoframe *frame,
506*c89d94adSVladimir Kondratyev 				 struct dp_sdp *sdp, u8 dp_version)
507*c89d94adSVladimir Kondratyev {
508*c89d94adSVladimir Kondratyev 	int ret;
509*c89d94adSVladimir Kondratyev 
510*c89d94adSVladimir Kondratyev 	ret = hdmi_audio_infoframe_check(frame);
511*c89d94adSVladimir Kondratyev 	if (ret)
512*c89d94adSVladimir Kondratyev 		return ret;
513*c89d94adSVladimir Kondratyev 
514*c89d94adSVladimir Kondratyev 	memset(sdp->db, 0, sizeof(sdp->db));
515*c89d94adSVladimir Kondratyev 
516*c89d94adSVladimir Kondratyev 	/* Secondary-data packet header */
517*c89d94adSVladimir Kondratyev 	sdp->sdp_header.HB0 = 0;
518*c89d94adSVladimir Kondratyev 	sdp->sdp_header.HB1 = frame->type;
519*c89d94adSVladimir Kondratyev 	sdp->sdp_header.HB2 = DP_SDP_AUDIO_INFOFRAME_HB2;
520*c89d94adSVladimir Kondratyev 	sdp->sdp_header.HB3 = (dp_version & 0x3f) << 2;
521*c89d94adSVladimir Kondratyev 
522*c89d94adSVladimir Kondratyev 	hdmi_audio_infoframe_pack_payload(frame, sdp->db);
523*c89d94adSVladimir Kondratyev 
524*c89d94adSVladimir Kondratyev 	/* Return size =  frame length + four HB for sdp_header */
525*c89d94adSVladimir Kondratyev 	return frame->length + 4;
526*c89d94adSVladimir Kondratyev }
527*c89d94adSVladimir Kondratyev EXPORT_SYMBOL(hdmi_audio_infoframe_pack_for_dp);
528*c89d94adSVladimir Kondratyev #endif
529*c89d94adSVladimir Kondratyev 
530f1d7ae31SEmmanuel Vadot /**
531f1d7ae31SEmmanuel Vadot  * hdmi_vendor_infoframe_init() - initialize an HDMI vendor infoframe
532f1d7ae31SEmmanuel Vadot  * @frame: HDMI vendor infoframe
533f1d7ae31SEmmanuel Vadot  *
534f1d7ae31SEmmanuel Vadot  * Returns 0 on success or a negative error code on failure.
535f1d7ae31SEmmanuel Vadot  */
hdmi_vendor_infoframe_init(struct hdmi_vendor_infoframe * frame)536f1d7ae31SEmmanuel Vadot int hdmi_vendor_infoframe_init(struct hdmi_vendor_infoframe *frame)
537f1d7ae31SEmmanuel Vadot {
538f1d7ae31SEmmanuel Vadot 	memset(frame, 0, sizeof(*frame));
539f1d7ae31SEmmanuel Vadot 
540f1d7ae31SEmmanuel Vadot 	frame->type = HDMI_INFOFRAME_TYPE_VENDOR;
541f1d7ae31SEmmanuel Vadot 	frame->version = 1;
542f1d7ae31SEmmanuel Vadot 
543f1d7ae31SEmmanuel Vadot 	frame->oui = HDMI_IEEE_OUI;
544f1d7ae31SEmmanuel Vadot 
545f1d7ae31SEmmanuel Vadot 	/*
546f1d7ae31SEmmanuel Vadot 	 * 0 is a valid value for s3d_struct, so we use a special "not set"
547f1d7ae31SEmmanuel Vadot 	 * value
548f1d7ae31SEmmanuel Vadot 	 */
549f1d7ae31SEmmanuel Vadot 	frame->s3d_struct = HDMI_3D_STRUCTURE_INVALID;
550f1d7ae31SEmmanuel Vadot 	frame->length = HDMI_VENDOR_INFOFRAME_SIZE;
551f1d7ae31SEmmanuel Vadot 
552f1d7ae31SEmmanuel Vadot 	return 0;
553f1d7ae31SEmmanuel Vadot }
554f1d7ae31SEmmanuel Vadot EXPORT_SYMBOL(hdmi_vendor_infoframe_init);
555f1d7ae31SEmmanuel Vadot 
hdmi_vendor_infoframe_length(const struct hdmi_vendor_infoframe * frame)556f1d7ae31SEmmanuel Vadot static int hdmi_vendor_infoframe_length(const struct hdmi_vendor_infoframe *frame)
557f1d7ae31SEmmanuel Vadot {
558f1d7ae31SEmmanuel Vadot 	/* for side by side (half) we also need to provide 3D_Ext_Data */
559f1d7ae31SEmmanuel Vadot 	if (frame->s3d_struct >= HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF)
560f1d7ae31SEmmanuel Vadot 		return 6;
561f1d7ae31SEmmanuel Vadot 	else if (frame->vic != 0 || frame->s3d_struct != HDMI_3D_STRUCTURE_INVALID)
562f1d7ae31SEmmanuel Vadot 		return 5;
563f1d7ae31SEmmanuel Vadot 	else
564f1d7ae31SEmmanuel Vadot 		return 4;
565f1d7ae31SEmmanuel Vadot }
566f1d7ae31SEmmanuel Vadot 
hdmi_vendor_infoframe_check_only(const struct hdmi_vendor_infoframe * frame)567f1d7ae31SEmmanuel Vadot static int hdmi_vendor_infoframe_check_only(const struct hdmi_vendor_infoframe *frame)
568f1d7ae31SEmmanuel Vadot {
569f1d7ae31SEmmanuel Vadot 	if (frame->type != HDMI_INFOFRAME_TYPE_VENDOR ||
570f1d7ae31SEmmanuel Vadot 	    frame->version != 1 ||
571f1d7ae31SEmmanuel Vadot 	    frame->oui != HDMI_IEEE_OUI)
572f1d7ae31SEmmanuel Vadot 		return -EINVAL;
573f1d7ae31SEmmanuel Vadot 
574f1d7ae31SEmmanuel Vadot 	/* only one of those can be supplied */
575f1d7ae31SEmmanuel Vadot 	if (frame->vic != 0 && frame->s3d_struct != HDMI_3D_STRUCTURE_INVALID)
576f1d7ae31SEmmanuel Vadot 		return -EINVAL;
577f1d7ae31SEmmanuel Vadot 
578f1d7ae31SEmmanuel Vadot 	if (frame->length != hdmi_vendor_infoframe_length(frame))
579f1d7ae31SEmmanuel Vadot 		return -EINVAL;
580f1d7ae31SEmmanuel Vadot 
581f1d7ae31SEmmanuel Vadot 	return 0;
582f1d7ae31SEmmanuel Vadot }
583f1d7ae31SEmmanuel Vadot 
584f1d7ae31SEmmanuel Vadot /**
585f1d7ae31SEmmanuel Vadot  * hdmi_vendor_infoframe_check() - check a HDMI vendor infoframe
586f1d7ae31SEmmanuel Vadot  * @frame: HDMI infoframe
587f1d7ae31SEmmanuel Vadot  *
588f1d7ae31SEmmanuel Vadot  * Validates that the infoframe is consistent and updates derived fields
589f1d7ae31SEmmanuel Vadot  * (eg. length) based on other fields.
590f1d7ae31SEmmanuel Vadot  *
591f1d7ae31SEmmanuel Vadot  * Returns 0 on success or a negative error code on failure.
592f1d7ae31SEmmanuel Vadot  */
hdmi_vendor_infoframe_check(struct hdmi_vendor_infoframe * frame)593f1d7ae31SEmmanuel Vadot int hdmi_vendor_infoframe_check(struct hdmi_vendor_infoframe *frame)
594f1d7ae31SEmmanuel Vadot {
595f1d7ae31SEmmanuel Vadot 	frame->length = hdmi_vendor_infoframe_length(frame);
596f1d7ae31SEmmanuel Vadot 
597f1d7ae31SEmmanuel Vadot 	return hdmi_vendor_infoframe_check_only(frame);
598f1d7ae31SEmmanuel Vadot }
599f1d7ae31SEmmanuel Vadot EXPORT_SYMBOL(hdmi_vendor_infoframe_check);
600f1d7ae31SEmmanuel Vadot 
601f1d7ae31SEmmanuel Vadot /**
602f1d7ae31SEmmanuel Vadot  * hdmi_vendor_infoframe_pack_only() - write a HDMI vendor infoframe to binary buffer
603f1d7ae31SEmmanuel Vadot  * @frame: HDMI infoframe
604f1d7ae31SEmmanuel Vadot  * @buffer: destination buffer
605f1d7ae31SEmmanuel Vadot  * @size: size of buffer
606f1d7ae31SEmmanuel Vadot  *
607f1d7ae31SEmmanuel Vadot  * Packs the information contained in the @frame structure into a binary
608f1d7ae31SEmmanuel Vadot  * representation that can be written into the corresponding controller
609f1d7ae31SEmmanuel Vadot  * registers. Also computes the checksum as required by section 5.3.5 of
610f1d7ae31SEmmanuel Vadot  * the HDMI 1.4 specification.
611f1d7ae31SEmmanuel Vadot  *
612f1d7ae31SEmmanuel Vadot  * Returns the number of bytes packed into the binary buffer or a negative
613f1d7ae31SEmmanuel Vadot  * error code on failure.
614f1d7ae31SEmmanuel Vadot  */
hdmi_vendor_infoframe_pack_only(const struct hdmi_vendor_infoframe * frame,void * buffer,size_t size)615f1d7ae31SEmmanuel Vadot ssize_t hdmi_vendor_infoframe_pack_only(const struct hdmi_vendor_infoframe *frame,
616f1d7ae31SEmmanuel Vadot 					void *buffer, size_t size)
617f1d7ae31SEmmanuel Vadot {
618f1d7ae31SEmmanuel Vadot 	u8 *ptr = buffer;
619f1d7ae31SEmmanuel Vadot 	size_t length;
620f1d7ae31SEmmanuel Vadot 	int ret;
621f1d7ae31SEmmanuel Vadot 
622f1d7ae31SEmmanuel Vadot 	ret = hdmi_vendor_infoframe_check_only(frame);
623f1d7ae31SEmmanuel Vadot 	if (ret)
624f1d7ae31SEmmanuel Vadot 		return ret;
625f1d7ae31SEmmanuel Vadot 
626f1d7ae31SEmmanuel Vadot 	length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;
627f1d7ae31SEmmanuel Vadot 
628f1d7ae31SEmmanuel Vadot 	if (size < length)
629f1d7ae31SEmmanuel Vadot 		return -ENOSPC;
630f1d7ae31SEmmanuel Vadot 
631f1d7ae31SEmmanuel Vadot 	memset(buffer, 0, size);
632f1d7ae31SEmmanuel Vadot 
633f1d7ae31SEmmanuel Vadot 	ptr[0] = frame->type;
634f1d7ae31SEmmanuel Vadot 	ptr[1] = frame->version;
635f1d7ae31SEmmanuel Vadot 	ptr[2] = frame->length;
636f1d7ae31SEmmanuel Vadot 	ptr[3] = 0; /* checksum */
637f1d7ae31SEmmanuel Vadot 
638f1d7ae31SEmmanuel Vadot 	/* HDMI OUI */
639f1d7ae31SEmmanuel Vadot 	ptr[4] = 0x03;
640f1d7ae31SEmmanuel Vadot 	ptr[5] = 0x0c;
641f1d7ae31SEmmanuel Vadot 	ptr[6] = 0x00;
642f1d7ae31SEmmanuel Vadot 
643f1d7ae31SEmmanuel Vadot 	if (frame->s3d_struct != HDMI_3D_STRUCTURE_INVALID) {
644f1d7ae31SEmmanuel Vadot 		ptr[7] = 0x2 << 5;	/* video format */
645f1d7ae31SEmmanuel Vadot 		ptr[8] = (frame->s3d_struct & 0xf) << 4;
646f1d7ae31SEmmanuel Vadot 		if (frame->s3d_struct >= HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF)
647f1d7ae31SEmmanuel Vadot 			ptr[9] = (frame->s3d_ext_data & 0xf) << 4;
648f1d7ae31SEmmanuel Vadot 	} else if (frame->vic) {
649f1d7ae31SEmmanuel Vadot 		ptr[7] = 0x1 << 5;	/* video format */
650f1d7ae31SEmmanuel Vadot 		ptr[8] = frame->vic;
651f1d7ae31SEmmanuel Vadot 	} else {
652f1d7ae31SEmmanuel Vadot 		ptr[7] = 0x0 << 5;	/* video format */
653f1d7ae31SEmmanuel Vadot 	}
654f1d7ae31SEmmanuel Vadot 
655f1d7ae31SEmmanuel Vadot 	hdmi_infoframe_set_checksum(buffer, length);
656f1d7ae31SEmmanuel Vadot 
657f1d7ae31SEmmanuel Vadot 	return length;
658f1d7ae31SEmmanuel Vadot }
659f1d7ae31SEmmanuel Vadot EXPORT_SYMBOL(hdmi_vendor_infoframe_pack_only);
660f1d7ae31SEmmanuel Vadot 
661f1d7ae31SEmmanuel Vadot /**
662f1d7ae31SEmmanuel Vadot  * hdmi_vendor_infoframe_pack() - check a HDMI Vendor infoframe,
663f1d7ae31SEmmanuel Vadot  *                                and write it to binary buffer
664f1d7ae31SEmmanuel Vadot  * @frame: HDMI Vendor infoframe
665f1d7ae31SEmmanuel Vadot  * @buffer: destination buffer
666f1d7ae31SEmmanuel Vadot  * @size: size of buffer
667f1d7ae31SEmmanuel Vadot  *
668f1d7ae31SEmmanuel Vadot  * Validates that the infoframe is consistent and updates derived fields
669f1d7ae31SEmmanuel Vadot  * (eg. length) based on other fields, after which it packs the information
670f1d7ae31SEmmanuel Vadot  * contained in the @frame structure into a binary representation that
671f1d7ae31SEmmanuel Vadot  * can be written into the corresponding controller registers. This function
672f1d7ae31SEmmanuel Vadot  * also computes the checksum as required by section 5.3.5 of the HDMI 1.4
673f1d7ae31SEmmanuel Vadot  * specification.
674f1d7ae31SEmmanuel Vadot  *
675f1d7ae31SEmmanuel Vadot  * Returns the number of bytes packed into the binary buffer or a negative
676f1d7ae31SEmmanuel Vadot  * error code on failure.
677f1d7ae31SEmmanuel Vadot  */
hdmi_vendor_infoframe_pack(struct hdmi_vendor_infoframe * frame,void * buffer,size_t size)678f1d7ae31SEmmanuel Vadot ssize_t hdmi_vendor_infoframe_pack(struct hdmi_vendor_infoframe *frame,
679f1d7ae31SEmmanuel Vadot 				   void *buffer, size_t size)
680f1d7ae31SEmmanuel Vadot {
681f1d7ae31SEmmanuel Vadot 	int ret;
682f1d7ae31SEmmanuel Vadot 
683f1d7ae31SEmmanuel Vadot 	ret = hdmi_vendor_infoframe_check(frame);
684f1d7ae31SEmmanuel Vadot 	if (ret)
685f1d7ae31SEmmanuel Vadot 		return ret;
686f1d7ae31SEmmanuel Vadot 
687f1d7ae31SEmmanuel Vadot 	return hdmi_vendor_infoframe_pack_only(frame, buffer, size);
688f1d7ae31SEmmanuel Vadot }
689f1d7ae31SEmmanuel Vadot EXPORT_SYMBOL(hdmi_vendor_infoframe_pack);
690f1d7ae31SEmmanuel Vadot 
691f1d7ae31SEmmanuel Vadot static int
hdmi_vendor_any_infoframe_check_only(const union hdmi_vendor_any_infoframe * frame)692f1d7ae31SEmmanuel Vadot hdmi_vendor_any_infoframe_check_only(const union hdmi_vendor_any_infoframe *frame)
693f1d7ae31SEmmanuel Vadot {
694f1d7ae31SEmmanuel Vadot 	if (frame->any.type != HDMI_INFOFRAME_TYPE_VENDOR ||
695f1d7ae31SEmmanuel Vadot 	    frame->any.version != 1)
696f1d7ae31SEmmanuel Vadot 		return -EINVAL;
697f1d7ae31SEmmanuel Vadot 
698f1d7ae31SEmmanuel Vadot 	return 0;
699f1d7ae31SEmmanuel Vadot }
700f1d7ae31SEmmanuel Vadot 
701f1d7ae31SEmmanuel Vadot /**
702f1d7ae31SEmmanuel Vadot  * hdmi_drm_infoframe_init() - initialize an HDMI Dynaminc Range and
703f1d7ae31SEmmanuel Vadot  * mastering infoframe
704f1d7ae31SEmmanuel Vadot  * @frame: HDMI DRM infoframe
705f1d7ae31SEmmanuel Vadot  *
706f1d7ae31SEmmanuel Vadot  * Returns 0 on success or a negative error code on failure.
707f1d7ae31SEmmanuel Vadot  */
hdmi_drm_infoframe_init(struct hdmi_drm_infoframe * frame)708f1d7ae31SEmmanuel Vadot int hdmi_drm_infoframe_init(struct hdmi_drm_infoframe *frame)
709f1d7ae31SEmmanuel Vadot {
710f1d7ae31SEmmanuel Vadot 	memset(frame, 0, sizeof(*frame));
711f1d7ae31SEmmanuel Vadot 
712f1d7ae31SEmmanuel Vadot 	frame->type = HDMI_INFOFRAME_TYPE_DRM;
713f1d7ae31SEmmanuel Vadot 	frame->version = 1;
714f1d7ae31SEmmanuel Vadot 	frame->length = HDMI_DRM_INFOFRAME_SIZE;
715f1d7ae31SEmmanuel Vadot 
716f1d7ae31SEmmanuel Vadot 	return 0;
717f1d7ae31SEmmanuel Vadot }
718f1d7ae31SEmmanuel Vadot EXPORT_SYMBOL(hdmi_drm_infoframe_init);
719f1d7ae31SEmmanuel Vadot 
hdmi_drm_infoframe_check_only(const struct hdmi_drm_infoframe * frame)720f1d7ae31SEmmanuel Vadot static int hdmi_drm_infoframe_check_only(const struct hdmi_drm_infoframe *frame)
721f1d7ae31SEmmanuel Vadot {
722f1d7ae31SEmmanuel Vadot 	if (frame->type != HDMI_INFOFRAME_TYPE_DRM ||
723f1d7ae31SEmmanuel Vadot 	    frame->version != 1)
724f1d7ae31SEmmanuel Vadot 		return -EINVAL;
725f1d7ae31SEmmanuel Vadot 
726f1d7ae31SEmmanuel Vadot 	if (frame->length != HDMI_DRM_INFOFRAME_SIZE)
727f1d7ae31SEmmanuel Vadot 		return -EINVAL;
728f1d7ae31SEmmanuel Vadot 
729f1d7ae31SEmmanuel Vadot 	return 0;
730f1d7ae31SEmmanuel Vadot }
731f1d7ae31SEmmanuel Vadot 
732f1d7ae31SEmmanuel Vadot /**
733f1d7ae31SEmmanuel Vadot  * hdmi_drm_infoframe_check() - check a HDMI DRM infoframe
734f1d7ae31SEmmanuel Vadot  * @frame: HDMI DRM infoframe
735f1d7ae31SEmmanuel Vadot  *
736f1d7ae31SEmmanuel Vadot  * Validates that the infoframe is consistent.
737f1d7ae31SEmmanuel Vadot  * Returns 0 on success or a negative error code on failure.
738f1d7ae31SEmmanuel Vadot  */
hdmi_drm_infoframe_check(struct hdmi_drm_infoframe * frame)739f1d7ae31SEmmanuel Vadot int hdmi_drm_infoframe_check(struct hdmi_drm_infoframe *frame)
740f1d7ae31SEmmanuel Vadot {
741f1d7ae31SEmmanuel Vadot 	return hdmi_drm_infoframe_check_only(frame);
742f1d7ae31SEmmanuel Vadot }
743f1d7ae31SEmmanuel Vadot EXPORT_SYMBOL(hdmi_drm_infoframe_check);
744f1d7ae31SEmmanuel Vadot 
745f1d7ae31SEmmanuel Vadot /**
746f1d7ae31SEmmanuel Vadot  * hdmi_drm_infoframe_pack_only() - write HDMI DRM infoframe to binary buffer
747f1d7ae31SEmmanuel Vadot  * @frame: HDMI DRM infoframe
748f1d7ae31SEmmanuel Vadot  * @buffer: destination buffer
749f1d7ae31SEmmanuel Vadot  * @size: size of buffer
750f1d7ae31SEmmanuel Vadot  *
751f1d7ae31SEmmanuel Vadot  * Packs the information contained in the @frame structure into a binary
752f1d7ae31SEmmanuel Vadot  * representation that can be written into the corresponding controller
753f1d7ae31SEmmanuel Vadot  * registers. Also computes the checksum as required by section 5.3.5 of
754f1d7ae31SEmmanuel Vadot  * the HDMI 1.4 specification.
755f1d7ae31SEmmanuel Vadot  *
756f1d7ae31SEmmanuel Vadot  * Returns the number of bytes packed into the binary buffer or a negative
757f1d7ae31SEmmanuel Vadot  * error code on failure.
758f1d7ae31SEmmanuel Vadot  */
hdmi_drm_infoframe_pack_only(const struct hdmi_drm_infoframe * frame,void * buffer,size_t size)759f1d7ae31SEmmanuel Vadot ssize_t hdmi_drm_infoframe_pack_only(const struct hdmi_drm_infoframe *frame,
760f1d7ae31SEmmanuel Vadot 				     void *buffer, size_t size)
761f1d7ae31SEmmanuel Vadot {
762f1d7ae31SEmmanuel Vadot 	u8 *ptr = buffer;
763f1d7ae31SEmmanuel Vadot 	size_t length;
764f1d7ae31SEmmanuel Vadot 	int i;
765f1d7ae31SEmmanuel Vadot 
766f1d7ae31SEmmanuel Vadot 	length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;
767f1d7ae31SEmmanuel Vadot 
768f1d7ae31SEmmanuel Vadot 	if (size < length)
769f1d7ae31SEmmanuel Vadot 		return -ENOSPC;
770f1d7ae31SEmmanuel Vadot 
771f1d7ae31SEmmanuel Vadot 	memset(buffer, 0, size);
772f1d7ae31SEmmanuel Vadot 
773f1d7ae31SEmmanuel Vadot 	ptr[0] = frame->type;
774f1d7ae31SEmmanuel Vadot 	ptr[1] = frame->version;
775f1d7ae31SEmmanuel Vadot 	ptr[2] = frame->length;
776f1d7ae31SEmmanuel Vadot 	ptr[3] = 0; /* checksum */
777f1d7ae31SEmmanuel Vadot 
778f1d7ae31SEmmanuel Vadot 	/* start infoframe payload */
779f1d7ae31SEmmanuel Vadot 	ptr += HDMI_INFOFRAME_HEADER_SIZE;
780f1d7ae31SEmmanuel Vadot 
781f1d7ae31SEmmanuel Vadot 	*ptr++ = frame->eotf;
782f1d7ae31SEmmanuel Vadot 	*ptr++ = frame->metadata_type;
783f1d7ae31SEmmanuel Vadot 
784f1d7ae31SEmmanuel Vadot 	for (i = 0; i < 3; i++) {
785f1d7ae31SEmmanuel Vadot 		*ptr++ = frame->display_primaries[i].x;
786f1d7ae31SEmmanuel Vadot 		*ptr++ = frame->display_primaries[i].x >> 8;
787f1d7ae31SEmmanuel Vadot 		*ptr++ = frame->display_primaries[i].y;
788f1d7ae31SEmmanuel Vadot 		*ptr++ = frame->display_primaries[i].y >> 8;
789f1d7ae31SEmmanuel Vadot 	}
790f1d7ae31SEmmanuel Vadot 
791f1d7ae31SEmmanuel Vadot 	*ptr++ = frame->white_point.x;
792f1d7ae31SEmmanuel Vadot 	*ptr++ = frame->white_point.x >> 8;
793f1d7ae31SEmmanuel Vadot 
794f1d7ae31SEmmanuel Vadot 	*ptr++ = frame->white_point.y;
795f1d7ae31SEmmanuel Vadot 	*ptr++ = frame->white_point.y >> 8;
796f1d7ae31SEmmanuel Vadot 
797f1d7ae31SEmmanuel Vadot 	*ptr++ = frame->max_display_mastering_luminance;
798f1d7ae31SEmmanuel Vadot 	*ptr++ = frame->max_display_mastering_luminance >> 8;
799f1d7ae31SEmmanuel Vadot 
800f1d7ae31SEmmanuel Vadot 	*ptr++ = frame->min_display_mastering_luminance;
801f1d7ae31SEmmanuel Vadot 	*ptr++ = frame->min_display_mastering_luminance >> 8;
802f1d7ae31SEmmanuel Vadot 
803f1d7ae31SEmmanuel Vadot 	*ptr++ = frame->max_cll;
804f1d7ae31SEmmanuel Vadot 	*ptr++ = frame->max_cll >> 8;
805f1d7ae31SEmmanuel Vadot 
806f1d7ae31SEmmanuel Vadot 	*ptr++ = frame->max_fall;
807f1d7ae31SEmmanuel Vadot 	*ptr++ = frame->max_fall >> 8;
808f1d7ae31SEmmanuel Vadot 
809f1d7ae31SEmmanuel Vadot 	hdmi_infoframe_set_checksum(buffer, length);
810f1d7ae31SEmmanuel Vadot 
811f1d7ae31SEmmanuel Vadot 	return length;
812f1d7ae31SEmmanuel Vadot }
813f1d7ae31SEmmanuel Vadot EXPORT_SYMBOL(hdmi_drm_infoframe_pack_only);
814f1d7ae31SEmmanuel Vadot 
815f1d7ae31SEmmanuel Vadot /**
816f1d7ae31SEmmanuel Vadot  * hdmi_drm_infoframe_pack() - check a HDMI DRM infoframe,
817f1d7ae31SEmmanuel Vadot  *                             and write it to binary buffer
818f1d7ae31SEmmanuel Vadot  * @frame: HDMI DRM infoframe
819f1d7ae31SEmmanuel Vadot  * @buffer: destination buffer
820f1d7ae31SEmmanuel Vadot  * @size: size of buffer
821f1d7ae31SEmmanuel Vadot  *
822f1d7ae31SEmmanuel Vadot  * Validates that the infoframe is consistent and updates derived fields
823f1d7ae31SEmmanuel Vadot  * (eg. length) based on other fields, after which it packs the information
824f1d7ae31SEmmanuel Vadot  * contained in the @frame structure into a binary representation that
825f1d7ae31SEmmanuel Vadot  * can be written into the corresponding controller registers. This function
826f1d7ae31SEmmanuel Vadot  * also computes the checksum as required by section 5.3.5 of the HDMI 1.4
827f1d7ae31SEmmanuel Vadot  * specification.
828f1d7ae31SEmmanuel Vadot  *
829f1d7ae31SEmmanuel Vadot  * Returns the number of bytes packed into the binary buffer or a negative
830f1d7ae31SEmmanuel Vadot  * error code on failure.
831f1d7ae31SEmmanuel Vadot  */
hdmi_drm_infoframe_pack(struct hdmi_drm_infoframe * frame,void * buffer,size_t size)832f1d7ae31SEmmanuel Vadot ssize_t hdmi_drm_infoframe_pack(struct hdmi_drm_infoframe *frame,
833f1d7ae31SEmmanuel Vadot 				void *buffer, size_t size)
834f1d7ae31SEmmanuel Vadot {
835f1d7ae31SEmmanuel Vadot 	int ret;
836f1d7ae31SEmmanuel Vadot 
837f1d7ae31SEmmanuel Vadot 	ret = hdmi_drm_infoframe_check(frame);
838f1d7ae31SEmmanuel Vadot 	if (ret)
839f1d7ae31SEmmanuel Vadot 		return ret;
840f1d7ae31SEmmanuel Vadot 
841f1d7ae31SEmmanuel Vadot 	return hdmi_drm_infoframe_pack_only(frame, buffer, size);
842f1d7ae31SEmmanuel Vadot }
843f1d7ae31SEmmanuel Vadot EXPORT_SYMBOL(hdmi_drm_infoframe_pack);
844f1d7ae31SEmmanuel Vadot 
845f1d7ae31SEmmanuel Vadot /*
846f1d7ae31SEmmanuel Vadot  * hdmi_vendor_any_infoframe_check() - check a vendor infoframe
847f1d7ae31SEmmanuel Vadot  */
848f1d7ae31SEmmanuel Vadot static int
hdmi_vendor_any_infoframe_check(union hdmi_vendor_any_infoframe * frame)849f1d7ae31SEmmanuel Vadot hdmi_vendor_any_infoframe_check(union hdmi_vendor_any_infoframe *frame)
850f1d7ae31SEmmanuel Vadot {
851f1d7ae31SEmmanuel Vadot 	int ret;
852f1d7ae31SEmmanuel Vadot 
853f1d7ae31SEmmanuel Vadot 	ret = hdmi_vendor_any_infoframe_check_only(frame);
854f1d7ae31SEmmanuel Vadot 	if (ret)
855f1d7ae31SEmmanuel Vadot 		return ret;
856f1d7ae31SEmmanuel Vadot 
857f1d7ae31SEmmanuel Vadot 	/* we only know about HDMI vendor infoframes */
858f1d7ae31SEmmanuel Vadot 	if (frame->any.oui != HDMI_IEEE_OUI)
859f1d7ae31SEmmanuel Vadot 		return -EINVAL;
860f1d7ae31SEmmanuel Vadot 
861f1d7ae31SEmmanuel Vadot 	return hdmi_vendor_infoframe_check(&frame->hdmi);
862f1d7ae31SEmmanuel Vadot }
863f1d7ae31SEmmanuel Vadot 
864f1d7ae31SEmmanuel Vadot /*
865f1d7ae31SEmmanuel Vadot  * hdmi_vendor_any_infoframe_pack_only() - write a vendor infoframe to binary buffer
866f1d7ae31SEmmanuel Vadot  */
867f1d7ae31SEmmanuel Vadot static ssize_t
hdmi_vendor_any_infoframe_pack_only(const union hdmi_vendor_any_infoframe * frame,void * buffer,size_t size)868f1d7ae31SEmmanuel Vadot hdmi_vendor_any_infoframe_pack_only(const union hdmi_vendor_any_infoframe *frame,
869f1d7ae31SEmmanuel Vadot 				    void *buffer, size_t size)
870f1d7ae31SEmmanuel Vadot {
871f1d7ae31SEmmanuel Vadot 	int ret;
872f1d7ae31SEmmanuel Vadot 
873f1d7ae31SEmmanuel Vadot 	ret = hdmi_vendor_any_infoframe_check_only(frame);
874f1d7ae31SEmmanuel Vadot 	if (ret)
875f1d7ae31SEmmanuel Vadot 		return ret;
876f1d7ae31SEmmanuel Vadot 
877f1d7ae31SEmmanuel Vadot 	/* we only know about HDMI vendor infoframes */
878f1d7ae31SEmmanuel Vadot 	if (frame->any.oui != HDMI_IEEE_OUI)
879f1d7ae31SEmmanuel Vadot 		return -EINVAL;
880f1d7ae31SEmmanuel Vadot 
881f1d7ae31SEmmanuel Vadot 	return hdmi_vendor_infoframe_pack_only(&frame->hdmi, buffer, size);
882f1d7ae31SEmmanuel Vadot }
883f1d7ae31SEmmanuel Vadot 
884f1d7ae31SEmmanuel Vadot /*
885f1d7ae31SEmmanuel Vadot  * hdmi_vendor_any_infoframe_pack() - check a vendor infoframe,
886f1d7ae31SEmmanuel Vadot  *                                    and write it to binary buffer
887f1d7ae31SEmmanuel Vadot  */
888f1d7ae31SEmmanuel Vadot static ssize_t
hdmi_vendor_any_infoframe_pack(union hdmi_vendor_any_infoframe * frame,void * buffer,size_t size)889f1d7ae31SEmmanuel Vadot hdmi_vendor_any_infoframe_pack(union hdmi_vendor_any_infoframe *frame,
890f1d7ae31SEmmanuel Vadot 			       void *buffer, size_t size)
891f1d7ae31SEmmanuel Vadot {
892f1d7ae31SEmmanuel Vadot 	int ret;
893f1d7ae31SEmmanuel Vadot 
894f1d7ae31SEmmanuel Vadot 	ret = hdmi_vendor_any_infoframe_check(frame);
895f1d7ae31SEmmanuel Vadot 	if (ret)
896f1d7ae31SEmmanuel Vadot 		return ret;
897f1d7ae31SEmmanuel Vadot 
898f1d7ae31SEmmanuel Vadot 	return hdmi_vendor_any_infoframe_pack_only(frame, buffer, size);
899f1d7ae31SEmmanuel Vadot }
900f1d7ae31SEmmanuel Vadot 
901f1d7ae31SEmmanuel Vadot /**
902f1d7ae31SEmmanuel Vadot  * hdmi_infoframe_check() - check a HDMI infoframe
903f1d7ae31SEmmanuel Vadot  * @frame: HDMI infoframe
904f1d7ae31SEmmanuel Vadot  *
905f1d7ae31SEmmanuel Vadot  * Validates that the infoframe is consistent and updates derived fields
906f1d7ae31SEmmanuel Vadot  * (eg. length) based on other fields.
907f1d7ae31SEmmanuel Vadot  *
908f1d7ae31SEmmanuel Vadot  * Returns 0 on success or a negative error code on failure.
909f1d7ae31SEmmanuel Vadot  */
910f1d7ae31SEmmanuel Vadot int
hdmi_infoframe_check(union hdmi_infoframe * frame)911f1d7ae31SEmmanuel Vadot hdmi_infoframe_check(union hdmi_infoframe *frame)
912f1d7ae31SEmmanuel Vadot {
913f1d7ae31SEmmanuel Vadot 	switch (frame->any.type) {
914f1d7ae31SEmmanuel Vadot 	case HDMI_INFOFRAME_TYPE_AVI:
915f1d7ae31SEmmanuel Vadot 		return hdmi_avi_infoframe_check(&frame->avi);
916f1d7ae31SEmmanuel Vadot 	case HDMI_INFOFRAME_TYPE_SPD:
917f1d7ae31SEmmanuel Vadot 		return hdmi_spd_infoframe_check(&frame->spd);
918f1d7ae31SEmmanuel Vadot 	case HDMI_INFOFRAME_TYPE_AUDIO:
919f1d7ae31SEmmanuel Vadot 		return hdmi_audio_infoframe_check(&frame->audio);
920f1d7ae31SEmmanuel Vadot 	case HDMI_INFOFRAME_TYPE_VENDOR:
921f1d7ae31SEmmanuel Vadot 		return hdmi_vendor_any_infoframe_check(&frame->vendor);
922f1d7ae31SEmmanuel Vadot 	default:
923f1d7ae31SEmmanuel Vadot 		WARN(1, "Bad infoframe type %d\n", frame->any.type);
924f1d7ae31SEmmanuel Vadot 		return -EINVAL;
925f1d7ae31SEmmanuel Vadot 	}
926f1d7ae31SEmmanuel Vadot }
927f1d7ae31SEmmanuel Vadot EXPORT_SYMBOL(hdmi_infoframe_check);
928f1d7ae31SEmmanuel Vadot 
929f1d7ae31SEmmanuel Vadot /**
930f1d7ae31SEmmanuel Vadot  * hdmi_infoframe_pack_only() - write a HDMI infoframe to binary buffer
931f1d7ae31SEmmanuel Vadot  * @frame: HDMI infoframe
932f1d7ae31SEmmanuel Vadot  * @buffer: destination buffer
933f1d7ae31SEmmanuel Vadot  * @size: size of buffer
934f1d7ae31SEmmanuel Vadot  *
935f1d7ae31SEmmanuel Vadot  * Packs the information contained in the @frame structure into a binary
936f1d7ae31SEmmanuel Vadot  * representation that can be written into the corresponding controller
937f1d7ae31SEmmanuel Vadot  * registers. Also computes the checksum as required by section 5.3.5 of
938f1d7ae31SEmmanuel Vadot  * the HDMI 1.4 specification.
939f1d7ae31SEmmanuel Vadot  *
940f1d7ae31SEmmanuel Vadot  * Returns the number of bytes packed into the binary buffer or a negative
941f1d7ae31SEmmanuel Vadot  * error code on failure.
942f1d7ae31SEmmanuel Vadot  */
943f1d7ae31SEmmanuel Vadot ssize_t
hdmi_infoframe_pack_only(const union hdmi_infoframe * frame,void * buffer,size_t size)944f1d7ae31SEmmanuel Vadot hdmi_infoframe_pack_only(const union hdmi_infoframe *frame, void *buffer, size_t size)
945f1d7ae31SEmmanuel Vadot {
946f1d7ae31SEmmanuel Vadot 	ssize_t length;
947f1d7ae31SEmmanuel Vadot 
948f1d7ae31SEmmanuel Vadot 	switch (frame->any.type) {
949f1d7ae31SEmmanuel Vadot 	case HDMI_INFOFRAME_TYPE_AVI:
950f1d7ae31SEmmanuel Vadot 		length = hdmi_avi_infoframe_pack_only(&frame->avi,
951f1d7ae31SEmmanuel Vadot 						      buffer, size);
952f1d7ae31SEmmanuel Vadot 		break;
953f1d7ae31SEmmanuel Vadot 	case HDMI_INFOFRAME_TYPE_DRM:
954f1d7ae31SEmmanuel Vadot 		length = hdmi_drm_infoframe_pack_only(&frame->drm,
955f1d7ae31SEmmanuel Vadot 						      buffer, size);
956f1d7ae31SEmmanuel Vadot 		break;
957f1d7ae31SEmmanuel Vadot 	case HDMI_INFOFRAME_TYPE_SPD:
958f1d7ae31SEmmanuel Vadot 		length = hdmi_spd_infoframe_pack_only(&frame->spd,
959f1d7ae31SEmmanuel Vadot 						      buffer, size);
960f1d7ae31SEmmanuel Vadot 		break;
961f1d7ae31SEmmanuel Vadot 	case HDMI_INFOFRAME_TYPE_AUDIO:
962f1d7ae31SEmmanuel Vadot 		length = hdmi_audio_infoframe_pack_only(&frame->audio,
963f1d7ae31SEmmanuel Vadot 							buffer, size);
964f1d7ae31SEmmanuel Vadot 		break;
965f1d7ae31SEmmanuel Vadot 	case HDMI_INFOFRAME_TYPE_VENDOR:
966f1d7ae31SEmmanuel Vadot 		length = hdmi_vendor_any_infoframe_pack_only(&frame->vendor,
967f1d7ae31SEmmanuel Vadot 							     buffer, size);
968f1d7ae31SEmmanuel Vadot 		break;
969f1d7ae31SEmmanuel Vadot 	default:
970f1d7ae31SEmmanuel Vadot 		WARN(1, "Bad infoframe type %d\n", frame->any.type);
971f1d7ae31SEmmanuel Vadot 		length = -EINVAL;
972f1d7ae31SEmmanuel Vadot 	}
973f1d7ae31SEmmanuel Vadot 
974f1d7ae31SEmmanuel Vadot 	return length;
975f1d7ae31SEmmanuel Vadot }
976f1d7ae31SEmmanuel Vadot EXPORT_SYMBOL(hdmi_infoframe_pack_only);
977f1d7ae31SEmmanuel Vadot 
978f1d7ae31SEmmanuel Vadot /**
979f1d7ae31SEmmanuel Vadot  * hdmi_infoframe_pack() - check a HDMI infoframe,
980f1d7ae31SEmmanuel Vadot  *                         and write it to binary buffer
981f1d7ae31SEmmanuel Vadot  * @frame: HDMI infoframe
982f1d7ae31SEmmanuel Vadot  * @buffer: destination buffer
983f1d7ae31SEmmanuel Vadot  * @size: size of buffer
984f1d7ae31SEmmanuel Vadot  *
985f1d7ae31SEmmanuel Vadot  * Validates that the infoframe is consistent and updates derived fields
986f1d7ae31SEmmanuel Vadot  * (eg. length) based on other fields, after which it packs the information
987f1d7ae31SEmmanuel Vadot  * contained in the @frame structure into a binary representation that
988f1d7ae31SEmmanuel Vadot  * can be written into the corresponding controller registers. This function
989f1d7ae31SEmmanuel Vadot  * also computes the checksum as required by section 5.3.5 of the HDMI 1.4
990f1d7ae31SEmmanuel Vadot  * specification.
991f1d7ae31SEmmanuel Vadot  *
992f1d7ae31SEmmanuel Vadot  * Returns the number of bytes packed into the binary buffer or a negative
993f1d7ae31SEmmanuel Vadot  * error code on failure.
994f1d7ae31SEmmanuel Vadot  */
995f1d7ae31SEmmanuel Vadot ssize_t
hdmi_infoframe_pack(union hdmi_infoframe * frame,void * buffer,size_t size)996f1d7ae31SEmmanuel Vadot hdmi_infoframe_pack(union hdmi_infoframe *frame,
997f1d7ae31SEmmanuel Vadot 		    void *buffer, size_t size)
998f1d7ae31SEmmanuel Vadot {
999f1d7ae31SEmmanuel Vadot 	ssize_t length;
1000f1d7ae31SEmmanuel Vadot 
1001f1d7ae31SEmmanuel Vadot 	switch (frame->any.type) {
1002f1d7ae31SEmmanuel Vadot 	case HDMI_INFOFRAME_TYPE_AVI:
1003f1d7ae31SEmmanuel Vadot 		length = hdmi_avi_infoframe_pack(&frame->avi, buffer, size);
1004f1d7ae31SEmmanuel Vadot 		break;
1005f1d7ae31SEmmanuel Vadot 	case HDMI_INFOFRAME_TYPE_DRM:
1006f1d7ae31SEmmanuel Vadot 		length = hdmi_drm_infoframe_pack(&frame->drm, buffer, size);
1007f1d7ae31SEmmanuel Vadot 		break;
1008f1d7ae31SEmmanuel Vadot 	case HDMI_INFOFRAME_TYPE_SPD:
1009f1d7ae31SEmmanuel Vadot 		length = hdmi_spd_infoframe_pack(&frame->spd, buffer, size);
1010f1d7ae31SEmmanuel Vadot 		break;
1011f1d7ae31SEmmanuel Vadot 	case HDMI_INFOFRAME_TYPE_AUDIO:
1012f1d7ae31SEmmanuel Vadot 		length = hdmi_audio_infoframe_pack(&frame->audio, buffer, size);
1013f1d7ae31SEmmanuel Vadot 		break;
1014f1d7ae31SEmmanuel Vadot 	case HDMI_INFOFRAME_TYPE_VENDOR:
1015f1d7ae31SEmmanuel Vadot 		length = hdmi_vendor_any_infoframe_pack(&frame->vendor,
1016f1d7ae31SEmmanuel Vadot 							buffer, size);
1017f1d7ae31SEmmanuel Vadot 		break;
1018f1d7ae31SEmmanuel Vadot 	default:
1019f1d7ae31SEmmanuel Vadot 		WARN(1, "Bad infoframe type %d\n", frame->any.type);
1020f1d7ae31SEmmanuel Vadot 		length = -EINVAL;
1021f1d7ae31SEmmanuel Vadot 	}
1022f1d7ae31SEmmanuel Vadot 
1023f1d7ae31SEmmanuel Vadot 	return length;
1024f1d7ae31SEmmanuel Vadot }
1025f1d7ae31SEmmanuel Vadot EXPORT_SYMBOL(hdmi_infoframe_pack);
1026f1d7ae31SEmmanuel Vadot 
hdmi_infoframe_type_get_name(enum hdmi_infoframe_type type)1027f1d7ae31SEmmanuel Vadot static const char *hdmi_infoframe_type_get_name(enum hdmi_infoframe_type type)
1028f1d7ae31SEmmanuel Vadot {
1029f1d7ae31SEmmanuel Vadot 	if (type < 0x80 || type > 0x9f)
1030f1d7ae31SEmmanuel Vadot 		return "Invalid";
1031f1d7ae31SEmmanuel Vadot 	switch (type) {
1032f1d7ae31SEmmanuel Vadot 	case HDMI_INFOFRAME_TYPE_VENDOR:
1033f1d7ae31SEmmanuel Vadot 		return "Vendor";
1034f1d7ae31SEmmanuel Vadot 	case HDMI_INFOFRAME_TYPE_AVI:
1035f1d7ae31SEmmanuel Vadot 		return "Auxiliary Video Information (AVI)";
1036f1d7ae31SEmmanuel Vadot 	case HDMI_INFOFRAME_TYPE_SPD:
1037f1d7ae31SEmmanuel Vadot 		return "Source Product Description (SPD)";
1038f1d7ae31SEmmanuel Vadot 	case HDMI_INFOFRAME_TYPE_AUDIO:
1039f1d7ae31SEmmanuel Vadot 		return "Audio";
1040f1d7ae31SEmmanuel Vadot 	case HDMI_INFOFRAME_TYPE_DRM:
1041f1d7ae31SEmmanuel Vadot 		return "Dynamic Range and Mastering";
1042f1d7ae31SEmmanuel Vadot 	}
1043f1d7ae31SEmmanuel Vadot 	return "Reserved";
1044f1d7ae31SEmmanuel Vadot }
1045f1d7ae31SEmmanuel Vadot 
hdmi_infoframe_log_header(const char * level,struct device * dev,const struct hdmi_any_infoframe * frame)1046f1d7ae31SEmmanuel Vadot static void hdmi_infoframe_log_header(const char *level,
1047f1d7ae31SEmmanuel Vadot 				      struct device *dev,
1048f1d7ae31SEmmanuel Vadot 				      const struct hdmi_any_infoframe *frame)
1049f1d7ae31SEmmanuel Vadot {
1050f1d7ae31SEmmanuel Vadot 	hdmi_log("HDMI infoframe: %s, version %u, length %u\n",
1051f1d7ae31SEmmanuel Vadot 		hdmi_infoframe_type_get_name(frame->type),
1052f1d7ae31SEmmanuel Vadot 		frame->version, frame->length);
1053f1d7ae31SEmmanuel Vadot }
1054f1d7ae31SEmmanuel Vadot 
hdmi_colorspace_get_name(enum hdmi_colorspace colorspace)1055f1d7ae31SEmmanuel Vadot static const char *hdmi_colorspace_get_name(enum hdmi_colorspace colorspace)
1056f1d7ae31SEmmanuel Vadot {
1057f1d7ae31SEmmanuel Vadot 	switch (colorspace) {
1058f1d7ae31SEmmanuel Vadot 	case HDMI_COLORSPACE_RGB:
1059f1d7ae31SEmmanuel Vadot 		return "RGB";
1060f1d7ae31SEmmanuel Vadot 	case HDMI_COLORSPACE_YUV422:
1061f1d7ae31SEmmanuel Vadot 		return "YCbCr 4:2:2";
1062f1d7ae31SEmmanuel Vadot 	case HDMI_COLORSPACE_YUV444:
1063f1d7ae31SEmmanuel Vadot 		return "YCbCr 4:4:4";
1064f1d7ae31SEmmanuel Vadot 	case HDMI_COLORSPACE_YUV420:
1065f1d7ae31SEmmanuel Vadot 		return "YCbCr 4:2:0";
1066f1d7ae31SEmmanuel Vadot 	case HDMI_COLORSPACE_RESERVED4:
1067f1d7ae31SEmmanuel Vadot 		return "Reserved (4)";
1068f1d7ae31SEmmanuel Vadot 	case HDMI_COLORSPACE_RESERVED5:
1069f1d7ae31SEmmanuel Vadot 		return "Reserved (5)";
1070f1d7ae31SEmmanuel Vadot 	case HDMI_COLORSPACE_RESERVED6:
1071f1d7ae31SEmmanuel Vadot 		return "Reserved (6)";
1072f1d7ae31SEmmanuel Vadot 	case HDMI_COLORSPACE_IDO_DEFINED:
1073f1d7ae31SEmmanuel Vadot 		return "IDO Defined";
1074f1d7ae31SEmmanuel Vadot 	}
1075f1d7ae31SEmmanuel Vadot 	return "Invalid";
1076f1d7ae31SEmmanuel Vadot }
1077f1d7ae31SEmmanuel Vadot 
hdmi_scan_mode_get_name(enum hdmi_scan_mode scan_mode)1078f1d7ae31SEmmanuel Vadot static const char *hdmi_scan_mode_get_name(enum hdmi_scan_mode scan_mode)
1079f1d7ae31SEmmanuel Vadot {
1080f1d7ae31SEmmanuel Vadot 	switch (scan_mode) {
1081f1d7ae31SEmmanuel Vadot 	case HDMI_SCAN_MODE_NONE:
1082f1d7ae31SEmmanuel Vadot 		return "No Data";
1083f1d7ae31SEmmanuel Vadot 	case HDMI_SCAN_MODE_OVERSCAN:
1084f1d7ae31SEmmanuel Vadot 		return "Overscan";
1085f1d7ae31SEmmanuel Vadot 	case HDMI_SCAN_MODE_UNDERSCAN:
1086f1d7ae31SEmmanuel Vadot 		return "Underscan";
1087f1d7ae31SEmmanuel Vadot 	case HDMI_SCAN_MODE_RESERVED:
1088f1d7ae31SEmmanuel Vadot 		return "Reserved";
1089f1d7ae31SEmmanuel Vadot 	}
1090f1d7ae31SEmmanuel Vadot 	return "Invalid";
1091f1d7ae31SEmmanuel Vadot }
1092f1d7ae31SEmmanuel Vadot 
hdmi_colorimetry_get_name(enum hdmi_colorimetry colorimetry)1093f1d7ae31SEmmanuel Vadot static const char *hdmi_colorimetry_get_name(enum hdmi_colorimetry colorimetry)
1094f1d7ae31SEmmanuel Vadot {
1095f1d7ae31SEmmanuel Vadot 	switch (colorimetry) {
1096f1d7ae31SEmmanuel Vadot 	case HDMI_COLORIMETRY_NONE:
1097f1d7ae31SEmmanuel Vadot 		return "No Data";
1098f1d7ae31SEmmanuel Vadot 	case HDMI_COLORIMETRY_ITU_601:
1099f1d7ae31SEmmanuel Vadot 		return "ITU601";
1100f1d7ae31SEmmanuel Vadot 	case HDMI_COLORIMETRY_ITU_709:
1101f1d7ae31SEmmanuel Vadot 		return "ITU709";
1102f1d7ae31SEmmanuel Vadot 	case HDMI_COLORIMETRY_EXTENDED:
1103f1d7ae31SEmmanuel Vadot 		return "Extended";
1104f1d7ae31SEmmanuel Vadot 	}
1105f1d7ae31SEmmanuel Vadot 	return "Invalid";
1106f1d7ae31SEmmanuel Vadot }
1107f1d7ae31SEmmanuel Vadot 
1108f1d7ae31SEmmanuel Vadot static const char *
hdmi_picture_aspect_get_name(enum hdmi_picture_aspect picture_aspect)1109f1d7ae31SEmmanuel Vadot hdmi_picture_aspect_get_name(enum hdmi_picture_aspect picture_aspect)
1110f1d7ae31SEmmanuel Vadot {
1111f1d7ae31SEmmanuel Vadot 	switch (picture_aspect) {
1112f1d7ae31SEmmanuel Vadot 	case HDMI_PICTURE_ASPECT_NONE:
1113f1d7ae31SEmmanuel Vadot 		return "No Data";
1114f1d7ae31SEmmanuel Vadot 	case HDMI_PICTURE_ASPECT_4_3:
1115f1d7ae31SEmmanuel Vadot 		return "4:3";
1116f1d7ae31SEmmanuel Vadot 	case HDMI_PICTURE_ASPECT_16_9:
1117f1d7ae31SEmmanuel Vadot 		return "16:9";
1118f1d7ae31SEmmanuel Vadot 	case HDMI_PICTURE_ASPECT_64_27:
1119f1d7ae31SEmmanuel Vadot 		return "64:27";
1120f1d7ae31SEmmanuel Vadot 	case HDMI_PICTURE_ASPECT_256_135:
1121f1d7ae31SEmmanuel Vadot 		return "256:135";
1122f1d7ae31SEmmanuel Vadot 	case HDMI_PICTURE_ASPECT_RESERVED:
1123f1d7ae31SEmmanuel Vadot 		return "Reserved";
1124f1d7ae31SEmmanuel Vadot 	}
1125f1d7ae31SEmmanuel Vadot 	return "Invalid";
1126f1d7ae31SEmmanuel Vadot }
1127f1d7ae31SEmmanuel Vadot 
1128f1d7ae31SEmmanuel Vadot static const char *
hdmi_active_aspect_get_name(enum hdmi_active_aspect active_aspect)1129f1d7ae31SEmmanuel Vadot hdmi_active_aspect_get_name(enum hdmi_active_aspect active_aspect)
1130f1d7ae31SEmmanuel Vadot {
1131f1d7ae31SEmmanuel Vadot 	if (active_aspect < 0 || active_aspect > 0xf)
1132f1d7ae31SEmmanuel Vadot 		return "Invalid";
1133f1d7ae31SEmmanuel Vadot 
1134f1d7ae31SEmmanuel Vadot 	switch (active_aspect) {
1135f1d7ae31SEmmanuel Vadot 	case HDMI_ACTIVE_ASPECT_16_9_TOP:
1136f1d7ae31SEmmanuel Vadot 		return "16:9 Top";
1137f1d7ae31SEmmanuel Vadot 	case HDMI_ACTIVE_ASPECT_14_9_TOP:
1138f1d7ae31SEmmanuel Vadot 		return "14:9 Top";
1139f1d7ae31SEmmanuel Vadot 	case HDMI_ACTIVE_ASPECT_16_9_CENTER:
1140f1d7ae31SEmmanuel Vadot 		return "16:9 Center";
1141f1d7ae31SEmmanuel Vadot 	case HDMI_ACTIVE_ASPECT_PICTURE:
1142f1d7ae31SEmmanuel Vadot 		return "Same as Picture";
1143f1d7ae31SEmmanuel Vadot 	case HDMI_ACTIVE_ASPECT_4_3:
1144f1d7ae31SEmmanuel Vadot 		return "4:3";
1145f1d7ae31SEmmanuel Vadot 	case HDMI_ACTIVE_ASPECT_16_9:
1146f1d7ae31SEmmanuel Vadot 		return "16:9";
1147f1d7ae31SEmmanuel Vadot 	case HDMI_ACTIVE_ASPECT_14_9:
1148f1d7ae31SEmmanuel Vadot 		return "14:9";
1149f1d7ae31SEmmanuel Vadot 	case HDMI_ACTIVE_ASPECT_4_3_SP_14_9:
1150f1d7ae31SEmmanuel Vadot 		return "4:3 SP 14:9";
1151f1d7ae31SEmmanuel Vadot 	case HDMI_ACTIVE_ASPECT_16_9_SP_14_9:
1152f1d7ae31SEmmanuel Vadot 		return "16:9 SP 14:9";
1153f1d7ae31SEmmanuel Vadot 	case HDMI_ACTIVE_ASPECT_16_9_SP_4_3:
1154f1d7ae31SEmmanuel Vadot 		return "16:9 SP 4:3";
1155f1d7ae31SEmmanuel Vadot 	}
1156f1d7ae31SEmmanuel Vadot 	return "Reserved";
1157f1d7ae31SEmmanuel Vadot }
1158f1d7ae31SEmmanuel Vadot 
1159f1d7ae31SEmmanuel Vadot static const char *
hdmi_extended_colorimetry_get_name(enum hdmi_extended_colorimetry ext_col)1160f1d7ae31SEmmanuel Vadot hdmi_extended_colorimetry_get_name(enum hdmi_extended_colorimetry ext_col)
1161f1d7ae31SEmmanuel Vadot {
1162f1d7ae31SEmmanuel Vadot 	switch (ext_col) {
1163f1d7ae31SEmmanuel Vadot 	case HDMI_EXTENDED_COLORIMETRY_XV_YCC_601:
1164f1d7ae31SEmmanuel Vadot 		return "xvYCC 601";
1165f1d7ae31SEmmanuel Vadot 	case HDMI_EXTENDED_COLORIMETRY_XV_YCC_709:
1166f1d7ae31SEmmanuel Vadot 		return "xvYCC 709";
1167f1d7ae31SEmmanuel Vadot 	case HDMI_EXTENDED_COLORIMETRY_S_YCC_601:
1168f1d7ae31SEmmanuel Vadot 		return "sYCC 601";
1169f1d7ae31SEmmanuel Vadot 	case HDMI_EXTENDED_COLORIMETRY_OPYCC_601:
1170f1d7ae31SEmmanuel Vadot 		return "opYCC 601";
1171f1d7ae31SEmmanuel Vadot 	case HDMI_EXTENDED_COLORIMETRY_OPRGB:
1172f1d7ae31SEmmanuel Vadot 		return "opRGB";
1173f1d7ae31SEmmanuel Vadot 	case HDMI_EXTENDED_COLORIMETRY_BT2020_CONST_LUM:
1174f1d7ae31SEmmanuel Vadot 		return "BT.2020 Constant Luminance";
1175f1d7ae31SEmmanuel Vadot 	case HDMI_EXTENDED_COLORIMETRY_BT2020:
1176f1d7ae31SEmmanuel Vadot 		return "BT.2020";
1177f1d7ae31SEmmanuel Vadot 	case HDMI_EXTENDED_COLORIMETRY_RESERVED:
1178f1d7ae31SEmmanuel Vadot 		return "Reserved";
1179f1d7ae31SEmmanuel Vadot 	}
1180f1d7ae31SEmmanuel Vadot 	return "Invalid";
1181f1d7ae31SEmmanuel Vadot }
1182f1d7ae31SEmmanuel Vadot 
1183f1d7ae31SEmmanuel Vadot static const char *
hdmi_quantization_range_get_name(enum hdmi_quantization_range qrange)1184f1d7ae31SEmmanuel Vadot hdmi_quantization_range_get_name(enum hdmi_quantization_range qrange)
1185f1d7ae31SEmmanuel Vadot {
1186f1d7ae31SEmmanuel Vadot 	switch (qrange) {
1187f1d7ae31SEmmanuel Vadot 	case HDMI_QUANTIZATION_RANGE_DEFAULT:
1188f1d7ae31SEmmanuel Vadot 		return "Default";
1189f1d7ae31SEmmanuel Vadot 	case HDMI_QUANTIZATION_RANGE_LIMITED:
1190f1d7ae31SEmmanuel Vadot 		return "Limited";
1191f1d7ae31SEmmanuel Vadot 	case HDMI_QUANTIZATION_RANGE_FULL:
1192f1d7ae31SEmmanuel Vadot 		return "Full";
1193f1d7ae31SEmmanuel Vadot 	case HDMI_QUANTIZATION_RANGE_RESERVED:
1194f1d7ae31SEmmanuel Vadot 		return "Reserved";
1195f1d7ae31SEmmanuel Vadot 	}
1196f1d7ae31SEmmanuel Vadot 	return "Invalid";
1197f1d7ae31SEmmanuel Vadot }
1198f1d7ae31SEmmanuel Vadot 
hdmi_nups_get_name(enum hdmi_nups nups)1199f1d7ae31SEmmanuel Vadot static const char *hdmi_nups_get_name(enum hdmi_nups nups)
1200f1d7ae31SEmmanuel Vadot {
1201f1d7ae31SEmmanuel Vadot 	switch (nups) {
1202f1d7ae31SEmmanuel Vadot 	case HDMI_NUPS_UNKNOWN:
1203f1d7ae31SEmmanuel Vadot 		return "Unknown Non-uniform Scaling";
1204f1d7ae31SEmmanuel Vadot 	case HDMI_NUPS_HORIZONTAL:
1205f1d7ae31SEmmanuel Vadot 		return "Horizontally Scaled";
1206f1d7ae31SEmmanuel Vadot 	case HDMI_NUPS_VERTICAL:
1207f1d7ae31SEmmanuel Vadot 		return "Vertically Scaled";
1208f1d7ae31SEmmanuel Vadot 	case HDMI_NUPS_BOTH:
1209f1d7ae31SEmmanuel Vadot 		return "Horizontally and Vertically Scaled";
1210f1d7ae31SEmmanuel Vadot 	}
1211f1d7ae31SEmmanuel Vadot 	return "Invalid";
1212f1d7ae31SEmmanuel Vadot }
1213f1d7ae31SEmmanuel Vadot 
1214f1d7ae31SEmmanuel Vadot static const char *
hdmi_ycc_quantization_range_get_name(enum hdmi_ycc_quantization_range qrange)1215f1d7ae31SEmmanuel Vadot hdmi_ycc_quantization_range_get_name(enum hdmi_ycc_quantization_range qrange)
1216f1d7ae31SEmmanuel Vadot {
1217f1d7ae31SEmmanuel Vadot 	switch (qrange) {
1218f1d7ae31SEmmanuel Vadot 	case HDMI_YCC_QUANTIZATION_RANGE_LIMITED:
1219f1d7ae31SEmmanuel Vadot 		return "Limited";
1220f1d7ae31SEmmanuel Vadot 	case HDMI_YCC_QUANTIZATION_RANGE_FULL:
1221f1d7ae31SEmmanuel Vadot 		return "Full";
1222f1d7ae31SEmmanuel Vadot 	}
1223f1d7ae31SEmmanuel Vadot 	return "Invalid";
1224f1d7ae31SEmmanuel Vadot }
1225f1d7ae31SEmmanuel Vadot 
1226f1d7ae31SEmmanuel Vadot static const char *
hdmi_content_type_get_name(enum hdmi_content_type content_type)1227f1d7ae31SEmmanuel Vadot hdmi_content_type_get_name(enum hdmi_content_type content_type)
1228f1d7ae31SEmmanuel Vadot {
1229f1d7ae31SEmmanuel Vadot 	switch (content_type) {
1230f1d7ae31SEmmanuel Vadot 	case HDMI_CONTENT_TYPE_GRAPHICS:
1231f1d7ae31SEmmanuel Vadot 		return "Graphics";
1232f1d7ae31SEmmanuel Vadot 	case HDMI_CONTENT_TYPE_PHOTO:
1233f1d7ae31SEmmanuel Vadot 		return "Photo";
1234f1d7ae31SEmmanuel Vadot 	case HDMI_CONTENT_TYPE_CINEMA:
1235f1d7ae31SEmmanuel Vadot 		return "Cinema";
1236f1d7ae31SEmmanuel Vadot 	case HDMI_CONTENT_TYPE_GAME:
1237f1d7ae31SEmmanuel Vadot 		return "Game";
1238f1d7ae31SEmmanuel Vadot 	}
1239f1d7ae31SEmmanuel Vadot 	return "Invalid";
1240f1d7ae31SEmmanuel Vadot }
1241f1d7ae31SEmmanuel Vadot 
hdmi_avi_infoframe_log(const char * level,struct device * dev,const struct hdmi_avi_infoframe * frame)1242f1d7ae31SEmmanuel Vadot static void hdmi_avi_infoframe_log(const char *level,
1243f1d7ae31SEmmanuel Vadot 				   struct device *dev,
1244f1d7ae31SEmmanuel Vadot 				   const struct hdmi_avi_infoframe *frame)
1245f1d7ae31SEmmanuel Vadot {
1246f1d7ae31SEmmanuel Vadot 	hdmi_infoframe_log_header(level, dev,
1247f1d7ae31SEmmanuel Vadot 				  (const struct hdmi_any_infoframe *)frame);
1248f1d7ae31SEmmanuel Vadot 
1249f1d7ae31SEmmanuel Vadot 	hdmi_log("    colorspace: %s\n",
1250f1d7ae31SEmmanuel Vadot 			hdmi_colorspace_get_name(frame->colorspace));
1251f1d7ae31SEmmanuel Vadot 	hdmi_log("    scan mode: %s\n",
1252f1d7ae31SEmmanuel Vadot 			hdmi_scan_mode_get_name(frame->scan_mode));
1253f1d7ae31SEmmanuel Vadot 	hdmi_log("    colorimetry: %s\n",
1254f1d7ae31SEmmanuel Vadot 			hdmi_colorimetry_get_name(frame->colorimetry));
1255f1d7ae31SEmmanuel Vadot 	hdmi_log("    picture aspect: %s\n",
1256f1d7ae31SEmmanuel Vadot 			hdmi_picture_aspect_get_name(frame->picture_aspect));
1257f1d7ae31SEmmanuel Vadot 	hdmi_log("    active aspect: %s\n",
1258f1d7ae31SEmmanuel Vadot 			hdmi_active_aspect_get_name(frame->active_aspect));
1259f1d7ae31SEmmanuel Vadot 	hdmi_log("    itc: %s\n", frame->itc ? "IT Content" : "No Data");
1260f1d7ae31SEmmanuel Vadot 	hdmi_log("    extended colorimetry: %s\n",
1261f1d7ae31SEmmanuel Vadot 			hdmi_extended_colorimetry_get_name(frame->extended_colorimetry));
1262f1d7ae31SEmmanuel Vadot 	hdmi_log("    quantization range: %s\n",
1263f1d7ae31SEmmanuel Vadot 			hdmi_quantization_range_get_name(frame->quantization_range));
1264f1d7ae31SEmmanuel Vadot 	hdmi_log("    nups: %s\n", hdmi_nups_get_name(frame->nups));
1265f1d7ae31SEmmanuel Vadot 	hdmi_log("    video code: %u\n", frame->video_code);
1266f1d7ae31SEmmanuel Vadot 	hdmi_log("    ycc quantization range: %s\n",
1267f1d7ae31SEmmanuel Vadot 			hdmi_ycc_quantization_range_get_name(frame->ycc_quantization_range));
1268f1d7ae31SEmmanuel Vadot 	hdmi_log("    hdmi content type: %s\n",
1269f1d7ae31SEmmanuel Vadot 			hdmi_content_type_get_name(frame->content_type));
1270f1d7ae31SEmmanuel Vadot 	hdmi_log("    pixel repeat: %u\n", frame->pixel_repeat);
1271f1d7ae31SEmmanuel Vadot 	hdmi_log("    bar top %u, bottom %u, left %u, right %u\n",
1272f1d7ae31SEmmanuel Vadot 			frame->top_bar, frame->bottom_bar,
1273f1d7ae31SEmmanuel Vadot 			frame->left_bar, frame->right_bar);
1274f1d7ae31SEmmanuel Vadot }
1275f1d7ae31SEmmanuel Vadot 
hdmi_spd_sdi_get_name(enum hdmi_spd_sdi sdi)1276f1d7ae31SEmmanuel Vadot static const char *hdmi_spd_sdi_get_name(enum hdmi_spd_sdi sdi)
1277f1d7ae31SEmmanuel Vadot {
1278f1d7ae31SEmmanuel Vadot 	if (sdi < 0 || sdi > 0xff)
1279f1d7ae31SEmmanuel Vadot 		return "Invalid";
1280f1d7ae31SEmmanuel Vadot 	switch (sdi) {
1281f1d7ae31SEmmanuel Vadot 	case HDMI_SPD_SDI_UNKNOWN:
1282f1d7ae31SEmmanuel Vadot 		return "Unknown";
1283f1d7ae31SEmmanuel Vadot 	case HDMI_SPD_SDI_DSTB:
1284f1d7ae31SEmmanuel Vadot 		return "Digital STB";
1285f1d7ae31SEmmanuel Vadot 	case HDMI_SPD_SDI_DVDP:
1286f1d7ae31SEmmanuel Vadot 		return "DVD Player";
1287f1d7ae31SEmmanuel Vadot 	case HDMI_SPD_SDI_DVHS:
1288f1d7ae31SEmmanuel Vadot 		return "D-VHS";
1289f1d7ae31SEmmanuel Vadot 	case HDMI_SPD_SDI_HDDVR:
1290f1d7ae31SEmmanuel Vadot 		return "HDD Videorecorder";
1291f1d7ae31SEmmanuel Vadot 	case HDMI_SPD_SDI_DVC:
1292f1d7ae31SEmmanuel Vadot 		return "DVC";
1293f1d7ae31SEmmanuel Vadot 	case HDMI_SPD_SDI_DSC:
1294f1d7ae31SEmmanuel Vadot 		return "DSC";
1295f1d7ae31SEmmanuel Vadot 	case HDMI_SPD_SDI_VCD:
1296f1d7ae31SEmmanuel Vadot 		return "Video CD";
1297f1d7ae31SEmmanuel Vadot 	case HDMI_SPD_SDI_GAME:
1298f1d7ae31SEmmanuel Vadot 		return "Game";
1299f1d7ae31SEmmanuel Vadot 	case HDMI_SPD_SDI_PC:
1300f1d7ae31SEmmanuel Vadot 		return "PC General";
1301f1d7ae31SEmmanuel Vadot 	case HDMI_SPD_SDI_BD:
1302f1d7ae31SEmmanuel Vadot 		return "Blu-Ray Disc (BD)";
1303f1d7ae31SEmmanuel Vadot 	case HDMI_SPD_SDI_SACD:
1304f1d7ae31SEmmanuel Vadot 		return "Super Audio CD";
1305f1d7ae31SEmmanuel Vadot 	case HDMI_SPD_SDI_HDDVD:
1306f1d7ae31SEmmanuel Vadot 		return "HD DVD";
1307f1d7ae31SEmmanuel Vadot 	case HDMI_SPD_SDI_PMP:
1308f1d7ae31SEmmanuel Vadot 		return "PMP";
1309f1d7ae31SEmmanuel Vadot 	}
1310f1d7ae31SEmmanuel Vadot 	return "Reserved";
1311f1d7ae31SEmmanuel Vadot }
1312f1d7ae31SEmmanuel Vadot 
hdmi_spd_infoframe_log(const char * level,struct device * dev,const struct hdmi_spd_infoframe * frame)1313f1d7ae31SEmmanuel Vadot static void hdmi_spd_infoframe_log(const char *level,
1314f1d7ae31SEmmanuel Vadot 				   struct device *dev,
1315f1d7ae31SEmmanuel Vadot 				   const struct hdmi_spd_infoframe *frame)
1316f1d7ae31SEmmanuel Vadot {
1317f1d7ae31SEmmanuel Vadot 	u8 buf[17];
1318f1d7ae31SEmmanuel Vadot 
1319f1d7ae31SEmmanuel Vadot 	hdmi_infoframe_log_header(level, dev,
1320f1d7ae31SEmmanuel Vadot 				  (const struct hdmi_any_infoframe *)frame);
1321f1d7ae31SEmmanuel Vadot 
1322f1d7ae31SEmmanuel Vadot 	memset(buf, 0, sizeof(buf));
1323f1d7ae31SEmmanuel Vadot 
1324f1d7ae31SEmmanuel Vadot 	strncpy(buf, frame->vendor, 8);
1325f1d7ae31SEmmanuel Vadot 	hdmi_log("    vendor: %s\n", buf);
1326f1d7ae31SEmmanuel Vadot 	strncpy(buf, frame->product, 16);
1327f1d7ae31SEmmanuel Vadot 	hdmi_log("    product: %s\n", buf);
1328f1d7ae31SEmmanuel Vadot 	hdmi_log("    source device information: %s (0x%x)\n",
1329f1d7ae31SEmmanuel Vadot 		hdmi_spd_sdi_get_name(frame->sdi), frame->sdi);
1330f1d7ae31SEmmanuel Vadot }
1331f1d7ae31SEmmanuel Vadot 
1332f1d7ae31SEmmanuel Vadot static const char *
hdmi_audio_coding_type_get_name(enum hdmi_audio_coding_type coding_type)1333f1d7ae31SEmmanuel Vadot hdmi_audio_coding_type_get_name(enum hdmi_audio_coding_type coding_type)
1334f1d7ae31SEmmanuel Vadot {
1335f1d7ae31SEmmanuel Vadot 	switch (coding_type) {
1336f1d7ae31SEmmanuel Vadot 	case HDMI_AUDIO_CODING_TYPE_STREAM:
1337f1d7ae31SEmmanuel Vadot 		return "Refer to Stream Header";
1338f1d7ae31SEmmanuel Vadot 	case HDMI_AUDIO_CODING_TYPE_PCM:
1339f1d7ae31SEmmanuel Vadot 		return "PCM";
1340f1d7ae31SEmmanuel Vadot 	case HDMI_AUDIO_CODING_TYPE_AC3:
1341f1d7ae31SEmmanuel Vadot 		return "AC-3";
1342f1d7ae31SEmmanuel Vadot 	case HDMI_AUDIO_CODING_TYPE_MPEG1:
1343f1d7ae31SEmmanuel Vadot 		return "MPEG1";
1344f1d7ae31SEmmanuel Vadot 	case HDMI_AUDIO_CODING_TYPE_MP3:
1345f1d7ae31SEmmanuel Vadot 		return "MP3";
1346f1d7ae31SEmmanuel Vadot 	case HDMI_AUDIO_CODING_TYPE_MPEG2:
1347f1d7ae31SEmmanuel Vadot 		return "MPEG2";
1348f1d7ae31SEmmanuel Vadot 	case HDMI_AUDIO_CODING_TYPE_AAC_LC:
1349f1d7ae31SEmmanuel Vadot 		return "AAC";
1350f1d7ae31SEmmanuel Vadot 	case HDMI_AUDIO_CODING_TYPE_DTS:
1351f1d7ae31SEmmanuel Vadot 		return "DTS";
1352f1d7ae31SEmmanuel Vadot 	case HDMI_AUDIO_CODING_TYPE_ATRAC:
1353f1d7ae31SEmmanuel Vadot 		return "ATRAC";
1354f1d7ae31SEmmanuel Vadot 	case HDMI_AUDIO_CODING_TYPE_DSD:
1355f1d7ae31SEmmanuel Vadot 		return "One Bit Audio";
1356f1d7ae31SEmmanuel Vadot 	case HDMI_AUDIO_CODING_TYPE_EAC3:
1357f1d7ae31SEmmanuel Vadot 		return "Dolby Digital +";
1358f1d7ae31SEmmanuel Vadot 	case HDMI_AUDIO_CODING_TYPE_DTS_HD:
1359f1d7ae31SEmmanuel Vadot 		return "DTS-HD";
1360f1d7ae31SEmmanuel Vadot 	case HDMI_AUDIO_CODING_TYPE_MLP:
1361f1d7ae31SEmmanuel Vadot 		return "MAT (MLP)";
1362f1d7ae31SEmmanuel Vadot 	case HDMI_AUDIO_CODING_TYPE_DST:
1363f1d7ae31SEmmanuel Vadot 		return "DST";
1364f1d7ae31SEmmanuel Vadot 	case HDMI_AUDIO_CODING_TYPE_WMA_PRO:
1365f1d7ae31SEmmanuel Vadot 		return "WMA PRO";
1366f1d7ae31SEmmanuel Vadot 	case HDMI_AUDIO_CODING_TYPE_CXT:
1367f1d7ae31SEmmanuel Vadot 		return "Refer to CXT";
1368f1d7ae31SEmmanuel Vadot 	}
1369f1d7ae31SEmmanuel Vadot 	return "Invalid";
1370f1d7ae31SEmmanuel Vadot }
1371f1d7ae31SEmmanuel Vadot 
1372f1d7ae31SEmmanuel Vadot static const char *
hdmi_audio_sample_size_get_name(enum hdmi_audio_sample_size sample_size)1373f1d7ae31SEmmanuel Vadot hdmi_audio_sample_size_get_name(enum hdmi_audio_sample_size sample_size)
1374f1d7ae31SEmmanuel Vadot {
1375f1d7ae31SEmmanuel Vadot 	switch (sample_size) {
1376f1d7ae31SEmmanuel Vadot 	case HDMI_AUDIO_SAMPLE_SIZE_STREAM:
1377f1d7ae31SEmmanuel Vadot 		return "Refer to Stream Header";
1378f1d7ae31SEmmanuel Vadot 	case HDMI_AUDIO_SAMPLE_SIZE_16:
1379f1d7ae31SEmmanuel Vadot 		return "16 bit";
1380f1d7ae31SEmmanuel Vadot 	case HDMI_AUDIO_SAMPLE_SIZE_20:
1381f1d7ae31SEmmanuel Vadot 		return "20 bit";
1382f1d7ae31SEmmanuel Vadot 	case HDMI_AUDIO_SAMPLE_SIZE_24:
1383f1d7ae31SEmmanuel Vadot 		return "24 bit";
1384f1d7ae31SEmmanuel Vadot 	}
1385f1d7ae31SEmmanuel Vadot 	return "Invalid";
1386f1d7ae31SEmmanuel Vadot }
1387f1d7ae31SEmmanuel Vadot 
1388f1d7ae31SEmmanuel Vadot static const char *
hdmi_audio_sample_frequency_get_name(enum hdmi_audio_sample_frequency freq)1389f1d7ae31SEmmanuel Vadot hdmi_audio_sample_frequency_get_name(enum hdmi_audio_sample_frequency freq)
1390f1d7ae31SEmmanuel Vadot {
1391f1d7ae31SEmmanuel Vadot 	switch (freq) {
1392f1d7ae31SEmmanuel Vadot 	case HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM:
1393f1d7ae31SEmmanuel Vadot 		return "Refer to Stream Header";
1394f1d7ae31SEmmanuel Vadot 	case HDMI_AUDIO_SAMPLE_FREQUENCY_32000:
1395f1d7ae31SEmmanuel Vadot 		return "32 kHz";
1396f1d7ae31SEmmanuel Vadot 	case HDMI_AUDIO_SAMPLE_FREQUENCY_44100:
1397f1d7ae31SEmmanuel Vadot 		return "44.1 kHz (CD)";
1398f1d7ae31SEmmanuel Vadot 	case HDMI_AUDIO_SAMPLE_FREQUENCY_48000:
1399f1d7ae31SEmmanuel Vadot 		return "48 kHz";
1400f1d7ae31SEmmanuel Vadot 	case HDMI_AUDIO_SAMPLE_FREQUENCY_88200:
1401f1d7ae31SEmmanuel Vadot 		return "88.2 kHz";
1402f1d7ae31SEmmanuel Vadot 	case HDMI_AUDIO_SAMPLE_FREQUENCY_96000:
1403f1d7ae31SEmmanuel Vadot 		return "96 kHz";
1404f1d7ae31SEmmanuel Vadot 	case HDMI_AUDIO_SAMPLE_FREQUENCY_176400:
1405f1d7ae31SEmmanuel Vadot 		return "176.4 kHz";
1406f1d7ae31SEmmanuel Vadot 	case HDMI_AUDIO_SAMPLE_FREQUENCY_192000:
1407f1d7ae31SEmmanuel Vadot 		return "192 kHz";
1408f1d7ae31SEmmanuel Vadot 	}
1409f1d7ae31SEmmanuel Vadot 	return "Invalid";
1410f1d7ae31SEmmanuel Vadot }
1411f1d7ae31SEmmanuel Vadot 
1412f1d7ae31SEmmanuel Vadot static const char *
hdmi_audio_coding_type_ext_get_name(enum hdmi_audio_coding_type_ext ctx)1413f1d7ae31SEmmanuel Vadot hdmi_audio_coding_type_ext_get_name(enum hdmi_audio_coding_type_ext ctx)
1414f1d7ae31SEmmanuel Vadot {
1415f1d7ae31SEmmanuel Vadot 	if (ctx < 0 || ctx > 0x1f)
1416f1d7ae31SEmmanuel Vadot 		return "Invalid";
1417f1d7ae31SEmmanuel Vadot 
1418f1d7ae31SEmmanuel Vadot 	switch (ctx) {
1419f1d7ae31SEmmanuel Vadot 	case HDMI_AUDIO_CODING_TYPE_EXT_CT:
1420f1d7ae31SEmmanuel Vadot 		return "Refer to CT";
1421f1d7ae31SEmmanuel Vadot 	case HDMI_AUDIO_CODING_TYPE_EXT_HE_AAC:
1422f1d7ae31SEmmanuel Vadot 		return "HE AAC";
1423f1d7ae31SEmmanuel Vadot 	case HDMI_AUDIO_CODING_TYPE_EXT_HE_AAC_V2:
1424f1d7ae31SEmmanuel Vadot 		return "HE AAC v2";
1425f1d7ae31SEmmanuel Vadot 	case HDMI_AUDIO_CODING_TYPE_EXT_MPEG_SURROUND:
1426f1d7ae31SEmmanuel Vadot 		return "MPEG SURROUND";
1427f1d7ae31SEmmanuel Vadot 	case HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_HE_AAC:
1428f1d7ae31SEmmanuel Vadot 		return "MPEG-4 HE AAC";
1429f1d7ae31SEmmanuel Vadot 	case HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_HE_AAC_V2:
1430f1d7ae31SEmmanuel Vadot 		return "MPEG-4 HE AAC v2";
1431f1d7ae31SEmmanuel Vadot 	case HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_AAC_LC:
1432f1d7ae31SEmmanuel Vadot 		return "MPEG-4 AAC LC";
1433f1d7ae31SEmmanuel Vadot 	case HDMI_AUDIO_CODING_TYPE_EXT_DRA:
1434f1d7ae31SEmmanuel Vadot 		return "DRA";
1435f1d7ae31SEmmanuel Vadot 	case HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_HE_AAC_SURROUND:
1436f1d7ae31SEmmanuel Vadot 		return "MPEG-4 HE AAC + MPEG Surround";
1437f1d7ae31SEmmanuel Vadot 	case HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_AAC_LC_SURROUND:
1438f1d7ae31SEmmanuel Vadot 		return "MPEG-4 AAC LC + MPEG Surround";
1439f1d7ae31SEmmanuel Vadot 	}
1440f1d7ae31SEmmanuel Vadot 	return "Reserved";
1441f1d7ae31SEmmanuel Vadot }
1442f1d7ae31SEmmanuel Vadot 
hdmi_audio_infoframe_log(const char * level,struct device * dev,const struct hdmi_audio_infoframe * frame)1443f1d7ae31SEmmanuel Vadot static void hdmi_audio_infoframe_log(const char *level,
1444f1d7ae31SEmmanuel Vadot 				     struct device *dev,
1445f1d7ae31SEmmanuel Vadot 				     const struct hdmi_audio_infoframe *frame)
1446f1d7ae31SEmmanuel Vadot {
1447f1d7ae31SEmmanuel Vadot 	hdmi_infoframe_log_header(level, dev,
1448f1d7ae31SEmmanuel Vadot 				  (const struct hdmi_any_infoframe *)frame);
1449f1d7ae31SEmmanuel Vadot 
1450f1d7ae31SEmmanuel Vadot 	if (frame->channels)
1451f1d7ae31SEmmanuel Vadot 		hdmi_log("    channels: %u\n", frame->channels - 1);
1452f1d7ae31SEmmanuel Vadot 	else
1453f1d7ae31SEmmanuel Vadot 		hdmi_log("    channels: Refer to stream header\n");
1454f1d7ae31SEmmanuel Vadot 	hdmi_log("    coding type: %s\n",
1455f1d7ae31SEmmanuel Vadot 			hdmi_audio_coding_type_get_name(frame->coding_type));
1456f1d7ae31SEmmanuel Vadot 	hdmi_log("    sample size: %s\n",
1457f1d7ae31SEmmanuel Vadot 			hdmi_audio_sample_size_get_name(frame->sample_size));
1458f1d7ae31SEmmanuel Vadot 	hdmi_log("    sample frequency: %s\n",
1459f1d7ae31SEmmanuel Vadot 			hdmi_audio_sample_frequency_get_name(frame->sample_frequency));
1460f1d7ae31SEmmanuel Vadot 	hdmi_log("    coding type ext: %s\n",
1461f1d7ae31SEmmanuel Vadot 			hdmi_audio_coding_type_ext_get_name(frame->coding_type_ext));
1462f1d7ae31SEmmanuel Vadot 	hdmi_log("    channel allocation: 0x%x\n",
1463f1d7ae31SEmmanuel Vadot 			frame->channel_allocation);
1464f1d7ae31SEmmanuel Vadot 	hdmi_log("    level shift value: %u dB\n",
1465f1d7ae31SEmmanuel Vadot 			frame->level_shift_value);
1466f1d7ae31SEmmanuel Vadot 	hdmi_log("    downmix inhibit: %s\n",
1467f1d7ae31SEmmanuel Vadot 			frame->downmix_inhibit ? "Yes" : "No");
1468f1d7ae31SEmmanuel Vadot }
1469f1d7ae31SEmmanuel Vadot 
hdmi_drm_infoframe_log(const char * level,struct device * dev,const struct hdmi_drm_infoframe * frame)1470f1d7ae31SEmmanuel Vadot static void hdmi_drm_infoframe_log(const char *level,
1471f1d7ae31SEmmanuel Vadot 				   struct device *dev,
1472f1d7ae31SEmmanuel Vadot 				   const struct hdmi_drm_infoframe *frame)
1473f1d7ae31SEmmanuel Vadot {
1474f1d7ae31SEmmanuel Vadot 	int i;
1475f1d7ae31SEmmanuel Vadot 
1476f1d7ae31SEmmanuel Vadot 	hdmi_infoframe_log_header(level, dev,
1477f1d7ae31SEmmanuel Vadot 				  (struct hdmi_any_infoframe *)frame);
1478f1d7ae31SEmmanuel Vadot 	hdmi_log("length: %d\n", frame->length);
1479f1d7ae31SEmmanuel Vadot 	hdmi_log("metadata type: %d\n", frame->metadata_type);
1480f1d7ae31SEmmanuel Vadot 	hdmi_log("eotf: %d\n", frame->eotf);
1481f1d7ae31SEmmanuel Vadot 	for (i = 0; i < 3; i++) {
1482f1d7ae31SEmmanuel Vadot 		hdmi_log("x[%d]: %d\n", i, frame->display_primaries[i].x);
1483f1d7ae31SEmmanuel Vadot 		hdmi_log("y[%d]: %d\n", i, frame->display_primaries[i].y);
1484f1d7ae31SEmmanuel Vadot 	}
1485f1d7ae31SEmmanuel Vadot 
1486f1d7ae31SEmmanuel Vadot 	hdmi_log("white point x: %d\n", frame->white_point.x);
1487f1d7ae31SEmmanuel Vadot 	hdmi_log("white point y: %d\n", frame->white_point.y);
1488f1d7ae31SEmmanuel Vadot 
1489f1d7ae31SEmmanuel Vadot 	hdmi_log("max_display_mastering_luminance: %d\n",
1490f1d7ae31SEmmanuel Vadot 		 frame->max_display_mastering_luminance);
1491f1d7ae31SEmmanuel Vadot 	hdmi_log("min_display_mastering_luminance: %d\n",
1492f1d7ae31SEmmanuel Vadot 		 frame->min_display_mastering_luminance);
1493f1d7ae31SEmmanuel Vadot 
1494f1d7ae31SEmmanuel Vadot 	hdmi_log("max_cll: %d\n", frame->max_cll);
1495f1d7ae31SEmmanuel Vadot 	hdmi_log("max_fall: %d\n", frame->max_fall);
1496f1d7ae31SEmmanuel Vadot }
1497f1d7ae31SEmmanuel Vadot 
1498f1d7ae31SEmmanuel Vadot static const char *
hdmi_3d_structure_get_name(enum hdmi_3d_structure s3d_struct)1499f1d7ae31SEmmanuel Vadot hdmi_3d_structure_get_name(enum hdmi_3d_structure s3d_struct)
1500f1d7ae31SEmmanuel Vadot {
1501f1d7ae31SEmmanuel Vadot 	if (s3d_struct < 0 || s3d_struct > 0xf)
1502f1d7ae31SEmmanuel Vadot 		return "Invalid";
1503f1d7ae31SEmmanuel Vadot 
1504f1d7ae31SEmmanuel Vadot 	switch (s3d_struct) {
1505f1d7ae31SEmmanuel Vadot 	case HDMI_3D_STRUCTURE_FRAME_PACKING:
1506f1d7ae31SEmmanuel Vadot 		return "Frame Packing";
1507f1d7ae31SEmmanuel Vadot 	case HDMI_3D_STRUCTURE_FIELD_ALTERNATIVE:
1508f1d7ae31SEmmanuel Vadot 		return "Field Alternative";
1509f1d7ae31SEmmanuel Vadot 	case HDMI_3D_STRUCTURE_LINE_ALTERNATIVE:
1510f1d7ae31SEmmanuel Vadot 		return "Line Alternative";
1511f1d7ae31SEmmanuel Vadot 	case HDMI_3D_STRUCTURE_SIDE_BY_SIDE_FULL:
1512f1d7ae31SEmmanuel Vadot 		return "Side-by-side (Full)";
1513f1d7ae31SEmmanuel Vadot 	case HDMI_3D_STRUCTURE_L_DEPTH:
1514f1d7ae31SEmmanuel Vadot 		return "L + Depth";
1515f1d7ae31SEmmanuel Vadot 	case HDMI_3D_STRUCTURE_L_DEPTH_GFX_GFX_DEPTH:
1516f1d7ae31SEmmanuel Vadot 		return "L + Depth + Graphics + Graphics-depth";
1517f1d7ae31SEmmanuel Vadot 	case HDMI_3D_STRUCTURE_TOP_AND_BOTTOM:
1518f1d7ae31SEmmanuel Vadot 		return "Top-and-Bottom";
1519f1d7ae31SEmmanuel Vadot 	case HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF:
1520f1d7ae31SEmmanuel Vadot 		return "Side-by-side (Half)";
1521f1d7ae31SEmmanuel Vadot 	default:
1522f1d7ae31SEmmanuel Vadot 		break;
1523f1d7ae31SEmmanuel Vadot 	}
1524f1d7ae31SEmmanuel Vadot 	return "Reserved";
1525f1d7ae31SEmmanuel Vadot }
1526f1d7ae31SEmmanuel Vadot 
1527f1d7ae31SEmmanuel Vadot static void
hdmi_vendor_any_infoframe_log(const char * level,struct device * dev,const union hdmi_vendor_any_infoframe * frame)1528f1d7ae31SEmmanuel Vadot hdmi_vendor_any_infoframe_log(const char *level,
1529f1d7ae31SEmmanuel Vadot 			      struct device *dev,
1530f1d7ae31SEmmanuel Vadot 			      const union hdmi_vendor_any_infoframe *frame)
1531f1d7ae31SEmmanuel Vadot {
1532f1d7ae31SEmmanuel Vadot 	const struct hdmi_vendor_infoframe *hvf = &frame->hdmi;
1533f1d7ae31SEmmanuel Vadot 
1534f1d7ae31SEmmanuel Vadot 	hdmi_infoframe_log_header(level, dev,
1535f1d7ae31SEmmanuel Vadot 				  (const struct hdmi_any_infoframe *)frame);
1536f1d7ae31SEmmanuel Vadot 
1537f1d7ae31SEmmanuel Vadot 	if (frame->any.oui != HDMI_IEEE_OUI) {
1538f1d7ae31SEmmanuel Vadot 		hdmi_log("    not a HDMI vendor infoframe\n");
1539f1d7ae31SEmmanuel Vadot 		return;
1540f1d7ae31SEmmanuel Vadot 	}
1541f1d7ae31SEmmanuel Vadot 	if (hvf->vic == 0 && hvf->s3d_struct == HDMI_3D_STRUCTURE_INVALID) {
1542f1d7ae31SEmmanuel Vadot 		hdmi_log("    empty frame\n");
1543f1d7ae31SEmmanuel Vadot 		return;
1544f1d7ae31SEmmanuel Vadot 	}
1545f1d7ae31SEmmanuel Vadot 
1546f1d7ae31SEmmanuel Vadot 	if (hvf->vic)
1547f1d7ae31SEmmanuel Vadot 		hdmi_log("    HDMI VIC: %u\n", hvf->vic);
1548f1d7ae31SEmmanuel Vadot 	if (hvf->s3d_struct != HDMI_3D_STRUCTURE_INVALID) {
1549f1d7ae31SEmmanuel Vadot 		hdmi_log("    3D structure: %s\n",
1550f1d7ae31SEmmanuel Vadot 				hdmi_3d_structure_get_name(hvf->s3d_struct));
1551f1d7ae31SEmmanuel Vadot 		if (hvf->s3d_struct >= HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF)
1552f1d7ae31SEmmanuel Vadot 			hdmi_log("    3D extension data: %d\n",
1553f1d7ae31SEmmanuel Vadot 					hvf->s3d_ext_data);
1554f1d7ae31SEmmanuel Vadot 	}
1555f1d7ae31SEmmanuel Vadot }
1556f1d7ae31SEmmanuel Vadot 
1557f1d7ae31SEmmanuel Vadot /**
1558f1d7ae31SEmmanuel Vadot  * hdmi_infoframe_log() - log info of HDMI infoframe
1559f1d7ae31SEmmanuel Vadot  * @level: logging level
1560f1d7ae31SEmmanuel Vadot  * @dev: device
1561f1d7ae31SEmmanuel Vadot  * @frame: HDMI infoframe
1562f1d7ae31SEmmanuel Vadot  */
hdmi_infoframe_log(const char * level,struct device * dev,const union hdmi_infoframe * frame)1563f1d7ae31SEmmanuel Vadot void hdmi_infoframe_log(const char *level,
1564f1d7ae31SEmmanuel Vadot 			struct device *dev,
1565f1d7ae31SEmmanuel Vadot 			const union hdmi_infoframe *frame)
1566f1d7ae31SEmmanuel Vadot {
1567f1d7ae31SEmmanuel Vadot 	switch (frame->any.type) {
1568f1d7ae31SEmmanuel Vadot 	case HDMI_INFOFRAME_TYPE_AVI:
1569f1d7ae31SEmmanuel Vadot 		hdmi_avi_infoframe_log(level, dev, &frame->avi);
1570f1d7ae31SEmmanuel Vadot 		break;
1571f1d7ae31SEmmanuel Vadot 	case HDMI_INFOFRAME_TYPE_SPD:
1572f1d7ae31SEmmanuel Vadot 		hdmi_spd_infoframe_log(level, dev, &frame->spd);
1573f1d7ae31SEmmanuel Vadot 		break;
1574f1d7ae31SEmmanuel Vadot 	case HDMI_INFOFRAME_TYPE_AUDIO:
1575f1d7ae31SEmmanuel Vadot 		hdmi_audio_infoframe_log(level, dev, &frame->audio);
1576f1d7ae31SEmmanuel Vadot 		break;
1577f1d7ae31SEmmanuel Vadot 	case HDMI_INFOFRAME_TYPE_VENDOR:
1578f1d7ae31SEmmanuel Vadot 		hdmi_vendor_any_infoframe_log(level, dev, &frame->vendor);
1579f1d7ae31SEmmanuel Vadot 		break;
1580f1d7ae31SEmmanuel Vadot 	case HDMI_INFOFRAME_TYPE_DRM:
1581f1d7ae31SEmmanuel Vadot 		hdmi_drm_infoframe_log(level, dev, &frame->drm);
1582f1d7ae31SEmmanuel Vadot 		break;
1583f1d7ae31SEmmanuel Vadot 	}
1584f1d7ae31SEmmanuel Vadot }
1585f1d7ae31SEmmanuel Vadot EXPORT_SYMBOL(hdmi_infoframe_log);
1586f1d7ae31SEmmanuel Vadot 
1587f1d7ae31SEmmanuel Vadot /**
1588f1d7ae31SEmmanuel Vadot  * hdmi_avi_infoframe_unpack() - unpack binary buffer to a HDMI AVI infoframe
1589f1d7ae31SEmmanuel Vadot  * @frame: HDMI AVI infoframe
1590f1d7ae31SEmmanuel Vadot  * @buffer: source buffer
1591f1d7ae31SEmmanuel Vadot  * @size: size of buffer
1592f1d7ae31SEmmanuel Vadot  *
1593f1d7ae31SEmmanuel Vadot  * Unpacks the information contained in binary @buffer into a structured
1594f1d7ae31SEmmanuel Vadot  * @frame of the HDMI Auxiliary Video (AVI) information frame.
1595f1d7ae31SEmmanuel Vadot  * Also verifies the checksum as required by section 5.3.5 of the HDMI 1.4
1596f1d7ae31SEmmanuel Vadot  * specification.
1597f1d7ae31SEmmanuel Vadot  *
1598f1d7ae31SEmmanuel Vadot  * Returns 0 on success or a negative error code on failure.
1599f1d7ae31SEmmanuel Vadot  */
hdmi_avi_infoframe_unpack(struct hdmi_avi_infoframe * frame,const void * buffer,size_t size)1600f1d7ae31SEmmanuel Vadot static int hdmi_avi_infoframe_unpack(struct hdmi_avi_infoframe *frame,
1601f1d7ae31SEmmanuel Vadot 				     const void *buffer, size_t size)
1602f1d7ae31SEmmanuel Vadot {
1603f1d7ae31SEmmanuel Vadot 	const u8 *ptr = buffer;
1604f1d7ae31SEmmanuel Vadot 
1605f1d7ae31SEmmanuel Vadot 	if (size < HDMI_INFOFRAME_SIZE(AVI))
1606f1d7ae31SEmmanuel Vadot 		return -EINVAL;
1607f1d7ae31SEmmanuel Vadot 
1608f1d7ae31SEmmanuel Vadot 	if (ptr[0] != HDMI_INFOFRAME_TYPE_AVI ||
1609f1d7ae31SEmmanuel Vadot 	    ptr[1] != 2 ||
1610f1d7ae31SEmmanuel Vadot 	    ptr[2] != HDMI_AVI_INFOFRAME_SIZE)
1611f1d7ae31SEmmanuel Vadot 		return -EINVAL;
1612f1d7ae31SEmmanuel Vadot 
1613f1d7ae31SEmmanuel Vadot 	if (hdmi_infoframe_checksum(buffer, HDMI_INFOFRAME_SIZE(AVI)) != 0)
1614f1d7ae31SEmmanuel Vadot 		return -EINVAL;
1615f1d7ae31SEmmanuel Vadot 
1616f1d7ae31SEmmanuel Vadot 	hdmi_avi_infoframe_init(frame);
1617f1d7ae31SEmmanuel Vadot 
1618f1d7ae31SEmmanuel Vadot 	ptr += HDMI_INFOFRAME_HEADER_SIZE;
1619f1d7ae31SEmmanuel Vadot 
1620f1d7ae31SEmmanuel Vadot 	frame->colorspace = (ptr[0] >> 5) & 0x3;
1621f1d7ae31SEmmanuel Vadot 	if (ptr[0] & 0x10)
1622f1d7ae31SEmmanuel Vadot 		frame->active_aspect = ptr[1] & 0xf;
1623f1d7ae31SEmmanuel Vadot 	if (ptr[0] & 0x8) {
1624f1d7ae31SEmmanuel Vadot 		frame->top_bar = (ptr[6] << 8) | ptr[5];
1625f1d7ae31SEmmanuel Vadot 		frame->bottom_bar = (ptr[8] << 8) | ptr[7];
1626f1d7ae31SEmmanuel Vadot 	}
1627f1d7ae31SEmmanuel Vadot 	if (ptr[0] & 0x4) {
1628f1d7ae31SEmmanuel Vadot 		frame->left_bar = (ptr[10] << 8) | ptr[9];
1629f1d7ae31SEmmanuel Vadot 		frame->right_bar = (ptr[12] << 8) | ptr[11];
1630f1d7ae31SEmmanuel Vadot 	}
1631f1d7ae31SEmmanuel Vadot 	frame->scan_mode = ptr[0] & 0x3;
1632f1d7ae31SEmmanuel Vadot 
1633f1d7ae31SEmmanuel Vadot 	frame->colorimetry = (ptr[1] >> 6) & 0x3;
1634f1d7ae31SEmmanuel Vadot 	frame->picture_aspect = (ptr[1] >> 4) & 0x3;
1635f1d7ae31SEmmanuel Vadot 	frame->active_aspect = ptr[1] & 0xf;
1636f1d7ae31SEmmanuel Vadot 
1637f1d7ae31SEmmanuel Vadot 	frame->itc = ptr[2] & 0x80 ? true : false;
1638f1d7ae31SEmmanuel Vadot 	frame->extended_colorimetry = (ptr[2] >> 4) & 0x7;
1639f1d7ae31SEmmanuel Vadot 	frame->quantization_range = (ptr[2] >> 2) & 0x3;
1640f1d7ae31SEmmanuel Vadot 	frame->nups = ptr[2] & 0x3;
1641f1d7ae31SEmmanuel Vadot 
1642f1d7ae31SEmmanuel Vadot 	frame->video_code = ptr[3] & 0x7f;
1643f1d7ae31SEmmanuel Vadot 	frame->ycc_quantization_range = (ptr[4] >> 6) & 0x3;
1644f1d7ae31SEmmanuel Vadot 	frame->content_type = (ptr[4] >> 4) & 0x3;
1645f1d7ae31SEmmanuel Vadot 
1646f1d7ae31SEmmanuel Vadot 	frame->pixel_repeat = ptr[4] & 0xf;
1647f1d7ae31SEmmanuel Vadot 
1648f1d7ae31SEmmanuel Vadot 	return 0;
1649f1d7ae31SEmmanuel Vadot }
1650f1d7ae31SEmmanuel Vadot 
1651f1d7ae31SEmmanuel Vadot /**
1652f1d7ae31SEmmanuel Vadot  * hdmi_spd_infoframe_unpack() - unpack binary buffer to a HDMI SPD infoframe
1653f1d7ae31SEmmanuel Vadot  * @frame: HDMI SPD infoframe
1654f1d7ae31SEmmanuel Vadot  * @buffer: source buffer
1655f1d7ae31SEmmanuel Vadot  * @size: size of buffer
1656f1d7ae31SEmmanuel Vadot  *
1657f1d7ae31SEmmanuel Vadot  * Unpacks the information contained in binary @buffer into a structured
1658f1d7ae31SEmmanuel Vadot  * @frame of the HDMI Source Product Description (SPD) information frame.
1659f1d7ae31SEmmanuel Vadot  * Also verifies the checksum as required by section 5.3.5 of the HDMI 1.4
1660f1d7ae31SEmmanuel Vadot  * specification.
1661f1d7ae31SEmmanuel Vadot  *
1662f1d7ae31SEmmanuel Vadot  * Returns 0 on success or a negative error code on failure.
1663f1d7ae31SEmmanuel Vadot  */
hdmi_spd_infoframe_unpack(struct hdmi_spd_infoframe * frame,const void * buffer,size_t size)1664f1d7ae31SEmmanuel Vadot static int hdmi_spd_infoframe_unpack(struct hdmi_spd_infoframe *frame,
1665f1d7ae31SEmmanuel Vadot 				     const void *buffer, size_t size)
1666f1d7ae31SEmmanuel Vadot {
1667f1d7ae31SEmmanuel Vadot 	const u8 *ptr = buffer;
1668f1d7ae31SEmmanuel Vadot 	int ret;
1669f1d7ae31SEmmanuel Vadot 
1670f1d7ae31SEmmanuel Vadot 	if (size < HDMI_INFOFRAME_SIZE(SPD))
1671f1d7ae31SEmmanuel Vadot 		return -EINVAL;
1672f1d7ae31SEmmanuel Vadot 
1673f1d7ae31SEmmanuel Vadot 	if (ptr[0] != HDMI_INFOFRAME_TYPE_SPD ||
1674f1d7ae31SEmmanuel Vadot 	    ptr[1] != 1 ||
1675f1d7ae31SEmmanuel Vadot 	    ptr[2] != HDMI_SPD_INFOFRAME_SIZE) {
1676f1d7ae31SEmmanuel Vadot 		return -EINVAL;
1677f1d7ae31SEmmanuel Vadot 	}
1678f1d7ae31SEmmanuel Vadot 
1679f1d7ae31SEmmanuel Vadot 	if (hdmi_infoframe_checksum(buffer, HDMI_INFOFRAME_SIZE(SPD)) != 0)
1680f1d7ae31SEmmanuel Vadot 		return -EINVAL;
1681f1d7ae31SEmmanuel Vadot 
1682f1d7ae31SEmmanuel Vadot 	ptr += HDMI_INFOFRAME_HEADER_SIZE;
1683f1d7ae31SEmmanuel Vadot 
1684f1d7ae31SEmmanuel Vadot 	ret = hdmi_spd_infoframe_init(frame, ptr, ptr + 8);
1685f1d7ae31SEmmanuel Vadot 	if (ret)
1686f1d7ae31SEmmanuel Vadot 		return ret;
1687f1d7ae31SEmmanuel Vadot 
1688f1d7ae31SEmmanuel Vadot 	frame->sdi = ptr[24];
1689f1d7ae31SEmmanuel Vadot 
1690f1d7ae31SEmmanuel Vadot 	return 0;
1691f1d7ae31SEmmanuel Vadot }
1692f1d7ae31SEmmanuel Vadot 
1693f1d7ae31SEmmanuel Vadot /**
1694f1d7ae31SEmmanuel Vadot  * hdmi_audio_infoframe_unpack() - unpack binary buffer to a HDMI AUDIO infoframe
1695f1d7ae31SEmmanuel Vadot  * @frame: HDMI Audio infoframe
1696f1d7ae31SEmmanuel Vadot  * @buffer: source buffer
1697f1d7ae31SEmmanuel Vadot  * @size: size of buffer
1698f1d7ae31SEmmanuel Vadot  *
1699f1d7ae31SEmmanuel Vadot  * Unpacks the information contained in binary @buffer into a structured
1700f1d7ae31SEmmanuel Vadot  * @frame of the HDMI Audio information frame.
1701f1d7ae31SEmmanuel Vadot  * Also verifies the checksum as required by section 5.3.5 of the HDMI 1.4
1702f1d7ae31SEmmanuel Vadot  * specification.
1703f1d7ae31SEmmanuel Vadot  *
1704f1d7ae31SEmmanuel Vadot  * Returns 0 on success or a negative error code on failure.
1705f1d7ae31SEmmanuel Vadot  */
hdmi_audio_infoframe_unpack(struct hdmi_audio_infoframe * frame,const void * buffer,size_t size)1706f1d7ae31SEmmanuel Vadot static int hdmi_audio_infoframe_unpack(struct hdmi_audio_infoframe *frame,
1707f1d7ae31SEmmanuel Vadot 				       const void *buffer, size_t size)
1708f1d7ae31SEmmanuel Vadot {
1709f1d7ae31SEmmanuel Vadot 	const u8 *ptr = buffer;
1710f1d7ae31SEmmanuel Vadot 	int ret;
1711f1d7ae31SEmmanuel Vadot 
1712f1d7ae31SEmmanuel Vadot 	if (size < HDMI_INFOFRAME_SIZE(AUDIO))
1713f1d7ae31SEmmanuel Vadot 		return -EINVAL;
1714f1d7ae31SEmmanuel Vadot 
1715f1d7ae31SEmmanuel Vadot 	if (ptr[0] != HDMI_INFOFRAME_TYPE_AUDIO ||
1716f1d7ae31SEmmanuel Vadot 	    ptr[1] != 1 ||
1717f1d7ae31SEmmanuel Vadot 	    ptr[2] != HDMI_AUDIO_INFOFRAME_SIZE) {
1718f1d7ae31SEmmanuel Vadot 		return -EINVAL;
1719f1d7ae31SEmmanuel Vadot 	}
1720f1d7ae31SEmmanuel Vadot 
1721f1d7ae31SEmmanuel Vadot 	if (hdmi_infoframe_checksum(buffer, HDMI_INFOFRAME_SIZE(AUDIO)) != 0)
1722f1d7ae31SEmmanuel Vadot 		return -EINVAL;
1723f1d7ae31SEmmanuel Vadot 
1724f1d7ae31SEmmanuel Vadot 	ret = hdmi_audio_infoframe_init(frame);
1725f1d7ae31SEmmanuel Vadot 	if (ret)
1726f1d7ae31SEmmanuel Vadot 		return ret;
1727f1d7ae31SEmmanuel Vadot 
1728f1d7ae31SEmmanuel Vadot 	ptr += HDMI_INFOFRAME_HEADER_SIZE;
1729f1d7ae31SEmmanuel Vadot 
1730f1d7ae31SEmmanuel Vadot 	frame->channels = ptr[0] & 0x7;
1731f1d7ae31SEmmanuel Vadot 	frame->coding_type = (ptr[0] >> 4) & 0xf;
1732f1d7ae31SEmmanuel Vadot 	frame->sample_size = ptr[1] & 0x3;
1733f1d7ae31SEmmanuel Vadot 	frame->sample_frequency = (ptr[1] >> 2) & 0x7;
1734f1d7ae31SEmmanuel Vadot 	frame->coding_type_ext = ptr[2] & 0x1f;
1735f1d7ae31SEmmanuel Vadot 	frame->channel_allocation = ptr[3];
1736f1d7ae31SEmmanuel Vadot 	frame->level_shift_value = (ptr[4] >> 3) & 0xf;
1737f1d7ae31SEmmanuel Vadot 	frame->downmix_inhibit = ptr[4] & 0x80 ? true : false;
1738f1d7ae31SEmmanuel Vadot 
1739f1d7ae31SEmmanuel Vadot 	return 0;
1740f1d7ae31SEmmanuel Vadot }
1741f1d7ae31SEmmanuel Vadot 
1742f1d7ae31SEmmanuel Vadot /**
1743f1d7ae31SEmmanuel Vadot  * hdmi_vendor_any_infoframe_unpack() - unpack binary buffer to a HDMI
1744f1d7ae31SEmmanuel Vadot  * 	vendor infoframe
1745f1d7ae31SEmmanuel Vadot  * @frame: HDMI Vendor infoframe
1746f1d7ae31SEmmanuel Vadot  * @buffer: source buffer
1747f1d7ae31SEmmanuel Vadot  * @size: size of buffer
1748f1d7ae31SEmmanuel Vadot  *
1749f1d7ae31SEmmanuel Vadot  * Unpacks the information contained in binary @buffer into a structured
1750f1d7ae31SEmmanuel Vadot  * @frame of the HDMI Vendor information frame.
1751f1d7ae31SEmmanuel Vadot  * Also verifies the checksum as required by section 5.3.5 of the HDMI 1.4
1752f1d7ae31SEmmanuel Vadot  * specification.
1753f1d7ae31SEmmanuel Vadot  *
1754f1d7ae31SEmmanuel Vadot  * Returns 0 on success or a negative error code on failure.
1755f1d7ae31SEmmanuel Vadot  */
1756f1d7ae31SEmmanuel Vadot static int
hdmi_vendor_any_infoframe_unpack(union hdmi_vendor_any_infoframe * frame,const void * buffer,size_t size)1757f1d7ae31SEmmanuel Vadot hdmi_vendor_any_infoframe_unpack(union hdmi_vendor_any_infoframe *frame,
1758f1d7ae31SEmmanuel Vadot 				 const void *buffer, size_t size)
1759f1d7ae31SEmmanuel Vadot {
1760f1d7ae31SEmmanuel Vadot 	const u8 *ptr = buffer;
1761f1d7ae31SEmmanuel Vadot 	size_t length;
1762f1d7ae31SEmmanuel Vadot 	int ret;
1763f1d7ae31SEmmanuel Vadot 	u8 hdmi_video_format;
1764f1d7ae31SEmmanuel Vadot 	struct hdmi_vendor_infoframe *hvf = &frame->hdmi;
1765f1d7ae31SEmmanuel Vadot 
1766f1d7ae31SEmmanuel Vadot 	if (size < HDMI_INFOFRAME_HEADER_SIZE)
1767f1d7ae31SEmmanuel Vadot 		return -EINVAL;
1768f1d7ae31SEmmanuel Vadot 
1769f1d7ae31SEmmanuel Vadot 	if (ptr[0] != HDMI_INFOFRAME_TYPE_VENDOR ||
1770f1d7ae31SEmmanuel Vadot 	    ptr[1] != 1 ||
1771f1d7ae31SEmmanuel Vadot 	    (ptr[2] != 4 && ptr[2] != 5 && ptr[2] != 6))
1772f1d7ae31SEmmanuel Vadot 		return -EINVAL;
1773f1d7ae31SEmmanuel Vadot 
1774f1d7ae31SEmmanuel Vadot 	length = ptr[2];
1775f1d7ae31SEmmanuel Vadot 
1776f1d7ae31SEmmanuel Vadot 	if (size < HDMI_INFOFRAME_HEADER_SIZE + length)
1777f1d7ae31SEmmanuel Vadot 		return -EINVAL;
1778f1d7ae31SEmmanuel Vadot 
1779f1d7ae31SEmmanuel Vadot 	if (hdmi_infoframe_checksum(buffer,
1780f1d7ae31SEmmanuel Vadot 				    HDMI_INFOFRAME_HEADER_SIZE + length) != 0)
1781f1d7ae31SEmmanuel Vadot 		return -EINVAL;
1782f1d7ae31SEmmanuel Vadot 
1783f1d7ae31SEmmanuel Vadot 	ptr += HDMI_INFOFRAME_HEADER_SIZE;
1784f1d7ae31SEmmanuel Vadot 
1785f1d7ae31SEmmanuel Vadot 	/* HDMI OUI */
1786f1d7ae31SEmmanuel Vadot 	if ((ptr[0] != 0x03) ||
1787f1d7ae31SEmmanuel Vadot 	    (ptr[1] != 0x0c) ||
1788f1d7ae31SEmmanuel Vadot 	    (ptr[2] != 0x00))
1789f1d7ae31SEmmanuel Vadot 		return -EINVAL;
1790f1d7ae31SEmmanuel Vadot 
1791f1d7ae31SEmmanuel Vadot 	hdmi_video_format = ptr[3] >> 5;
1792f1d7ae31SEmmanuel Vadot 
1793f1d7ae31SEmmanuel Vadot 	if (hdmi_video_format > 0x2)
1794f1d7ae31SEmmanuel Vadot 		return -EINVAL;
1795f1d7ae31SEmmanuel Vadot 
1796f1d7ae31SEmmanuel Vadot 	ret = hdmi_vendor_infoframe_init(hvf);
1797f1d7ae31SEmmanuel Vadot 	if (ret)
1798f1d7ae31SEmmanuel Vadot 		return ret;
1799f1d7ae31SEmmanuel Vadot 
1800f1d7ae31SEmmanuel Vadot 	hvf->length = length;
1801f1d7ae31SEmmanuel Vadot 
1802f1d7ae31SEmmanuel Vadot 	if (hdmi_video_format == 0x2) {
1803f1d7ae31SEmmanuel Vadot 		if (length != 5 && length != 6)
1804f1d7ae31SEmmanuel Vadot 			return -EINVAL;
1805f1d7ae31SEmmanuel Vadot 		hvf->s3d_struct = ptr[4] >> 4;
1806f1d7ae31SEmmanuel Vadot 		if (hvf->s3d_struct >= HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF) {
1807f1d7ae31SEmmanuel Vadot 			if (length != 6)
1808f1d7ae31SEmmanuel Vadot 				return -EINVAL;
1809f1d7ae31SEmmanuel Vadot 			hvf->s3d_ext_data = ptr[5] >> 4;
1810f1d7ae31SEmmanuel Vadot 		}
1811f1d7ae31SEmmanuel Vadot 	} else if (hdmi_video_format == 0x1) {
1812f1d7ae31SEmmanuel Vadot 		if (length != 5)
1813f1d7ae31SEmmanuel Vadot 			return -EINVAL;
1814f1d7ae31SEmmanuel Vadot 		hvf->vic = ptr[4];
1815f1d7ae31SEmmanuel Vadot 	} else {
1816f1d7ae31SEmmanuel Vadot 		if (length != 4)
1817f1d7ae31SEmmanuel Vadot 			return -EINVAL;
1818f1d7ae31SEmmanuel Vadot 	}
1819f1d7ae31SEmmanuel Vadot 
1820f1d7ae31SEmmanuel Vadot 	return 0;
1821f1d7ae31SEmmanuel Vadot }
1822f1d7ae31SEmmanuel Vadot 
1823f1d7ae31SEmmanuel Vadot /**
1824f1d7ae31SEmmanuel Vadot  * hdmi_drm_infoframe_unpack_only() - unpack binary buffer of CTA-861-G DRM
1825f1d7ae31SEmmanuel Vadot  *                                    infoframe DataBytes to a HDMI DRM
1826f1d7ae31SEmmanuel Vadot  *                                    infoframe
1827f1d7ae31SEmmanuel Vadot  * @frame: HDMI DRM infoframe
1828f1d7ae31SEmmanuel Vadot  * @buffer: source buffer
1829f1d7ae31SEmmanuel Vadot  * @size: size of buffer
1830f1d7ae31SEmmanuel Vadot  *
1831f1d7ae31SEmmanuel Vadot  * Unpacks CTA-861-G DRM infoframe DataBytes contained in the binary @buffer
1832f1d7ae31SEmmanuel Vadot  * into a structured @frame of the HDMI Dynamic Range and Mastering (DRM)
1833f1d7ae31SEmmanuel Vadot  * infoframe.
1834f1d7ae31SEmmanuel Vadot  *
1835f1d7ae31SEmmanuel Vadot  * Returns 0 on success or a negative error code on failure.
1836f1d7ae31SEmmanuel Vadot  */
hdmi_drm_infoframe_unpack_only(struct hdmi_drm_infoframe * frame,const void * buffer,size_t size)1837f1d7ae31SEmmanuel Vadot int hdmi_drm_infoframe_unpack_only(struct hdmi_drm_infoframe *frame,
1838f1d7ae31SEmmanuel Vadot 				   const void *buffer, size_t size)
1839f1d7ae31SEmmanuel Vadot {
1840f1d7ae31SEmmanuel Vadot 	const u8 *ptr = buffer;
1841f1d7ae31SEmmanuel Vadot 	const u8 *temp;
1842f1d7ae31SEmmanuel Vadot 	u8 x_lsb, x_msb;
1843f1d7ae31SEmmanuel Vadot 	u8 y_lsb, y_msb;
1844f1d7ae31SEmmanuel Vadot 	int ret;
1845f1d7ae31SEmmanuel Vadot 	int i;
1846f1d7ae31SEmmanuel Vadot 
1847f1d7ae31SEmmanuel Vadot 	if (size < HDMI_DRM_INFOFRAME_SIZE)
1848f1d7ae31SEmmanuel Vadot 		return -EINVAL;
1849f1d7ae31SEmmanuel Vadot 
1850f1d7ae31SEmmanuel Vadot 	ret = hdmi_drm_infoframe_init(frame);
1851f1d7ae31SEmmanuel Vadot 	if (ret)
1852f1d7ae31SEmmanuel Vadot 		return ret;
1853f1d7ae31SEmmanuel Vadot 
1854f1d7ae31SEmmanuel Vadot 	frame->eotf = ptr[0] & 0x7;
1855f1d7ae31SEmmanuel Vadot 	frame->metadata_type = ptr[1] & 0x7;
1856f1d7ae31SEmmanuel Vadot 
1857f1d7ae31SEmmanuel Vadot 	temp = ptr + 2;
1858f1d7ae31SEmmanuel Vadot 	for (i = 0; i < 3; i++) {
1859f1d7ae31SEmmanuel Vadot 		x_lsb = *temp++;
1860f1d7ae31SEmmanuel Vadot 		x_msb = *temp++;
1861f1d7ae31SEmmanuel Vadot 		frame->display_primaries[i].x = (x_msb << 8) | x_lsb;
1862f1d7ae31SEmmanuel Vadot 		y_lsb = *temp++;
1863f1d7ae31SEmmanuel Vadot 		y_msb = *temp++;
1864f1d7ae31SEmmanuel Vadot 		frame->display_primaries[i].y = (y_msb << 8) | y_lsb;
1865f1d7ae31SEmmanuel Vadot 	}
1866f1d7ae31SEmmanuel Vadot 
1867f1d7ae31SEmmanuel Vadot 	frame->white_point.x = (ptr[15] << 8) | ptr[14];
1868f1d7ae31SEmmanuel Vadot 	frame->white_point.y = (ptr[17] << 8) | ptr[16];
1869f1d7ae31SEmmanuel Vadot 
1870f1d7ae31SEmmanuel Vadot 	frame->max_display_mastering_luminance = (ptr[19] << 8) | ptr[18];
1871f1d7ae31SEmmanuel Vadot 	frame->min_display_mastering_luminance = (ptr[21] << 8) | ptr[20];
1872f1d7ae31SEmmanuel Vadot 	frame->max_cll = (ptr[23] << 8) | ptr[22];
1873f1d7ae31SEmmanuel Vadot 	frame->max_fall = (ptr[25] << 8) | ptr[24];
1874f1d7ae31SEmmanuel Vadot 
1875f1d7ae31SEmmanuel Vadot 	return 0;
1876f1d7ae31SEmmanuel Vadot }
1877f1d7ae31SEmmanuel Vadot EXPORT_SYMBOL(hdmi_drm_infoframe_unpack_only);
1878f1d7ae31SEmmanuel Vadot 
1879f1d7ae31SEmmanuel Vadot /**
1880f1d7ae31SEmmanuel Vadot  * hdmi_drm_infoframe_unpack() - unpack binary buffer to a HDMI DRM infoframe
1881f1d7ae31SEmmanuel Vadot  * @frame: HDMI DRM infoframe
1882f1d7ae31SEmmanuel Vadot  * @buffer: source buffer
1883f1d7ae31SEmmanuel Vadot  * @size: size of buffer
1884f1d7ae31SEmmanuel Vadot  *
1885f1d7ae31SEmmanuel Vadot  * Unpacks the CTA-861-G DRM infoframe contained in the binary @buffer into
1886f1d7ae31SEmmanuel Vadot  * a structured @frame of the HDMI Dynamic Range and Mastering (DRM)
1887f1d7ae31SEmmanuel Vadot  * infoframe. It also verifies the checksum as required by section 5.3.5 of
1888f1d7ae31SEmmanuel Vadot  * the HDMI 1.4 specification.
1889f1d7ae31SEmmanuel Vadot  *
1890f1d7ae31SEmmanuel Vadot  * Returns 0 on success or a negative error code on failure.
1891f1d7ae31SEmmanuel Vadot  */
hdmi_drm_infoframe_unpack(struct hdmi_drm_infoframe * frame,const void * buffer,size_t size)1892f1d7ae31SEmmanuel Vadot static int hdmi_drm_infoframe_unpack(struct hdmi_drm_infoframe *frame,
1893f1d7ae31SEmmanuel Vadot 				     const void *buffer, size_t size)
1894f1d7ae31SEmmanuel Vadot {
1895f1d7ae31SEmmanuel Vadot 	const u8 *ptr = buffer;
1896f1d7ae31SEmmanuel Vadot 	int ret;
1897f1d7ae31SEmmanuel Vadot 
1898f1d7ae31SEmmanuel Vadot 	if (size < HDMI_INFOFRAME_SIZE(DRM))
1899f1d7ae31SEmmanuel Vadot 		return -EINVAL;
1900f1d7ae31SEmmanuel Vadot 
1901f1d7ae31SEmmanuel Vadot 	if (ptr[0] != HDMI_INFOFRAME_TYPE_DRM ||
1902f1d7ae31SEmmanuel Vadot 	    ptr[1] != 1 ||
1903f1d7ae31SEmmanuel Vadot 	    ptr[2] != HDMI_DRM_INFOFRAME_SIZE)
1904f1d7ae31SEmmanuel Vadot 		return -EINVAL;
1905f1d7ae31SEmmanuel Vadot 
1906f1d7ae31SEmmanuel Vadot 	if (hdmi_infoframe_checksum(buffer, HDMI_INFOFRAME_SIZE(DRM)) != 0)
1907f1d7ae31SEmmanuel Vadot 		return -EINVAL;
1908f1d7ae31SEmmanuel Vadot 
1909f1d7ae31SEmmanuel Vadot 	ret = hdmi_drm_infoframe_unpack_only(frame, ptr + HDMI_INFOFRAME_HEADER_SIZE,
1910f1d7ae31SEmmanuel Vadot 					     size - HDMI_INFOFRAME_HEADER_SIZE);
1911f1d7ae31SEmmanuel Vadot 	return ret;
1912f1d7ae31SEmmanuel Vadot }
1913f1d7ae31SEmmanuel Vadot 
1914f1d7ae31SEmmanuel Vadot /**
1915f1d7ae31SEmmanuel Vadot  * hdmi_infoframe_unpack() - unpack binary buffer to a HDMI infoframe
1916f1d7ae31SEmmanuel Vadot  * @frame: HDMI infoframe
1917f1d7ae31SEmmanuel Vadot  * @buffer: source buffer
1918f1d7ae31SEmmanuel Vadot  * @size: size of buffer
1919f1d7ae31SEmmanuel Vadot  *
1920f1d7ae31SEmmanuel Vadot  * Unpacks the information contained in binary buffer @buffer into a structured
1921f1d7ae31SEmmanuel Vadot  * @frame of a HDMI infoframe.
1922f1d7ae31SEmmanuel Vadot  * Also verifies the checksum as required by section 5.3.5 of the HDMI 1.4
1923f1d7ae31SEmmanuel Vadot  * specification.
1924f1d7ae31SEmmanuel Vadot  *
1925f1d7ae31SEmmanuel Vadot  * Returns 0 on success or a negative error code on failure.
1926f1d7ae31SEmmanuel Vadot  */
hdmi_infoframe_unpack(union hdmi_infoframe * frame,const void * buffer,size_t size)1927f1d7ae31SEmmanuel Vadot int hdmi_infoframe_unpack(union hdmi_infoframe *frame,
1928f1d7ae31SEmmanuel Vadot 			  const void *buffer, size_t size)
1929f1d7ae31SEmmanuel Vadot {
1930f1d7ae31SEmmanuel Vadot 	int ret;
1931f1d7ae31SEmmanuel Vadot 	const u8 *ptr = buffer;
1932f1d7ae31SEmmanuel Vadot 
1933f1d7ae31SEmmanuel Vadot 	if (size < HDMI_INFOFRAME_HEADER_SIZE)
1934f1d7ae31SEmmanuel Vadot 		return -EINVAL;
1935f1d7ae31SEmmanuel Vadot 
1936f1d7ae31SEmmanuel Vadot 	switch (ptr[0]) {
1937f1d7ae31SEmmanuel Vadot 	case HDMI_INFOFRAME_TYPE_AVI:
1938f1d7ae31SEmmanuel Vadot 		ret = hdmi_avi_infoframe_unpack(&frame->avi, buffer, size);
1939f1d7ae31SEmmanuel Vadot 		break;
1940f1d7ae31SEmmanuel Vadot 	case HDMI_INFOFRAME_TYPE_DRM:
1941f1d7ae31SEmmanuel Vadot 		ret = hdmi_drm_infoframe_unpack(&frame->drm, buffer, size);
1942f1d7ae31SEmmanuel Vadot 		break;
1943f1d7ae31SEmmanuel Vadot 	case HDMI_INFOFRAME_TYPE_SPD:
1944f1d7ae31SEmmanuel Vadot 		ret = hdmi_spd_infoframe_unpack(&frame->spd, buffer, size);
1945f1d7ae31SEmmanuel Vadot 		break;
1946f1d7ae31SEmmanuel Vadot 	case HDMI_INFOFRAME_TYPE_AUDIO:
1947f1d7ae31SEmmanuel Vadot 		ret = hdmi_audio_infoframe_unpack(&frame->audio, buffer, size);
1948f1d7ae31SEmmanuel Vadot 		break;
1949f1d7ae31SEmmanuel Vadot 	case HDMI_INFOFRAME_TYPE_VENDOR:
1950f1d7ae31SEmmanuel Vadot 		ret = hdmi_vendor_any_infoframe_unpack(&frame->vendor, buffer, size);
1951f1d7ae31SEmmanuel Vadot 		break;
1952f1d7ae31SEmmanuel Vadot 	default:
1953f1d7ae31SEmmanuel Vadot 		ret = -EINVAL;
1954f1d7ae31SEmmanuel Vadot 		break;
1955f1d7ae31SEmmanuel Vadot 	}
1956f1d7ae31SEmmanuel Vadot 
1957f1d7ae31SEmmanuel Vadot 	return ret;
1958f1d7ae31SEmmanuel Vadot }
1959f1d7ae31SEmmanuel Vadot EXPORT_SYMBOL(hdmi_infoframe_unpack);
1960