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