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