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