xref: /dragonfly/sys/dev/drm/linux_hdmi.c (revision 3f2dd94a569761201b5b0a18b2f697f97fe1b9dc)
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 
hdmi_infoframe_checksum(u8 * ptr,size_t size)34 static u8 hdmi_infoframe_checksum(u8 *ptr, size_t size)
35 {
36           u8 csum = 0;
37           size_t i;
38 
39           /* compute checksum */
40           for (i = 0; i < size; i++)
41                     csum += ptr[i];
42 
43           return 256 - csum;
44 }
45 
hdmi_infoframe_set_checksum(void * buffer,size_t size)46 static void hdmi_infoframe_set_checksum(void *buffer, size_t size)
47 {
48           u8 *ptr = buffer;
49 
50           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  */
hdmi_avi_infoframe_init(struct hdmi_avi_infoframe * frame)59 int hdmi_avi_infoframe_init(struct hdmi_avi_infoframe *frame)
60 {
61           memset(frame, 0, sizeof(*frame));
62 
63           frame->type = HDMI_INFOFRAME_TYPE_AVI;
64           frame->version = 2;
65           frame->length = HDMI_AVI_INFOFRAME_SIZE;
66 
67           return 0;
68 }
69 EXPORT_SYMBOL(hdmi_avi_infoframe_init);
70 
71 /**
72  * hdmi_avi_infoframe_pack() - write HDMI AVI infoframe to binary buffer
73  * @frame: HDMI AVI infoframe
74  * @buffer: destination buffer
75  * @size: size of buffer
76  *
77  * Packs the information contained in the @frame structure into a binary
78  * representation that can be written into the corresponding controller
79  * registers. Also computes the checksum as required by section 5.3.5 of
80  * the HDMI 1.4 specification.
81  *
82  * Returns the number of bytes packed into the binary buffer or a negative
83  * error code on failure.
84  */
hdmi_avi_infoframe_pack(struct hdmi_avi_infoframe * frame,void * buffer,size_t size)85 ssize_t hdmi_avi_infoframe_pack(struct hdmi_avi_infoframe *frame, void *buffer,
86                                         size_t size)
87 {
88           u8 *ptr = buffer;
89           size_t length;
90 
91           length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;
92 
93           if (size < length)
94                     return -ENOSPC;
95 
96           memset(buffer, 0, size);
97 
98           ptr[0] = frame->type;
99           ptr[1] = frame->version;
100           ptr[2] = frame->length;
101           ptr[3] = 0; /* checksum */
102 
103           /* start infoframe payload */
104           ptr += HDMI_INFOFRAME_HEADER_SIZE;
105 
106           ptr[0] = ((frame->colorspace & 0x3) << 5) | (frame->scan_mode & 0x3);
107 
108           /*
109            * Data byte 1, bit 4 has to be set if we provide the active format
110            * aspect ratio
111            */
112           if (frame->active_aspect & 0xf)
113                     ptr[0] |= BIT(4);
114 
115           /* Bit 3 and 2 indicate if we transmit horizontal/vertical bar data */
116           if (frame->top_bar || frame->bottom_bar)
117                     ptr[0] |= BIT(3);
118 
119           if (frame->left_bar || frame->right_bar)
120                     ptr[0] |= BIT(2);
121 
122           ptr[1] = ((frame->colorimetry & 0x3) << 6) |
123                      ((frame->picture_aspect & 0x3) << 4) |
124                      (frame->active_aspect & 0xf);
125 
126           ptr[2] = ((frame->extended_colorimetry & 0x7) << 4) |
127                      ((frame->quantization_range & 0x3) << 2) |
128                      (frame->nups & 0x3);
129 
130           if (frame->itc)
131                     ptr[2] |= BIT(7);
132 
133           ptr[3] = frame->video_code & 0x7f;
134 
135           ptr[4] = ((frame->ycc_quantization_range & 0x3) << 6) |
136                      ((frame->content_type & 0x3) << 4) |
137                      (frame->pixel_repeat & 0xf);
138 
139           ptr[5] = frame->top_bar & 0xff;
140           ptr[6] = (frame->top_bar >> 8) & 0xff;
141           ptr[7] = frame->bottom_bar & 0xff;
142           ptr[8] = (frame->bottom_bar >> 8) & 0xff;
143           ptr[9] = frame->left_bar & 0xff;
144           ptr[10] = (frame->left_bar >> 8) & 0xff;
145           ptr[11] = frame->right_bar & 0xff;
146           ptr[12] = (frame->right_bar >> 8) & 0xff;
147 
148           hdmi_infoframe_set_checksum(buffer, length);
149 
150           return length;
151 }
152 EXPORT_SYMBOL(hdmi_avi_infoframe_pack);
153 
154 /**
155  * hdmi_spd_infoframe_init() - initialize an HDMI SPD infoframe
156  * @frame: HDMI SPD infoframe
157  * @vendor: vendor string
158  * @product: product string
159  *
160  * Returns 0 on success or a negative error code on failure.
161  */
hdmi_spd_infoframe_init(struct hdmi_spd_infoframe * frame,const char * vendor,const char * product)162 int hdmi_spd_infoframe_init(struct hdmi_spd_infoframe *frame,
163                                   const char *vendor, const char *product)
164 {
165           memset(frame, 0, sizeof(*frame));
166 
167           frame->type = HDMI_INFOFRAME_TYPE_SPD;
168           frame->version = 1;
169           frame->length = HDMI_SPD_INFOFRAME_SIZE;
170 
171           strncpy(frame->vendor, vendor, sizeof(frame->vendor));
172           strncpy(frame->product, product, sizeof(frame->product));
173 
174           return 0;
175 }
176 EXPORT_SYMBOL(hdmi_spd_infoframe_init);
177 
178 /**
179  * hdmi_spd_infoframe_pack() - write HDMI SPD infoframe to binary buffer
180  * @frame: HDMI SPD infoframe
181  * @buffer: destination buffer
182  * @size: size of buffer
183  *
184  * Packs the information contained in the @frame structure into a binary
185  * representation that can be written into the corresponding controller
186  * registers. Also computes the checksum as required by section 5.3.5 of
187  * the HDMI 1.4 specification.
188  *
189  * Returns the number of bytes packed into the binary buffer or a negative
190  * error code on failure.
191  */
hdmi_spd_infoframe_pack(struct hdmi_spd_infoframe * frame,void * buffer,size_t size)192 ssize_t hdmi_spd_infoframe_pack(struct hdmi_spd_infoframe *frame, void *buffer,
193                                         size_t size)
194 {
195           u8 *ptr = buffer;
196           size_t length;
197 
198           length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;
199 
200           if (size < length)
201                     return -ENOSPC;
202 
203           memset(buffer, 0, size);
204 
205           ptr[0] = frame->type;
206           ptr[1] = frame->version;
207           ptr[2] = frame->length;
208           ptr[3] = 0; /* checksum */
209 
210           /* start infoframe payload */
211           ptr += HDMI_INFOFRAME_HEADER_SIZE;
212 
213           memcpy(ptr, frame->vendor, sizeof(frame->vendor));
214           memcpy(ptr + 8, frame->product, sizeof(frame->product));
215 
216           ptr[24] = frame->sdi;
217 
218           hdmi_infoframe_set_checksum(buffer, length);
219 
220           return length;
221 }
222 EXPORT_SYMBOL(hdmi_spd_infoframe_pack);
223 
224 /**
225  * hdmi_audio_infoframe_init() - initialize an HDMI audio infoframe
226  * @frame: HDMI audio infoframe
227  *
228  * Returns 0 on success or a negative error code on failure.
229  */
hdmi_audio_infoframe_init(struct hdmi_audio_infoframe * frame)230 int hdmi_audio_infoframe_init(struct hdmi_audio_infoframe *frame)
231 {
232           memset(frame, 0, sizeof(*frame));
233 
234           frame->type = HDMI_INFOFRAME_TYPE_AUDIO;
235           frame->version = 1;
236           frame->length = HDMI_AUDIO_INFOFRAME_SIZE;
237 
238           return 0;
239 }
240 EXPORT_SYMBOL(hdmi_audio_infoframe_init);
241 
242 /**
243  * hdmi_audio_infoframe_pack() - write HDMI audio infoframe to binary buffer
244  * @frame: HDMI audio infoframe
245  * @buffer: destination buffer
246  * @size: size of buffer
247  *
248  * Packs the information contained in the @frame structure into a binary
249  * representation that can be written into the corresponding controller
250  * registers. Also computes the checksum as required by section 5.3.5 of
251  * the HDMI 1.4 specification.
252  *
253  * Returns the number of bytes packed into the binary buffer or a negative
254  * error code on failure.
255  */
hdmi_audio_infoframe_pack(struct hdmi_audio_infoframe * frame,void * buffer,size_t size)256 ssize_t hdmi_audio_infoframe_pack(struct hdmi_audio_infoframe *frame,
257                                           void *buffer, size_t size)
258 {
259           unsigned char channels;
260           u8 *ptr = buffer;
261           size_t length;
262 
263           length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;
264 
265           if (size < length)
266                     return -ENOSPC;
267 
268           memset(buffer, 0, size);
269 
270           if (frame->channels >= 2)
271                     channels = frame->channels - 1;
272           else
273                     channels = 0;
274 
275           ptr[0] = frame->type;
276           ptr[1] = frame->version;
277           ptr[2] = frame->length;
278           ptr[3] = 0; /* checksum */
279 
280           /* start infoframe payload */
281           ptr += HDMI_INFOFRAME_HEADER_SIZE;
282 
283           ptr[0] = ((frame->coding_type & 0xf) << 4) | (channels & 0x7);
284           ptr[1] = ((frame->sample_frequency & 0x7) << 2) |
285                      (frame->sample_size & 0x3);
286           ptr[2] = frame->coding_type_ext & 0x1f;
287           ptr[3] = frame->channel_allocation;
288           ptr[4] = (frame->level_shift_value & 0xf) << 3;
289 
290           if (frame->downmix_inhibit)
291                     ptr[4] |= BIT(7);
292 
293           hdmi_infoframe_set_checksum(buffer, length);
294 
295           return length;
296 }
297 EXPORT_SYMBOL(hdmi_audio_infoframe_pack);
298 
299 /**
300  * hdmi_vendor_infoframe_init() - initialize an HDMI vendor infoframe
301  * @frame: HDMI vendor infoframe
302  *
303  * Returns 0 on success or a negative error code on failure.
304  */
hdmi_vendor_infoframe_init(struct hdmi_vendor_infoframe * frame)305 int hdmi_vendor_infoframe_init(struct hdmi_vendor_infoframe *frame)
306 {
307           memset(frame, 0, sizeof(*frame));
308 
309           frame->type = HDMI_INFOFRAME_TYPE_VENDOR;
310           frame->version = 1;
311 
312           frame->oui = HDMI_IEEE_OUI;
313 
314           /*
315            * 0 is a valid value for s3d_struct, so we use a special "not set"
316            * value
317            */
318           frame->s3d_struct = HDMI_3D_STRUCTURE_INVALID;
319 
320           return 0;
321 }
322 EXPORT_SYMBOL(hdmi_vendor_infoframe_init);
323 
324 /**
325  * hdmi_vendor_infoframe_pack() - write a HDMI vendor infoframe to binary buffer
326  * @frame: HDMI infoframe
327  * @buffer: destination buffer
328  * @size: size of buffer
329  *
330  * Packs the information contained in the @frame structure into a binary
331  * representation that can be written into the corresponding controller
332  * registers. Also computes the checksum as required by section 5.3.5 of
333  * the HDMI 1.4 specification.
334  *
335  * Returns the number of bytes packed into the binary buffer or a negative
336  * error code on failure.
337  */
hdmi_vendor_infoframe_pack(struct hdmi_vendor_infoframe * frame,void * buffer,size_t size)338 ssize_t hdmi_vendor_infoframe_pack(struct hdmi_vendor_infoframe *frame,
339                                          void *buffer, size_t size)
340 {
341           u8 *ptr = buffer;
342           size_t length;
343 
344           /* empty info frame */
345           if (frame->vic == 0 && frame->s3d_struct == HDMI_3D_STRUCTURE_INVALID)
346                     return -EINVAL;
347 
348           /* only one of those can be supplied */
349           if (frame->vic != 0 && frame->s3d_struct != HDMI_3D_STRUCTURE_INVALID)
350                     return -EINVAL;
351 
352           /* for side by side (half) we also need to provide 3D_Ext_Data */
353           if (frame->s3d_struct >= HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF)
354                     frame->length = 6;
355           else
356                     frame->length = 5;
357 
358           length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;
359 
360           if (size < length)
361                     return -ENOSPC;
362 
363           memset(buffer, 0, size);
364 
365           ptr[0] = frame->type;
366           ptr[1] = frame->version;
367           ptr[2] = frame->length;
368           ptr[3] = 0; /* checksum */
369 
370           /* HDMI OUI */
371           ptr[4] = 0x03;
372           ptr[5] = 0x0c;
373           ptr[6] = 0x00;
374 
375           if (frame->vic) {
376                     ptr[7] = 0x1 << 5;  /* video format */
377                     ptr[8] = frame->vic;
378           } else {
379                     ptr[7] = 0x2 << 5;  /* video format */
380                     ptr[8] = (frame->s3d_struct & 0xf) << 4;
381                     if (frame->s3d_struct >= HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF)
382                               ptr[9] = (frame->s3d_ext_data & 0xf) << 4;
383           }
384 
385           hdmi_infoframe_set_checksum(buffer, length);
386 
387           return length;
388 }
389 EXPORT_SYMBOL(hdmi_vendor_infoframe_pack);
390 
391 /*
392  * hdmi_vendor_any_infoframe_pack() - write a vendor infoframe to binary buffer
393  */
394 static ssize_t
hdmi_vendor_any_infoframe_pack(union hdmi_vendor_any_infoframe * frame,void * buffer,size_t size)395 hdmi_vendor_any_infoframe_pack(union hdmi_vendor_any_infoframe *frame,
396                                  void *buffer, size_t size)
397 {
398           /* we only know about HDMI vendor infoframes */
399           if (frame->any.oui != HDMI_IEEE_OUI)
400                     return -EINVAL;
401 
402           return hdmi_vendor_infoframe_pack(&frame->hdmi, buffer, size);
403 }
404 
405 /**
406  * hdmi_infoframe_pack() - write a HDMI infoframe to binary buffer
407  * @frame: HDMI infoframe
408  * @buffer: destination buffer
409  * @size: size of buffer
410  *
411  * Packs the information contained in the @frame structure into a binary
412  * representation that can be written into the corresponding controller
413  * registers. Also computes the checksum as required by section 5.3.5 of
414  * the HDMI 1.4 specification.
415  *
416  * Returns the number of bytes packed into the binary buffer or a negative
417  * error code on failure.
418  */
419 ssize_t
hdmi_infoframe_pack(union hdmi_infoframe * frame,void * buffer,size_t size)420 hdmi_infoframe_pack(union hdmi_infoframe *frame, void *buffer, size_t size)
421 {
422           ssize_t length;
423 
424           switch (frame->any.type) {
425           case HDMI_INFOFRAME_TYPE_AVI:
426                     length = hdmi_avi_infoframe_pack(&frame->avi, buffer, size);
427                     break;
428           case HDMI_INFOFRAME_TYPE_SPD:
429                     length = hdmi_spd_infoframe_pack(&frame->spd, buffer, size);
430                     break;
431           case HDMI_INFOFRAME_TYPE_AUDIO:
432                     length = hdmi_audio_infoframe_pack(&frame->audio, buffer, size);
433                     break;
434           case HDMI_INFOFRAME_TYPE_VENDOR:
435                     length = hdmi_vendor_any_infoframe_pack(&frame->vendor,
436                                                                       buffer, size);
437                     break;
438           default:
439                     WARN(1, "Bad infoframe type %d\n", frame->any.type);
440                     length = -EINVAL;
441           }
442 
443           return length;
444 }
445 EXPORT_SYMBOL(hdmi_infoframe_pack);
446 
hdmi_infoframe_type_get_name(enum hdmi_infoframe_type type)447 static const char *hdmi_infoframe_type_get_name(enum hdmi_infoframe_type type)
448 {
449           if (type < 0x80 || type > 0x9f)
450                     return "Invalid";
451           switch (type) {
452           case HDMI_INFOFRAME_TYPE_VENDOR:
453                     return "Vendor";
454           case HDMI_INFOFRAME_TYPE_AVI:
455                     return "Auxiliary Video Information (AVI)";
456           case HDMI_INFOFRAME_TYPE_SPD:
457                     return "Source Product Description (SPD)";
458           case HDMI_INFOFRAME_TYPE_AUDIO:
459                     return "Audio";
460           }
461           return "Reserved";
462 }
463 
hdmi_infoframe_log_header(const char * level,struct device * dev,struct hdmi_any_infoframe * frame)464 static void hdmi_infoframe_log_header(const char *level,
465                                               struct device *dev,
466                                               struct hdmi_any_infoframe *frame)
467 {
468           hdmi_log("HDMI infoframe: %s, version %u, length %u\n",
469                     hdmi_infoframe_type_get_name(frame->type),
470                     frame->version, frame->length);
471 }
472 
hdmi_colorspace_get_name(enum hdmi_colorspace colorspace)473 static const char *hdmi_colorspace_get_name(enum hdmi_colorspace colorspace)
474 {
475           switch (colorspace) {
476           case HDMI_COLORSPACE_RGB:
477                     return "RGB";
478           case HDMI_COLORSPACE_YUV422:
479                     return "YCbCr 4:2:2";
480           case HDMI_COLORSPACE_YUV444:
481                     return "YCbCr 4:4:4";
482           case HDMI_COLORSPACE_YUV420:
483                     return "YCbCr 4:2:0";
484           case HDMI_COLORSPACE_RESERVED4:
485                     return "Reserved (4)";
486           case HDMI_COLORSPACE_RESERVED5:
487                     return "Reserved (5)";
488           case HDMI_COLORSPACE_RESERVED6:
489                     return "Reserved (6)";
490           case HDMI_COLORSPACE_IDO_DEFINED:
491                     return "IDO Defined";
492           }
493           return "Invalid";
494 }
495 
hdmi_scan_mode_get_name(enum hdmi_scan_mode scan_mode)496 static const char *hdmi_scan_mode_get_name(enum hdmi_scan_mode scan_mode)
497 {
498           switch (scan_mode) {
499           case HDMI_SCAN_MODE_NONE:
500                     return "No Data";
501           case HDMI_SCAN_MODE_OVERSCAN:
502                     return "Overscan";
503           case HDMI_SCAN_MODE_UNDERSCAN:
504                     return "Underscan";
505           case HDMI_SCAN_MODE_RESERVED:
506                     return "Reserved";
507           }
508           return "Invalid";
509 }
510 
hdmi_colorimetry_get_name(enum hdmi_colorimetry colorimetry)511 static const char *hdmi_colorimetry_get_name(enum hdmi_colorimetry colorimetry)
512 {
513           switch (colorimetry) {
514           case HDMI_COLORIMETRY_NONE:
515                     return "No Data";
516           case HDMI_COLORIMETRY_ITU_601:
517                     return "ITU601";
518           case HDMI_COLORIMETRY_ITU_709:
519                     return "ITU709";
520           case HDMI_COLORIMETRY_EXTENDED:
521                     return "Extended";
522           }
523           return "Invalid";
524 }
525 
526 static const char *
hdmi_picture_aspect_get_name(enum hdmi_picture_aspect picture_aspect)527 hdmi_picture_aspect_get_name(enum hdmi_picture_aspect picture_aspect)
528 {
529           switch (picture_aspect) {
530           case HDMI_PICTURE_ASPECT_NONE:
531                     return "No Data";
532           case HDMI_PICTURE_ASPECT_4_3:
533                     return "4:3";
534           case HDMI_PICTURE_ASPECT_16_9:
535                     return "16:9";
536           case HDMI_PICTURE_ASPECT_64_27:
537                     return "64:27";
538           case HDMI_PICTURE_ASPECT_256_135:
539                     return "256:135";
540           case HDMI_PICTURE_ASPECT_RESERVED:
541                     return "Reserved";
542           }
543           return "Invalid";
544 }
545 
546 static const char *
hdmi_active_aspect_get_name(enum hdmi_active_aspect active_aspect)547 hdmi_active_aspect_get_name(enum hdmi_active_aspect active_aspect)
548 {
549           if (active_aspect < 0 || active_aspect > 0xf)
550                     return "Invalid";
551 
552           switch (active_aspect) {
553           case HDMI_ACTIVE_ASPECT_16_9_TOP:
554                     return "16:9 Top";
555           case HDMI_ACTIVE_ASPECT_14_9_TOP:
556                     return "14:9 Top";
557           case HDMI_ACTIVE_ASPECT_16_9_CENTER:
558                     return "16:9 Center";
559           case HDMI_ACTIVE_ASPECT_PICTURE:
560                     return "Same as Picture";
561           case HDMI_ACTIVE_ASPECT_4_3:
562                     return "4:3";
563           case HDMI_ACTIVE_ASPECT_16_9:
564                     return "16:9";
565           case HDMI_ACTIVE_ASPECT_14_9:
566                     return "14:9";
567           case HDMI_ACTIVE_ASPECT_4_3_SP_14_9:
568                     return "4:3 SP 14:9";
569           case HDMI_ACTIVE_ASPECT_16_9_SP_14_9:
570                     return "16:9 SP 14:9";
571           case HDMI_ACTIVE_ASPECT_16_9_SP_4_3:
572                     return "16:9 SP 4:3";
573           }
574           return "Reserved";
575 }
576 
577 static const char *
hdmi_extended_colorimetry_get_name(enum hdmi_extended_colorimetry ext_col)578 hdmi_extended_colorimetry_get_name(enum hdmi_extended_colorimetry ext_col)
579 {
580           switch (ext_col) {
581           case HDMI_EXTENDED_COLORIMETRY_XV_YCC_601:
582                     return "xvYCC 601";
583           case HDMI_EXTENDED_COLORIMETRY_XV_YCC_709:
584                     return "xvYCC 709";
585           case HDMI_EXTENDED_COLORIMETRY_S_YCC_601:
586                     return "sYCC 601";
587           case HDMI_EXTENDED_COLORIMETRY_ADOBE_YCC_601:
588                     return "Adobe YCC 601";
589           case HDMI_EXTENDED_COLORIMETRY_ADOBE_RGB:
590                     return "Adobe RGB";
591           case HDMI_EXTENDED_COLORIMETRY_BT2020_CONST_LUM:
592                     return "BT.2020 Constant Luminance";
593           case HDMI_EXTENDED_COLORIMETRY_BT2020:
594                     return "BT.2020";
595           case HDMI_EXTENDED_COLORIMETRY_RESERVED:
596                     return "Reserved";
597           }
598           return "Invalid";
599 }
600 
601 static const char *
hdmi_quantization_range_get_name(enum hdmi_quantization_range qrange)602 hdmi_quantization_range_get_name(enum hdmi_quantization_range qrange)
603 {
604           switch (qrange) {
605           case HDMI_QUANTIZATION_RANGE_DEFAULT:
606                     return "Default";
607           case HDMI_QUANTIZATION_RANGE_LIMITED:
608                     return "Limited";
609           case HDMI_QUANTIZATION_RANGE_FULL:
610                     return "Full";
611           case HDMI_QUANTIZATION_RANGE_RESERVED:
612                     return "Reserved";
613           }
614           return "Invalid";
615 }
616 
hdmi_nups_get_name(enum hdmi_nups nups)617 static const char *hdmi_nups_get_name(enum hdmi_nups nups)
618 {
619           switch (nups) {
620           case HDMI_NUPS_UNKNOWN:
621                     return "Unknown Non-uniform Scaling";
622           case HDMI_NUPS_HORIZONTAL:
623                     return "Horizontally Scaled";
624           case HDMI_NUPS_VERTICAL:
625                     return "Vertically Scaled";
626           case HDMI_NUPS_BOTH:
627                     return "Horizontally and Vertically Scaled";
628           }
629           return "Invalid";
630 }
631 
632 static const char *
hdmi_ycc_quantization_range_get_name(enum hdmi_ycc_quantization_range qrange)633 hdmi_ycc_quantization_range_get_name(enum hdmi_ycc_quantization_range qrange)
634 {
635           switch (qrange) {
636           case HDMI_YCC_QUANTIZATION_RANGE_LIMITED:
637                     return "Limited";
638           case HDMI_YCC_QUANTIZATION_RANGE_FULL:
639                     return "Full";
640           }
641           return "Invalid";
642 }
643 
644 static const char *
hdmi_content_type_get_name(enum hdmi_content_type content_type)645 hdmi_content_type_get_name(enum hdmi_content_type content_type)
646 {
647           switch (content_type) {
648           case HDMI_CONTENT_TYPE_GRAPHICS:
649                     return "Graphics";
650           case HDMI_CONTENT_TYPE_PHOTO:
651                     return "Photo";
652           case HDMI_CONTENT_TYPE_CINEMA:
653                     return "Cinema";
654           case HDMI_CONTENT_TYPE_GAME:
655                     return "Game";
656           }
657           return "Invalid";
658 }
659 
660 /**
661  * hdmi_avi_infoframe_log() - log info of HDMI AVI infoframe
662  * @level: logging level
663  * @dev: device
664  * @frame: HDMI AVI infoframe
665  */
hdmi_avi_infoframe_log(const char * level,struct device * dev,struct hdmi_avi_infoframe * frame)666 static void hdmi_avi_infoframe_log(const char *level,
667                                            struct device *dev,
668                                            struct hdmi_avi_infoframe *frame)
669 {
670           hdmi_infoframe_log_header(level, dev,
671                                           (struct hdmi_any_infoframe *)frame);
672 
673           hdmi_log("    colorspace: %s\n",
674                               hdmi_colorspace_get_name(frame->colorspace));
675           hdmi_log("    scan mode: %s\n",
676                               hdmi_scan_mode_get_name(frame->scan_mode));
677           hdmi_log("    colorimetry: %s\n",
678                               hdmi_colorimetry_get_name(frame->colorimetry));
679           hdmi_log("    picture aspect: %s\n",
680                               hdmi_picture_aspect_get_name(frame->picture_aspect));
681           hdmi_log("    active aspect: %s\n",
682                               hdmi_active_aspect_get_name(frame->active_aspect));
683           hdmi_log("    itc: %s\n", frame->itc ? "IT Content" : "No Data");
684           hdmi_log("    extended colorimetry: %s\n",
685                               hdmi_extended_colorimetry_get_name(frame->extended_colorimetry));
686           hdmi_log("    quantization range: %s\n",
687                               hdmi_quantization_range_get_name(frame->quantization_range));
688           hdmi_log("    nups: %s\n", hdmi_nups_get_name(frame->nups));
689           hdmi_log("    video code: %u\n", frame->video_code);
690           hdmi_log("    ycc quantization range: %s\n",
691                               hdmi_ycc_quantization_range_get_name(frame->ycc_quantization_range));
692           hdmi_log("    hdmi content type: %s\n",
693                               hdmi_content_type_get_name(frame->content_type));
694           hdmi_log("    pixel repeat: %u\n", frame->pixel_repeat);
695           hdmi_log("    bar top %u, bottom %u, left %u, right %u\n",
696                               frame->top_bar, frame->bottom_bar,
697                               frame->left_bar, frame->right_bar);
698 }
699 
hdmi_spd_sdi_get_name(enum hdmi_spd_sdi sdi)700 static const char *hdmi_spd_sdi_get_name(enum hdmi_spd_sdi sdi)
701 {
702           if (sdi < 0 || sdi > 0xff)
703                     return "Invalid";
704           switch (sdi) {
705           case HDMI_SPD_SDI_UNKNOWN:
706                     return "Unknown";
707           case HDMI_SPD_SDI_DSTB:
708                     return "Digital STB";
709           case HDMI_SPD_SDI_DVDP:
710                     return "DVD Player";
711           case HDMI_SPD_SDI_DVHS:
712                     return "D-VHS";
713           case HDMI_SPD_SDI_HDDVR:
714                     return "HDD Videorecorder";
715           case HDMI_SPD_SDI_DVC:
716                     return "DVC";
717           case HDMI_SPD_SDI_DSC:
718                     return "DSC";
719           case HDMI_SPD_SDI_VCD:
720                     return "Video CD";
721           case HDMI_SPD_SDI_GAME:
722                     return "Game";
723           case HDMI_SPD_SDI_PC:
724                     return "PC General";
725           case HDMI_SPD_SDI_BD:
726                     return "Blu-Ray Disc (BD)";
727           case HDMI_SPD_SDI_SACD:
728                     return "Super Audio CD";
729           case HDMI_SPD_SDI_HDDVD:
730                     return "HD DVD";
731           case HDMI_SPD_SDI_PMP:
732                     return "PMP";
733           }
734           return "Reserved";
735 }
736 
737 /**
738  * hdmi_spd_infoframe_log() - log info of HDMI SPD infoframe
739  * @level: logging level
740  * @dev: device
741  * @frame: HDMI SPD infoframe
742  */
hdmi_spd_infoframe_log(const char * level,struct device * dev,struct hdmi_spd_infoframe * frame)743 static void hdmi_spd_infoframe_log(const char *level,
744                                            struct device *dev,
745                                            struct hdmi_spd_infoframe *frame)
746 {
747           u8 buf[17];
748 
749           hdmi_infoframe_log_header(level, dev,
750                                           (struct hdmi_any_infoframe *)frame);
751 
752           memset(buf, 0, sizeof(buf));
753 
754           strncpy(buf, frame->vendor, 8);
755           hdmi_log("    vendor: %s\n", buf);
756           strncpy(buf, frame->product, 16);
757           hdmi_log("    product: %s\n", buf);
758           hdmi_log("    source device information: %s (0x%x)\n",
759                     hdmi_spd_sdi_get_name(frame->sdi), frame->sdi);
760 }
761 
762 static const char *
hdmi_audio_coding_type_get_name(enum hdmi_audio_coding_type coding_type)763 hdmi_audio_coding_type_get_name(enum hdmi_audio_coding_type coding_type)
764 {
765           switch (coding_type) {
766           case HDMI_AUDIO_CODING_TYPE_STREAM:
767                     return "Refer to Stream Header";
768           case HDMI_AUDIO_CODING_TYPE_PCM:
769                     return "PCM";
770           case HDMI_AUDIO_CODING_TYPE_AC3:
771                     return "AC-3";
772           case HDMI_AUDIO_CODING_TYPE_MPEG1:
773                     return "MPEG1";
774           case HDMI_AUDIO_CODING_TYPE_MP3:
775                     return "MP3";
776           case HDMI_AUDIO_CODING_TYPE_MPEG2:
777                     return "MPEG2";
778           case HDMI_AUDIO_CODING_TYPE_AAC_LC:
779                     return "AAC";
780           case HDMI_AUDIO_CODING_TYPE_DTS:
781                     return "DTS";
782           case HDMI_AUDIO_CODING_TYPE_ATRAC:
783                     return "ATRAC";
784           case HDMI_AUDIO_CODING_TYPE_DSD:
785                     return "One Bit Audio";
786           case HDMI_AUDIO_CODING_TYPE_EAC3:
787                     return "Dolby Digital +";
788           case HDMI_AUDIO_CODING_TYPE_DTS_HD:
789                     return "DTS-HD";
790           case HDMI_AUDIO_CODING_TYPE_MLP:
791                     return "MAT (MLP)";
792           case HDMI_AUDIO_CODING_TYPE_DST:
793                     return "DST";
794           case HDMI_AUDIO_CODING_TYPE_WMA_PRO:
795                     return "WMA PRO";
796           case HDMI_AUDIO_CODING_TYPE_CXT:
797                     return "Refer to CXT";
798           }
799           return "Invalid";
800 }
801 
802 static const char *
hdmi_audio_sample_size_get_name(enum hdmi_audio_sample_size sample_size)803 hdmi_audio_sample_size_get_name(enum hdmi_audio_sample_size sample_size)
804 {
805           switch (sample_size) {
806           case HDMI_AUDIO_SAMPLE_SIZE_STREAM:
807                     return "Refer to Stream Header";
808           case HDMI_AUDIO_SAMPLE_SIZE_16:
809                     return "16 bit";
810           case HDMI_AUDIO_SAMPLE_SIZE_20:
811                     return "20 bit";
812           case HDMI_AUDIO_SAMPLE_SIZE_24:
813                     return "24 bit";
814           }
815           return "Invalid";
816 }
817 
818 static const char *
hdmi_audio_sample_frequency_get_name(enum hdmi_audio_sample_frequency freq)819 hdmi_audio_sample_frequency_get_name(enum hdmi_audio_sample_frequency freq)
820 {
821           switch (freq) {
822           case HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM:
823                     return "Refer to Stream Header";
824           case HDMI_AUDIO_SAMPLE_FREQUENCY_32000:
825                     return "32 kHz";
826           case HDMI_AUDIO_SAMPLE_FREQUENCY_44100:
827                     return "44.1 kHz (CD)";
828           case HDMI_AUDIO_SAMPLE_FREQUENCY_48000:
829                     return "48 kHz";
830           case HDMI_AUDIO_SAMPLE_FREQUENCY_88200:
831                     return "88.2 kHz";
832           case HDMI_AUDIO_SAMPLE_FREQUENCY_96000:
833                     return "96 kHz";
834           case HDMI_AUDIO_SAMPLE_FREQUENCY_176400:
835                     return "176.4 kHz";
836           case HDMI_AUDIO_SAMPLE_FREQUENCY_192000:
837                     return "192 kHz";
838           }
839           return "Invalid";
840 }
841 
842 static const char *
hdmi_audio_coding_type_ext_get_name(enum hdmi_audio_coding_type_ext ctx)843 hdmi_audio_coding_type_ext_get_name(enum hdmi_audio_coding_type_ext ctx)
844 {
845           if (ctx < 0 || ctx > 0x1f)
846                     return "Invalid";
847 
848           switch (ctx) {
849           case HDMI_AUDIO_CODING_TYPE_EXT_CT:
850                     return "Refer to CT";
851           case HDMI_AUDIO_CODING_TYPE_EXT_HE_AAC:
852                     return "HE AAC";
853           case HDMI_AUDIO_CODING_TYPE_EXT_HE_AAC_V2:
854                     return "HE AAC v2";
855           case HDMI_AUDIO_CODING_TYPE_EXT_MPEG_SURROUND:
856                     return "MPEG SURROUND";
857           case HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_HE_AAC:
858                     return "MPEG-4 HE AAC";
859           case HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_HE_AAC_V2:
860                     return "MPEG-4 HE AAC v2";
861           case HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_AAC_LC:
862                     return "MPEG-4 AAC LC";
863           case HDMI_AUDIO_CODING_TYPE_EXT_DRA:
864                     return "DRA";
865           case HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_HE_AAC_SURROUND:
866                     return "MPEG-4 HE AAC + MPEG Surround";
867           case HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_AAC_LC_SURROUND:
868                     return "MPEG-4 AAC LC + MPEG Surround";
869           }
870           return "Reserved";
871 }
872 
873 /**
874  * hdmi_audio_infoframe_log() - log info of HDMI AUDIO infoframe
875  * @level: logging level
876  * @dev: device
877  * @frame: HDMI AUDIO infoframe
878  */
hdmi_audio_infoframe_log(const char * level,struct device * dev,struct hdmi_audio_infoframe * frame)879 static void hdmi_audio_infoframe_log(const char *level,
880                                              struct device *dev,
881                                              struct hdmi_audio_infoframe *frame)
882 {
883           hdmi_infoframe_log_header(level, dev,
884                                           (struct hdmi_any_infoframe *)frame);
885 
886           if (frame->channels)
887                     hdmi_log("    channels: %u\n", frame->channels - 1);
888           else
889                     hdmi_log("    channels: Refer to stream header\n");
890           hdmi_log("    coding type: %s\n",
891                               hdmi_audio_coding_type_get_name(frame->coding_type));
892           hdmi_log("    sample size: %s\n",
893                               hdmi_audio_sample_size_get_name(frame->sample_size));
894           hdmi_log("    sample frequency: %s\n",
895                               hdmi_audio_sample_frequency_get_name(frame->sample_frequency));
896           hdmi_log("    coding type ext: %s\n",
897                               hdmi_audio_coding_type_ext_get_name(frame->coding_type_ext));
898           hdmi_log("    channel allocation: 0x%x\n",
899                               frame->channel_allocation);
900           hdmi_log("    level shift value: %u dB\n",
901                               frame->level_shift_value);
902           hdmi_log("    downmix inhibit: %s\n",
903                               frame->downmix_inhibit ? "Yes" : "No");
904 }
905 
906 static const char *
hdmi_3d_structure_get_name(enum hdmi_3d_structure s3d_struct)907 hdmi_3d_structure_get_name(enum hdmi_3d_structure s3d_struct)
908 {
909           if (s3d_struct < 0 || s3d_struct > 0xf)
910                     return "Invalid";
911 
912           switch (s3d_struct) {
913           case HDMI_3D_STRUCTURE_FRAME_PACKING:
914                     return "Frame Packing";
915           case HDMI_3D_STRUCTURE_FIELD_ALTERNATIVE:
916                     return "Field Alternative";
917           case HDMI_3D_STRUCTURE_LINE_ALTERNATIVE:
918                     return "Line Alternative";
919           case HDMI_3D_STRUCTURE_SIDE_BY_SIDE_FULL:
920                     return "Side-by-side (Full)";
921           case HDMI_3D_STRUCTURE_L_DEPTH:
922                     return "L + Depth";
923           case HDMI_3D_STRUCTURE_L_DEPTH_GFX_GFX_DEPTH:
924                     return "L + Depth + Graphics + Graphics-depth";
925           case HDMI_3D_STRUCTURE_TOP_AND_BOTTOM:
926                     return "Top-and-Bottom";
927           case HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF:
928                     return "Side-by-side (Half)";
929           default:
930                     break;
931           }
932           return "Reserved";
933 }
934 
935 /**
936  * hdmi_vendor_infoframe_log() - log info of HDMI VENDOR infoframe
937  * @level: logging level
938  * @dev: device
939  * @frame: HDMI VENDOR infoframe
940  */
941 static void
hdmi_vendor_any_infoframe_log(const char * level,struct device * dev,union hdmi_vendor_any_infoframe * frame)942 hdmi_vendor_any_infoframe_log(const char *level,
943                                     struct device *dev,
944                                     union hdmi_vendor_any_infoframe *frame)
945 {
946           struct hdmi_vendor_infoframe *hvf = &frame->hdmi;
947 
948           hdmi_infoframe_log_header(level, dev,
949                                           (struct hdmi_any_infoframe *)frame);
950 
951           if (frame->any.oui != HDMI_IEEE_OUI) {
952                     hdmi_log("    not a HDMI vendor infoframe\n");
953                     return;
954           }
955           if (hvf->vic == 0 && hvf->s3d_struct == HDMI_3D_STRUCTURE_INVALID) {
956                     hdmi_log("    empty frame\n");
957                     return;
958           }
959 
960           if (hvf->vic)
961                     hdmi_log("    HDMI VIC: %u\n", hvf->vic);
962           if (hvf->s3d_struct != HDMI_3D_STRUCTURE_INVALID) {
963                     hdmi_log("    3D structure: %s\n",
964                                         hdmi_3d_structure_get_name(hvf->s3d_struct));
965                     if (hvf->s3d_struct >= HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF)
966                               hdmi_log("    3D extension data: %d\n",
967                                                   hvf->s3d_ext_data);
968           }
969 }
970 
971 /**
972  * hdmi_infoframe_log() - log info of HDMI infoframe
973  * @level: logging level
974  * @dev: device
975  * @frame: HDMI infoframe
976  */
hdmi_infoframe_log(const char * level,struct device * dev,union hdmi_infoframe * frame)977 void hdmi_infoframe_log(const char *level,
978                               struct device *dev,
979                               union hdmi_infoframe *frame)
980 {
981           switch (frame->any.type) {
982           case HDMI_INFOFRAME_TYPE_AVI:
983                     hdmi_avi_infoframe_log(level, dev, &frame->avi);
984                     break;
985           case HDMI_INFOFRAME_TYPE_SPD:
986                     hdmi_spd_infoframe_log(level, dev, &frame->spd);
987                     break;
988           case HDMI_INFOFRAME_TYPE_AUDIO:
989                     hdmi_audio_infoframe_log(level, dev, &frame->audio);
990                     break;
991           case HDMI_INFOFRAME_TYPE_VENDOR:
992                     hdmi_vendor_any_infoframe_log(level, dev, &frame->vendor);
993                     break;
994           }
995 }
996 EXPORT_SYMBOL(hdmi_infoframe_log);
997 
998 /**
999  * hdmi_avi_infoframe_unpack() - unpack binary buffer to a HDMI AVI infoframe
1000  * @buffer: source buffer
1001  * @frame: HDMI AVI infoframe
1002  *
1003  * Unpacks the information contained in binary @buffer into a structured
1004  * @frame of the HDMI Auxiliary Video (AVI) information frame.
1005  * Also verifies the checksum as required by section 5.3.5 of the HDMI 1.4
1006  * specification.
1007  *
1008  * Returns 0 on success or a negative error code on failure.
1009  */
hdmi_avi_infoframe_unpack(struct hdmi_avi_infoframe * frame,void * buffer)1010 static int hdmi_avi_infoframe_unpack(struct hdmi_avi_infoframe *frame,
1011                                              void *buffer)
1012 {
1013           u8 *ptr = buffer;
1014           int ret;
1015 
1016           if (ptr[0] != HDMI_INFOFRAME_TYPE_AVI ||
1017               ptr[1] != 2 ||
1018               ptr[2] != HDMI_AVI_INFOFRAME_SIZE)
1019                     return -EINVAL;
1020 
1021           if (hdmi_infoframe_checksum(buffer, HDMI_INFOFRAME_SIZE(AVI)) != 0)
1022                     return -EINVAL;
1023 
1024           ret = hdmi_avi_infoframe_init(frame);
1025           if (ret)
1026                     return ret;
1027 
1028           ptr += HDMI_INFOFRAME_HEADER_SIZE;
1029 
1030           frame->colorspace = (ptr[0] >> 5) & 0x3;
1031           if (ptr[0] & 0x10)
1032                     frame->active_aspect = ptr[1] & 0xf;
1033           if (ptr[0] & 0x8) {
1034                     frame->top_bar = (ptr[5] << 8) + ptr[6];
1035                     frame->bottom_bar = (ptr[7] << 8) + ptr[8];
1036           }
1037           if (ptr[0] & 0x4) {
1038                     frame->left_bar = (ptr[9] << 8) + ptr[10];
1039                     frame->right_bar = (ptr[11] << 8) + ptr[12];
1040           }
1041           frame->scan_mode = ptr[0] & 0x3;
1042 
1043           frame->colorimetry = (ptr[1] >> 6) & 0x3;
1044           frame->picture_aspect = (ptr[1] >> 4) & 0x3;
1045           frame->active_aspect = ptr[1] & 0xf;
1046 
1047           frame->itc = ptr[2] & 0x80 ? true : false;
1048           frame->extended_colorimetry = (ptr[2] >> 4) & 0x7;
1049           frame->quantization_range = (ptr[2] >> 2) & 0x3;
1050           frame->nups = ptr[2] & 0x3;
1051 
1052           frame->video_code = ptr[3] & 0x7f;
1053           frame->ycc_quantization_range = (ptr[4] >> 6) & 0x3;
1054           frame->content_type = (ptr[4] >> 4) & 0x3;
1055 
1056           frame->pixel_repeat = ptr[4] & 0xf;
1057 
1058           return 0;
1059 }
1060 
1061 /**
1062  * hdmi_spd_infoframe_unpack() - unpack binary buffer to a HDMI SPD infoframe
1063  * @buffer: source buffer
1064  * @frame: HDMI SPD infoframe
1065  *
1066  * Unpacks the information contained in binary @buffer into a structured
1067  * @frame of the HDMI Source Product Description (SPD) information frame.
1068  * Also verifies the checksum as required by section 5.3.5 of the HDMI 1.4
1069  * specification.
1070  *
1071  * Returns 0 on success or a negative error code on failure.
1072  */
hdmi_spd_infoframe_unpack(struct hdmi_spd_infoframe * frame,void * buffer)1073 static int hdmi_spd_infoframe_unpack(struct hdmi_spd_infoframe *frame,
1074                                              void *buffer)
1075 {
1076           u8 *ptr = buffer;
1077           int ret;
1078 
1079           if (ptr[0] != HDMI_INFOFRAME_TYPE_SPD ||
1080               ptr[1] != 1 ||
1081               ptr[2] != HDMI_SPD_INFOFRAME_SIZE) {
1082                     return -EINVAL;
1083           }
1084 
1085           if (hdmi_infoframe_checksum(buffer, HDMI_INFOFRAME_SIZE(SPD)) != 0)
1086                     return -EINVAL;
1087 
1088           ptr += HDMI_INFOFRAME_HEADER_SIZE;
1089 
1090           ret = hdmi_spd_infoframe_init(frame, ptr, ptr + 8);
1091           if (ret)
1092                     return ret;
1093 
1094           frame->sdi = ptr[24];
1095 
1096           return 0;
1097 }
1098 
1099 /**
1100  * hdmi_audio_infoframe_unpack() - unpack binary buffer to a HDMI AUDIO infoframe
1101  * @buffer: source buffer
1102  * @frame: HDMI Audio infoframe
1103  *
1104  * Unpacks the information contained in binary @buffer into a structured
1105  * @frame of the HDMI Audio information frame.
1106  * Also verifies the checksum as required by section 5.3.5 of the HDMI 1.4
1107  * specification.
1108  *
1109  * Returns 0 on success or a negative error code on failure.
1110  */
hdmi_audio_infoframe_unpack(struct hdmi_audio_infoframe * frame,void * buffer)1111 static int hdmi_audio_infoframe_unpack(struct hdmi_audio_infoframe *frame,
1112                                                void *buffer)
1113 {
1114           u8 *ptr = buffer;
1115           int ret;
1116 
1117           if (ptr[0] != HDMI_INFOFRAME_TYPE_AUDIO ||
1118               ptr[1] != 1 ||
1119               ptr[2] != HDMI_AUDIO_INFOFRAME_SIZE) {
1120                     return -EINVAL;
1121           }
1122 
1123           if (hdmi_infoframe_checksum(buffer, HDMI_INFOFRAME_SIZE(AUDIO)) != 0)
1124                     return -EINVAL;
1125 
1126           ret = hdmi_audio_infoframe_init(frame);
1127           if (ret)
1128                     return ret;
1129 
1130           ptr += HDMI_INFOFRAME_HEADER_SIZE;
1131 
1132           frame->channels = ptr[0] & 0x7;
1133           frame->coding_type = (ptr[0] >> 4) & 0xf;
1134           frame->sample_size = ptr[1] & 0x3;
1135           frame->sample_frequency = (ptr[1] >> 2) & 0x7;
1136           frame->coding_type_ext = ptr[2] & 0x1f;
1137           frame->channel_allocation = ptr[3];
1138           frame->level_shift_value = (ptr[4] >> 3) & 0xf;
1139           frame->downmix_inhibit = ptr[4] & 0x80 ? true : false;
1140 
1141           return 0;
1142 }
1143 
1144 /**
1145  * hdmi_vendor_infoframe_unpack() - unpack binary buffer to a HDMI vendor infoframe
1146  * @buffer: source buffer
1147  * @frame: HDMI Vendor infoframe
1148  *
1149  * Unpacks the information contained in binary @buffer into a structured
1150  * @frame of the HDMI Vendor information frame.
1151  * Also verifies the checksum as required by section 5.3.5 of the HDMI 1.4
1152  * specification.
1153  *
1154  * Returns 0 on success or a negative error code on failure.
1155  */
1156 static int
hdmi_vendor_any_infoframe_unpack(union hdmi_vendor_any_infoframe * frame,void * buffer)1157 hdmi_vendor_any_infoframe_unpack(union hdmi_vendor_any_infoframe *frame,
1158                                          void *buffer)
1159 {
1160           u8 *ptr = buffer;
1161           size_t length;
1162           int ret;
1163           u8 hdmi_video_format;
1164           struct hdmi_vendor_infoframe *hvf = &frame->hdmi;
1165 
1166           if (ptr[0] != HDMI_INFOFRAME_TYPE_VENDOR ||
1167               ptr[1] != 1 ||
1168               (ptr[2] != 5 && ptr[2] != 6))
1169                     return -EINVAL;
1170 
1171           length = ptr[2];
1172 
1173           if (hdmi_infoframe_checksum(buffer,
1174                                             HDMI_INFOFRAME_HEADER_SIZE + length) != 0)
1175                     return -EINVAL;
1176 
1177           ptr += HDMI_INFOFRAME_HEADER_SIZE;
1178 
1179           /* HDMI OUI */
1180           if ((ptr[0] != 0x03) ||
1181               (ptr[1] != 0x0c) ||
1182               (ptr[2] != 0x00))
1183                     return -EINVAL;
1184 
1185           hdmi_video_format = ptr[3] >> 5;
1186 
1187           if (hdmi_video_format > 0x2)
1188                     return -EINVAL;
1189 
1190           ret = hdmi_vendor_infoframe_init(hvf);
1191           if (ret)
1192                     return ret;
1193 
1194           hvf->length = length;
1195 
1196           if (hdmi_video_format == 0x1) {
1197                     hvf->vic = ptr[4];
1198           } else if (hdmi_video_format == 0x2) {
1199                     hvf->s3d_struct = ptr[4] >> 4;
1200                     if (hvf->s3d_struct >= HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF) {
1201                               if (length == 6)
1202                                         hvf->s3d_ext_data = ptr[5] >> 4;
1203                               else
1204                                         return -EINVAL;
1205                     }
1206           }
1207 
1208           return 0;
1209 }
1210 
1211 /**
1212  * hdmi_infoframe_unpack() - unpack binary buffer to a HDMI infoframe
1213  * @buffer: source buffer
1214  * @frame: HDMI infoframe
1215  *
1216  * Unpacks the information contained in binary buffer @buffer into a structured
1217  * @frame of a HDMI infoframe.
1218  * Also verifies the checksum as required by section 5.3.5 of the HDMI 1.4
1219  * specification.
1220  *
1221  * Returns 0 on success or a negative error code on failure.
1222  */
hdmi_infoframe_unpack(union hdmi_infoframe * frame,void * buffer)1223 int hdmi_infoframe_unpack(union hdmi_infoframe *frame, void *buffer)
1224 {
1225           int ret;
1226           u8 *ptr = buffer;
1227 
1228           switch (ptr[0]) {
1229           case HDMI_INFOFRAME_TYPE_AVI:
1230                     ret = hdmi_avi_infoframe_unpack(&frame->avi, buffer);
1231                     break;
1232           case HDMI_INFOFRAME_TYPE_SPD:
1233                     ret = hdmi_spd_infoframe_unpack(&frame->spd, buffer);
1234                     break;
1235           case HDMI_INFOFRAME_TYPE_AUDIO:
1236                     ret = hdmi_audio_infoframe_unpack(&frame->audio, buffer);
1237                     break;
1238           case HDMI_INFOFRAME_TYPE_VENDOR:
1239                     ret = hdmi_vendor_any_infoframe_unpack(&frame->vendor, buffer);
1240                     break;
1241           default:
1242                     ret = -EINVAL;
1243                     break;
1244           }
1245 
1246           return ret;
1247 }
1248 EXPORT_SYMBOL(hdmi_infoframe_unpack);
1249