1*193032a3SAndroid Build Coastguard Worker // SPDX-License-Identifier: MIT
2*193032a3SAndroid Build Coastguard Worker /*
3*193032a3SAndroid Build Coastguard Worker * Copyright 2006-2012 Red Hat, Inc.
4*193032a3SAndroid Build Coastguard Worker * Copyright 2018-2020 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
5*193032a3SAndroid Build Coastguard Worker *
6*193032a3SAndroid Build Coastguard Worker * Author: Adam Jackson <[email protected]>
7*193032a3SAndroid Build Coastguard Worker * Maintainer: Hans Verkuil <[email protected]>
8*193032a3SAndroid Build Coastguard Worker */
9*193032a3SAndroid Build Coastguard Worker
10*193032a3SAndroid Build Coastguard Worker #include <stdio.h>
11*193032a3SAndroid Build Coastguard Worker #include <math.h>
12*193032a3SAndroid Build Coastguard Worker
13*193032a3SAndroid Build Coastguard Worker #include "edid-decode.h"
14*193032a3SAndroid Build Coastguard Worker
15*193032a3SAndroid Build Coastguard Worker static const struct timings edid_cta_modes1[] = {
16*193032a3SAndroid Build Coastguard Worker /* VIC 1 */
17*193032a3SAndroid Build Coastguard Worker { 640, 480, 4, 3, 25175, 0, false, 16, 96, 48, false, 10, 2, 33, false },
18*193032a3SAndroid Build Coastguard Worker { 720, 480, 4, 3, 27000, 0, false, 16, 62, 60, false, 9, 6, 30, false },
19*193032a3SAndroid Build Coastguard Worker { 720, 480, 16, 9, 27000, 0, false, 16, 62, 60, false, 9, 6, 30, false },
20*193032a3SAndroid Build Coastguard Worker { 1280, 720, 16, 9, 74250, 0, false, 110, 40, 220, true, 5, 5, 20, true },
21*193032a3SAndroid Build Coastguard Worker { 1920, 1080, 16, 9, 74250, 0, true, 88, 44, 148, true, 2, 5, 15, true },
22*193032a3SAndroid Build Coastguard Worker { 1440, 480, 4, 3, 27000, 0, true, 38, 124, 114, false, 4, 3, 15, false },
23*193032a3SAndroid Build Coastguard Worker { 1440, 480, 16, 9, 27000, 0, true, 38, 124, 114, false, 4, 3, 15, false },
24*193032a3SAndroid Build Coastguard Worker { 1440, 240, 4, 3, 27000, 0, false, 38, 124, 114, false, 4, 3, 15, false },
25*193032a3SAndroid Build Coastguard Worker { 1440, 240, 16, 9, 27000, 0, false, 38, 124, 114, false, 4, 3, 15, false },
26*193032a3SAndroid Build Coastguard Worker { 2880, 480, 4, 3, 54000, 0, true, 76, 248, 228, false, 4, 3, 15, false },
27*193032a3SAndroid Build Coastguard Worker /* VIC 11 */
28*193032a3SAndroid Build Coastguard Worker { 2880, 480, 16, 9, 54000, 0, true, 76, 248, 228, false, 4, 3, 15, false },
29*193032a3SAndroid Build Coastguard Worker { 2880, 240, 4, 3, 54000, 0, false, 76, 248, 228, false, 4, 3, 15, false },
30*193032a3SAndroid Build Coastguard Worker { 2880, 240, 16, 9, 54000, 0, false, 76, 248, 228, false, 4, 3, 15, false },
31*193032a3SAndroid Build Coastguard Worker { 1440, 480, 4, 3, 54000, 0, false, 32, 124, 120, false, 9, 6, 30, false },
32*193032a3SAndroid Build Coastguard Worker { 1440, 480, 16, 9, 54000, 0, false, 32, 124, 120, false, 9, 6, 30, false },
33*193032a3SAndroid Build Coastguard Worker { 1920, 1080, 16, 9, 148500, 0, false, 88, 44, 148, true, 4, 5, 36, true },
34*193032a3SAndroid Build Coastguard Worker { 720, 576, 4, 3, 27000, 0, false, 12, 64, 68, false, 5, 5, 39, false },
35*193032a3SAndroid Build Coastguard Worker { 720, 576, 16, 9, 27000, 0, false, 12, 64, 68, false, 5, 5, 39, false },
36*193032a3SAndroid Build Coastguard Worker { 1280, 720, 16, 9, 74250, 0, false, 440, 40, 220, true, 5, 5, 20, true },
37*193032a3SAndroid Build Coastguard Worker { 1920, 1080, 16, 9, 74250, 0, true, 528, 44, 148, true, 2, 5, 15, true },
38*193032a3SAndroid Build Coastguard Worker /* VIC 21 */
39*193032a3SAndroid Build Coastguard Worker { 1440, 576, 4, 3, 27000, 0, true, 24, 126, 138, false, 2, 3, 19, false },
40*193032a3SAndroid Build Coastguard Worker { 1440, 576, 16, 9, 27000, 0, true, 24, 126, 138, false, 2, 3, 19, false },
41*193032a3SAndroid Build Coastguard Worker { 1440, 288, 4, 3, 27000, 0, false, 24, 126, 138, false, 2, 3, 19, false },
42*193032a3SAndroid Build Coastguard Worker { 1440, 288, 16, 9, 27000, 0, false, 24, 126, 138, false, 2, 3, 19, false },
43*193032a3SAndroid Build Coastguard Worker { 2880, 576, 4, 3, 54000, 0, true, 48, 252, 276, false, 2, 3, 19, false },
44*193032a3SAndroid Build Coastguard Worker { 2880, 576, 16, 9, 54000, 0, true, 48, 252, 276, false, 2, 3, 19, false },
45*193032a3SAndroid Build Coastguard Worker { 2880, 288, 4, 3, 54000, 0, false, 48, 252, 276, false, 2, 3, 19, false },
46*193032a3SAndroid Build Coastguard Worker { 2880, 288, 16, 9, 54000, 0, false, 48, 252, 276, false, 2, 3, 19, false },
47*193032a3SAndroid Build Coastguard Worker { 1440, 576, 4, 3, 54000, 0, false, 24, 128, 136, false, 5, 5, 39, false },
48*193032a3SAndroid Build Coastguard Worker { 1440, 576, 16, 9, 54000, 0, false, 24, 128, 136, false, 5, 5, 39, false },
49*193032a3SAndroid Build Coastguard Worker /* VIC 31 */
50*193032a3SAndroid Build Coastguard Worker { 1920, 1080, 16, 9, 148500, 0, false, 528, 44, 148, true, 4, 5, 36, true },
51*193032a3SAndroid Build Coastguard Worker { 1920, 1080, 16, 9, 74250, 0, false, 638, 44, 148, true, 4, 5, 36, true },
52*193032a3SAndroid Build Coastguard Worker { 1920, 1080, 16, 9, 74250, 0, false, 528, 44, 148, true, 4, 5, 36, true },
53*193032a3SAndroid Build Coastguard Worker { 1920, 1080, 16, 9, 74250, 0, false, 88, 44, 148, true, 4, 5, 36, true },
54*193032a3SAndroid Build Coastguard Worker { 2880, 480, 4, 3, 108000, 0, false, 64, 248, 240, false, 9, 6, 30, false },
55*193032a3SAndroid Build Coastguard Worker { 2880, 480, 16, 9, 108000, 0, false, 64, 248, 240, false, 9, 6, 30, false },
56*193032a3SAndroid Build Coastguard Worker { 2880, 576, 4, 3, 108000, 0, false, 48, 256, 272, false, 5, 5, 39, false },
57*193032a3SAndroid Build Coastguard Worker { 2880, 576, 16, 9, 108000, 0, false, 48, 256, 272, false, 5, 5, 39, false },
58*193032a3SAndroid Build Coastguard Worker { 1920, 1080, 16, 9, 72000, 0, true, 32, 168, 184, true, 23, 5, 57, false, 0, 0, true },
59*193032a3SAndroid Build Coastguard Worker { 1920, 1080, 16, 9, 148500, 0, true, 528, 44, 148, true, 2, 5, 15, true },
60*193032a3SAndroid Build Coastguard Worker /* VIC 41 */
61*193032a3SAndroid Build Coastguard Worker { 1280, 720, 16, 9, 148500, 0, false, 440, 40, 220, true, 5, 5, 20, true },
62*193032a3SAndroid Build Coastguard Worker { 720, 576, 4, 3, 54000, 0, false, 12, 64, 68, false, 5, 5, 39, false },
63*193032a3SAndroid Build Coastguard Worker { 720, 576, 16, 9, 54000, 0, false, 12, 64, 68, false, 5, 5, 39, false },
64*193032a3SAndroid Build Coastguard Worker { 1440, 576, 4, 3, 54000, 0, true, 24, 126, 138, false, 2, 3, 19, false },
65*193032a3SAndroid Build Coastguard Worker { 1440, 576, 16, 9, 54000, 0, true, 24, 126, 138, false, 2, 3, 19, false },
66*193032a3SAndroid Build Coastguard Worker { 1920, 1080, 16, 9, 148500, 0, true, 88, 44, 148, true, 2, 5, 15, true },
67*193032a3SAndroid Build Coastguard Worker { 1280, 720, 16, 9, 148500, 0, false, 110, 40, 220, true, 5, 5, 20, true },
68*193032a3SAndroid Build Coastguard Worker { 720, 480, 4, 3, 54000, 0, false, 16, 62, 60, false, 9, 6, 30, false },
69*193032a3SAndroid Build Coastguard Worker { 720, 480, 16, 9, 54000, 0, false, 16, 62, 60, false, 9, 6, 30, false },
70*193032a3SAndroid Build Coastguard Worker { 1440, 480, 4, 3, 54000, 0, true, 38, 124, 114, false, 4, 3, 15, false },
71*193032a3SAndroid Build Coastguard Worker /* VIC 51 */
72*193032a3SAndroid Build Coastguard Worker { 1440, 480, 16, 9, 54000, 0, true, 38, 124, 114, false, 4, 3, 15, false },
73*193032a3SAndroid Build Coastguard Worker { 720, 576, 4, 3, 108000, 0, false, 12, 64, 68, false, 5, 5, 39, false },
74*193032a3SAndroid Build Coastguard Worker { 720, 576, 16, 9, 108000, 0, false, 12, 64, 68, false, 5, 5, 39, false },
75*193032a3SAndroid Build Coastguard Worker { 1440, 576, 4, 3, 108000, 0, true, 24, 126, 138, false, 2, 3, 19, false },
76*193032a3SAndroid Build Coastguard Worker { 1440, 576, 16, 9, 108000, 0, true, 24, 126, 138, false, 2, 3, 19, false },
77*193032a3SAndroid Build Coastguard Worker { 720, 480, 4, 3, 108000, 0, false, 16, 62, 60, false, 9, 6, 30, false },
78*193032a3SAndroid Build Coastguard Worker { 720, 480, 16, 9, 108000, 0, false, 16, 62, 60, false, 9, 6, 30, false },
79*193032a3SAndroid Build Coastguard Worker { 1440, 480, 4, 3, 108000, 0, true, 38, 124, 114, false, 4, 3, 15, false },
80*193032a3SAndroid Build Coastguard Worker { 1440, 480, 16, 9, 108000, 0, true, 38, 124, 114, false, 4, 3, 15, false },
81*193032a3SAndroid Build Coastguard Worker { 1280, 720, 16, 9, 59400, 0, false, 1760, 40, 220, true, 5, 5, 20, true },
82*193032a3SAndroid Build Coastguard Worker /* VIC 61 */
83*193032a3SAndroid Build Coastguard Worker { 1280, 720, 16, 9, 74250, 0, false, 2420, 40, 220, true, 5, 5, 20, true },
84*193032a3SAndroid Build Coastguard Worker { 1280, 720, 16, 9, 74250, 0, false, 1760, 40, 220, true, 5, 5, 20, true },
85*193032a3SAndroid Build Coastguard Worker { 1920, 1080, 16, 9, 297000, 0, false, 88, 44, 148, true, 4, 5, 36, true },
86*193032a3SAndroid Build Coastguard Worker { 1920, 1080, 16, 9, 297000, 0, false, 528, 44, 148, true, 4, 5, 36, true },
87*193032a3SAndroid Build Coastguard Worker { 1280, 720, 64, 27, 59400, 0, false, 1760, 40, 220, true, 5, 5, 20, true },
88*193032a3SAndroid Build Coastguard Worker { 1280, 720, 64, 27, 74250, 0, false, 2420, 40, 220, true, 5, 5, 20, true },
89*193032a3SAndroid Build Coastguard Worker { 1280, 720, 64, 27, 74250, 0, false, 1760, 40, 220, true, 5, 5, 20, true },
90*193032a3SAndroid Build Coastguard Worker { 1280, 720, 64, 27, 74250, 0, false, 440, 40, 220, true, 5, 5, 20, true },
91*193032a3SAndroid Build Coastguard Worker { 1280, 720, 64, 27, 74250, 0, false, 110, 40, 220, true, 5, 5, 20, true },
92*193032a3SAndroid Build Coastguard Worker { 1280, 720, 64, 27, 148500, 0, false, 440, 40, 220, true, 5, 5, 20, true },
93*193032a3SAndroid Build Coastguard Worker /* VIC 71 */
94*193032a3SAndroid Build Coastguard Worker { 1280, 720, 64, 27, 148500, 0, false, 110, 40, 220, true, 5, 5, 20, true },
95*193032a3SAndroid Build Coastguard Worker { 1920, 1080, 64, 27, 74250, 0, false, 638, 44, 148, true, 4, 5, 36, true },
96*193032a3SAndroid Build Coastguard Worker { 1920, 1080, 64, 27, 74250, 0, false, 528, 44, 148, true, 4, 5, 36, true },
97*193032a3SAndroid Build Coastguard Worker { 1920, 1080, 64, 27, 74250, 0, false, 88, 44, 148, true, 4, 5, 36, true },
98*193032a3SAndroid Build Coastguard Worker { 1920, 1080, 64, 27, 148500, 0, false, 528, 44, 148, true, 4, 5, 36, true },
99*193032a3SAndroid Build Coastguard Worker { 1920, 1080, 64, 27, 148500, 0, false, 88, 44, 148, true, 4, 5, 36, true },
100*193032a3SAndroid Build Coastguard Worker { 1920, 1080, 64, 27, 297000, 0, false, 528, 44, 148, true, 4, 5, 36, true },
101*193032a3SAndroid Build Coastguard Worker { 1920, 1080, 64, 27, 297000, 0, false, 88, 44, 148, true, 4, 5, 36, true },
102*193032a3SAndroid Build Coastguard Worker { 1680, 720, 64, 27, 59400, 0, false, 1360, 40, 220, true, 5, 5, 20, true },
103*193032a3SAndroid Build Coastguard Worker { 1680, 720, 64, 27, 59400, 0, false, 1228, 40, 220, true, 5, 5, 20, true },
104*193032a3SAndroid Build Coastguard Worker /* VIC 81 */
105*193032a3SAndroid Build Coastguard Worker { 1680, 720, 64, 27, 59400, 0, false, 700, 40, 220, true, 5, 5, 20, true },
106*193032a3SAndroid Build Coastguard Worker { 1680, 720, 64, 27, 82500, 0, false, 260, 40, 220, true, 5, 5, 20, true },
107*193032a3SAndroid Build Coastguard Worker { 1680, 720, 64, 27, 99000, 0, false, 260, 40, 220, true, 5, 5, 20, true },
108*193032a3SAndroid Build Coastguard Worker { 1680, 720, 64, 27, 165000, 0, false, 60, 40, 220, true, 5, 5, 95, true },
109*193032a3SAndroid Build Coastguard Worker { 1680, 720, 64, 27, 198000, 0, false, 60, 40, 220, true, 5, 5, 95, true },
110*193032a3SAndroid Build Coastguard Worker { 2560, 1080, 64, 27, 99000, 0, false, 998, 44, 148, true, 4, 5, 11, true },
111*193032a3SAndroid Build Coastguard Worker { 2560, 1080, 64, 27, 90000, 0, false, 448, 44, 148, true, 4, 5, 36, true },
112*193032a3SAndroid Build Coastguard Worker { 2560, 1080, 64, 27, 118800, 0, false, 768, 44, 148, true, 4, 5, 36, true },
113*193032a3SAndroid Build Coastguard Worker { 2560, 1080, 64, 27, 185625, 0, false, 548, 44, 148, true, 4, 5, 36, true },
114*193032a3SAndroid Build Coastguard Worker { 2560, 1080, 64, 27, 198000, 0, false, 248, 44, 148, true, 4, 5, 11, true },
115*193032a3SAndroid Build Coastguard Worker /* VIC 91 */
116*193032a3SAndroid Build Coastguard Worker { 2560, 1080, 64, 27, 371250, 0, false, 218, 44, 148, true, 4, 5, 161, true },
117*193032a3SAndroid Build Coastguard Worker { 2560, 1080, 64, 27, 495000, 0, false, 548, 44, 148, true, 4, 5, 161, true },
118*193032a3SAndroid Build Coastguard Worker { 3840, 2160, 16, 9, 297000, 0, false, 1276, 88, 296, true, 8, 10, 72, true },
119*193032a3SAndroid Build Coastguard Worker { 3840, 2160, 16, 9, 297000, 0, false, 1056, 88, 296, true, 8, 10, 72, true },
120*193032a3SAndroid Build Coastguard Worker { 3840, 2160, 16, 9, 297000, 0, false, 176, 88, 296, true, 8, 10, 72, true },
121*193032a3SAndroid Build Coastguard Worker { 3840, 2160, 16, 9, 594000, 0, false, 1056, 88, 296, true, 8, 10, 72, true },
122*193032a3SAndroid Build Coastguard Worker { 3840, 2160, 16, 9, 594000, 0, false, 176, 88, 296, true, 8, 10, 72, true },
123*193032a3SAndroid Build Coastguard Worker { 4096, 2160, 256, 135, 297000, 0, false, 1020, 88, 296, true, 8, 10, 72, true },
124*193032a3SAndroid Build Coastguard Worker { 4096, 2160, 256, 135, 297000, 0, false, 968, 88, 128, true, 8, 10, 72, true },
125*193032a3SAndroid Build Coastguard Worker { 4096, 2160, 256, 135, 297000, 0, false, 88, 88, 128, true, 8, 10, 72, true },
126*193032a3SAndroid Build Coastguard Worker /* VIC 101 */
127*193032a3SAndroid Build Coastguard Worker { 4096, 2160, 256, 135, 594000, 0, false, 968, 88, 128, true, 8, 10, 72, true },
128*193032a3SAndroid Build Coastguard Worker { 4096, 2160, 256, 135, 594000, 0, false, 88, 88, 128, true, 8, 10, 72, true },
129*193032a3SAndroid Build Coastguard Worker { 3840, 2160, 64, 27, 297000, 0, false, 1276, 88, 296, true, 8, 10, 72, true },
130*193032a3SAndroid Build Coastguard Worker { 3840, 2160, 64, 27, 297000, 0, false, 1056, 88, 296, true, 8, 10, 72, true },
131*193032a3SAndroid Build Coastguard Worker { 3840, 2160, 64, 27, 297000, 0, false, 176, 88, 296, true, 8, 10, 72, true },
132*193032a3SAndroid Build Coastguard Worker { 3840, 2160, 64, 27, 594000, 0, false, 1056, 88, 296, true, 8, 10, 72, true },
133*193032a3SAndroid Build Coastguard Worker { 3840, 2160, 64, 27, 594000, 0, false, 176, 88, 296, true, 8, 10, 72, true },
134*193032a3SAndroid Build Coastguard Worker { 1280, 720, 16, 9, 90000, 0, false, 960, 40, 220, true, 5, 5, 20, true },
135*193032a3SAndroid Build Coastguard Worker { 1280, 720, 64, 27, 90000, 0, false, 960, 40, 220, true, 5, 5, 20, true },
136*193032a3SAndroid Build Coastguard Worker { 1680, 720, 64, 27, 99000, 0, false, 810, 40, 220, true, 5, 5, 20, true },
137*193032a3SAndroid Build Coastguard Worker /* VIC 111 */
138*193032a3SAndroid Build Coastguard Worker { 1920, 1080, 16, 9, 148500, 0, false, 638, 44, 148, true, 4, 5, 36, true },
139*193032a3SAndroid Build Coastguard Worker { 1920, 1080, 64, 27, 148500, 0, false, 638, 44, 148, true, 4, 5, 36, true },
140*193032a3SAndroid Build Coastguard Worker { 2560, 1080, 64, 27, 198000, 0, false, 998, 44, 148, true, 4, 5, 11, true },
141*193032a3SAndroid Build Coastguard Worker { 3840, 2160, 16, 9, 594000, 0, false, 1276, 88, 296, true, 8, 10, 72, true },
142*193032a3SAndroid Build Coastguard Worker { 4096, 2160, 256, 135, 594000, 0, false, 1020, 88, 296, true, 8, 10, 72, true },
143*193032a3SAndroid Build Coastguard Worker { 3840, 2160, 64, 27, 594000, 0, false, 1276, 88, 296, true, 8, 10, 72, true },
144*193032a3SAndroid Build Coastguard Worker { 3840, 2160, 16, 9, 1188000, 0, false, 1056, 88, 296, true, 8, 10, 72, true },
145*193032a3SAndroid Build Coastguard Worker { 3840, 2160, 16, 9, 1188000, 0, false, 176, 88, 296, true, 8, 10, 72, true },
146*193032a3SAndroid Build Coastguard Worker { 3840, 2160, 64, 27, 1188000, 0, false, 1056, 88, 296, true, 8, 10, 72, true },
147*193032a3SAndroid Build Coastguard Worker { 3840, 2160, 64, 27, 1188000, 0, false, 176, 88, 296, true, 8, 10, 72, true },
148*193032a3SAndroid Build Coastguard Worker /* VIC 121 */
149*193032a3SAndroid Build Coastguard Worker { 5120, 2160, 64, 27, 396000, 0, false, 1996, 88, 296, true, 8, 10, 22, true },
150*193032a3SAndroid Build Coastguard Worker { 5120, 2160, 64, 27, 396000, 0, false, 1696, 88, 296, true, 8, 10, 22, true },
151*193032a3SAndroid Build Coastguard Worker { 5120, 2160, 64, 27, 396000, 0, false, 664, 88, 128, true, 8, 10, 22, true },
152*193032a3SAndroid Build Coastguard Worker { 5120, 2160, 64, 27, 742500, 0, false, 746, 88, 296, true, 8, 10, 297, true },
153*193032a3SAndroid Build Coastguard Worker { 5120, 2160, 64, 27, 742500, 0, false, 1096, 88, 296, true, 8, 10, 72, true },
154*193032a3SAndroid Build Coastguard Worker { 5120, 2160, 64, 27, 742500, 0, false, 164, 88, 128, true, 8, 10, 72, true },
155*193032a3SAndroid Build Coastguard Worker { 5120, 2160, 64, 27, 1485000, 0, false, 1096, 88, 296, true, 8, 10, 72, true },
156*193032a3SAndroid Build Coastguard Worker };
157*193032a3SAndroid Build Coastguard Worker
158*193032a3SAndroid Build Coastguard Worker static const struct timings edid_cta_modes2[] = {
159*193032a3SAndroid Build Coastguard Worker /* VIC 193 */
160*193032a3SAndroid Build Coastguard Worker { 5120, 2160, 64, 27, 1485000, 0, false, 164, 88, 128, true, 8, 10, 72, true },
161*193032a3SAndroid Build Coastguard Worker { 7680, 4320, 16, 9, 1188000, 0, false, 2552, 176, 592, true, 16, 20, 144, true },
162*193032a3SAndroid Build Coastguard Worker { 7680, 4320, 16, 9, 1188000, 0, false, 2352, 176, 592, true, 16, 20, 44, true },
163*193032a3SAndroid Build Coastguard Worker { 7680, 4320, 16, 9, 1188000, 0, false, 552, 176, 592, true, 16, 20, 44, true },
164*193032a3SAndroid Build Coastguard Worker { 7680, 4320, 16, 9, 2376000, 0, false, 2552, 176, 592, true, 16, 20, 144, true },
165*193032a3SAndroid Build Coastguard Worker { 7680, 4320, 16, 9, 2376000, 0, false, 2352, 176, 592, true, 16, 20, 44, true },
166*193032a3SAndroid Build Coastguard Worker { 7680, 4320, 16, 9, 2376000, 0, false, 552, 176, 592, true, 16, 20, 44, true },
167*193032a3SAndroid Build Coastguard Worker { 7680, 4320, 16, 9, 4752000, 0, false, 2112, 176, 592, true, 16, 20, 144, true },
168*193032a3SAndroid Build Coastguard Worker /* VIC 201 */
169*193032a3SAndroid Build Coastguard Worker { 7680, 4320, 16, 9, 4752000, 0, false, 352, 176, 592, true, 16, 20, 144, true },
170*193032a3SAndroid Build Coastguard Worker { 7680, 4320, 64, 27, 1188000, 0, false, 2552, 176, 592, true, 16, 20, 144, true },
171*193032a3SAndroid Build Coastguard Worker { 7680, 4320, 64, 27, 1188000, 0, false, 2352, 176, 592, true, 16, 20, 44, true },
172*193032a3SAndroid Build Coastguard Worker { 7680, 4320, 64, 27, 1188000, 0, false, 552, 176, 592, true, 16, 20, 44, true },
173*193032a3SAndroid Build Coastguard Worker { 7680, 4320, 64, 27, 2376000, 0, false, 2552, 176, 592, true, 16, 20, 144, true },
174*193032a3SAndroid Build Coastguard Worker { 7680, 4320, 64, 27, 2376000, 0, false, 2352, 176, 592, true, 16, 20, 44, true },
175*193032a3SAndroid Build Coastguard Worker { 7680, 4320, 64, 27, 2376000, 0, false, 552, 176, 592, true, 16, 20, 44, true },
176*193032a3SAndroid Build Coastguard Worker { 7680, 4320, 64, 27, 4752000, 0, false, 2112, 176, 592, true, 16, 20, 144, true },
177*193032a3SAndroid Build Coastguard Worker { 7680, 4320, 64, 27, 4752000, 0, false, 352, 176, 592, true, 16, 20, 144, true },
178*193032a3SAndroid Build Coastguard Worker { 10240, 4320, 64, 27, 1485000, 0, false, 1492, 176, 592, true, 16, 20, 594, true },
179*193032a3SAndroid Build Coastguard Worker /* VIC 211 */
180*193032a3SAndroid Build Coastguard Worker { 10240, 4320, 64, 27, 1485000, 0, false, 2492, 176, 592, true, 16, 20, 44, true },
181*193032a3SAndroid Build Coastguard Worker { 10240, 4320, 64, 27, 1485000, 0, false, 288, 176, 296, true, 16, 20, 144, true },
182*193032a3SAndroid Build Coastguard Worker { 10240, 4320, 64, 27, 2970000, 0, false, 1492, 176, 592, true, 16, 20, 594, true },
183*193032a3SAndroid Build Coastguard Worker { 10240, 4320, 64, 27, 2970000, 0, false, 2492, 176, 592, true, 16, 20, 44, true },
184*193032a3SAndroid Build Coastguard Worker { 10240, 4320, 64, 27, 2970000, 0, false, 288, 176, 296, true, 16, 20, 144, true },
185*193032a3SAndroid Build Coastguard Worker { 10240, 4320, 64, 27, 5940000, 0, false, 2192, 176, 592, true, 16, 20, 144, true },
186*193032a3SAndroid Build Coastguard Worker { 10240, 4320, 64, 27, 5940000, 0, false, 288, 176, 296, true, 16, 20, 144, true },
187*193032a3SAndroid Build Coastguard Worker { 4096, 2160, 256, 135, 1188000, 0, false, 800, 88, 296, true, 8, 10, 72, true },
188*193032a3SAndroid Build Coastguard Worker { 4096, 2160, 256, 135, 1188000, 0, false, 88, 88, 128, true, 8, 10, 72, true },
189*193032a3SAndroid Build Coastguard Worker };
190*193032a3SAndroid Build Coastguard Worker
191*193032a3SAndroid Build Coastguard Worker static const unsigned char edid_hdmi_mode_map[] = { 95, 94, 93, 98 };
192*193032a3SAndroid Build Coastguard Worker
hdmi_vic_to_vic(unsigned char hdmi_vic)193*193032a3SAndroid Build Coastguard Worker unsigned char hdmi_vic_to_vic(unsigned char hdmi_vic)
194*193032a3SAndroid Build Coastguard Worker {
195*193032a3SAndroid Build Coastguard Worker if (hdmi_vic > 0 && hdmi_vic <= ARRAY_SIZE(edid_hdmi_mode_map))
196*193032a3SAndroid Build Coastguard Worker return edid_hdmi_mode_map[hdmi_vic - 1];
197*193032a3SAndroid Build Coastguard Worker return 0;
198*193032a3SAndroid Build Coastguard Worker }
199*193032a3SAndroid Build Coastguard Worker
find_vic_id(unsigned char vic)200*193032a3SAndroid Build Coastguard Worker const struct timings *find_vic_id(unsigned char vic)
201*193032a3SAndroid Build Coastguard Worker {
202*193032a3SAndroid Build Coastguard Worker if (vic > 0 && vic <= ARRAY_SIZE(edid_cta_modes1))
203*193032a3SAndroid Build Coastguard Worker return edid_cta_modes1 + vic - 1;
204*193032a3SAndroid Build Coastguard Worker if (vic >= 193 && vic < ARRAY_SIZE(edid_cta_modes2) + 193)
205*193032a3SAndroid Build Coastguard Worker return edid_cta_modes2 + vic - 193;
206*193032a3SAndroid Build Coastguard Worker return NULL;
207*193032a3SAndroid Build Coastguard Worker }
208*193032a3SAndroid Build Coastguard Worker
find_hdmi_vic_id(unsigned char hdmi_vic)209*193032a3SAndroid Build Coastguard Worker const struct timings *find_hdmi_vic_id(unsigned char hdmi_vic)
210*193032a3SAndroid Build Coastguard Worker {
211*193032a3SAndroid Build Coastguard Worker if (hdmi_vic > 0 && hdmi_vic <= ARRAY_SIZE(edid_hdmi_mode_map))
212*193032a3SAndroid Build Coastguard Worker return find_vic_id(edid_hdmi_mode_map[hdmi_vic - 1]);
213*193032a3SAndroid Build Coastguard Worker return NULL;
214*193032a3SAndroid Build Coastguard Worker }
215*193032a3SAndroid Build Coastguard Worker
cta_close_match_to_vic(const timings & t,unsigned & vic)216*193032a3SAndroid Build Coastguard Worker const struct timings *cta_close_match_to_vic(const timings &t, unsigned &vic)
217*193032a3SAndroid Build Coastguard Worker {
218*193032a3SAndroid Build Coastguard Worker for (vic = 1; vic <= ARRAY_SIZE(edid_cta_modes1); vic++) {
219*193032a3SAndroid Build Coastguard Worker if (timings_close_match(t, edid_cta_modes1[vic - 1]))
220*193032a3SAndroid Build Coastguard Worker return &edid_cta_modes1[vic - 1];
221*193032a3SAndroid Build Coastguard Worker }
222*193032a3SAndroid Build Coastguard Worker for (vic = 193; vic < ARRAY_SIZE(edid_cta_modes2) + 193; vic++) {
223*193032a3SAndroid Build Coastguard Worker if (timings_close_match(t, edid_cta_modes1[vic - 193]))
224*193032a3SAndroid Build Coastguard Worker return &edid_cta_modes1[vic - 193];
225*193032a3SAndroid Build Coastguard Worker }
226*193032a3SAndroid Build Coastguard Worker vic = 0;
227*193032a3SAndroid Build Coastguard Worker return NULL;
228*193032a3SAndroid Build Coastguard Worker }
229*193032a3SAndroid Build Coastguard Worker
cta_list_vics()230*193032a3SAndroid Build Coastguard Worker void edid_state::cta_list_vics()
231*193032a3SAndroid Build Coastguard Worker {
232*193032a3SAndroid Build Coastguard Worker char type[16];
233*193032a3SAndroid Build Coastguard Worker for (unsigned vic = 1; vic <= ARRAY_SIZE(edid_cta_modes1); vic++) {
234*193032a3SAndroid Build Coastguard Worker sprintf(type, "VIC %3u", vic);
235*193032a3SAndroid Build Coastguard Worker print_timings("", &edid_cta_modes1[vic - 1], type, "", false, false);
236*193032a3SAndroid Build Coastguard Worker }
237*193032a3SAndroid Build Coastguard Worker for (unsigned vic = 193; vic < ARRAY_SIZE(edid_cta_modes2) + 193; vic++) {
238*193032a3SAndroid Build Coastguard Worker sprintf(type, "VIC %3u", vic);
239*193032a3SAndroid Build Coastguard Worker print_timings("", &edid_cta_modes2[vic - 193], type, "", false, false);
240*193032a3SAndroid Build Coastguard Worker }
241*193032a3SAndroid Build Coastguard Worker }
242*193032a3SAndroid Build Coastguard Worker
cta_list_hdmi_vics()243*193032a3SAndroid Build Coastguard Worker void edid_state::cta_list_hdmi_vics()
244*193032a3SAndroid Build Coastguard Worker {
245*193032a3SAndroid Build Coastguard Worker for (unsigned i = 0; i < ARRAY_SIZE(edid_hdmi_mode_map); i++) {
246*193032a3SAndroid Build Coastguard Worker unsigned vic = edid_hdmi_mode_map[i];
247*193032a3SAndroid Build Coastguard Worker char type[16];
248*193032a3SAndroid Build Coastguard Worker
249*193032a3SAndroid Build Coastguard Worker sprintf(type, "HDMI VIC %u", i + 1);
250*193032a3SAndroid Build Coastguard Worker print_timings("", find_vic_id(vic), type, "", false, false);
251*193032a3SAndroid Build Coastguard Worker }
252*193032a3SAndroid Build Coastguard Worker }
253*193032a3SAndroid Build Coastguard Worker
audio_ext_format(unsigned char x)254*193032a3SAndroid Build Coastguard Worker static std::string audio_ext_format(unsigned char x)
255*193032a3SAndroid Build Coastguard Worker {
256*193032a3SAndroid Build Coastguard Worker if (x >= 1 && x <= 3)
257*193032a3SAndroid Build Coastguard Worker fail("Obsolete Audio Ext Format 0x%02x.\n", x);
258*193032a3SAndroid Build Coastguard Worker switch (x) {
259*193032a3SAndroid Build Coastguard Worker case 1: return "HE AAC (Obsolete)";
260*193032a3SAndroid Build Coastguard Worker case 2: return "HE AAC v2 (Obsolete)";
261*193032a3SAndroid Build Coastguard Worker case 3: return "MPEG Surround (Obsolete)";
262*193032a3SAndroid Build Coastguard Worker case 4: return "MPEG-4 HE AAC";
263*193032a3SAndroid Build Coastguard Worker case 5: return "MPEG-4 HE AAC v2";
264*193032a3SAndroid Build Coastguard Worker case 6: return "MPEG-4 AAC LC";
265*193032a3SAndroid Build Coastguard Worker case 7: return "DRA";
266*193032a3SAndroid Build Coastguard Worker case 8: return "MPEG-4 HE AAC + MPEG Surround";
267*193032a3SAndroid Build Coastguard Worker case 10: return "MPEG-4 AAC LC + MPEG Surround";
268*193032a3SAndroid Build Coastguard Worker case 11: return "MPEG-H 3D Audio";
269*193032a3SAndroid Build Coastguard Worker case 12: return "AC-4";
270*193032a3SAndroid Build Coastguard Worker case 13: return "L-PCM 3D Audio";
271*193032a3SAndroid Build Coastguard Worker default: break;
272*193032a3SAndroid Build Coastguard Worker }
273*193032a3SAndroid Build Coastguard Worker fail("Unknown Audio Ext Format 0x%02x.\n", x);
274*193032a3SAndroid Build Coastguard Worker return std::string("Unknown Audio Ext Format (") + utohex(x) + ")";
275*193032a3SAndroid Build Coastguard Worker }
276*193032a3SAndroid Build Coastguard Worker
audio_format(unsigned char x)277*193032a3SAndroid Build Coastguard Worker static std::string audio_format(unsigned char x)
278*193032a3SAndroid Build Coastguard Worker {
279*193032a3SAndroid Build Coastguard Worker switch (x) {
280*193032a3SAndroid Build Coastguard Worker case 1: return "Linear PCM";
281*193032a3SAndroid Build Coastguard Worker case 2: return "AC-3";
282*193032a3SAndroid Build Coastguard Worker case 3: return "MPEG 1 (Layers 1 & 2)";
283*193032a3SAndroid Build Coastguard Worker case 4: return "MPEG 1 Layer 3 (MP3)";
284*193032a3SAndroid Build Coastguard Worker case 5: return "MPEG2 (multichannel)";
285*193032a3SAndroid Build Coastguard Worker case 6: return "AAC LC";
286*193032a3SAndroid Build Coastguard Worker case 7: return "DTS";
287*193032a3SAndroid Build Coastguard Worker case 8: return "ATRAC";
288*193032a3SAndroid Build Coastguard Worker case 9: return "One Bit Audio";
289*193032a3SAndroid Build Coastguard Worker case 10: return "Enhanced AC-3 (DD+)";
290*193032a3SAndroid Build Coastguard Worker case 11: return "DTS-HD";
291*193032a3SAndroid Build Coastguard Worker case 12: return "MAT (MLP)";
292*193032a3SAndroid Build Coastguard Worker case 13: return "DST";
293*193032a3SAndroid Build Coastguard Worker case 14: return "WMA Pro";
294*193032a3SAndroid Build Coastguard Worker default: break;
295*193032a3SAndroid Build Coastguard Worker }
296*193032a3SAndroid Build Coastguard Worker fail("Unknown Audio Format 0x%02x.\n", x);
297*193032a3SAndroid Build Coastguard Worker return std::string("Unknown Audio Format (") + utohex(x) + ")";
298*193032a3SAndroid Build Coastguard Worker }
299*193032a3SAndroid Build Coastguard Worker
mpeg_h_3d_audio_level(unsigned char x)300*193032a3SAndroid Build Coastguard Worker static std::string mpeg_h_3d_audio_level(unsigned char x)
301*193032a3SAndroid Build Coastguard Worker {
302*193032a3SAndroid Build Coastguard Worker switch (x) {
303*193032a3SAndroid Build Coastguard Worker case 0: return "Unspecified";
304*193032a3SAndroid Build Coastguard Worker case 1: return "Level 1";
305*193032a3SAndroid Build Coastguard Worker case 2: return "Level 2";
306*193032a3SAndroid Build Coastguard Worker case 3: return "Level 3";
307*193032a3SAndroid Build Coastguard Worker case 4: return "Level 4";
308*193032a3SAndroid Build Coastguard Worker case 5: return "Level 5";
309*193032a3SAndroid Build Coastguard Worker default: break;
310*193032a3SAndroid Build Coastguard Worker }
311*193032a3SAndroid Build Coastguard Worker fail("Unknown MPEG-H 3D Audio Level 0x%02x.\n", x);
312*193032a3SAndroid Build Coastguard Worker return std::string("Unknown MPEG-H 3D Audio Level (") + utohex(x) + ")";
313*193032a3SAndroid Build Coastguard Worker }
314*193032a3SAndroid Build Coastguard Worker
cta_audio_block(const unsigned char * x,unsigned length)315*193032a3SAndroid Build Coastguard Worker static void cta_audio_block(const unsigned char *x, unsigned length)
316*193032a3SAndroid Build Coastguard Worker {
317*193032a3SAndroid Build Coastguard Worker unsigned i, format, ext_format;
318*193032a3SAndroid Build Coastguard Worker
319*193032a3SAndroid Build Coastguard Worker if (length % 3) {
320*193032a3SAndroid Build Coastguard Worker fail("Broken CTA-861 audio block length %d.\n", length);
321*193032a3SAndroid Build Coastguard Worker return;
322*193032a3SAndroid Build Coastguard Worker }
323*193032a3SAndroid Build Coastguard Worker
324*193032a3SAndroid Build Coastguard Worker for (i = 0; i < length; i += 3) {
325*193032a3SAndroid Build Coastguard Worker format = (x[i] & 0x78) >> 3;
326*193032a3SAndroid Build Coastguard Worker if (format == 0) {
327*193032a3SAndroid Build Coastguard Worker printf(" Reserved (0x00)\n");
328*193032a3SAndroid Build Coastguard Worker fail("Audio Format Code 0x00 is reserved.\n");
329*193032a3SAndroid Build Coastguard Worker continue;
330*193032a3SAndroid Build Coastguard Worker }
331*193032a3SAndroid Build Coastguard Worker if (format != 15) {
332*193032a3SAndroid Build Coastguard Worker ext_format = 0;
333*193032a3SAndroid Build Coastguard Worker printf(" %s:\n", audio_format(format).c_str());
334*193032a3SAndroid Build Coastguard Worker } else {
335*193032a3SAndroid Build Coastguard Worker ext_format = (x[i + 2] & 0xf8) >> 3;
336*193032a3SAndroid Build Coastguard Worker printf(" %s:\n", audio_ext_format(ext_format).c_str());
337*193032a3SAndroid Build Coastguard Worker }
338*193032a3SAndroid Build Coastguard Worker if (format != 15)
339*193032a3SAndroid Build Coastguard Worker printf(" Max channels: %u\n", (x[i] & 0x07)+1);
340*193032a3SAndroid Build Coastguard Worker else if (ext_format == 11)
341*193032a3SAndroid Build Coastguard Worker printf(" MPEG-H 3D Audio Level: %s\n",
342*193032a3SAndroid Build Coastguard Worker mpeg_h_3d_audio_level(x[i] & 0x07).c_str());
343*193032a3SAndroid Build Coastguard Worker else if (ext_format == 13)
344*193032a3SAndroid Build Coastguard Worker printf(" Max channels: %u\n",
345*193032a3SAndroid Build Coastguard Worker (((x[i + 1] & 0x80) >> 3) | ((x[i] & 0x80) >> 4) |
346*193032a3SAndroid Build Coastguard Worker (x[i] & 0x07))+1);
347*193032a3SAndroid Build Coastguard Worker else
348*193032a3SAndroid Build Coastguard Worker printf(" Max channels: %u\n", (x[i] & 0x07)+1);
349*193032a3SAndroid Build Coastguard Worker
350*193032a3SAndroid Build Coastguard Worker printf(" Supported sample rates (kHz):%s%s%s%s%s%s%s\n",
351*193032a3SAndroid Build Coastguard Worker (x[i+1] & 0x40) ? " 192" : "",
352*193032a3SAndroid Build Coastguard Worker (x[i+1] & 0x20) ? " 176.4" : "",
353*193032a3SAndroid Build Coastguard Worker (x[i+1] & 0x10) ? " 96" : "",
354*193032a3SAndroid Build Coastguard Worker (x[i+1] & 0x08) ? " 88.2" : "",
355*193032a3SAndroid Build Coastguard Worker (x[i+1] & 0x04) ? " 48" : "",
356*193032a3SAndroid Build Coastguard Worker (x[i+1] & 0x02) ? " 44.1" : "",
357*193032a3SAndroid Build Coastguard Worker (x[i+1] & 0x01) ? " 32" : "");
358*193032a3SAndroid Build Coastguard Worker if (format == 1 || ext_format == 13) {
359*193032a3SAndroid Build Coastguard Worker printf(" Supported sample sizes (bits):%s%s%s\n",
360*193032a3SAndroid Build Coastguard Worker (x[i+2] & 0x04) ? " 24" : "",
361*193032a3SAndroid Build Coastguard Worker (x[i+2] & 0x02) ? " 20" : "",
362*193032a3SAndroid Build Coastguard Worker (x[i+2] & 0x01) ? " 16" : "");
363*193032a3SAndroid Build Coastguard Worker } else if (format <= 8) {
364*193032a3SAndroid Build Coastguard Worker printf(" Maximum bit rate: %u kb/s\n", x[i+2] * 8);
365*193032a3SAndroid Build Coastguard Worker } else if (format == 10) {
366*193032a3SAndroid Build Coastguard Worker // As specified by the "Dolby Audio and Dolby Atmos over HDMI"
367*193032a3SAndroid Build Coastguard Worker // specification (v1.0).
368*193032a3SAndroid Build Coastguard Worker if (x[i+2] & 1)
369*193032a3SAndroid Build Coastguard Worker printf(" Supports Joint Object Coding\n");
370*193032a3SAndroid Build Coastguard Worker if (x[i+2] & 2)
371*193032a3SAndroid Build Coastguard Worker printf(" Supports Joint Object Coding with ACMOD28\n");
372*193032a3SAndroid Build Coastguard Worker } else if (format == 12) {
373*193032a3SAndroid Build Coastguard Worker if (x[i+2] & 1) {
374*193032a3SAndroid Build Coastguard Worker printf(" Supports Dolby TrueHD, object audio PCM and channel-based PCM\n");
375*193032a3SAndroid Build Coastguard Worker printf(" Hash calculation %srequired for object audio PCM or channel-based PCM\n",
376*193032a3SAndroid Build Coastguard Worker (x[i+2] & 2) ? "not " : "");
377*193032a3SAndroid Build Coastguard Worker } else {
378*193032a3SAndroid Build Coastguard Worker printf(" Supports only Dolby TrueHD\n");
379*193032a3SAndroid Build Coastguard Worker }
380*193032a3SAndroid Build Coastguard Worker } else if (format == 14) {
381*193032a3SAndroid Build Coastguard Worker printf(" Profile: %u\n", x[i+2] & 7);
382*193032a3SAndroid Build Coastguard Worker } else if (format >= 9 && format <= 13) {
383*193032a3SAndroid Build Coastguard Worker printf(" Audio Format Code dependent value: 0x%02x\n", x[i+2]);
384*193032a3SAndroid Build Coastguard Worker } else if (ext_format == 11 && (x[i+2] & 1)) {
385*193032a3SAndroid Build Coastguard Worker printf(" Supports MPEG-H 3D Audio Low Complexity Profile\n");
386*193032a3SAndroid Build Coastguard Worker } else if ((ext_format >= 4 && ext_format <= 6) ||
387*193032a3SAndroid Build Coastguard Worker ext_format == 8 || ext_format == 10) {
388*193032a3SAndroid Build Coastguard Worker printf(" AAC audio frame lengths:%s%s\n",
389*193032a3SAndroid Build Coastguard Worker (x[i+2] & 4) ? " 1024_TL" : "",
390*193032a3SAndroid Build Coastguard Worker (x[i+2] & 2) ? " 960_TL" : "");
391*193032a3SAndroid Build Coastguard Worker if (ext_format >= 8 && (x[i+2] & 1))
392*193032a3SAndroid Build Coastguard Worker printf(" Supports %s signaled MPEG Surround data\n",
393*193032a3SAndroid Build Coastguard Worker (x[i+2] & 1) ? "implicitly and explicitly" : "only implicitly");
394*193032a3SAndroid Build Coastguard Worker if (ext_format == 6 && (x[i+2] & 1))
395*193032a3SAndroid Build Coastguard Worker printf(" Supports 22.2ch System H\n");
396*193032a3SAndroid Build Coastguard Worker }
397*193032a3SAndroid Build Coastguard Worker }
398*193032a3SAndroid Build Coastguard Worker }
399*193032a3SAndroid Build Coastguard Worker
cta_svd(const unsigned char * x,unsigned n,bool for_ycbcr420)400*193032a3SAndroid Build Coastguard Worker void edid_state::cta_svd(const unsigned char *x, unsigned n, bool for_ycbcr420)
401*193032a3SAndroid Build Coastguard Worker {
402*193032a3SAndroid Build Coastguard Worker unsigned i;
403*193032a3SAndroid Build Coastguard Worker
404*193032a3SAndroid Build Coastguard Worker for (i = 0; i < n; i++) {
405*193032a3SAndroid Build Coastguard Worker const struct timings *t = NULL;
406*193032a3SAndroid Build Coastguard Worker unsigned char svd = x[i];
407*193032a3SAndroid Build Coastguard Worker unsigned char native;
408*193032a3SAndroid Build Coastguard Worker unsigned char vic;
409*193032a3SAndroid Build Coastguard Worker
410*193032a3SAndroid Build Coastguard Worker if ((svd & 0x7f) == 0)
411*193032a3SAndroid Build Coastguard Worker continue;
412*193032a3SAndroid Build Coastguard Worker
413*193032a3SAndroid Build Coastguard Worker if ((svd - 1) & 0x40) {
414*193032a3SAndroid Build Coastguard Worker vic = svd;
415*193032a3SAndroid Build Coastguard Worker native = 0;
416*193032a3SAndroid Build Coastguard Worker } else {
417*193032a3SAndroid Build Coastguard Worker vic = svd & 0x7f;
418*193032a3SAndroid Build Coastguard Worker native = svd & 0x80;
419*193032a3SAndroid Build Coastguard Worker }
420*193032a3SAndroid Build Coastguard Worker
421*193032a3SAndroid Build Coastguard Worker t = find_vic_id(vic);
422*193032a3SAndroid Build Coastguard Worker if (t) {
423*193032a3SAndroid Build Coastguard Worker switch (vic) {
424*193032a3SAndroid Build Coastguard Worker case 95:
425*193032a3SAndroid Build Coastguard Worker cta.supported_hdmi_vic_vsb_codes |= 1 << 0;
426*193032a3SAndroid Build Coastguard Worker break;
427*193032a3SAndroid Build Coastguard Worker case 94:
428*193032a3SAndroid Build Coastguard Worker cta.supported_hdmi_vic_vsb_codes |= 1 << 1;
429*193032a3SAndroid Build Coastguard Worker break;
430*193032a3SAndroid Build Coastguard Worker case 93:
431*193032a3SAndroid Build Coastguard Worker cta.supported_hdmi_vic_vsb_codes |= 1 << 2;
432*193032a3SAndroid Build Coastguard Worker break;
433*193032a3SAndroid Build Coastguard Worker case 98:
434*193032a3SAndroid Build Coastguard Worker cta.supported_hdmi_vic_vsb_codes |= 1 << 3;
435*193032a3SAndroid Build Coastguard Worker break;
436*193032a3SAndroid Build Coastguard Worker }
437*193032a3SAndroid Build Coastguard Worker bool first_svd = cta.first_svd && !for_ycbcr420;
438*193032a3SAndroid Build Coastguard Worker bool override_pref = first_svd && cta.first_svd_might_be_preferred;
439*193032a3SAndroid Build Coastguard Worker
440*193032a3SAndroid Build Coastguard Worker char type[16];
441*193032a3SAndroid Build Coastguard Worker sprintf(type, "VIC %3u", vic);
442*193032a3SAndroid Build Coastguard Worker const char *flags = native ? "native" : "";
443*193032a3SAndroid Build Coastguard Worker
444*193032a3SAndroid Build Coastguard Worker if (for_ycbcr420) {
445*193032a3SAndroid Build Coastguard Worker struct timings tmp = *t;
446*193032a3SAndroid Build Coastguard Worker tmp.ycbcr420 = true;
447*193032a3SAndroid Build Coastguard Worker print_timings(" ", &tmp, type, flags);
448*193032a3SAndroid Build Coastguard Worker } else {
449*193032a3SAndroid Build Coastguard Worker print_timings(" ", t, type, flags);
450*193032a3SAndroid Build Coastguard Worker }
451*193032a3SAndroid Build Coastguard Worker if (override_pref) {
452*193032a3SAndroid Build Coastguard Worker if (!cta.preferred_timings.empty()) {
453*193032a3SAndroid Build Coastguard Worker if (match_timings(cta.preferred_timings[0].t, *t))
454*193032a3SAndroid Build Coastguard Worker warn("For improved preferred timing interoperability, set 'Native detailed modes' to 1.\n");
455*193032a3SAndroid Build Coastguard Worker else
456*193032a3SAndroid Build Coastguard Worker warn("VIC %u is the preferred timing, overriding the first detailed timings. Is this intended?\n", vic);
457*193032a3SAndroid Build Coastguard Worker }
458*193032a3SAndroid Build Coastguard Worker cta.preferred_timings.insert(cta.preferred_timings.begin(),
459*193032a3SAndroid Build Coastguard Worker timings_ext(*t, type, flags));
460*193032a3SAndroid Build Coastguard Worker } else if (first_svd) {
461*193032a3SAndroid Build Coastguard Worker cta.preferred_timings.push_back(timings_ext(*t, type, flags));
462*193032a3SAndroid Build Coastguard Worker }
463*193032a3SAndroid Build Coastguard Worker if (first_svd) {
464*193032a3SAndroid Build Coastguard Worker cta.first_svd = false;
465*193032a3SAndroid Build Coastguard Worker cta.first_svd_might_be_preferred = false;
466*193032a3SAndroid Build Coastguard Worker }
467*193032a3SAndroid Build Coastguard Worker if (native)
468*193032a3SAndroid Build Coastguard Worker cta.native_timings.push_back(timings_ext(*t, type, flags));
469*193032a3SAndroid Build Coastguard Worker } else {
470*193032a3SAndroid Build Coastguard Worker printf(" Unknown (VIC %3u)\n", vic);
471*193032a3SAndroid Build Coastguard Worker fail("Unknown VIC %u.\n", vic);
472*193032a3SAndroid Build Coastguard Worker }
473*193032a3SAndroid Build Coastguard Worker
474*193032a3SAndroid Build Coastguard Worker if (vic == 1 && !for_ycbcr420)
475*193032a3SAndroid Build Coastguard Worker cta.has_vic_1 = 1;
476*193032a3SAndroid Build Coastguard Worker if (++cta.vics[vic][for_ycbcr420] == 2)
477*193032a3SAndroid Build Coastguard Worker fail("Duplicate %sVIC %u.\n", for_ycbcr420 ? "YCbCr 4:2:0 " : "", vic);
478*193032a3SAndroid Build Coastguard Worker if (for_ycbcr420 && cta.preparsed_has_vic[0][vic])
479*193032a3SAndroid Build Coastguard Worker fail("YCbCr 4:2:0-only VIC %u is also a regular VIC.\n", vic);
480*193032a3SAndroid Build Coastguard Worker }
481*193032a3SAndroid Build Coastguard Worker }
482*193032a3SAndroid Build Coastguard Worker
print_vic_index(const char * prefix,unsigned idx,const char * suffix,bool ycbcr420)483*193032a3SAndroid Build Coastguard Worker void edid_state::print_vic_index(const char *prefix, unsigned idx, const char *suffix, bool ycbcr420)
484*193032a3SAndroid Build Coastguard Worker {
485*193032a3SAndroid Build Coastguard Worker if (!suffix)
486*193032a3SAndroid Build Coastguard Worker suffix = "";
487*193032a3SAndroid Build Coastguard Worker if (idx < cta.preparsed_svds[0].size()) {
488*193032a3SAndroid Build Coastguard Worker unsigned char vic = cta.preparsed_svds[0][idx];
489*193032a3SAndroid Build Coastguard Worker const struct timings *t = find_vic_id(vic);
490*193032a3SAndroid Build Coastguard Worker char buf[16];
491*193032a3SAndroid Build Coastguard Worker
492*193032a3SAndroid Build Coastguard Worker sprintf(buf, "VIC %3u", vic);
493*193032a3SAndroid Build Coastguard Worker
494*193032a3SAndroid Build Coastguard Worker if (t) {
495*193032a3SAndroid Build Coastguard Worker struct timings tmp = *t;
496*193032a3SAndroid Build Coastguard Worker tmp.ycbcr420 = ycbcr420;
497*193032a3SAndroid Build Coastguard Worker print_timings(prefix, &tmp, buf, suffix);
498*193032a3SAndroid Build Coastguard Worker } else {
499*193032a3SAndroid Build Coastguard Worker printf("%sUnknown (%s%s%s)\n", prefix, buf,
500*193032a3SAndroid Build Coastguard Worker *suffix ? ", " : "", suffix);
501*193032a3SAndroid Build Coastguard Worker }
502*193032a3SAndroid Build Coastguard Worker } else {
503*193032a3SAndroid Build Coastguard Worker // Should not happen!
504*193032a3SAndroid Build Coastguard Worker printf("%sSVD Index %u is out of range", prefix, idx + 1);
505*193032a3SAndroid Build Coastguard Worker if (*suffix)
506*193032a3SAndroid Build Coastguard Worker printf(" (%s)", suffix);
507*193032a3SAndroid Build Coastguard Worker printf("\n");
508*193032a3SAndroid Build Coastguard Worker }
509*193032a3SAndroid Build Coastguard Worker }
510*193032a3SAndroid Build Coastguard Worker
cta_y420cmdb(const unsigned char * x,unsigned length)511*193032a3SAndroid Build Coastguard Worker void edid_state::cta_y420cmdb(const unsigned char *x, unsigned length)
512*193032a3SAndroid Build Coastguard Worker {
513*193032a3SAndroid Build Coastguard Worker unsigned max_idx = 0;
514*193032a3SAndroid Build Coastguard Worker unsigned i;
515*193032a3SAndroid Build Coastguard Worker
516*193032a3SAndroid Build Coastguard Worker if (!length) {
517*193032a3SAndroid Build Coastguard Worker printf(" All VDB SVDs\n");
518*193032a3SAndroid Build Coastguard Worker return;
519*193032a3SAndroid Build Coastguard Worker }
520*193032a3SAndroid Build Coastguard Worker
521*193032a3SAndroid Build Coastguard Worker if (memchk(x, length)) {
522*193032a3SAndroid Build Coastguard Worker printf(" Empty Capability Map\n");
523*193032a3SAndroid Build Coastguard Worker fail("Empty Capability Map.\n");
524*193032a3SAndroid Build Coastguard Worker return;
525*193032a3SAndroid Build Coastguard Worker }
526*193032a3SAndroid Build Coastguard Worker
527*193032a3SAndroid Build Coastguard Worker for (i = 0; i < length; i++) {
528*193032a3SAndroid Build Coastguard Worker unsigned char v = x[i];
529*193032a3SAndroid Build Coastguard Worker unsigned j;
530*193032a3SAndroid Build Coastguard Worker
531*193032a3SAndroid Build Coastguard Worker for (j = 0; j < 8; j++) {
532*193032a3SAndroid Build Coastguard Worker if (!(v & (1 << j)))
533*193032a3SAndroid Build Coastguard Worker continue;
534*193032a3SAndroid Build Coastguard Worker
535*193032a3SAndroid Build Coastguard Worker print_vic_index(" ", i * 8 + j, "", true);
536*193032a3SAndroid Build Coastguard Worker max_idx = i * 8 + j;
537*193032a3SAndroid Build Coastguard Worker if (max_idx < cta.preparsed_svds[0].size()) {
538*193032a3SAndroid Build Coastguard Worker unsigned vic = cta.preparsed_svds[0][max_idx];
539*193032a3SAndroid Build Coastguard Worker if (cta.preparsed_has_vic[1][vic])
540*193032a3SAndroid Build Coastguard Worker fail("VIC %u is also a YCbCr 4:2:0-only VIC.\n", vic);
541*193032a3SAndroid Build Coastguard Worker }
542*193032a3SAndroid Build Coastguard Worker }
543*193032a3SAndroid Build Coastguard Worker }
544*193032a3SAndroid Build Coastguard Worker if (max_idx >= cta.preparsed_svds[0].size())
545*193032a3SAndroid Build Coastguard Worker fail("Max index %u > %u (#SVDs).\n",
546*193032a3SAndroid Build Coastguard Worker max_idx + 1, cta.preparsed_svds[0].size());
547*193032a3SAndroid Build Coastguard Worker }
548*193032a3SAndroid Build Coastguard Worker
cta_vfpdb(const unsigned char * x,unsigned length)549*193032a3SAndroid Build Coastguard Worker void edid_state::cta_vfpdb(const unsigned char *x, unsigned length)
550*193032a3SAndroid Build Coastguard Worker {
551*193032a3SAndroid Build Coastguard Worker unsigned i;
552*193032a3SAndroid Build Coastguard Worker
553*193032a3SAndroid Build Coastguard Worker if (length == 0) {
554*193032a3SAndroid Build Coastguard Worker fail("Empty Data Block with length %u.\n", length);
555*193032a3SAndroid Build Coastguard Worker return;
556*193032a3SAndroid Build Coastguard Worker }
557*193032a3SAndroid Build Coastguard Worker cta.preferred_timings.clear();
558*193032a3SAndroid Build Coastguard Worker for (i = 0; i < length; i++) {
559*193032a3SAndroid Build Coastguard Worker unsigned char svr = x[i];
560*193032a3SAndroid Build Coastguard Worker char suffix[16];
561*193032a3SAndroid Build Coastguard Worker
562*193032a3SAndroid Build Coastguard Worker if ((svr > 0 && svr < 128) || (svr > 192 && svr < 254)) {
563*193032a3SAndroid Build Coastguard Worker const struct timings *t;
564*193032a3SAndroid Build Coastguard Worker unsigned char vic = svr;
565*193032a3SAndroid Build Coastguard Worker
566*193032a3SAndroid Build Coastguard Worker sprintf(suffix, "VIC %3u", vic);
567*193032a3SAndroid Build Coastguard Worker
568*193032a3SAndroid Build Coastguard Worker t = find_vic_id(vic);
569*193032a3SAndroid Build Coastguard Worker if (t) {
570*193032a3SAndroid Build Coastguard Worker print_timings(" ", t, suffix);
571*193032a3SAndroid Build Coastguard Worker cta.preferred_timings.push_back(timings_ext(*t, suffix, ""));
572*193032a3SAndroid Build Coastguard Worker } else {
573*193032a3SAndroid Build Coastguard Worker printf(" %s: Unknown\n", suffix);
574*193032a3SAndroid Build Coastguard Worker fail("Unknown VIC %u.\n", vic);
575*193032a3SAndroid Build Coastguard Worker }
576*193032a3SAndroid Build Coastguard Worker
577*193032a3SAndroid Build Coastguard Worker } else if (svr >= 129 && svr <= 144) {
578*193032a3SAndroid Build Coastguard Worker sprintf(suffix, "DTD %3u", svr - 128);
579*193032a3SAndroid Build Coastguard Worker if (svr >= cta.preparsed_total_dtds + 129) {
580*193032a3SAndroid Build Coastguard Worker printf(" %s: Invalid\n", suffix);
581*193032a3SAndroid Build Coastguard Worker fail("Invalid DTD %u.\n", svr - 128);
582*193032a3SAndroid Build Coastguard Worker } else {
583*193032a3SAndroid Build Coastguard Worker printf(" %s\n", suffix);
584*193032a3SAndroid Build Coastguard Worker cta.preferred_timings.push_back(timings_ext(svr, suffix));
585*193032a3SAndroid Build Coastguard Worker }
586*193032a3SAndroid Build Coastguard Worker } else if (svr >= 145 && svr <= 160) {
587*193032a3SAndroid Build Coastguard Worker sprintf(suffix, "VTDB %3u", svr - 144);
588*193032a3SAndroid Build Coastguard Worker if (svr >= cta.preparsed_total_vtdbs + 145) {
589*193032a3SAndroid Build Coastguard Worker printf(" %s: Invalid\n", suffix);
590*193032a3SAndroid Build Coastguard Worker fail("Invalid VTDB %u.\n", svr - 144);
591*193032a3SAndroid Build Coastguard Worker } else {
592*193032a3SAndroid Build Coastguard Worker printf(" %s\n", suffix);
593*193032a3SAndroid Build Coastguard Worker cta.preferred_timings.push_back(timings_ext(svr, suffix));
594*193032a3SAndroid Build Coastguard Worker }
595*193032a3SAndroid Build Coastguard Worker } else if (svr == 254) {
596*193032a3SAndroid Build Coastguard Worker sprintf(suffix, "T8VTDB");
597*193032a3SAndroid Build Coastguard Worker if (!cta.preparsed_has_t8vtdb) {
598*193032a3SAndroid Build Coastguard Worker printf(" %s: Invalid\n", suffix);
599*193032a3SAndroid Build Coastguard Worker fail("Invalid T8VTDB.\n");
600*193032a3SAndroid Build Coastguard Worker } else {
601*193032a3SAndroid Build Coastguard Worker printf(" %s\n", suffix);
602*193032a3SAndroid Build Coastguard Worker cta.preferred_timings.push_back(timings_ext(svr, suffix));
603*193032a3SAndroid Build Coastguard Worker }
604*193032a3SAndroid Build Coastguard Worker }
605*193032a3SAndroid Build Coastguard Worker }
606*193032a3SAndroid Build Coastguard Worker }
607*193032a3SAndroid Build Coastguard Worker
hdmi_latency2s(unsigned char l,bool is_video)608*193032a3SAndroid Build Coastguard Worker static std::string hdmi_latency2s(unsigned char l, bool is_video)
609*193032a3SAndroid Build Coastguard Worker {
610*193032a3SAndroid Build Coastguard Worker if (!l)
611*193032a3SAndroid Build Coastguard Worker return "Unknown";
612*193032a3SAndroid Build Coastguard Worker if (l == 0xff)
613*193032a3SAndroid Build Coastguard Worker return is_video ? "Video not supported" : "Audio not supported";
614*193032a3SAndroid Build Coastguard Worker return std::to_string(1 + 2 * l) + " ms";
615*193032a3SAndroid Build Coastguard Worker }
616*193032a3SAndroid Build Coastguard Worker
hdmi_latency(unsigned char vid_lat,unsigned char aud_lat,bool is_ilaced)617*193032a3SAndroid Build Coastguard Worker void edid_state::hdmi_latency(unsigned char vid_lat, unsigned char aud_lat,
618*193032a3SAndroid Build Coastguard Worker bool is_ilaced)
619*193032a3SAndroid Build Coastguard Worker {
620*193032a3SAndroid Build Coastguard Worker const char *vid = is_ilaced ? "Interlaced video" : "Video";
621*193032a3SAndroid Build Coastguard Worker const char *aud = is_ilaced ? "Interlaced audio" : "Audio";
622*193032a3SAndroid Build Coastguard Worker
623*193032a3SAndroid Build Coastguard Worker printf(" %s latency: %s\n", vid, hdmi_latency2s(vid_lat, true).c_str());
624*193032a3SAndroid Build Coastguard Worker printf(" %s latency: %s\n", aud, hdmi_latency2s(aud_lat, false).c_str());
625*193032a3SAndroid Build Coastguard Worker
626*193032a3SAndroid Build Coastguard Worker if (vid_lat > 251 && vid_lat != 0xff)
627*193032a3SAndroid Build Coastguard Worker fail("Invalid %s latency value %u.\n", vid, vid_lat);
628*193032a3SAndroid Build Coastguard Worker if (aud_lat > 251 && aud_lat != 0xff)
629*193032a3SAndroid Build Coastguard Worker fail("Invalid %s latency value %u.\n", aud, aud_lat);
630*193032a3SAndroid Build Coastguard Worker
631*193032a3SAndroid Build Coastguard Worker if (!vid_lat || vid_lat > 251)
632*193032a3SAndroid Build Coastguard Worker return;
633*193032a3SAndroid Build Coastguard Worker if (!aud_lat || aud_lat > 251)
634*193032a3SAndroid Build Coastguard Worker return;
635*193032a3SAndroid Build Coastguard Worker
636*193032a3SAndroid Build Coastguard Worker unsigned vid_ms = 1 + 2 * vid_lat;
637*193032a3SAndroid Build Coastguard Worker unsigned aud_ms = 1 + 2 * aud_lat;
638*193032a3SAndroid Build Coastguard Worker
639*193032a3SAndroid Build Coastguard Worker // HDMI 2.0 latency checks for devices without HDMI output
640*193032a3SAndroid Build Coastguard Worker if (aud_ms < vid_ms)
641*193032a3SAndroid Build Coastguard Worker warn("%s latency < %s latency (%u ms < %u ms). This is discouraged for devices without HDMI output.\n",
642*193032a3SAndroid Build Coastguard Worker aud, vid, aud_ms, vid_ms);
643*193032a3SAndroid Build Coastguard Worker else if (vid_ms + 20 < aud_ms)
644*193032a3SAndroid Build Coastguard Worker warn("%s latency + 20 < %s latency (%u + 20 ms < %u ms). This is forbidden for devices without HDMI output.\n",
645*193032a3SAndroid Build Coastguard Worker vid, aud, vid_ms, aud_ms);
646*193032a3SAndroid Build Coastguard Worker else if (vid_ms < aud_ms)
647*193032a3SAndroid Build Coastguard Worker warn("%s latency < %s latency (%u ms < %u ms). This is discouraged for devices without HDMI output.\n",
648*193032a3SAndroid Build Coastguard Worker vid, aud, vid_ms, aud_ms);
649*193032a3SAndroid Build Coastguard Worker }
650*193032a3SAndroid Build Coastguard Worker
cta_hdmi_block(const unsigned char * x,unsigned length)651*193032a3SAndroid Build Coastguard Worker void edid_state::cta_hdmi_block(const unsigned char *x, unsigned length)
652*193032a3SAndroid Build Coastguard Worker {
653*193032a3SAndroid Build Coastguard Worker unsigned len_vic, len_3d;
654*193032a3SAndroid Build Coastguard Worker
655*193032a3SAndroid Build Coastguard Worker if (length < 4) {
656*193032a3SAndroid Build Coastguard Worker fail("Empty Data Block with length %u.\n", length);
657*193032a3SAndroid Build Coastguard Worker return;
658*193032a3SAndroid Build Coastguard Worker }
659*193032a3SAndroid Build Coastguard Worker printf(" Source physical address: %x.%x.%x.%x\n", x[3] >> 4, x[3] & 0x0f,
660*193032a3SAndroid Build Coastguard Worker x[4] >> 4, x[4] & 0x0f);
661*193032a3SAndroid Build Coastguard Worker
662*193032a3SAndroid Build Coastguard Worker if (length < 6)
663*193032a3SAndroid Build Coastguard Worker return;
664*193032a3SAndroid Build Coastguard Worker
665*193032a3SAndroid Build Coastguard Worker if (x[5] & 0x80)
666*193032a3SAndroid Build Coastguard Worker printf(" Supports_AI\n");
667*193032a3SAndroid Build Coastguard Worker if (x[5] & 0x40)
668*193032a3SAndroid Build Coastguard Worker printf(" DC_48bit\n");
669*193032a3SAndroid Build Coastguard Worker if (x[5] & 0x20)
670*193032a3SAndroid Build Coastguard Worker printf(" DC_36bit\n");
671*193032a3SAndroid Build Coastguard Worker if (x[5] & 0x10)
672*193032a3SAndroid Build Coastguard Worker printf(" DC_30bit\n");
673*193032a3SAndroid Build Coastguard Worker if (x[5] & 0x08)
674*193032a3SAndroid Build Coastguard Worker printf(" DC_Y444\n");
675*193032a3SAndroid Build Coastguard Worker /* two reserved bits */
676*193032a3SAndroid Build Coastguard Worker if (x[5] & 0x01)
677*193032a3SAndroid Build Coastguard Worker printf(" DVI_Dual\n");
678*193032a3SAndroid Build Coastguard Worker
679*193032a3SAndroid Build Coastguard Worker if (length < 7)
680*193032a3SAndroid Build Coastguard Worker return;
681*193032a3SAndroid Build Coastguard Worker
682*193032a3SAndroid Build Coastguard Worker printf(" Maximum TMDS clock: %u MHz\n", x[6] * 5);
683*193032a3SAndroid Build Coastguard Worker if (x[6] * 5 > 340)
684*193032a3SAndroid Build Coastguard Worker fail("HDMI VSDB Max TMDS rate is > 340.\n");
685*193032a3SAndroid Build Coastguard Worker
686*193032a3SAndroid Build Coastguard Worker if (length < 8)
687*193032a3SAndroid Build Coastguard Worker return;
688*193032a3SAndroid Build Coastguard Worker
689*193032a3SAndroid Build Coastguard Worker if (x[7] & 0x0f) {
690*193032a3SAndroid Build Coastguard Worker printf(" Supported Content Types:\n");
691*193032a3SAndroid Build Coastguard Worker if (x[7] & 0x01)
692*193032a3SAndroid Build Coastguard Worker printf(" Graphics\n");
693*193032a3SAndroid Build Coastguard Worker if (x[7] & 0x02)
694*193032a3SAndroid Build Coastguard Worker printf(" Photo\n");
695*193032a3SAndroid Build Coastguard Worker if (x[7] & 0x04)
696*193032a3SAndroid Build Coastguard Worker printf(" Cinema\n");
697*193032a3SAndroid Build Coastguard Worker if (x[7] & 0x08)
698*193032a3SAndroid Build Coastguard Worker printf(" Game\n");
699*193032a3SAndroid Build Coastguard Worker }
700*193032a3SAndroid Build Coastguard Worker
701*193032a3SAndroid Build Coastguard Worker unsigned b = 8;
702*193032a3SAndroid Build Coastguard Worker if (x[7] & 0x80) {
703*193032a3SAndroid Build Coastguard Worker hdmi_latency(x[b], x[b + 1], false);
704*193032a3SAndroid Build Coastguard Worker
705*193032a3SAndroid Build Coastguard Worker if (x[7] & 0x40) {
706*193032a3SAndroid Build Coastguard Worker if (x[b] == x[b + 2] &&
707*193032a3SAndroid Build Coastguard Worker x[b + 1] == x[b + 3])
708*193032a3SAndroid Build Coastguard Worker warn("Progressive and Interlaced latency values are identical, no need for both.\n");
709*193032a3SAndroid Build Coastguard Worker b += 2;
710*193032a3SAndroid Build Coastguard Worker hdmi_latency(x[b], x[b + 1], true);
711*193032a3SAndroid Build Coastguard Worker }
712*193032a3SAndroid Build Coastguard Worker b += 2;
713*193032a3SAndroid Build Coastguard Worker }
714*193032a3SAndroid Build Coastguard Worker
715*193032a3SAndroid Build Coastguard Worker if (!(x[7] & 0x20))
716*193032a3SAndroid Build Coastguard Worker return;
717*193032a3SAndroid Build Coastguard Worker
718*193032a3SAndroid Build Coastguard Worker bool mask = false;
719*193032a3SAndroid Build Coastguard Worker bool formats = false;
720*193032a3SAndroid Build Coastguard Worker
721*193032a3SAndroid Build Coastguard Worker printf(" Extended HDMI video details:\n");
722*193032a3SAndroid Build Coastguard Worker if (x[b] & 0x80)
723*193032a3SAndroid Build Coastguard Worker printf(" 3D present\n");
724*193032a3SAndroid Build Coastguard Worker if ((x[b] & 0x60) == 0x20) {
725*193032a3SAndroid Build Coastguard Worker printf(" All advertised VICs are 3D-capable\n");
726*193032a3SAndroid Build Coastguard Worker formats = true;
727*193032a3SAndroid Build Coastguard Worker }
728*193032a3SAndroid Build Coastguard Worker if ((x[b] & 0x60) == 0x40) {
729*193032a3SAndroid Build Coastguard Worker printf(" 3D-capable-VIC mask present\n");
730*193032a3SAndroid Build Coastguard Worker formats = true;
731*193032a3SAndroid Build Coastguard Worker mask = true;
732*193032a3SAndroid Build Coastguard Worker }
733*193032a3SAndroid Build Coastguard Worker switch (x[b] & 0x18) {
734*193032a3SAndroid Build Coastguard Worker case 0x00: break;
735*193032a3SAndroid Build Coastguard Worker case 0x08:
736*193032a3SAndroid Build Coastguard Worker printf(" Base EDID image size is aspect ratio\n");
737*193032a3SAndroid Build Coastguard Worker break;
738*193032a3SAndroid Build Coastguard Worker case 0x10:
739*193032a3SAndroid Build Coastguard Worker printf(" Base EDID image size is in units of 1 cm\n");
740*193032a3SAndroid Build Coastguard Worker break;
741*193032a3SAndroid Build Coastguard Worker case 0x18:
742*193032a3SAndroid Build Coastguard Worker printf(" Base EDID image size is in units of 5 cm\n");
743*193032a3SAndroid Build Coastguard Worker base.max_display_width_mm *= 5;
744*193032a3SAndroid Build Coastguard Worker base.max_display_height_mm *= 5;
745*193032a3SAndroid Build Coastguard Worker printf(" Recalculated image size: %u cm x %u cm\n",
746*193032a3SAndroid Build Coastguard Worker base.max_display_width_mm / 10, base.max_display_height_mm / 10);
747*193032a3SAndroid Build Coastguard Worker break;
748*193032a3SAndroid Build Coastguard Worker }
749*193032a3SAndroid Build Coastguard Worker b++;
750*193032a3SAndroid Build Coastguard Worker len_vic = (x[b] & 0xe0) >> 5;
751*193032a3SAndroid Build Coastguard Worker len_3d = (x[b] & 0x1f) >> 0;
752*193032a3SAndroid Build Coastguard Worker b++;
753*193032a3SAndroid Build Coastguard Worker
754*193032a3SAndroid Build Coastguard Worker if (len_vic) {
755*193032a3SAndroid Build Coastguard Worker unsigned i;
756*193032a3SAndroid Build Coastguard Worker
757*193032a3SAndroid Build Coastguard Worker printf(" HDMI VICs:\n");
758*193032a3SAndroid Build Coastguard Worker for (i = 0; i < len_vic; i++) {
759*193032a3SAndroid Build Coastguard Worker unsigned char vic = x[b + i];
760*193032a3SAndroid Build Coastguard Worker const struct timings *t;
761*193032a3SAndroid Build Coastguard Worker
762*193032a3SAndroid Build Coastguard Worker if (vic && vic <= ARRAY_SIZE(edid_hdmi_mode_map)) {
763*193032a3SAndroid Build Coastguard Worker std::string suffix = "HDMI VIC " + std::to_string(vic);
764*193032a3SAndroid Build Coastguard Worker cta.supported_hdmi_vic_codes |= 1 << (vic - 1);
765*193032a3SAndroid Build Coastguard Worker t = find_vic_id(edid_hdmi_mode_map[vic - 1]);
766*193032a3SAndroid Build Coastguard Worker print_timings(" ", t, suffix.c_str());
767*193032a3SAndroid Build Coastguard Worker } else {
768*193032a3SAndroid Build Coastguard Worker printf(" Unknown (HDMI VIC %u)\n", vic);
769*193032a3SAndroid Build Coastguard Worker fail("Unknown HDMI VIC %u.\n", vic);
770*193032a3SAndroid Build Coastguard Worker }
771*193032a3SAndroid Build Coastguard Worker }
772*193032a3SAndroid Build Coastguard Worker
773*193032a3SAndroid Build Coastguard Worker b += len_vic;
774*193032a3SAndroid Build Coastguard Worker }
775*193032a3SAndroid Build Coastguard Worker
776*193032a3SAndroid Build Coastguard Worker if (!len_3d)
777*193032a3SAndroid Build Coastguard Worker return;
778*193032a3SAndroid Build Coastguard Worker
779*193032a3SAndroid Build Coastguard Worker if (formats) {
780*193032a3SAndroid Build Coastguard Worker /* 3D_Structure_ALL_15..8 */
781*193032a3SAndroid Build Coastguard Worker if (x[b] & 0x80)
782*193032a3SAndroid Build Coastguard Worker printf(" 3D: Side-by-side (half, quincunx)\n");
783*193032a3SAndroid Build Coastguard Worker if (x[b] & 0x01)
784*193032a3SAndroid Build Coastguard Worker printf(" 3D: Side-by-side (half, horizontal)\n");
785*193032a3SAndroid Build Coastguard Worker /* 3D_Structure_ALL_7..0 */
786*193032a3SAndroid Build Coastguard Worker b++;
787*193032a3SAndroid Build Coastguard Worker if (x[b] & 0x40)
788*193032a3SAndroid Build Coastguard Worker printf(" 3D: Top-and-bottom\n");
789*193032a3SAndroid Build Coastguard Worker if (x[b] & 0x20)
790*193032a3SAndroid Build Coastguard Worker printf(" 3D: L + depth + gfx + gfx-depth\n");
791*193032a3SAndroid Build Coastguard Worker if (x[b] & 0x10)
792*193032a3SAndroid Build Coastguard Worker printf(" 3D: L + depth\n");
793*193032a3SAndroid Build Coastguard Worker if (x[b] & 0x08)
794*193032a3SAndroid Build Coastguard Worker printf(" 3D: Side-by-side (full)\n");
795*193032a3SAndroid Build Coastguard Worker if (x[b] & 0x04)
796*193032a3SAndroid Build Coastguard Worker printf(" 3D: Line-alternative\n");
797*193032a3SAndroid Build Coastguard Worker if (x[b] & 0x02)
798*193032a3SAndroid Build Coastguard Worker printf(" 3D: Field-alternative\n");
799*193032a3SAndroid Build Coastguard Worker if (x[b] & 0x01)
800*193032a3SAndroid Build Coastguard Worker printf(" 3D: Frame-packing\n");
801*193032a3SAndroid Build Coastguard Worker b++;
802*193032a3SAndroid Build Coastguard Worker len_3d -= 2;
803*193032a3SAndroid Build Coastguard Worker }
804*193032a3SAndroid Build Coastguard Worker
805*193032a3SAndroid Build Coastguard Worker if (mask) {
806*193032a3SAndroid Build Coastguard Worker int max_idx = -1;
807*193032a3SAndroid Build Coastguard Worker unsigned i;
808*193032a3SAndroid Build Coastguard Worker
809*193032a3SAndroid Build Coastguard Worker printf(" 3D VIC indices that support these capabilities:\n");
810*193032a3SAndroid Build Coastguard Worker /* worst bit ordering ever */
811*193032a3SAndroid Build Coastguard Worker for (i = 0; i < 8; i++)
812*193032a3SAndroid Build Coastguard Worker if (x[b + 1] & (1 << i)) {
813*193032a3SAndroid Build Coastguard Worker print_vic_index(" ", i, "");
814*193032a3SAndroid Build Coastguard Worker max_idx = i;
815*193032a3SAndroid Build Coastguard Worker }
816*193032a3SAndroid Build Coastguard Worker for (i = 0; i < 8; i++)
817*193032a3SAndroid Build Coastguard Worker if (x[b] & (1 << i)) {
818*193032a3SAndroid Build Coastguard Worker print_vic_index(" ", i + 8, "");
819*193032a3SAndroid Build Coastguard Worker max_idx = i + 8;
820*193032a3SAndroid Build Coastguard Worker }
821*193032a3SAndroid Build Coastguard Worker b += 2;
822*193032a3SAndroid Build Coastguard Worker len_3d -= 2;
823*193032a3SAndroid Build Coastguard Worker if (max_idx >= (int)cta.preparsed_svds[0].size())
824*193032a3SAndroid Build Coastguard Worker fail("HDMI 3D VIC indices max index %d > %u (#SVDs).\n",
825*193032a3SAndroid Build Coastguard Worker max_idx + 1, cta.preparsed_svds[0].size());
826*193032a3SAndroid Build Coastguard Worker }
827*193032a3SAndroid Build Coastguard Worker
828*193032a3SAndroid Build Coastguard Worker /*
829*193032a3SAndroid Build Coastguard Worker * list of nibbles:
830*193032a3SAndroid Build Coastguard Worker * 2D_VIC_Order_X
831*193032a3SAndroid Build Coastguard Worker * 3D_Structure_X
832*193032a3SAndroid Build Coastguard Worker * (optionally: 3D_Detail_X and reserved)
833*193032a3SAndroid Build Coastguard Worker */
834*193032a3SAndroid Build Coastguard Worker if (!len_3d)
835*193032a3SAndroid Build Coastguard Worker return;
836*193032a3SAndroid Build Coastguard Worker
837*193032a3SAndroid Build Coastguard Worker unsigned end = b + len_3d;
838*193032a3SAndroid Build Coastguard Worker int max_idx = -1;
839*193032a3SAndroid Build Coastguard Worker
840*193032a3SAndroid Build Coastguard Worker printf(" 3D VIC indices with specific capabilities:\n");
841*193032a3SAndroid Build Coastguard Worker while (b < end) {
842*193032a3SAndroid Build Coastguard Worker unsigned char idx = x[b] >> 4;
843*193032a3SAndroid Build Coastguard Worker std::string s;
844*193032a3SAndroid Build Coastguard Worker
845*193032a3SAndroid Build Coastguard Worker if (idx > max_idx)
846*193032a3SAndroid Build Coastguard Worker max_idx = idx;
847*193032a3SAndroid Build Coastguard Worker switch (x[b] & 0x0f) {
848*193032a3SAndroid Build Coastguard Worker case 0: s = "frame packing"; break;
849*193032a3SAndroid Build Coastguard Worker case 1: s = "field alternative"; break;
850*193032a3SAndroid Build Coastguard Worker case 2: s = "line alternative"; break;
851*193032a3SAndroid Build Coastguard Worker case 3: s = "side-by-side (full)"; break;
852*193032a3SAndroid Build Coastguard Worker case 4: s = "L + depth"; break;
853*193032a3SAndroid Build Coastguard Worker case 5: s = "L + depth + gfx + gfx-depth"; break;
854*193032a3SAndroid Build Coastguard Worker case 6: s = "top-and-bottom"; break;
855*193032a3SAndroid Build Coastguard Worker case 8:
856*193032a3SAndroid Build Coastguard Worker s = "side-by-side";
857*193032a3SAndroid Build Coastguard Worker switch (x[b + 1] >> 4) {
858*193032a3SAndroid Build Coastguard Worker case 0x00: s += ", any subsampling"; break;
859*193032a3SAndroid Build Coastguard Worker case 0x01: s += ", horizontal"; break;
860*193032a3SAndroid Build Coastguard Worker case 0x02: case 0x03: case 0x04: case 0x05:
861*193032a3SAndroid Build Coastguard Worker s += ", not in use";
862*193032a3SAndroid Build Coastguard Worker fail("not-in-use 3D_Detail_X value 0x%02x.\n",
863*193032a3SAndroid Build Coastguard Worker x[b + 1] >> 4);
864*193032a3SAndroid Build Coastguard Worker break;
865*193032a3SAndroid Build Coastguard Worker case 0x06: s += ", all quincunx combinations"; break;
866*193032a3SAndroid Build Coastguard Worker case 0x07: s += ", quincunx odd/left, odd/right"; break;
867*193032a3SAndroid Build Coastguard Worker case 0x08: s += ", quincunx odd/left, even/right"; break;
868*193032a3SAndroid Build Coastguard Worker case 0x09: s += ", quincunx even/left, odd/right"; break;
869*193032a3SAndroid Build Coastguard Worker case 0x0a: s += ", quincunx even/left, even/right"; break;
870*193032a3SAndroid Build Coastguard Worker default:
871*193032a3SAndroid Build Coastguard Worker s += ", reserved";
872*193032a3SAndroid Build Coastguard Worker fail("reserved 3D_Detail_X value 0x%02x.\n",
873*193032a3SAndroid Build Coastguard Worker x[b + 1] >> 4);
874*193032a3SAndroid Build Coastguard Worker break;
875*193032a3SAndroid Build Coastguard Worker }
876*193032a3SAndroid Build Coastguard Worker break;
877*193032a3SAndroid Build Coastguard Worker default:
878*193032a3SAndroid Build Coastguard Worker s = "unknown (";
879*193032a3SAndroid Build Coastguard Worker s += utohex(x[b] & 0x0f) + ")";
880*193032a3SAndroid Build Coastguard Worker fail("Unknown 3D_Structure_X value 0x%02x.\n", x[b] & 0x0f);
881*193032a3SAndroid Build Coastguard Worker break;
882*193032a3SAndroid Build Coastguard Worker }
883*193032a3SAndroid Build Coastguard Worker print_vic_index(" ", idx, s.c_str());
884*193032a3SAndroid Build Coastguard Worker if ((x[b] & 0x0f) >= 8)
885*193032a3SAndroid Build Coastguard Worker b++;
886*193032a3SAndroid Build Coastguard Worker b++;
887*193032a3SAndroid Build Coastguard Worker }
888*193032a3SAndroid Build Coastguard Worker if (max_idx >= (int)cta.preparsed_svds[0].size())
889*193032a3SAndroid Build Coastguard Worker fail("HDMI 2D VIC indices max index %d > %u (#SVDs).\n",
890*193032a3SAndroid Build Coastguard Worker max_idx + 1, cta.preparsed_svds[0].size());
891*193032a3SAndroid Build Coastguard Worker }
892*193032a3SAndroid Build Coastguard Worker
893*193032a3SAndroid Build Coastguard Worker static const char *max_frl_rates[] = {
894*193032a3SAndroid Build Coastguard Worker "Not Supported",
895*193032a3SAndroid Build Coastguard Worker "3 Gbps per lane on 3 lanes",
896*193032a3SAndroid Build Coastguard Worker "3 and 6 Gbps per lane on 3 lanes",
897*193032a3SAndroid Build Coastguard Worker "3 and 6 Gbps per lane on 3 lanes, 6 Gbps on 4 lanes",
898*193032a3SAndroid Build Coastguard Worker "3 and 6 Gbps per lane on 3 lanes, 6 and 8 Gbps on 4 lanes",
899*193032a3SAndroid Build Coastguard Worker "3 and 6 Gbps per lane on 3 lanes, 6, 8 and 10 Gbps on 4 lanes",
900*193032a3SAndroid Build Coastguard Worker "3 and 6 Gbps per lane on 3 lanes, 6, 8, 10 and 12 Gbps on 4 lanes",
901*193032a3SAndroid Build Coastguard Worker };
902*193032a3SAndroid Build Coastguard Worker
903*193032a3SAndroid Build Coastguard Worker static const char *dsc_max_slices[] = {
904*193032a3SAndroid Build Coastguard Worker "Not Supported",
905*193032a3SAndroid Build Coastguard Worker "up to 1 slice and up to (340 MHz/Ksliceadjust) pixel clock per slice",
906*193032a3SAndroid Build Coastguard Worker "up to 2 slices and up to (340 MHz/Ksliceadjust) pixel clock per slice",
907*193032a3SAndroid Build Coastguard Worker "up to 4 slices and up to (340 MHz/Ksliceadjust) pixel clock per slice",
908*193032a3SAndroid Build Coastguard Worker "up to 8 slices and up to (340 MHz/Ksliceadjust) pixel clock per slice",
909*193032a3SAndroid Build Coastguard Worker "up to 8 slices and up to (400 MHz/Ksliceadjust) pixel clock per slice",
910*193032a3SAndroid Build Coastguard Worker "up to 12 slices and up to (400 MHz/Ksliceadjust) pixel clock per slice",
911*193032a3SAndroid Build Coastguard Worker "up to 16 slices and up to (400 MHz/Ksliceadjust) pixel clock per slice",
912*193032a3SAndroid Build Coastguard Worker };
913*193032a3SAndroid Build Coastguard Worker
cta_hf_eeodb(const unsigned char * x,unsigned length)914*193032a3SAndroid Build Coastguard Worker static void cta_hf_eeodb(const unsigned char *x, unsigned length)
915*193032a3SAndroid Build Coastguard Worker {
916*193032a3SAndroid Build Coastguard Worker printf(" EDID Extension Block Count: %u\n", x[0]);
917*193032a3SAndroid Build Coastguard Worker if (length != 1 || x[0] == 0)
918*193032a3SAndroid Build Coastguard Worker fail("Block is too long or reports a 0 block count.\n");
919*193032a3SAndroid Build Coastguard Worker }
920*193032a3SAndroid Build Coastguard Worker
cta_hf_scdb(const unsigned char * x,unsigned length)921*193032a3SAndroid Build Coastguard Worker static void cta_hf_scdb(const unsigned char *x, unsigned length)
922*193032a3SAndroid Build Coastguard Worker {
923*193032a3SAndroid Build Coastguard Worker unsigned rate = x[1] * 5;
924*193032a3SAndroid Build Coastguard Worker
925*193032a3SAndroid Build Coastguard Worker printf(" Version: %u\n", x[0]);
926*193032a3SAndroid Build Coastguard Worker if (rate) {
927*193032a3SAndroid Build Coastguard Worker printf(" Maximum TMDS Character Rate: %u MHz\n", rate);
928*193032a3SAndroid Build Coastguard Worker if (rate <= 340 || rate > 600)
929*193032a3SAndroid Build Coastguard Worker fail("Max TMDS rate is > 0 and <= 340 or > 600.\n");
930*193032a3SAndroid Build Coastguard Worker }
931*193032a3SAndroid Build Coastguard Worker if (x[2] & 0x80)
932*193032a3SAndroid Build Coastguard Worker printf(" SCDC Present\n");
933*193032a3SAndroid Build Coastguard Worker if (x[2] & 0x40)
934*193032a3SAndroid Build Coastguard Worker printf(" SCDC Read Request Capable\n");
935*193032a3SAndroid Build Coastguard Worker if (x[2] & 0x10)
936*193032a3SAndroid Build Coastguard Worker printf(" Supports Color Content Bits Per Component Indication\n");
937*193032a3SAndroid Build Coastguard Worker if (x[2] & 0x08)
938*193032a3SAndroid Build Coastguard Worker printf(" Supports scrambling for <= 340 Mcsc\n");
939*193032a3SAndroid Build Coastguard Worker if (x[2] & 0x04)
940*193032a3SAndroid Build Coastguard Worker printf(" Supports 3D Independent View signaling\n");
941*193032a3SAndroid Build Coastguard Worker if (x[2] & 0x02)
942*193032a3SAndroid Build Coastguard Worker printf(" Supports 3D Dual View signaling\n");
943*193032a3SAndroid Build Coastguard Worker if (x[2] & 0x01)
944*193032a3SAndroid Build Coastguard Worker printf(" Supports 3D OSD Disparity signaling\n");
945*193032a3SAndroid Build Coastguard Worker if (x[3] & 0xf0) {
946*193032a3SAndroid Build Coastguard Worker unsigned max_frl_rate = x[3] >> 4;
947*193032a3SAndroid Build Coastguard Worker
948*193032a3SAndroid Build Coastguard Worker printf(" Max Fixed Rate Link: ");
949*193032a3SAndroid Build Coastguard Worker if (max_frl_rate < ARRAY_SIZE(max_frl_rates)) {
950*193032a3SAndroid Build Coastguard Worker printf("%s\n", max_frl_rates[max_frl_rate]);
951*193032a3SAndroid Build Coastguard Worker } else {
952*193032a3SAndroid Build Coastguard Worker printf("Unknown (0x%02x)\n", max_frl_rate);
953*193032a3SAndroid Build Coastguard Worker fail("Unknown Max Fixed Rate Link (0x%02x).\n", max_frl_rate);
954*193032a3SAndroid Build Coastguard Worker }
955*193032a3SAndroid Build Coastguard Worker if (max_frl_rate == 1 && rate < 300)
956*193032a3SAndroid Build Coastguard Worker fail("Max Fixed Rate Link is 1, but Max TMDS rate < 300.\n");
957*193032a3SAndroid Build Coastguard Worker else if (max_frl_rate >= 2 && rate < 600)
958*193032a3SAndroid Build Coastguard Worker fail("Max Fixed Rate Link is >= 2, but Max TMDS rate < 600.\n");
959*193032a3SAndroid Build Coastguard Worker }
960*193032a3SAndroid Build Coastguard Worker if (x[3] & 0x08)
961*193032a3SAndroid Build Coastguard Worker printf(" Supports UHD VIC\n");
962*193032a3SAndroid Build Coastguard Worker if (x[3] & 0x04)
963*193032a3SAndroid Build Coastguard Worker printf(" Supports 16-bits/component Deep Color 4:2:0 Pixel Encoding\n");
964*193032a3SAndroid Build Coastguard Worker if (x[3] & 0x02)
965*193032a3SAndroid Build Coastguard Worker printf(" Supports 12-bits/component Deep Color 4:2:0 Pixel Encoding\n");
966*193032a3SAndroid Build Coastguard Worker if (x[3] & 0x01)
967*193032a3SAndroid Build Coastguard Worker printf(" Supports 10-bits/component Deep Color 4:2:0 Pixel Encoding\n");
968*193032a3SAndroid Build Coastguard Worker
969*193032a3SAndroid Build Coastguard Worker if (length <= 4)
970*193032a3SAndroid Build Coastguard Worker return;
971*193032a3SAndroid Build Coastguard Worker
972*193032a3SAndroid Build Coastguard Worker if (x[4] & 0x20)
973*193032a3SAndroid Build Coastguard Worker printf(" Supports Mdelta\n");
974*193032a3SAndroid Build Coastguard Worker if (x[4] & 0x10)
975*193032a3SAndroid Build Coastguard Worker printf(" Supports media rates below VRRmin (CinemaVRR)\n");
976*193032a3SAndroid Build Coastguard Worker if (x[4] & 0x08)
977*193032a3SAndroid Build Coastguard Worker printf(" Supports negative Mvrr values\n");
978*193032a3SAndroid Build Coastguard Worker if (x[4] & 0x04)
979*193032a3SAndroid Build Coastguard Worker printf(" Supports Fast Vactive\n");
980*193032a3SAndroid Build Coastguard Worker if (x[4] & 0x02)
981*193032a3SAndroid Build Coastguard Worker printf(" Supports Auto Low-Latency Mode\n");
982*193032a3SAndroid Build Coastguard Worker if (x[4] & 0x01)
983*193032a3SAndroid Build Coastguard Worker printf(" Supports a FAPA in blanking after first active video line\n");
984*193032a3SAndroid Build Coastguard Worker
985*193032a3SAndroid Build Coastguard Worker if (length <= 5)
986*193032a3SAndroid Build Coastguard Worker return;
987*193032a3SAndroid Build Coastguard Worker
988*193032a3SAndroid Build Coastguard Worker printf(" VRRmin: %d Hz\n", x[5] & 0x3f);
989*193032a3SAndroid Build Coastguard Worker printf(" VRRmax: %d Hz\n", (x[5] & 0xc0) << 2 | x[6]);
990*193032a3SAndroid Build Coastguard Worker
991*193032a3SAndroid Build Coastguard Worker if (length <= 7)
992*193032a3SAndroid Build Coastguard Worker return;
993*193032a3SAndroid Build Coastguard Worker
994*193032a3SAndroid Build Coastguard Worker if (x[7] & 0x80)
995*193032a3SAndroid Build Coastguard Worker printf(" Supports VESA DSC 1.2a compression\n");
996*193032a3SAndroid Build Coastguard Worker if (x[7] & 0x40)
997*193032a3SAndroid Build Coastguard Worker printf(" Supports Compressed Video Transport for 4:2:0 Pixel Encoding\n");
998*193032a3SAndroid Build Coastguard Worker if (x[7] & 0x08)
999*193032a3SAndroid Build Coastguard Worker printf(" Supports Compressed Video Transport at any valid 1/16th bit bpp\n");
1000*193032a3SAndroid Build Coastguard Worker if (x[7] & 0x04)
1001*193032a3SAndroid Build Coastguard Worker printf(" Supports 16 bpc Compressed Video Transport\n");
1002*193032a3SAndroid Build Coastguard Worker if (x[7] & 0x02)
1003*193032a3SAndroid Build Coastguard Worker printf(" Supports 12 bpc Compressed Video Transport\n");
1004*193032a3SAndroid Build Coastguard Worker if (x[7] & 0x01)
1005*193032a3SAndroid Build Coastguard Worker printf(" Supports 10 bpc Compressed Video Transport\n");
1006*193032a3SAndroid Build Coastguard Worker if (x[8] & 0xf) {
1007*193032a3SAndroid Build Coastguard Worker unsigned max_slices = x[8] & 0xf;
1008*193032a3SAndroid Build Coastguard Worker
1009*193032a3SAndroid Build Coastguard Worker printf(" DSC Max Slices: ");
1010*193032a3SAndroid Build Coastguard Worker if (max_slices < ARRAY_SIZE(dsc_max_slices)) {
1011*193032a3SAndroid Build Coastguard Worker printf("%s\n", dsc_max_slices[max_slices]);
1012*193032a3SAndroid Build Coastguard Worker } else {
1013*193032a3SAndroid Build Coastguard Worker printf("Unknown (0x%02x)\n", max_slices);
1014*193032a3SAndroid Build Coastguard Worker fail("Unknown DSC Max Slices (0x%02x).\n", max_slices);
1015*193032a3SAndroid Build Coastguard Worker }
1016*193032a3SAndroid Build Coastguard Worker }
1017*193032a3SAndroid Build Coastguard Worker if (x[8] & 0xf0) {
1018*193032a3SAndroid Build Coastguard Worker unsigned max_frl_rate = x[8] >> 4;
1019*193032a3SAndroid Build Coastguard Worker
1020*193032a3SAndroid Build Coastguard Worker printf(" DSC Max Fixed Rate Link: ");
1021*193032a3SAndroid Build Coastguard Worker if (max_frl_rate < ARRAY_SIZE(max_frl_rates)) {
1022*193032a3SAndroid Build Coastguard Worker printf("%s\n", max_frl_rates[max_frl_rate]);
1023*193032a3SAndroid Build Coastguard Worker } else {
1024*193032a3SAndroid Build Coastguard Worker printf("Unknown (0x%02x)\n", max_frl_rate);
1025*193032a3SAndroid Build Coastguard Worker fail("Unknown DSC Max Fixed Rate Link (0x%02x).\n", max_frl_rate);
1026*193032a3SAndroid Build Coastguard Worker }
1027*193032a3SAndroid Build Coastguard Worker }
1028*193032a3SAndroid Build Coastguard Worker if (x[9] & 0x3f)
1029*193032a3SAndroid Build Coastguard Worker printf(" Maximum number of bytes in a line of chunks: %u\n",
1030*193032a3SAndroid Build Coastguard Worker 1024 * (1 + (x[9] & 0x3f)));
1031*193032a3SAndroid Build Coastguard Worker }
1032*193032a3SAndroid Build Coastguard Worker
cta_amd(const unsigned char * x,unsigned length)1033*193032a3SAndroid Build Coastguard Worker static void cta_amd(const unsigned char *x, unsigned length)
1034*193032a3SAndroid Build Coastguard Worker {
1035*193032a3SAndroid Build Coastguard Worker // These Freesync values are reversed engineered by looking
1036*193032a3SAndroid Build Coastguard Worker // at existing EDIDs.
1037*193032a3SAndroid Build Coastguard Worker printf(" Version: %u.%u\n", x[0], x[1]);
1038*193032a3SAndroid Build Coastguard Worker printf(" Minimum Refresh Rate: %u Hz\n", x[2]);
1039*193032a3SAndroid Build Coastguard Worker printf(" Maximum Refresh Rate: %u Hz\n", x[3]);
1040*193032a3SAndroid Build Coastguard Worker // Freesync 1.x flags
1041*193032a3SAndroid Build Coastguard Worker // One or more of the 0xe6 bits signal that the VESA MCCS
1042*193032a3SAndroid Build Coastguard Worker // protocol is used to switch the Freesync range
1043*193032a3SAndroid Build Coastguard Worker printf(" Flags 1.x: 0x%02x%s\n", x[4],
1044*193032a3SAndroid Build Coastguard Worker (x[4] & 0xe6) ? " (MCCS)" : "");
1045*193032a3SAndroid Build Coastguard Worker if (length >= 10) {
1046*193032a3SAndroid Build Coastguard Worker // Freesync 2.x flags
1047*193032a3SAndroid Build Coastguard Worker // Bit 2 no doubt indicates if the monitor supports Local Dimming
1048*193032a3SAndroid Build Coastguard Worker // There are probably also bits to signal support of the
1049*193032a3SAndroid Build Coastguard Worker // FreeSync2_scRGB and FreeSync2_Gamma22 HDR display modes.
1050*193032a3SAndroid Build Coastguard Worker // I suspect bits 0 and 1.
1051*193032a3SAndroid Build Coastguard Worker printf(" Flags 2.x: 0x%02x\n", x[5]);
1052*193032a3SAndroid Build Coastguard Worker // The AMD tone mapping tutorial referred to in the URL below
1053*193032a3SAndroid Build Coastguard Worker // mentions that the Freesync HDR info reports max/min
1054*193032a3SAndroid Build Coastguard Worker // luminance of the monitor with and without local dimming.
1055*193032a3SAndroid Build Coastguard Worker //
1056*193032a3SAndroid Build Coastguard Worker // https://gpuopen.com/learn/using-amd-freesync-premium-pro-hdr-code-samples/
1057*193032a3SAndroid Build Coastguard Worker //
1058*193032a3SAndroid Build Coastguard Worker // So I assume that the first two luminance values are
1059*193032a3SAndroid Build Coastguard Worker // the max/min luminance of the display and the next two
1060*193032a3SAndroid Build Coastguard Worker // luminance values are the max/min luminance values when
1061*193032a3SAndroid Build Coastguard Worker // local dimming is disabled. The values I get seem to
1062*193032a3SAndroid Build Coastguard Worker // support that.
1063*193032a3SAndroid Build Coastguard Worker printf(" Maximum luminance: %u (%.3f cd/m^2)\n",
1064*193032a3SAndroid Build Coastguard Worker x[6], 50.0 * pow(2, x[6] / 32.0));
1065*193032a3SAndroid Build Coastguard Worker printf(" Minimum luminance: %u (%.3f cd/m^2)\n",
1066*193032a3SAndroid Build Coastguard Worker x[7], (50.0 * pow(2, x[6] / 32.0)) * pow(x[7] / 255.0, 2) / 100.0);
1067*193032a3SAndroid Build Coastguard Worker if (x[5] & 4) {
1068*193032a3SAndroid Build Coastguard Worker // One or both bytes can be 0. The meaning of that
1069*193032a3SAndroid Build Coastguard Worker // is unknown.
1070*193032a3SAndroid Build Coastguard Worker printf(" Maximum luminance (without local dimming): %u (%.3f cd/m^2)\n",
1071*193032a3SAndroid Build Coastguard Worker x[8], 50.0 * pow(2, x[8] / 32.0));
1072*193032a3SAndroid Build Coastguard Worker printf(" Minimum luminance (without local dimming): %u (%.3f cd/m^2)\n",
1073*193032a3SAndroid Build Coastguard Worker x[9], (50.0 * pow(2, x[8] / 32.0)) * pow(x[9] / 255.0, 2) / 100.0);
1074*193032a3SAndroid Build Coastguard Worker } else {
1075*193032a3SAndroid Build Coastguard Worker // These bytes are always 0x08 0x2f. If these values
1076*193032a3SAndroid Build Coastguard Worker // represent max/min luminance as well, then these
1077*193032a3SAndroid Build Coastguard Worker // would map to 59.460 and 0.020 cd/m^2 respectively.
1078*193032a3SAndroid Build Coastguard Worker // I wonder if this somehow relates to SDR.
1079*193032a3SAndroid Build Coastguard Worker printf(" Unknown: 0x%02x 0x%02x\n", x[8], x[9]);
1080*193032a3SAndroid Build Coastguard Worker }
1081*193032a3SAndroid Build Coastguard Worker }
1082*193032a3SAndroid Build Coastguard Worker }
1083*193032a3SAndroid Build Coastguard Worker
display_use_case(unsigned char x)1084*193032a3SAndroid Build Coastguard Worker static std::string display_use_case(unsigned char x)
1085*193032a3SAndroid Build Coastguard Worker {
1086*193032a3SAndroid Build Coastguard Worker switch (x) {
1087*193032a3SAndroid Build Coastguard Worker case 1: return "Test equipment";
1088*193032a3SAndroid Build Coastguard Worker case 2: return "Generic display";
1089*193032a3SAndroid Build Coastguard Worker case 3: return "Television display";
1090*193032a3SAndroid Build Coastguard Worker case 4: return "Desktop productivity display";
1091*193032a3SAndroid Build Coastguard Worker case 5: return "Desktop gaming display";
1092*193032a3SAndroid Build Coastguard Worker case 6: return "Presentation display";
1093*193032a3SAndroid Build Coastguard Worker case 7: return "Virtual reality headset";
1094*193032a3SAndroid Build Coastguard Worker case 8: return "Augmented reality";
1095*193032a3SAndroid Build Coastguard Worker case 16: return "Video wall display";
1096*193032a3SAndroid Build Coastguard Worker case 17: return "Medical imaging display";
1097*193032a3SAndroid Build Coastguard Worker case 18: return "Dedicated gaming display";
1098*193032a3SAndroid Build Coastguard Worker case 19: return "Dedicated video monitor display";
1099*193032a3SAndroid Build Coastguard Worker case 20: return "Accessory display";
1100*193032a3SAndroid Build Coastguard Worker default: break;
1101*193032a3SAndroid Build Coastguard Worker }
1102*193032a3SAndroid Build Coastguard Worker fail("Unknown Display product primary use case 0x%02x.\n", x);
1103*193032a3SAndroid Build Coastguard Worker return std::string("Unknown display use case (") + utohex(x) + ")";
1104*193032a3SAndroid Build Coastguard Worker }
1105*193032a3SAndroid Build Coastguard Worker
cta_microsoft(const unsigned char * x,unsigned length)1106*193032a3SAndroid Build Coastguard Worker static void cta_microsoft(const unsigned char *x, unsigned length)
1107*193032a3SAndroid Build Coastguard Worker {
1108*193032a3SAndroid Build Coastguard Worker // This VSDB is documented at:
1109*193032a3SAndroid Build Coastguard Worker // https://docs.microsoft.com/en-us/windows-hardware/drivers/display/specialized-monitors-edid-extension
1110*193032a3SAndroid Build Coastguard Worker printf(" Version: %u\n", x[0]);
1111*193032a3SAndroid Build Coastguard Worker if (x[0] > 2) {
1112*193032a3SAndroid Build Coastguard Worker // In version 1 and 2 these bits should always be set to 0.
1113*193032a3SAndroid Build Coastguard Worker printf(" Desktop Usage: %u\n", (x[1] >> 6) & 1);
1114*193032a3SAndroid Build Coastguard Worker printf(" Third-Party Usage: %u\n", (x[1] >> 5) & 1);
1115*193032a3SAndroid Build Coastguard Worker }
1116*193032a3SAndroid Build Coastguard Worker printf(" Display Product Primary Use Case: %u (%s)\n", x[1] & 0x1f,
1117*193032a3SAndroid Build Coastguard Worker display_use_case(x[1] & 0x1f).c_str());
1118*193032a3SAndroid Build Coastguard Worker printf(" Container ID: %s\n", containerid2s(x + 2).c_str());
1119*193032a3SAndroid Build Coastguard Worker }
1120*193032a3SAndroid Build Coastguard Worker
cta_hdr10plus(const unsigned char * x,unsigned length)1121*193032a3SAndroid Build Coastguard Worker static void cta_hdr10plus(const unsigned char *x, unsigned length)
1122*193032a3SAndroid Build Coastguard Worker {
1123*193032a3SAndroid Build Coastguard Worker printf(" Application Version: %u", x[0]);
1124*193032a3SAndroid Build Coastguard Worker if (length > 1)
1125*193032a3SAndroid Build Coastguard Worker hex_block(" ", x + 1, length - 1);
1126*193032a3SAndroid Build Coastguard Worker else
1127*193032a3SAndroid Build Coastguard Worker printf("\n");
1128*193032a3SAndroid Build Coastguard Worker }
1129*193032a3SAndroid Build Coastguard Worker
cta_dolby_video(const unsigned char * x,unsigned length)1130*193032a3SAndroid Build Coastguard Worker static void cta_dolby_video(const unsigned char *x, unsigned length)
1131*193032a3SAndroid Build Coastguard Worker {
1132*193032a3SAndroid Build Coastguard Worker unsigned char version = (x[0] >> 5) & 0x07;
1133*193032a3SAndroid Build Coastguard Worker
1134*193032a3SAndroid Build Coastguard Worker printf(" Version: %u (%u bytes)\n", version, length + 5);
1135*193032a3SAndroid Build Coastguard Worker if (x[0] & 0x01)
1136*193032a3SAndroid Build Coastguard Worker printf(" Supports YUV422 12 bit\n");
1137*193032a3SAndroid Build Coastguard Worker
1138*193032a3SAndroid Build Coastguard Worker if (version == 0) {
1139*193032a3SAndroid Build Coastguard Worker if (x[0] & 0x02)
1140*193032a3SAndroid Build Coastguard Worker printf(" Supports 2160p60\n");
1141*193032a3SAndroid Build Coastguard Worker if (x[0] & 0x04)
1142*193032a3SAndroid Build Coastguard Worker printf(" Supports global dimming\n");
1143*193032a3SAndroid Build Coastguard Worker unsigned char dm_version = x[16];
1144*193032a3SAndroid Build Coastguard Worker printf(" DM Version: %u.%u\n", dm_version >> 4, dm_version & 0xf);
1145*193032a3SAndroid Build Coastguard Worker printf(" Target Min PQ: %u\n", (x[14] << 4) | (x[13] >> 4));
1146*193032a3SAndroid Build Coastguard Worker printf(" Target Max PQ: %u\n", (x[15] << 4) | (x[13] & 0xf));
1147*193032a3SAndroid Build Coastguard Worker printf(" Rx, Ry: %.8f, %.8f\n",
1148*193032a3SAndroid Build Coastguard Worker ((x[1] >> 4) | (x[2] << 4)) / 4096.0,
1149*193032a3SAndroid Build Coastguard Worker ((x[1] & 0xf) | (x[3] << 4)) / 4096.0);
1150*193032a3SAndroid Build Coastguard Worker printf(" Gx, Gy: %.8f, %.8f\n",
1151*193032a3SAndroid Build Coastguard Worker ((x[4] >> 4) | (x[5] << 4)) / 4096.0,
1152*193032a3SAndroid Build Coastguard Worker ((x[4] & 0xf) | (x[6] << 4)) / 4096.0);
1153*193032a3SAndroid Build Coastguard Worker printf(" Bx, By: %.8f, %.8f\n",
1154*193032a3SAndroid Build Coastguard Worker ((x[7] >> 4) | (x[8] << 4)) / 4096.0,
1155*193032a3SAndroid Build Coastguard Worker ((x[7] & 0xf) | (x[9] << 4)) / 4096.0);
1156*193032a3SAndroid Build Coastguard Worker printf(" Wx, Wy: %.8f, %.8f\n",
1157*193032a3SAndroid Build Coastguard Worker ((x[10] >> 4) | (x[11] << 4)) / 4096.0,
1158*193032a3SAndroid Build Coastguard Worker ((x[10] & 0xf) | (x[12] << 4)) / 4096.0);
1159*193032a3SAndroid Build Coastguard Worker return;
1160*193032a3SAndroid Build Coastguard Worker }
1161*193032a3SAndroid Build Coastguard Worker
1162*193032a3SAndroid Build Coastguard Worker if (version == 1) {
1163*193032a3SAndroid Build Coastguard Worker if (x[0] & 0x02)
1164*193032a3SAndroid Build Coastguard Worker printf(" Supports 2160p60\n");
1165*193032a3SAndroid Build Coastguard Worker if (x[1] & 0x01)
1166*193032a3SAndroid Build Coastguard Worker printf(" Supports global dimming\n");
1167*193032a3SAndroid Build Coastguard Worker unsigned char dm_version = (x[0] >> 2) & 0x07;
1168*193032a3SAndroid Build Coastguard Worker printf(" DM Version: %u.x\n", dm_version + 2);
1169*193032a3SAndroid Build Coastguard Worker printf(" Colorimetry: %s\n", (x[2] & 0x01) ? "P3-D65" : "ITU-R BT.709");
1170*193032a3SAndroid Build Coastguard Worker printf(" Low Latency: %s\n", (x[3] & 0x01) ? "Standard + Low Latency" : "Only Standard");
1171*193032a3SAndroid Build Coastguard Worker printf(" Target Max Luminance: %u cd/m^2\n", 100 + (x[1] >> 1) * 50);
1172*193032a3SAndroid Build Coastguard Worker double lm = (x[2] >> 1) / 127.0;
1173*193032a3SAndroid Build Coastguard Worker printf(" Target Min Luminance: %.8f cd/m^2\n", lm * lm);
1174*193032a3SAndroid Build Coastguard Worker if (length == 10) {
1175*193032a3SAndroid Build Coastguard Worker printf(" Rx, Ry: %.8f, %.8f\n", x[4] / 256.0, x[5] / 256.0);
1176*193032a3SAndroid Build Coastguard Worker printf(" Gx, Gy: %.8f, %.8f\n", x[6] / 256.0, x[7] / 256.0);
1177*193032a3SAndroid Build Coastguard Worker printf(" Bx, By: %.8f, %.8f\n", x[8] / 256.0, x[9] / 256.0);
1178*193032a3SAndroid Build Coastguard Worker } else {
1179*193032a3SAndroid Build Coastguard Worker double xmin = 0.625;
1180*193032a3SAndroid Build Coastguard Worker double xstep = (0.74609375 - xmin) / 31.0;
1181*193032a3SAndroid Build Coastguard Worker double ymin = 0.25;
1182*193032a3SAndroid Build Coastguard Worker double ystep = (0.37109375 - ymin) / 31.0;
1183*193032a3SAndroid Build Coastguard Worker
1184*193032a3SAndroid Build Coastguard Worker printf(" Unique Rx, Ry: %.8f, %.8f\n",
1185*193032a3SAndroid Build Coastguard Worker xmin + xstep * (x[6] >> 3),
1186*193032a3SAndroid Build Coastguard Worker ymin + ystep * (((x[6] & 0x7) << 2) | (x[4] & 0x01) | ((x[5] & 0x01) << 1)));
1187*193032a3SAndroid Build Coastguard Worker xstep = 0.49609375 / 127.0;
1188*193032a3SAndroid Build Coastguard Worker ymin = 0.5;
1189*193032a3SAndroid Build Coastguard Worker ystep = (0.99609375 - ymin) / 127.0;
1190*193032a3SAndroid Build Coastguard Worker printf(" Unique Gx, Gy: %.8f, %.8f\n",
1191*193032a3SAndroid Build Coastguard Worker xstep * (x[4] >> 1), ymin + ystep * (x[5] >> 1));
1192*193032a3SAndroid Build Coastguard Worker xmin = 0.125;
1193*193032a3SAndroid Build Coastguard Worker xstep = (0.15234375 - xmin) / 7.0;
1194*193032a3SAndroid Build Coastguard Worker ymin = 0.03125;
1195*193032a3SAndroid Build Coastguard Worker ystep = (0.05859375 - ymin) / 7.0;
1196*193032a3SAndroid Build Coastguard Worker printf(" Unique Bx, By: %.8f, %.8f\n",
1197*193032a3SAndroid Build Coastguard Worker xmin + xstep * (x[3] >> 5),
1198*193032a3SAndroid Build Coastguard Worker ymin + ystep * ((x[3] >> 2) & 0x07));
1199*193032a3SAndroid Build Coastguard Worker }
1200*193032a3SAndroid Build Coastguard Worker return;
1201*193032a3SAndroid Build Coastguard Worker }
1202*193032a3SAndroid Build Coastguard Worker
1203*193032a3SAndroid Build Coastguard Worker if (version == 2) {
1204*193032a3SAndroid Build Coastguard Worker if (x[0] & 0x02)
1205*193032a3SAndroid Build Coastguard Worker printf(" Supports Backlight Control\n");
1206*193032a3SAndroid Build Coastguard Worker if (x[1] & 0x04)
1207*193032a3SAndroid Build Coastguard Worker printf(" Supports global dimming\n");
1208*193032a3SAndroid Build Coastguard Worker unsigned char dm_version = (x[0] >> 2) & 0x07;
1209*193032a3SAndroid Build Coastguard Worker printf(" DM Version: %u.x\n", dm_version + 2);
1210*193032a3SAndroid Build Coastguard Worker printf(" Backlt Min Luma: %u cd/m^2\n", 25 + (x[1] & 0x03) * 25);
1211*193032a3SAndroid Build Coastguard Worker printf(" Interface: ");
1212*193032a3SAndroid Build Coastguard Worker switch (x[2] & 0x03) {
1213*193032a3SAndroid Build Coastguard Worker case 0: printf("Low-Latency\n"); break;
1214*193032a3SAndroid Build Coastguard Worker case 1: printf("Low-Latency + Low-Latency-HDMI\n"); break;
1215*193032a3SAndroid Build Coastguard Worker case 2: printf("Standard + Low-Latency\n"); break;
1216*193032a3SAndroid Build Coastguard Worker case 3: printf("Standard + Low-Latency + Low-Latency-HDMI\n"); break;
1217*193032a3SAndroid Build Coastguard Worker }
1218*193032a3SAndroid Build Coastguard Worker printf(" Supports 10b 12b 444: ");
1219*193032a3SAndroid Build Coastguard Worker switch ((x[3] & 0x01) << 1 | (x[4] & 0x01)) {
1220*193032a3SAndroid Build Coastguard Worker case 0: printf("Not supported\n"); break;
1221*193032a3SAndroid Build Coastguard Worker case 1: printf("10 bit\n"); break;
1222*193032a3SAndroid Build Coastguard Worker case 2: printf("12 bit\n"); break;
1223*193032a3SAndroid Build Coastguard Worker case 3: printf("Reserved\n"); break;
1224*193032a3SAndroid Build Coastguard Worker }
1225*193032a3SAndroid Build Coastguard Worker printf(" Target Min PQ v2: %u\n", 20 * (x[1] >> 3));
1226*193032a3SAndroid Build Coastguard Worker printf(" Target Max PQ v2: %u\n", 2055 + 65 * (x[2] >> 3));
1227*193032a3SAndroid Build Coastguard Worker
1228*193032a3SAndroid Build Coastguard Worker double xmin = 0.625;
1229*193032a3SAndroid Build Coastguard Worker double xstep = (0.74609375 - xmin) / 31.0;
1230*193032a3SAndroid Build Coastguard Worker double ymin = 0.25;
1231*193032a3SAndroid Build Coastguard Worker double ystep = (0.37109375 - ymin) / 31.0;
1232*193032a3SAndroid Build Coastguard Worker
1233*193032a3SAndroid Build Coastguard Worker printf(" Unique Rx, Ry: %.8f, %.8f\n",
1234*193032a3SAndroid Build Coastguard Worker xmin + xstep * (x[5] >> 3),
1235*193032a3SAndroid Build Coastguard Worker ymin + ystep * (x[6] >> 3));
1236*193032a3SAndroid Build Coastguard Worker xstep = 0.49609375 / 127.0;
1237*193032a3SAndroid Build Coastguard Worker ymin = 0.5;
1238*193032a3SAndroid Build Coastguard Worker ystep = (0.99609375 - ymin) / 127.0;
1239*193032a3SAndroid Build Coastguard Worker printf(" Unique Gx, Gy: %.8f, %.8f\n",
1240*193032a3SAndroid Build Coastguard Worker xstep * (x[3] >> 1), ymin + ystep * (x[4] >> 1));
1241*193032a3SAndroid Build Coastguard Worker xmin = 0.125;
1242*193032a3SAndroid Build Coastguard Worker xstep = (0.15234375 - xmin) / 7.0;
1243*193032a3SAndroid Build Coastguard Worker ymin = 0.03125;
1244*193032a3SAndroid Build Coastguard Worker ystep = (0.05859375 - ymin) / 7.0;
1245*193032a3SAndroid Build Coastguard Worker printf(" Unique Bx, By: %.8f, %.8f\n",
1246*193032a3SAndroid Build Coastguard Worker xmin + xstep * (x[5] & 0x07),
1247*193032a3SAndroid Build Coastguard Worker ymin + ystep * (x[6] & 0x07));
1248*193032a3SAndroid Build Coastguard Worker }
1249*193032a3SAndroid Build Coastguard Worker }
1250*193032a3SAndroid Build Coastguard Worker
cta_dolby_audio(const unsigned char * x,unsigned length)1251*193032a3SAndroid Build Coastguard Worker static void cta_dolby_audio(const unsigned char *x, unsigned length)
1252*193032a3SAndroid Build Coastguard Worker {
1253*193032a3SAndroid Build Coastguard Worker unsigned char version = 1 + (x[0] & 0x07);
1254*193032a3SAndroid Build Coastguard Worker
1255*193032a3SAndroid Build Coastguard Worker printf(" Version: %u (%u bytes)\n", version, length + 5);
1256*193032a3SAndroid Build Coastguard Worker if (x[0] & 0x80)
1257*193032a3SAndroid Build Coastguard Worker printf(" Headphone playback only\n");
1258*193032a3SAndroid Build Coastguard Worker if (x[0] & 0x40)
1259*193032a3SAndroid Build Coastguard Worker printf(" Height speaker zone present\n");
1260*193032a3SAndroid Build Coastguard Worker if (x[0] & 0x20)
1261*193032a3SAndroid Build Coastguard Worker printf(" Surround speaker zone present\n");
1262*193032a3SAndroid Build Coastguard Worker if (x[0] & 0x10)
1263*193032a3SAndroid Build Coastguard Worker printf(" Center speaker zone present\n");
1264*193032a3SAndroid Build Coastguard Worker if (x[1] & 0x01)
1265*193032a3SAndroid Build Coastguard Worker printf(" Supports Dolby MAT PCM decoding at 48 kHz only, does not support TrueHD\n");
1266*193032a3SAndroid Build Coastguard Worker }
1267*193032a3SAndroid Build Coastguard Worker
1268*193032a3SAndroid Build Coastguard Worker static const char *speaker_map[] = {
1269*193032a3SAndroid Build Coastguard Worker "FL/FR - Front Left/Right",
1270*193032a3SAndroid Build Coastguard Worker "LFE1 - Low Frequency Effects 1",
1271*193032a3SAndroid Build Coastguard Worker "FC - Front Center",
1272*193032a3SAndroid Build Coastguard Worker "BL/BR - Back Left/Right",
1273*193032a3SAndroid Build Coastguard Worker "BC - Back Center",
1274*193032a3SAndroid Build Coastguard Worker "FLc/FRc - Front Left/Right of Center",
1275*193032a3SAndroid Build Coastguard Worker "RLC/RRC - Rear Left/Right of Center (Deprecated)",
1276*193032a3SAndroid Build Coastguard Worker "FLw/FRw - Front Left/Right Wide",
1277*193032a3SAndroid Build Coastguard Worker "TpFL/TpFR - Top Front Left/Right",
1278*193032a3SAndroid Build Coastguard Worker "TpC - Top Center",
1279*193032a3SAndroid Build Coastguard Worker "TpFC - Top Front Center",
1280*193032a3SAndroid Build Coastguard Worker "LS/RS - Left/Right Surround",
1281*193032a3SAndroid Build Coastguard Worker "LFE2 - Low Frequency Effects 2",
1282*193032a3SAndroid Build Coastguard Worker "TpBC - Top Back Center",
1283*193032a3SAndroid Build Coastguard Worker "SiL/SiR - Side Left/Right",
1284*193032a3SAndroid Build Coastguard Worker "TpSiL/TpSiR - Top Side Left/Right",
1285*193032a3SAndroid Build Coastguard Worker "TpBL/TpBR - Top Back Left/Right",
1286*193032a3SAndroid Build Coastguard Worker "BtFC - Bottom Front Center",
1287*193032a3SAndroid Build Coastguard Worker "BtFL/BtFR - Bottom Front Left/Right",
1288*193032a3SAndroid Build Coastguard Worker "TpLS/TpRS - Top Left/Right Surround (Deprecated for CTA-861)",
1289*193032a3SAndroid Build Coastguard Worker "LSd/RSd - Left/Right Surround Direct (HDMI only)",
1290*193032a3SAndroid Build Coastguard Worker };
1291*193032a3SAndroid Build Coastguard Worker
cta_sadb(const unsigned char * x,unsigned length)1292*193032a3SAndroid Build Coastguard Worker static void cta_sadb(const unsigned char *x, unsigned length)
1293*193032a3SAndroid Build Coastguard Worker {
1294*193032a3SAndroid Build Coastguard Worker unsigned sad;
1295*193032a3SAndroid Build Coastguard Worker unsigned i;
1296*193032a3SAndroid Build Coastguard Worker
1297*193032a3SAndroid Build Coastguard Worker if (length < 3) {
1298*193032a3SAndroid Build Coastguard Worker fail("Empty Data Block with length %u.\n", length);
1299*193032a3SAndroid Build Coastguard Worker return;
1300*193032a3SAndroid Build Coastguard Worker }
1301*193032a3SAndroid Build Coastguard Worker
1302*193032a3SAndroid Build Coastguard Worker sad = ((x[2] << 16) | (x[1] << 8) | x[0]);
1303*193032a3SAndroid Build Coastguard Worker
1304*193032a3SAndroid Build Coastguard Worker for (i = 0; i < ARRAY_SIZE(speaker_map); i++) {
1305*193032a3SAndroid Build Coastguard Worker if ((sad >> i) & 1)
1306*193032a3SAndroid Build Coastguard Worker printf(" %s\n", speaker_map[i]);
1307*193032a3SAndroid Build Coastguard Worker }
1308*193032a3SAndroid Build Coastguard Worker }
1309*193032a3SAndroid Build Coastguard Worker
cta_vesa_dtcdb(const unsigned char * x,unsigned length)1310*193032a3SAndroid Build Coastguard Worker static void cta_vesa_dtcdb(const unsigned char *x, unsigned length)
1311*193032a3SAndroid Build Coastguard Worker {
1312*193032a3SAndroid Build Coastguard Worker if (length != 7 && length != 15 && length != 31) {
1313*193032a3SAndroid Build Coastguard Worker fail("Invalid length %u.\n", length);
1314*193032a3SAndroid Build Coastguard Worker return;
1315*193032a3SAndroid Build Coastguard Worker }
1316*193032a3SAndroid Build Coastguard Worker
1317*193032a3SAndroid Build Coastguard Worker switch (x[0] >> 6) {
1318*193032a3SAndroid Build Coastguard Worker case 0: printf(" White"); break;
1319*193032a3SAndroid Build Coastguard Worker case 1: printf(" Red"); break;
1320*193032a3SAndroid Build Coastguard Worker case 2: printf(" Green"); break;
1321*193032a3SAndroid Build Coastguard Worker case 3: printf(" Blue"); break;
1322*193032a3SAndroid Build Coastguard Worker }
1323*193032a3SAndroid Build Coastguard Worker unsigned v = x[0] & 0x3f;
1324*193032a3SAndroid Build Coastguard Worker printf(" transfer characteristics: %u", v);
1325*193032a3SAndroid Build Coastguard Worker for (unsigned i = 1; i < length; i++)
1326*193032a3SAndroid Build Coastguard Worker printf(" %u", v += x[i]);
1327*193032a3SAndroid Build Coastguard Worker printf(" 1023\n");
1328*193032a3SAndroid Build Coastguard Worker }
1329*193032a3SAndroid Build Coastguard Worker
cta_vesa_vdddb(const unsigned char * x,unsigned length)1330*193032a3SAndroid Build Coastguard Worker static void cta_vesa_vdddb(const unsigned char *x, unsigned length)
1331*193032a3SAndroid Build Coastguard Worker {
1332*193032a3SAndroid Build Coastguard Worker if (length != 30) {
1333*193032a3SAndroid Build Coastguard Worker fail("Invalid length %u.\n", length);
1334*193032a3SAndroid Build Coastguard Worker return;
1335*193032a3SAndroid Build Coastguard Worker }
1336*193032a3SAndroid Build Coastguard Worker
1337*193032a3SAndroid Build Coastguard Worker printf(" Interface Type: ");
1338*193032a3SAndroid Build Coastguard Worker unsigned char v = x[0];
1339*193032a3SAndroid Build Coastguard Worker switch (v >> 4) {
1340*193032a3SAndroid Build Coastguard Worker case 0: printf("Analog (");
1341*193032a3SAndroid Build Coastguard Worker switch (v & 0xf) {
1342*193032a3SAndroid Build Coastguard Worker case 0: printf("15HD/VGA"); break;
1343*193032a3SAndroid Build Coastguard Worker case 1: printf("VESA NAVI-V (15HD)"); break;
1344*193032a3SAndroid Build Coastguard Worker case 2: printf("VESA NAVI-D"); break;
1345*193032a3SAndroid Build Coastguard Worker default: printf("Reserved"); break;
1346*193032a3SAndroid Build Coastguard Worker }
1347*193032a3SAndroid Build Coastguard Worker printf(")\n");
1348*193032a3SAndroid Build Coastguard Worker break;
1349*193032a3SAndroid Build Coastguard Worker case 1: printf("LVDS %u lanes", v & 0xf); break;
1350*193032a3SAndroid Build Coastguard Worker case 2: printf("RSDS %u lanes", v & 0xf); break;
1351*193032a3SAndroid Build Coastguard Worker case 3: printf("DVI-D %u channels", v & 0xf); break;
1352*193032a3SAndroid Build Coastguard Worker case 4: printf("DVI-I analog"); break;
1353*193032a3SAndroid Build Coastguard Worker case 5: printf("DVI-I digital %u channels", v & 0xf); break;
1354*193032a3SAndroid Build Coastguard Worker case 6: printf("HDMI-A"); break;
1355*193032a3SAndroid Build Coastguard Worker case 7: printf("HDMI-B"); break;
1356*193032a3SAndroid Build Coastguard Worker case 8: printf("MDDI %u channels", v & 0xf); break;
1357*193032a3SAndroid Build Coastguard Worker case 9: printf("DisplayPort %u channels", v & 0xf); break;
1358*193032a3SAndroid Build Coastguard Worker case 10: printf("IEEE-1394"); break;
1359*193032a3SAndroid Build Coastguard Worker case 11: printf("M1 analog"); break;
1360*193032a3SAndroid Build Coastguard Worker case 12: printf("M1 digital %u channels", v & 0xf); break;
1361*193032a3SAndroid Build Coastguard Worker default: printf("Reserved"); break;
1362*193032a3SAndroid Build Coastguard Worker }
1363*193032a3SAndroid Build Coastguard Worker printf("\n");
1364*193032a3SAndroid Build Coastguard Worker
1365*193032a3SAndroid Build Coastguard Worker printf(" Interface Standard Version: %u.%u\n", x[1] >> 4, x[1] & 0xf);
1366*193032a3SAndroid Build Coastguard Worker printf(" Content Protection Support: ");
1367*193032a3SAndroid Build Coastguard Worker switch (x[2]) {
1368*193032a3SAndroid Build Coastguard Worker case 0: printf("None\n"); break;
1369*193032a3SAndroid Build Coastguard Worker case 1: printf("HDCP\n"); break;
1370*193032a3SAndroid Build Coastguard Worker case 2: printf("DTCP\n"); break;
1371*193032a3SAndroid Build Coastguard Worker case 3: printf("DPCP\n"); break;
1372*193032a3SAndroid Build Coastguard Worker default: printf("Reserved\n"); break;
1373*193032a3SAndroid Build Coastguard Worker }
1374*193032a3SAndroid Build Coastguard Worker
1375*193032a3SAndroid Build Coastguard Worker printf(" Minimum Clock Frequency: %u MHz\n", x[3] >> 2);
1376*193032a3SAndroid Build Coastguard Worker printf(" Maximum Clock Frequency: %u MHz\n", ((x[3] & 0x03) << 8) | x[4]);
1377*193032a3SAndroid Build Coastguard Worker printf(" Device Native Pixel Format: %ux%u\n",
1378*193032a3SAndroid Build Coastguard Worker x[5] | (x[6] << 8), x[7] | (x[8] << 8));
1379*193032a3SAndroid Build Coastguard Worker printf(" Aspect Ratio: %.2f\n", (100 + x[9]) / 100.0);
1380*193032a3SAndroid Build Coastguard Worker v = x[0x0a];
1381*193032a3SAndroid Build Coastguard Worker printf(" Default Orientation: ");
1382*193032a3SAndroid Build Coastguard Worker switch ((v & 0xc0) >> 6) {
1383*193032a3SAndroid Build Coastguard Worker case 0x00: printf("Landscape\n"); break;
1384*193032a3SAndroid Build Coastguard Worker case 0x01: printf("Portrait\n"); break;
1385*193032a3SAndroid Build Coastguard Worker case 0x02: printf("Not Fixed\n"); break;
1386*193032a3SAndroid Build Coastguard Worker case 0x03: printf("Undefined\n"); break;
1387*193032a3SAndroid Build Coastguard Worker }
1388*193032a3SAndroid Build Coastguard Worker printf(" Rotation Capability: ");
1389*193032a3SAndroid Build Coastguard Worker switch ((v & 0x30) >> 4) {
1390*193032a3SAndroid Build Coastguard Worker case 0x00: printf("None\n"); break;
1391*193032a3SAndroid Build Coastguard Worker case 0x01: printf("Can rotate 90 degrees clockwise\n"); break;
1392*193032a3SAndroid Build Coastguard Worker case 0x02: printf("Can rotate 90 degrees counterclockwise\n"); break;
1393*193032a3SAndroid Build Coastguard Worker case 0x03: printf("Can rotate 90 degrees in either direction)\n"); break;
1394*193032a3SAndroid Build Coastguard Worker }
1395*193032a3SAndroid Build Coastguard Worker printf(" Zero Pixel Location: ");
1396*193032a3SAndroid Build Coastguard Worker switch ((v & 0x0c) >> 2) {
1397*193032a3SAndroid Build Coastguard Worker case 0x00: printf("Upper Left\n"); break;
1398*193032a3SAndroid Build Coastguard Worker case 0x01: printf("Upper Right\n"); break;
1399*193032a3SAndroid Build Coastguard Worker case 0x02: printf("Lower Left\n"); break;
1400*193032a3SAndroid Build Coastguard Worker case 0x03: printf("Lower Right\n"); break;
1401*193032a3SAndroid Build Coastguard Worker }
1402*193032a3SAndroid Build Coastguard Worker printf(" Scan Direction: ");
1403*193032a3SAndroid Build Coastguard Worker switch (v & 0x03) {
1404*193032a3SAndroid Build Coastguard Worker case 0x00: printf("Not defined\n"); break;
1405*193032a3SAndroid Build Coastguard Worker case 0x01: printf("Fast Scan is on the Major (Long) Axis and Slow Scan is on the Minor Axis\n"); break;
1406*193032a3SAndroid Build Coastguard Worker case 0x02: printf("Fast Scan is on the Minor (Short) Axis and Slow Scan is on the Major Axis\n"); break;
1407*193032a3SAndroid Build Coastguard Worker case 0x03: printf("Reserved\n");
1408*193032a3SAndroid Build Coastguard Worker fail("Scan Direction used the reserved value 0x03.\n");
1409*193032a3SAndroid Build Coastguard Worker break;
1410*193032a3SAndroid Build Coastguard Worker }
1411*193032a3SAndroid Build Coastguard Worker printf(" Subpixel Information: ");
1412*193032a3SAndroid Build Coastguard Worker switch (x[0x0b]) {
1413*193032a3SAndroid Build Coastguard Worker case 0x00: printf("Not defined\n"); break;
1414*193032a3SAndroid Build Coastguard Worker case 0x01: printf("RGB vertical stripes\n"); break;
1415*193032a3SAndroid Build Coastguard Worker case 0x02: printf("RGB horizontal stripes\n"); break;
1416*193032a3SAndroid Build Coastguard Worker case 0x03: printf("Vertical stripes using primary order\n"); break;
1417*193032a3SAndroid Build Coastguard Worker case 0x04: printf("Horizontal stripes using primary order\n"); break;
1418*193032a3SAndroid Build Coastguard Worker case 0x05: printf("Quad sub-pixels, red at top left\n"); break;
1419*193032a3SAndroid Build Coastguard Worker case 0x06: printf("Quad sub-pixels, red at bottom left\n"); break;
1420*193032a3SAndroid Build Coastguard Worker case 0x07: printf("Delta (triad) RGB sub-pixels\n"); break;
1421*193032a3SAndroid Build Coastguard Worker case 0x08: printf("Mosaic\n"); break;
1422*193032a3SAndroid Build Coastguard Worker case 0x09: printf("Quad sub-pixels, RGB + 1 additional color\n"); break;
1423*193032a3SAndroid Build Coastguard Worker case 0x0a: printf("Five sub-pixels, RGB + 2 additional colors\n"); break;
1424*193032a3SAndroid Build Coastguard Worker case 0x0b: printf("Six sub-pixels, RGB + 3 additional colors\n"); break;
1425*193032a3SAndroid Build Coastguard Worker case 0x0c: printf("Clairvoyante, Inc. PenTile Matrix (tm) layout\n"); break;
1426*193032a3SAndroid Build Coastguard Worker default: printf("Reserved\n"); break;
1427*193032a3SAndroid Build Coastguard Worker }
1428*193032a3SAndroid Build Coastguard Worker printf(" Horizontal and vertical dot/pixel pitch: %.2f x %.2f mm\n",
1429*193032a3SAndroid Build Coastguard Worker (double)(x[0x0c]) / 100.0, (double)(x[0x0d]) / 100.0);
1430*193032a3SAndroid Build Coastguard Worker v = x[0x0e];
1431*193032a3SAndroid Build Coastguard Worker printf(" Dithering: ");
1432*193032a3SAndroid Build Coastguard Worker switch (v >> 6) {
1433*193032a3SAndroid Build Coastguard Worker case 0: printf("None\n"); break;
1434*193032a3SAndroid Build Coastguard Worker case 1: printf("Spatial\n"); break;
1435*193032a3SAndroid Build Coastguard Worker case 2: printf("Temporal\n"); break;
1436*193032a3SAndroid Build Coastguard Worker case 3: printf("Spatial and Temporal\n"); break;
1437*193032a3SAndroid Build Coastguard Worker }
1438*193032a3SAndroid Build Coastguard Worker printf(" Direct Drive: %s\n", (v & 0x20) ? "Yes" : "No");
1439*193032a3SAndroid Build Coastguard Worker printf(" Overdrive %srecommended\n", (v & 0x10) ? "not " : "");
1440*193032a3SAndroid Build Coastguard Worker printf(" Deinterlacing: %s\n", (v & 0x08) ? "Yes" : "No");
1441*193032a3SAndroid Build Coastguard Worker
1442*193032a3SAndroid Build Coastguard Worker v = x[0x0f];
1443*193032a3SAndroid Build Coastguard Worker printf(" Audio Support: %s\n", (v & 0x80) ? "Yes" : "No");
1444*193032a3SAndroid Build Coastguard Worker printf(" Separate Audio Inputs Provided: %s\n", (v & 0x40) ? "Yes" : "No");
1445*193032a3SAndroid Build Coastguard Worker printf(" Audio Input Override: %s\n", (v & 0x20) ? "Yes" : "No");
1446*193032a3SAndroid Build Coastguard Worker v = x[0x10];
1447*193032a3SAndroid Build Coastguard Worker if (v)
1448*193032a3SAndroid Build Coastguard Worker printf(" Audio Delay: %s%u ms\n", (v & 0x80) ? "" : "-", (v & 0x7f) * 2);
1449*193032a3SAndroid Build Coastguard Worker else
1450*193032a3SAndroid Build Coastguard Worker printf(" Audio Delay: no information provided\n");
1451*193032a3SAndroid Build Coastguard Worker v = x[0x11];
1452*193032a3SAndroid Build Coastguard Worker printf(" Frame Rate/Mode Conversion: ");
1453*193032a3SAndroid Build Coastguard Worker switch (v >> 6) {
1454*193032a3SAndroid Build Coastguard Worker case 0: printf("None\n"); break;
1455*193032a3SAndroid Build Coastguard Worker case 1: printf("Single Buffering\n"); break;
1456*193032a3SAndroid Build Coastguard Worker case 2: printf("Double Buffering\n"); break;
1457*193032a3SAndroid Build Coastguard Worker case 3: printf("Advanced Frame Rate Conversion\n"); break;
1458*193032a3SAndroid Build Coastguard Worker }
1459*193032a3SAndroid Build Coastguard Worker if (v & 0x3f)
1460*193032a3SAndroid Build Coastguard Worker printf(" Frame Rate Range: %u fps +/- %u fps\n",
1461*193032a3SAndroid Build Coastguard Worker x[0x12], v & 0x3f);
1462*193032a3SAndroid Build Coastguard Worker else
1463*193032a3SAndroid Build Coastguard Worker printf(" Nominal Frame Rate: %u fps\n", x[0x12]);
1464*193032a3SAndroid Build Coastguard Worker printf(" Color Bit Depth: %u @ interface, %u @ display\n",
1465*193032a3SAndroid Build Coastguard Worker (x[0x13] >> 4) + 1, (x[0x13] & 0xf) + 1);
1466*193032a3SAndroid Build Coastguard Worker v = x[0x15] & 3;
1467*193032a3SAndroid Build Coastguard Worker if (v) {
1468*193032a3SAndroid Build Coastguard Worker printf(" Additional Primary Chromaticities:\n");
1469*193032a3SAndroid Build Coastguard Worker unsigned col_x = (x[0x16] << 2) | (x[0x14] >> 6);
1470*193032a3SAndroid Build Coastguard Worker unsigned col_y = (x[0x17] << 2) | ((x[0x14] >> 4) & 3);
1471*193032a3SAndroid Build Coastguard Worker printf(" Primary 4: 0.%04u, 0.%04u\n",
1472*193032a3SAndroid Build Coastguard Worker (col_x * 10000) / 1024, (col_y * 10000) / 1024);
1473*193032a3SAndroid Build Coastguard Worker if (v > 1) {
1474*193032a3SAndroid Build Coastguard Worker col_x = (x[0x18] << 2) | ((x[0x14] >> 2) & 3);
1475*193032a3SAndroid Build Coastguard Worker col_y = (x[0x19] << 2) | (x[0x14] & 3);
1476*193032a3SAndroid Build Coastguard Worker printf(" Primary 5: 0.%04u, 0.%04u\n",
1477*193032a3SAndroid Build Coastguard Worker (col_x * 10000) / 1024, (col_y * 10000) / 1024);
1478*193032a3SAndroid Build Coastguard Worker if (v > 2) {
1479*193032a3SAndroid Build Coastguard Worker col_x = (x[0x1a] << 2) | (x[0x15] >> 6);
1480*193032a3SAndroid Build Coastguard Worker col_y = (x[0x1b] << 2) | ((x[0x15] >> 4) & 3);
1481*193032a3SAndroid Build Coastguard Worker printf(" Primary 6: 0.%04u, 0.%04u\n",
1482*193032a3SAndroid Build Coastguard Worker (col_x * 10000) / 1024, (col_y * 10000) / 1024);
1483*193032a3SAndroid Build Coastguard Worker }
1484*193032a3SAndroid Build Coastguard Worker }
1485*193032a3SAndroid Build Coastguard Worker }
1486*193032a3SAndroid Build Coastguard Worker
1487*193032a3SAndroid Build Coastguard Worker v = x[0x1c];
1488*193032a3SAndroid Build Coastguard Worker printf(" Response Time %s: %u ms\n",
1489*193032a3SAndroid Build Coastguard Worker (v & 0x80) ? "White -> Black" : "Black -> White", v & 0x7f);
1490*193032a3SAndroid Build Coastguard Worker v = x[0x1d];
1491*193032a3SAndroid Build Coastguard Worker printf(" Overscan: %u%% x %u%%\n", v >> 4, v & 0xf);
1492*193032a3SAndroid Build Coastguard Worker }
1493*193032a3SAndroid Build Coastguard Worker
decode_uchar_as_double(unsigned char x)1494*193032a3SAndroid Build Coastguard Worker static double decode_uchar_as_double(unsigned char x)
1495*193032a3SAndroid Build Coastguard Worker {
1496*193032a3SAndroid Build Coastguard Worker signed char s = (signed char)x;
1497*193032a3SAndroid Build Coastguard Worker
1498*193032a3SAndroid Build Coastguard Worker return s / 64.0;
1499*193032a3SAndroid Build Coastguard Worker }
1500*193032a3SAndroid Build Coastguard Worker
cta_rcdb(const unsigned char * x,unsigned length)1501*193032a3SAndroid Build Coastguard Worker void edid_state::cta_rcdb(const unsigned char *x, unsigned length)
1502*193032a3SAndroid Build Coastguard Worker {
1503*193032a3SAndroid Build Coastguard Worker unsigned spm = ((x[3] << 16) | (x[2] << 8) | x[1]);
1504*193032a3SAndroid Build Coastguard Worker unsigned i;
1505*193032a3SAndroid Build Coastguard Worker
1506*193032a3SAndroid Build Coastguard Worker if (length < 4) {
1507*193032a3SAndroid Build Coastguard Worker fail("Empty Data Block with length %u.\n", length);
1508*193032a3SAndroid Build Coastguard Worker return;
1509*193032a3SAndroid Build Coastguard Worker }
1510*193032a3SAndroid Build Coastguard Worker
1511*193032a3SAndroid Build Coastguard Worker if ((x[0] & 0x20) && !cta.has_sldb)
1512*193032a3SAndroid Build Coastguard Worker fail("'SLD' flag is 1, but no Speaker Location Data Block is found.\n");
1513*193032a3SAndroid Build Coastguard Worker else if (!(x[0] & 0x20) && cta.has_sldb)
1514*193032a3SAndroid Build Coastguard Worker fail("'SLD' flag is 0, but a Speaker Location Data Block is present.\n");
1515*193032a3SAndroid Build Coastguard Worker
1516*193032a3SAndroid Build Coastguard Worker if (x[0] & 0x40) {
1517*193032a3SAndroid Build Coastguard Worker printf(" Speaker count: %u\n", (x[0] & 0x1f) + 1);
1518*193032a3SAndroid Build Coastguard Worker } else {
1519*193032a3SAndroid Build Coastguard Worker if (x[0] & 0x1f)
1520*193032a3SAndroid Build Coastguard Worker fail("'Speaker' flag is 0, but 'Speaker Count' is != 0.\n");
1521*193032a3SAndroid Build Coastguard Worker if (x[0] & 0x20)
1522*193032a3SAndroid Build Coastguard Worker fail("'SLD' flag is 1, but 'Speaker' is 0.\n");
1523*193032a3SAndroid Build Coastguard Worker }
1524*193032a3SAndroid Build Coastguard Worker
1525*193032a3SAndroid Build Coastguard Worker printf(" Speaker Presence Mask:\n");
1526*193032a3SAndroid Build Coastguard Worker for (i = 0; i < ARRAY_SIZE(speaker_map); i++) {
1527*193032a3SAndroid Build Coastguard Worker if ((spm >> i) & 1)
1528*193032a3SAndroid Build Coastguard Worker printf(" %s\n", speaker_map[i]);
1529*193032a3SAndroid Build Coastguard Worker }
1530*193032a3SAndroid Build Coastguard Worker
1531*193032a3SAndroid Build Coastguard Worker if ((x[0] & 0xa0) == 0x80)
1532*193032a3SAndroid Build Coastguard Worker fail("'Display' flag set, but not the 'SLD' flag.\n");
1533*193032a3SAndroid Build Coastguard Worker
1534*193032a3SAndroid Build Coastguard Worker bool valid_max = cta.preparsed_sld_has_coord || (x[0] & 0x80);
1535*193032a3SAndroid Build Coastguard Worker
1536*193032a3SAndroid Build Coastguard Worker if (valid_max && length >= 7) {
1537*193032a3SAndroid Build Coastguard Worker printf(" Xmax: %u dm\n", x[4]);
1538*193032a3SAndroid Build Coastguard Worker printf(" Ymax: %u dm\n", x[5]);
1539*193032a3SAndroid Build Coastguard Worker printf(" Zmax: %u dm\n", x[6]);
1540*193032a3SAndroid Build Coastguard Worker } else if (!valid_max && length >= 7) {
1541*193032a3SAndroid Build Coastguard Worker // The RCDB should have been truncated.
1542*193032a3SAndroid Build Coastguard Worker warn("'Display' flag is 0 and 'Coord' is 0 for all SLDs, but the Max coordinates are still present.\n");
1543*193032a3SAndroid Build Coastguard Worker }
1544*193032a3SAndroid Build Coastguard Worker if ((x[0] & 0x80) && length >= 10) {
1545*193032a3SAndroid Build Coastguard Worker printf(" DisplayX: %.3f * Xmax\n", decode_uchar_as_double(x[7]));
1546*193032a3SAndroid Build Coastguard Worker printf(" DisplayY: %.3f * Ymax\n", decode_uchar_as_double(x[8]));
1547*193032a3SAndroid Build Coastguard Worker printf(" DisplayZ: %.3f * Zmax\n", decode_uchar_as_double(x[9]));
1548*193032a3SAndroid Build Coastguard Worker } else if (!(x[0] & 0x80) && length >= 10) {
1549*193032a3SAndroid Build Coastguard Worker // The RCDB should have been truncated.
1550*193032a3SAndroid Build Coastguard Worker warn("'Display' flag is 0, but the Display coordinates are still present.\n");
1551*193032a3SAndroid Build Coastguard Worker }
1552*193032a3SAndroid Build Coastguard Worker }
1553*193032a3SAndroid Build Coastguard Worker
1554*193032a3SAndroid Build Coastguard Worker static const char *speaker_location[] = {
1555*193032a3SAndroid Build Coastguard Worker "FL - Front Left",
1556*193032a3SAndroid Build Coastguard Worker "FR - Front Right",
1557*193032a3SAndroid Build Coastguard Worker "FC - Front Center",
1558*193032a3SAndroid Build Coastguard Worker "LFE1 - Low Frequency Effects 1",
1559*193032a3SAndroid Build Coastguard Worker "BL - Back Left",
1560*193032a3SAndroid Build Coastguard Worker "BR - Back Right",
1561*193032a3SAndroid Build Coastguard Worker "FLC - Front Left of Center",
1562*193032a3SAndroid Build Coastguard Worker "FRC - Front Right of Center",
1563*193032a3SAndroid Build Coastguard Worker "BC - Back Center",
1564*193032a3SAndroid Build Coastguard Worker "LFE2 - Low Frequency Effects 2",
1565*193032a3SAndroid Build Coastguard Worker "SiL - Side Left",
1566*193032a3SAndroid Build Coastguard Worker "SiR - Side Right",
1567*193032a3SAndroid Build Coastguard Worker "TpFL - Top Front Left",
1568*193032a3SAndroid Build Coastguard Worker "TpFR - Top Front Right",
1569*193032a3SAndroid Build Coastguard Worker "TpFC - Top Front Center",
1570*193032a3SAndroid Build Coastguard Worker "TpC - Top Center",
1571*193032a3SAndroid Build Coastguard Worker "TpBL - Top Back Left",
1572*193032a3SAndroid Build Coastguard Worker "TpBR - Top Back Right",
1573*193032a3SAndroid Build Coastguard Worker "TpSiL - Top Side Left",
1574*193032a3SAndroid Build Coastguard Worker "TpSiR - Top Side Right",
1575*193032a3SAndroid Build Coastguard Worker "TpBC - Top Back Center",
1576*193032a3SAndroid Build Coastguard Worker "BtFC - Bottom Front Center",
1577*193032a3SAndroid Build Coastguard Worker "BtFL - Bottom Front Left",
1578*193032a3SAndroid Build Coastguard Worker "BtFR - Bottom Front Right",
1579*193032a3SAndroid Build Coastguard Worker "FLW - Front Left Wide",
1580*193032a3SAndroid Build Coastguard Worker "FRW - Front Right Wide",
1581*193032a3SAndroid Build Coastguard Worker "LS - Left Surround",
1582*193032a3SAndroid Build Coastguard Worker "RS - Right Surround",
1583*193032a3SAndroid Build Coastguard Worker };
1584*193032a3SAndroid Build Coastguard Worker
cta_sldb(const unsigned char * x,unsigned length)1585*193032a3SAndroid Build Coastguard Worker void edid_state::cta_sldb(const unsigned char *x, unsigned length)
1586*193032a3SAndroid Build Coastguard Worker {
1587*193032a3SAndroid Build Coastguard Worker if (length < 2) {
1588*193032a3SAndroid Build Coastguard Worker fail("Empty Data Block with length %u.\n", length);
1589*193032a3SAndroid Build Coastguard Worker return;
1590*193032a3SAndroid Build Coastguard Worker }
1591*193032a3SAndroid Build Coastguard Worker
1592*193032a3SAndroid Build Coastguard Worker unsigned active_cnt = 0;
1593*193032a3SAndroid Build Coastguard Worker unsigned channel_is_active = 0;
1594*193032a3SAndroid Build Coastguard Worker
1595*193032a3SAndroid Build Coastguard Worker while (length >= 2) {
1596*193032a3SAndroid Build Coastguard Worker printf(" Channel: %u (%sactive)\n", x[0] & 0x1f,
1597*193032a3SAndroid Build Coastguard Worker (x[0] & 0x20) ? "" : "not ");
1598*193032a3SAndroid Build Coastguard Worker if (x[0] & 0x20) {
1599*193032a3SAndroid Build Coastguard Worker if (channel_is_active & (1U << (x[0] & 0x1f)))
1600*193032a3SAndroid Build Coastguard Worker fail("Channel Index %u was already marked 'Active'.\n",
1601*193032a3SAndroid Build Coastguard Worker x[0] & 0x1f);
1602*193032a3SAndroid Build Coastguard Worker channel_is_active |= 1U << (x[0] & 0x1f);
1603*193032a3SAndroid Build Coastguard Worker active_cnt++;
1604*193032a3SAndroid Build Coastguard Worker }
1605*193032a3SAndroid Build Coastguard Worker if ((x[1] & 0x1f) < ARRAY_SIZE(speaker_location))
1606*193032a3SAndroid Build Coastguard Worker printf(" Speaker: %s\n", speaker_location[x[1] & 0x1f]);
1607*193032a3SAndroid Build Coastguard Worker if (length >= 5 && (x[0] & 0x40)) {
1608*193032a3SAndroid Build Coastguard Worker printf(" X: %.3f * Xmax\n", decode_uchar_as_double(x[2]));
1609*193032a3SAndroid Build Coastguard Worker printf(" Y: %.3f * Ymax\n", decode_uchar_as_double(x[3]));
1610*193032a3SAndroid Build Coastguard Worker printf(" Z: %.3f * Zmax\n", decode_uchar_as_double(x[4]));
1611*193032a3SAndroid Build Coastguard Worker length -= 3;
1612*193032a3SAndroid Build Coastguard Worker x += 3;
1613*193032a3SAndroid Build Coastguard Worker }
1614*193032a3SAndroid Build Coastguard Worker
1615*193032a3SAndroid Build Coastguard Worker length -= 2;
1616*193032a3SAndroid Build Coastguard Worker x += 2;
1617*193032a3SAndroid Build Coastguard Worker }
1618*193032a3SAndroid Build Coastguard Worker if (active_cnt != cta.preparsed_speaker_count)
1619*193032a3SAndroid Build Coastguard Worker fail("There are %u active speakers, but 'Speaker Count' is %u.\n",
1620*193032a3SAndroid Build Coastguard Worker active_cnt, cta.preparsed_speaker_count);
1621*193032a3SAndroid Build Coastguard Worker }
1622*193032a3SAndroid Build Coastguard Worker
cta_preparse_sldb(const unsigned char * x,unsigned length)1623*193032a3SAndroid Build Coastguard Worker void edid_state::cta_preparse_sldb(const unsigned char *x, unsigned length)
1624*193032a3SAndroid Build Coastguard Worker {
1625*193032a3SAndroid Build Coastguard Worker cta.has_sldb = true;
1626*193032a3SAndroid Build Coastguard Worker while (length >= 2) {
1627*193032a3SAndroid Build Coastguard Worker if (length >= 5 && (x[0] & 0x40)) {
1628*193032a3SAndroid Build Coastguard Worker cta.preparsed_sld_has_coord = true;
1629*193032a3SAndroid Build Coastguard Worker return;
1630*193032a3SAndroid Build Coastguard Worker }
1631*193032a3SAndroid Build Coastguard Worker length -= 2;
1632*193032a3SAndroid Build Coastguard Worker x += 2;
1633*193032a3SAndroid Build Coastguard Worker }
1634*193032a3SAndroid Build Coastguard Worker }
1635*193032a3SAndroid Build Coastguard Worker
cta_vcdb(const unsigned char * x,unsigned length)1636*193032a3SAndroid Build Coastguard Worker void edid_state::cta_vcdb(const unsigned char *x, unsigned length)
1637*193032a3SAndroid Build Coastguard Worker {
1638*193032a3SAndroid Build Coastguard Worker unsigned char d = x[0];
1639*193032a3SAndroid Build Coastguard Worker
1640*193032a3SAndroid Build Coastguard Worker cta.has_vcdb = true;
1641*193032a3SAndroid Build Coastguard Worker if (length < 1) {
1642*193032a3SAndroid Build Coastguard Worker fail("Empty Data Block with length %u.\n", length);
1643*193032a3SAndroid Build Coastguard Worker return;
1644*193032a3SAndroid Build Coastguard Worker }
1645*193032a3SAndroid Build Coastguard Worker printf(" YCbCr quantization: %s\n",
1646*193032a3SAndroid Build Coastguard Worker (d & 0x80) ? "Selectable (via AVI YQ)" : "No Data");
1647*193032a3SAndroid Build Coastguard Worker printf(" RGB quantization: %s\n",
1648*193032a3SAndroid Build Coastguard Worker (d & 0x40) ? "Selectable (via AVI Q)" : "No Data");
1649*193032a3SAndroid Build Coastguard Worker /*
1650*193032a3SAndroid Build Coastguard Worker * If this bit is not set then that will result in interoperability
1651*193032a3SAndroid Build Coastguard Worker * problems (specifically with PCs/laptops) that quite often do not
1652*193032a3SAndroid Build Coastguard Worker * follow the default rules with respect to RGB Quantization Range
1653*193032a3SAndroid Build Coastguard Worker * handling.
1654*193032a3SAndroid Build Coastguard Worker *
1655*193032a3SAndroid Build Coastguard Worker * Starting with the CTA-861-H spec this bit is now required to be
1656*193032a3SAndroid Build Coastguard Worker * 1 for new designs.
1657*193032a3SAndroid Build Coastguard Worker */
1658*193032a3SAndroid Build Coastguard Worker if (!(d & 0x40))
1659*193032a3SAndroid Build Coastguard Worker fail("Set Selectable RGB Quantization to avoid interop issues.\n");
1660*193032a3SAndroid Build Coastguard Worker /*
1661*193032a3SAndroid Build Coastguard Worker * Since most YCbCr formats use limited range, the interop issues are
1662*193032a3SAndroid Build Coastguard Worker * less noticable than for RGB formats.
1663*193032a3SAndroid Build Coastguard Worker *
1664*193032a3SAndroid Build Coastguard Worker * Starting with the CTA-861-H spec this bit is now required to be
1665*193032a3SAndroid Build Coastguard Worker * 1 for new designs, but just warn about it (for now).
1666*193032a3SAndroid Build Coastguard Worker */
1667*193032a3SAndroid Build Coastguard Worker if ((cta.byte3 & 0x30) && !(d & 0x80))
1668*193032a3SAndroid Build Coastguard Worker warn("Set Selectable YCbCr Quantization to avoid interop issues.\n");
1669*193032a3SAndroid Build Coastguard Worker
1670*193032a3SAndroid Build Coastguard Worker unsigned char s_pt = (d >> 4) & 0x03;
1671*193032a3SAndroid Build Coastguard Worker unsigned char s_it = (d >> 2) & 0x03;
1672*193032a3SAndroid Build Coastguard Worker unsigned char s_ce = d & 0x03;
1673*193032a3SAndroid Build Coastguard Worker
1674*193032a3SAndroid Build Coastguard Worker printf(" PT scan behavior: ");
1675*193032a3SAndroid Build Coastguard Worker switch (s_pt) {
1676*193032a3SAndroid Build Coastguard Worker case 0: printf("No Data\n"); break;
1677*193032a3SAndroid Build Coastguard Worker case 1: printf("Always Overscanned\n"); break;
1678*193032a3SAndroid Build Coastguard Worker case 2: printf("Always Underscanned\n"); break;
1679*193032a3SAndroid Build Coastguard Worker case 3: printf("Supports both over- and underscan\n"); break;
1680*193032a3SAndroid Build Coastguard Worker }
1681*193032a3SAndroid Build Coastguard Worker printf(" IT scan behavior: ");
1682*193032a3SAndroid Build Coastguard Worker switch (s_it) {
1683*193032a3SAndroid Build Coastguard Worker case 0: printf("IT video formats not supported\n"); break;
1684*193032a3SAndroid Build Coastguard Worker case 1:
1685*193032a3SAndroid Build Coastguard Worker printf("Always Overscanned\n");
1686*193032a3SAndroid Build Coastguard Worker // See Table 52 of CTA-861-G for a description of Byte 3
1687*193032a3SAndroid Build Coastguard Worker if (cta.byte3 & 0x80)
1688*193032a3SAndroid Build Coastguard Worker fail("IT video formats are always overscanned, but bit 7 of Byte 3 of the CTA-861 Extension header is set to underscanned.\n");
1689*193032a3SAndroid Build Coastguard Worker break;
1690*193032a3SAndroid Build Coastguard Worker case 2:
1691*193032a3SAndroid Build Coastguard Worker printf("Always Underscanned\n");
1692*193032a3SAndroid Build Coastguard Worker // See Table 52 of CTA-861-G for a description of Byte 3
1693*193032a3SAndroid Build Coastguard Worker if (!(cta.byte3 & 0x80))
1694*193032a3SAndroid Build Coastguard Worker fail("IT video formats are always underscanned, but bit 7 of Byte 3 of the CTA-861 Extension header is set to overscanned.\n");
1695*193032a3SAndroid Build Coastguard Worker break;
1696*193032a3SAndroid Build Coastguard Worker case 3: printf("Supports both over- and underscan\n"); break;
1697*193032a3SAndroid Build Coastguard Worker }
1698*193032a3SAndroid Build Coastguard Worker if (s_it < 2)
1699*193032a3SAndroid Build Coastguard Worker warn("IT scan behavior is expected to support underscanned.\n");
1700*193032a3SAndroid Build Coastguard Worker printf(" CE scan behavior: ");
1701*193032a3SAndroid Build Coastguard Worker switch (s_ce) {
1702*193032a3SAndroid Build Coastguard Worker case 0: printf("CE video formats not supported\n"); break;
1703*193032a3SAndroid Build Coastguard Worker case 1: printf("Always Overscanned\n"); break;
1704*193032a3SAndroid Build Coastguard Worker case 2: printf("Always Underscanned\n"); break;
1705*193032a3SAndroid Build Coastguard Worker case 3: printf("Supports both over- and underscan\n"); break;
1706*193032a3SAndroid Build Coastguard Worker }
1707*193032a3SAndroid Build Coastguard Worker if (s_ce == 0)
1708*193032a3SAndroid Build Coastguard Worker warn("'CE video formats not supported' makes no sense.\n");
1709*193032a3SAndroid Build Coastguard Worker else if (s_pt == s_it && s_pt == s_ce)
1710*193032a3SAndroid Build Coastguard Worker warn("S_PT is equal to S_IT and S_CE, so should be set to 0 instead.\n");
1711*193032a3SAndroid Build Coastguard Worker }
1712*193032a3SAndroid Build Coastguard Worker
1713*193032a3SAndroid Build Coastguard Worker static const char *colorimetry_map[] = {
1714*193032a3SAndroid Build Coastguard Worker "xvYCC601",
1715*193032a3SAndroid Build Coastguard Worker "xvYCC709",
1716*193032a3SAndroid Build Coastguard Worker "sYCC601",
1717*193032a3SAndroid Build Coastguard Worker "opYCC601",
1718*193032a3SAndroid Build Coastguard Worker "opRGB",
1719*193032a3SAndroid Build Coastguard Worker "BT2020cYCC",
1720*193032a3SAndroid Build Coastguard Worker "BT2020YCC",
1721*193032a3SAndroid Build Coastguard Worker "BT2020RGB",
1722*193032a3SAndroid Build Coastguard Worker };
1723*193032a3SAndroid Build Coastguard Worker
cta_colorimetry_block(const unsigned char * x,unsigned length)1724*193032a3SAndroid Build Coastguard Worker static void cta_colorimetry_block(const unsigned char *x, unsigned length)
1725*193032a3SAndroid Build Coastguard Worker {
1726*193032a3SAndroid Build Coastguard Worker unsigned i;
1727*193032a3SAndroid Build Coastguard Worker
1728*193032a3SAndroid Build Coastguard Worker if (length < 2) {
1729*193032a3SAndroid Build Coastguard Worker fail("Empty Data Block with length %u.\n", length);
1730*193032a3SAndroid Build Coastguard Worker return;
1731*193032a3SAndroid Build Coastguard Worker }
1732*193032a3SAndroid Build Coastguard Worker for (i = 0; i < ARRAY_SIZE(colorimetry_map); i++) {
1733*193032a3SAndroid Build Coastguard Worker if (x[0] & (1 << i))
1734*193032a3SAndroid Build Coastguard Worker printf(" %s\n", colorimetry_map[i]);
1735*193032a3SAndroid Build Coastguard Worker }
1736*193032a3SAndroid Build Coastguard Worker if (x[1] & 0x80)
1737*193032a3SAndroid Build Coastguard Worker printf(" DCI-P3\n");
1738*193032a3SAndroid Build Coastguard Worker if (x[1] & 0x40)
1739*193032a3SAndroid Build Coastguard Worker printf(" ICtCp\n");
1740*193032a3SAndroid Build Coastguard Worker }
1741*193032a3SAndroid Build Coastguard Worker
1742*193032a3SAndroid Build Coastguard Worker static const char *eotf_map[] = {
1743*193032a3SAndroid Build Coastguard Worker "Traditional gamma - SDR luminance range",
1744*193032a3SAndroid Build Coastguard Worker "Traditional gamma - HDR luminance range",
1745*193032a3SAndroid Build Coastguard Worker "SMPTE ST2084",
1746*193032a3SAndroid Build Coastguard Worker "Hybrid Log-Gamma",
1747*193032a3SAndroid Build Coastguard Worker };
1748*193032a3SAndroid Build Coastguard Worker
cta_hdr_static_metadata_block(const unsigned char * x,unsigned length)1749*193032a3SAndroid Build Coastguard Worker static void cta_hdr_static_metadata_block(const unsigned char *x, unsigned length)
1750*193032a3SAndroid Build Coastguard Worker {
1751*193032a3SAndroid Build Coastguard Worker unsigned i;
1752*193032a3SAndroid Build Coastguard Worker
1753*193032a3SAndroid Build Coastguard Worker if (length < 2) {
1754*193032a3SAndroid Build Coastguard Worker fail("Empty Data Block with length %u.\n", length);
1755*193032a3SAndroid Build Coastguard Worker return;
1756*193032a3SAndroid Build Coastguard Worker }
1757*193032a3SAndroid Build Coastguard Worker printf(" Electro optical transfer functions:\n");
1758*193032a3SAndroid Build Coastguard Worker for (i = 0; i < 6; i++) {
1759*193032a3SAndroid Build Coastguard Worker if (x[0] & (1 << i)) {
1760*193032a3SAndroid Build Coastguard Worker if (i < ARRAY_SIZE(eotf_map)) {
1761*193032a3SAndroid Build Coastguard Worker printf(" %s\n", eotf_map[i]);
1762*193032a3SAndroid Build Coastguard Worker } else {
1763*193032a3SAndroid Build Coastguard Worker printf(" Unknown (%u)\n", i);
1764*193032a3SAndroid Build Coastguard Worker fail("Unknown EOTF (%u).\n", i);
1765*193032a3SAndroid Build Coastguard Worker }
1766*193032a3SAndroid Build Coastguard Worker }
1767*193032a3SAndroid Build Coastguard Worker }
1768*193032a3SAndroid Build Coastguard Worker printf(" Supported static metadata descriptors:\n");
1769*193032a3SAndroid Build Coastguard Worker for (i = 0; i < 8; i++) {
1770*193032a3SAndroid Build Coastguard Worker if (x[1] & (1 << i))
1771*193032a3SAndroid Build Coastguard Worker printf(" Static metadata type %u\n", i + 1);
1772*193032a3SAndroid Build Coastguard Worker }
1773*193032a3SAndroid Build Coastguard Worker
1774*193032a3SAndroid Build Coastguard Worker if (length >= 3)
1775*193032a3SAndroid Build Coastguard Worker printf(" Desired content max luminance: %u (%.3f cd/m^2)\n",
1776*193032a3SAndroid Build Coastguard Worker x[2], 50.0 * pow(2, x[2] / 32.0));
1777*193032a3SAndroid Build Coastguard Worker
1778*193032a3SAndroid Build Coastguard Worker if (length >= 4)
1779*193032a3SAndroid Build Coastguard Worker printf(" Desired content max frame-average luminance: %u (%.3f cd/m^2)\n",
1780*193032a3SAndroid Build Coastguard Worker x[3], 50.0 * pow(2, x[3] / 32.0));
1781*193032a3SAndroid Build Coastguard Worker
1782*193032a3SAndroid Build Coastguard Worker if (length >= 5)
1783*193032a3SAndroid Build Coastguard Worker printf(" Desired content min luminance: %u (%.3f cd/m^2)\n",
1784*193032a3SAndroid Build Coastguard Worker x[4], (50.0 * pow(2, x[2] / 32.0)) * pow(x[4] / 255.0, 2) / 100.0);
1785*193032a3SAndroid Build Coastguard Worker }
1786*193032a3SAndroid Build Coastguard Worker
cta_hdr_dyn_metadata_block(const unsigned char * x,unsigned length)1787*193032a3SAndroid Build Coastguard Worker static void cta_hdr_dyn_metadata_block(const unsigned char *x, unsigned length)
1788*193032a3SAndroid Build Coastguard Worker {
1789*193032a3SAndroid Build Coastguard Worker if (length < 3) {
1790*193032a3SAndroid Build Coastguard Worker fail("Empty Data Block with length %u.\n", length);
1791*193032a3SAndroid Build Coastguard Worker return;
1792*193032a3SAndroid Build Coastguard Worker }
1793*193032a3SAndroid Build Coastguard Worker while (length >= 3) {
1794*193032a3SAndroid Build Coastguard Worker unsigned type_len = x[0];
1795*193032a3SAndroid Build Coastguard Worker unsigned type = x[1] | (x[2] << 8);
1796*193032a3SAndroid Build Coastguard Worker
1797*193032a3SAndroid Build Coastguard Worker if (length < type_len + 1)
1798*193032a3SAndroid Build Coastguard Worker return;
1799*193032a3SAndroid Build Coastguard Worker printf(" HDR Dynamic Metadata Type %u\n", type);
1800*193032a3SAndroid Build Coastguard Worker switch (type) {
1801*193032a3SAndroid Build Coastguard Worker case 1:
1802*193032a3SAndroid Build Coastguard Worker case 4:
1803*193032a3SAndroid Build Coastguard Worker if (type_len > 2)
1804*193032a3SAndroid Build Coastguard Worker printf(" Version: %u\n", x[3] & 0xf);
1805*193032a3SAndroid Build Coastguard Worker break;
1806*193032a3SAndroid Build Coastguard Worker case 2:
1807*193032a3SAndroid Build Coastguard Worker if (type_len > 2) {
1808*193032a3SAndroid Build Coastguard Worker unsigned version = x[3] & 0xf;
1809*193032a3SAndroid Build Coastguard Worker printf(" Version: %u\n", version);
1810*193032a3SAndroid Build Coastguard Worker if (version >= 1) {
1811*193032a3SAndroid Build Coastguard Worker if (x[3] & 0x10) printf(" Supports SL-HDR1 (ETSI TS 103 433-1)\n");
1812*193032a3SAndroid Build Coastguard Worker if (x[3] & 0x20) printf(" Supports SL-HDR2 (ETSI TS 103 433-2)\n");
1813*193032a3SAndroid Build Coastguard Worker if (x[3] & 0x40) printf(" Supports SL-HDR3 (ETSI TS 103 433-3)\n");
1814*193032a3SAndroid Build Coastguard Worker }
1815*193032a3SAndroid Build Coastguard Worker }
1816*193032a3SAndroid Build Coastguard Worker break;
1817*193032a3SAndroid Build Coastguard Worker default:
1818*193032a3SAndroid Build Coastguard Worker break;
1819*193032a3SAndroid Build Coastguard Worker }
1820*193032a3SAndroid Build Coastguard Worker length -= type_len + 1;
1821*193032a3SAndroid Build Coastguard Worker x += type_len + 1;
1822*193032a3SAndroid Build Coastguard Worker }
1823*193032a3SAndroid Build Coastguard Worker }
1824*193032a3SAndroid Build Coastguard Worker
cta_ifdb(const unsigned char * x,unsigned length)1825*193032a3SAndroid Build Coastguard Worker static void cta_ifdb(const unsigned char *x, unsigned length)
1826*193032a3SAndroid Build Coastguard Worker {
1827*193032a3SAndroid Build Coastguard Worker unsigned len_hdr = x[0] >> 5;
1828*193032a3SAndroid Build Coastguard Worker
1829*193032a3SAndroid Build Coastguard Worker if (length < 2) {
1830*193032a3SAndroid Build Coastguard Worker fail("Empty Data Block with length %u.\n", length);
1831*193032a3SAndroid Build Coastguard Worker return;
1832*193032a3SAndroid Build Coastguard Worker }
1833*193032a3SAndroid Build Coastguard Worker printf(" VSIFs: %u\n", x[1]);
1834*193032a3SAndroid Build Coastguard Worker if (length < len_hdr + 2)
1835*193032a3SAndroid Build Coastguard Worker return;
1836*193032a3SAndroid Build Coastguard Worker length -= len_hdr + 2;
1837*193032a3SAndroid Build Coastguard Worker x += len_hdr + 2;
1838*193032a3SAndroid Build Coastguard Worker while (length > 0) {
1839*193032a3SAndroid Build Coastguard Worker int payload_len = x[0] >> 5;
1840*193032a3SAndroid Build Coastguard Worker
1841*193032a3SAndroid Build Coastguard Worker if ((x[0] & 0x1f) == 1 && length >= 4) {
1842*193032a3SAndroid Build Coastguard Worker unsigned oui = (x[3] << 16) | (x[2] << 8) | x[1];
1843*193032a3SAndroid Build Coastguard Worker
1844*193032a3SAndroid Build Coastguard Worker printf(" InfoFrame Type Code %u, OUI %s\n",
1845*193032a3SAndroid Build Coastguard Worker x[0] & 0x1f, ouitohex(oui).c_str());
1846*193032a3SAndroid Build Coastguard Worker x += 4;
1847*193032a3SAndroid Build Coastguard Worker length -= 4;
1848*193032a3SAndroid Build Coastguard Worker } else {
1849*193032a3SAndroid Build Coastguard Worker printf(" InfoFrame Type Code %u\n", x[0] & 0x1f);
1850*193032a3SAndroid Build Coastguard Worker x++;
1851*193032a3SAndroid Build Coastguard Worker length--;
1852*193032a3SAndroid Build Coastguard Worker }
1853*193032a3SAndroid Build Coastguard Worker x += payload_len;
1854*193032a3SAndroid Build Coastguard Worker length -= payload_len;
1855*193032a3SAndroid Build Coastguard Worker }
1856*193032a3SAndroid Build Coastguard Worker }
1857*193032a3SAndroid Build Coastguard Worker
cta_displayid_type_7(const unsigned char * x,unsigned length)1858*193032a3SAndroid Build Coastguard Worker void edid_state::cta_displayid_type_7(const unsigned char *x, unsigned length)
1859*193032a3SAndroid Build Coastguard Worker {
1860*193032a3SAndroid Build Coastguard Worker check_displayid_datablock_revision(x[0], 0x00, 2);
1861*193032a3SAndroid Build Coastguard Worker
1862*193032a3SAndroid Build Coastguard Worker if (length < 21U + ((x[0] & 0x70) >> 4)) {
1863*193032a3SAndroid Build Coastguard Worker fail("Empty Data Block with length %u.\n", length);
1864*193032a3SAndroid Build Coastguard Worker return;
1865*193032a3SAndroid Build Coastguard Worker }
1866*193032a3SAndroid Build Coastguard Worker parse_displayid_type_1_7_timing(x + 1, true, 2, true);
1867*193032a3SAndroid Build Coastguard Worker }
1868*193032a3SAndroid Build Coastguard Worker
cta_displayid_type_8(const unsigned char * x,unsigned length)1869*193032a3SAndroid Build Coastguard Worker void edid_state::cta_displayid_type_8(const unsigned char *x, unsigned length)
1870*193032a3SAndroid Build Coastguard Worker {
1871*193032a3SAndroid Build Coastguard Worker check_displayid_datablock_revision(x[0], 0xe8, 1);
1872*193032a3SAndroid Build Coastguard Worker if (length < ((x[0] & 0x08) ? 3 : 2)) {
1873*193032a3SAndroid Build Coastguard Worker fail("Empty Data Block with length %u.\n", length);
1874*193032a3SAndroid Build Coastguard Worker return;
1875*193032a3SAndroid Build Coastguard Worker }
1876*193032a3SAndroid Build Coastguard Worker
1877*193032a3SAndroid Build Coastguard Worker unsigned sz = (x[0] & 0x08) ? 2 : 1;
1878*193032a3SAndroid Build Coastguard Worker unsigned type = x[0] >> 6;
1879*193032a3SAndroid Build Coastguard Worker
1880*193032a3SAndroid Build Coastguard Worker if (type) {
1881*193032a3SAndroid Build Coastguard Worker fail("Only code type 0 is supported.\n");
1882*193032a3SAndroid Build Coastguard Worker return;
1883*193032a3SAndroid Build Coastguard Worker }
1884*193032a3SAndroid Build Coastguard Worker
1885*193032a3SAndroid Build Coastguard Worker if (x[0] & 0x20)
1886*193032a3SAndroid Build Coastguard Worker printf(" Also supports YCbCr 4:2:0\n");
1887*193032a3SAndroid Build Coastguard Worker
1888*193032a3SAndroid Build Coastguard Worker x++;
1889*193032a3SAndroid Build Coastguard Worker length--;
1890*193032a3SAndroid Build Coastguard Worker for (unsigned i = 0; i < length / sz; i++) {
1891*193032a3SAndroid Build Coastguard Worker unsigned id = x[i * sz];
1892*193032a3SAndroid Build Coastguard Worker
1893*193032a3SAndroid Build Coastguard Worker if (sz == 2)
1894*193032a3SAndroid Build Coastguard Worker id |= x[i * sz + 1] << 8;
1895*193032a3SAndroid Build Coastguard Worker parse_displayid_type_4_8_timing(type, id, true);
1896*193032a3SAndroid Build Coastguard Worker }
1897*193032a3SAndroid Build Coastguard Worker }
1898*193032a3SAndroid Build Coastguard Worker
cta_displayid_type_10(const unsigned char * x,unsigned length)1899*193032a3SAndroid Build Coastguard Worker void edid_state::cta_displayid_type_10(const unsigned char *x, unsigned length)
1900*193032a3SAndroid Build Coastguard Worker {
1901*193032a3SAndroid Build Coastguard Worker check_displayid_datablock_revision(x[0], 0x70);
1902*193032a3SAndroid Build Coastguard Worker if (length < 7U + ((x[0] & 0x70) >> 4)) {
1903*193032a3SAndroid Build Coastguard Worker fail("Empty Data Block with length %u.\n", length);
1904*193032a3SAndroid Build Coastguard Worker return;
1905*193032a3SAndroid Build Coastguard Worker }
1906*193032a3SAndroid Build Coastguard Worker
1907*193032a3SAndroid Build Coastguard Worker unsigned sz = 6U + ((x[0] & 0x70) >> 4);
1908*193032a3SAndroid Build Coastguard Worker x++;
1909*193032a3SAndroid Build Coastguard Worker length--;
1910*193032a3SAndroid Build Coastguard Worker for (unsigned i = 0; i < length / sz; i++)
1911*193032a3SAndroid Build Coastguard Worker parse_displayid_type_10_timing(x + i * sz, true);
1912*193032a3SAndroid Build Coastguard Worker }
1913*193032a3SAndroid Build Coastguard Worker
cta_hdmi_audio_block(const unsigned char * x,unsigned length)1914*193032a3SAndroid Build Coastguard Worker static void cta_hdmi_audio_block(const unsigned char *x, unsigned length)
1915*193032a3SAndroid Build Coastguard Worker {
1916*193032a3SAndroid Build Coastguard Worker unsigned num_descs;
1917*193032a3SAndroid Build Coastguard Worker
1918*193032a3SAndroid Build Coastguard Worker if (length < 2) {
1919*193032a3SAndroid Build Coastguard Worker fail("Empty Data Block with length %u.\n", length);
1920*193032a3SAndroid Build Coastguard Worker return;
1921*193032a3SAndroid Build Coastguard Worker }
1922*193032a3SAndroid Build Coastguard Worker if (x[0] & 3)
1923*193032a3SAndroid Build Coastguard Worker printf(" Max Stream Count: %u\n", (x[0] & 3) + 1);
1924*193032a3SAndroid Build Coastguard Worker if (x[0] & 4)
1925*193032a3SAndroid Build Coastguard Worker printf(" Supports MS NonMixed\n");
1926*193032a3SAndroid Build Coastguard Worker
1927*193032a3SAndroid Build Coastguard Worker num_descs = x[1] & 7;
1928*193032a3SAndroid Build Coastguard Worker if (num_descs == 0)
1929*193032a3SAndroid Build Coastguard Worker return;
1930*193032a3SAndroid Build Coastguard Worker length -= 2;
1931*193032a3SAndroid Build Coastguard Worker x += 2;
1932*193032a3SAndroid Build Coastguard Worker while (length >= 4) {
1933*193032a3SAndroid Build Coastguard Worker if (length > 4) {
1934*193032a3SAndroid Build Coastguard Worker unsigned format = x[0] & 0xf;
1935*193032a3SAndroid Build Coastguard Worker
1936*193032a3SAndroid Build Coastguard Worker printf(" %s, max channels %u\n", audio_format(format).c_str(),
1937*193032a3SAndroid Build Coastguard Worker (x[1] & 0x1f)+1);
1938*193032a3SAndroid Build Coastguard Worker printf(" Supported sample rates (kHz):%s%s%s%s%s%s%s\n",
1939*193032a3SAndroid Build Coastguard Worker (x[2] & 0x40) ? " 192" : "",
1940*193032a3SAndroid Build Coastguard Worker (x[2] & 0x20) ? " 176.4" : "",
1941*193032a3SAndroid Build Coastguard Worker (x[2] & 0x10) ? " 96" : "",
1942*193032a3SAndroid Build Coastguard Worker (x[2] & 0x08) ? " 88.2" : "",
1943*193032a3SAndroid Build Coastguard Worker (x[2] & 0x04) ? " 48" : "",
1944*193032a3SAndroid Build Coastguard Worker (x[2] & 0x02) ? " 44.1" : "",
1945*193032a3SAndroid Build Coastguard Worker (x[2] & 0x01) ? " 32" : "");
1946*193032a3SAndroid Build Coastguard Worker if (format == 1)
1947*193032a3SAndroid Build Coastguard Worker printf(" Supported sample sizes (bits):%s%s%s\n",
1948*193032a3SAndroid Build Coastguard Worker (x[3] & 0x04) ? " 24" : "",
1949*193032a3SAndroid Build Coastguard Worker (x[3] & 0x02) ? " 20" : "",
1950*193032a3SAndroid Build Coastguard Worker (x[3] & 0x01) ? " 16" : "");
1951*193032a3SAndroid Build Coastguard Worker } else {
1952*193032a3SAndroid Build Coastguard Worker unsigned sad = ((x[2] << 16) | (x[1] << 8) | x[0]);
1953*193032a3SAndroid Build Coastguard Worker unsigned i;
1954*193032a3SAndroid Build Coastguard Worker
1955*193032a3SAndroid Build Coastguard Worker switch (x[3] >> 4) {
1956*193032a3SAndroid Build Coastguard Worker case 1:
1957*193032a3SAndroid Build Coastguard Worker printf(" Speaker Allocation for 10.2 channels:\n");
1958*193032a3SAndroid Build Coastguard Worker break;
1959*193032a3SAndroid Build Coastguard Worker case 2:
1960*193032a3SAndroid Build Coastguard Worker printf(" Speaker Allocation for 22.2 channels:\n");
1961*193032a3SAndroid Build Coastguard Worker break;
1962*193032a3SAndroid Build Coastguard Worker case 3:
1963*193032a3SAndroid Build Coastguard Worker printf(" Speaker Allocation for 30.2 channels:\n");
1964*193032a3SAndroid Build Coastguard Worker break;
1965*193032a3SAndroid Build Coastguard Worker default:
1966*193032a3SAndroid Build Coastguard Worker printf(" Unknown Speaker Allocation (0x%02x)\n", x[3] >> 4);
1967*193032a3SAndroid Build Coastguard Worker return;
1968*193032a3SAndroid Build Coastguard Worker }
1969*193032a3SAndroid Build Coastguard Worker
1970*193032a3SAndroid Build Coastguard Worker for (i = 0; i < ARRAY_SIZE(speaker_map); i++) {
1971*193032a3SAndroid Build Coastguard Worker if ((sad >> i) & 1)
1972*193032a3SAndroid Build Coastguard Worker printf(" %s\n", speaker_map[i]);
1973*193032a3SAndroid Build Coastguard Worker }
1974*193032a3SAndroid Build Coastguard Worker }
1975*193032a3SAndroid Build Coastguard Worker length -= 4;
1976*193032a3SAndroid Build Coastguard Worker x += 4;
1977*193032a3SAndroid Build Coastguard Worker }
1978*193032a3SAndroid Build Coastguard Worker }
1979*193032a3SAndroid Build Coastguard Worker
cta_ext_block(const unsigned char * x,unsigned length,bool duplicate)1980*193032a3SAndroid Build Coastguard Worker void edid_state::cta_ext_block(const unsigned char *x, unsigned length,
1981*193032a3SAndroid Build Coastguard Worker bool duplicate)
1982*193032a3SAndroid Build Coastguard Worker {
1983*193032a3SAndroid Build Coastguard Worker const char *name;
1984*193032a3SAndroid Build Coastguard Worker unsigned oui;
1985*193032a3SAndroid Build Coastguard Worker bool reverse = false;
1986*193032a3SAndroid Build Coastguard Worker bool audio_block = false;
1987*193032a3SAndroid Build Coastguard Worker
1988*193032a3SAndroid Build Coastguard Worker switch (x[0]) {
1989*193032a3SAndroid Build Coastguard Worker case 0x00: data_block = "Video Capability Data Block"; break;
1990*193032a3SAndroid Build Coastguard Worker case 0x01: data_block.clear(); break;
1991*193032a3SAndroid Build Coastguard Worker case 0x02: data_block = "VESA Video Display Device Data Block"; break;
1992*193032a3SAndroid Build Coastguard Worker case 0x03: data_block = "VESA Video Timing Block Extension"; break;
1993*193032a3SAndroid Build Coastguard Worker case 0x04: data_block = "Reserved for HDMI Video Data Block"; break;
1994*193032a3SAndroid Build Coastguard Worker case 0x05: data_block = "Colorimetry Data Block"; break;
1995*193032a3SAndroid Build Coastguard Worker case 0x06: data_block = "HDR Static Metadata Data Block"; break;
1996*193032a3SAndroid Build Coastguard Worker case 0x07: data_block = "HDR Dynamic Metadata Data Block"; break;
1997*193032a3SAndroid Build Coastguard Worker
1998*193032a3SAndroid Build Coastguard Worker case 0x0d: data_block = "Video Format Preference Data Block"; break;
1999*193032a3SAndroid Build Coastguard Worker case 0x0e: data_block = "YCbCr 4:2:0 Video Data Block"; break;
2000*193032a3SAndroid Build Coastguard Worker case 0x0f: data_block = "YCbCr 4:2:0 Capability Map Data Block"; break;
2001*193032a3SAndroid Build Coastguard Worker case 0x10: data_block = "Reserved for CTA-861 Miscellaneous Audio Fields"; break;
2002*193032a3SAndroid Build Coastguard Worker case 0x11: data_block.clear(); audio_block = true; break;
2003*193032a3SAndroid Build Coastguard Worker case 0x12: data_block = "HDMI Audio Data Block"; audio_block = true; break;
2004*193032a3SAndroid Build Coastguard Worker case 0x13: data_block = "Room Configuration Data Block"; audio_block = true; break;
2005*193032a3SAndroid Build Coastguard Worker case 0x14: data_block = "Speaker Location Data Block"; audio_block = true; break;
2006*193032a3SAndroid Build Coastguard Worker
2007*193032a3SAndroid Build Coastguard Worker case 0x20: data_block = "InfoFrame Data Block"; break;
2008*193032a3SAndroid Build Coastguard Worker
2009*193032a3SAndroid Build Coastguard Worker case 0x34: data_block = "DisplayID Type VII Video Timing Data Block"; break;
2010*193032a3SAndroid Build Coastguard Worker case 0x35: data_block = "DisplayID Type VIII Video Timing Data Block"; break;
2011*193032a3SAndroid Build Coastguard Worker case 0x42: data_block = "DisplayID Type X Video Timing Data Block"; break;
2012*193032a3SAndroid Build Coastguard Worker
2013*193032a3SAndroid Build Coastguard Worker case 0x78: data_block = "HDMI Forum EDID Extension Override Data Block"; break;
2014*193032a3SAndroid Build Coastguard Worker case 0x79: data_block = "HDMI Forum Sink Capability Data Block"; break;
2015*193032a3SAndroid Build Coastguard Worker default:
2016*193032a3SAndroid Build Coastguard Worker if (x[0] <= 12)
2017*193032a3SAndroid Build Coastguard Worker printf(" Unknown CTA-861 Video-Related");
2018*193032a3SAndroid Build Coastguard Worker else if (x[0] <= 31)
2019*193032a3SAndroid Build Coastguard Worker printf(" Unknown CTA-861 Audio-Related");
2020*193032a3SAndroid Build Coastguard Worker else if (x[0] >= 120 && x[0] <= 127)
2021*193032a3SAndroid Build Coastguard Worker printf(" Unknown CTA-861 HDMI-Related");
2022*193032a3SAndroid Build Coastguard Worker else
2023*193032a3SAndroid Build Coastguard Worker printf(" Unknown CTA-861");
2024*193032a3SAndroid Build Coastguard Worker printf(" Data Block (extended tag 0x%02x, length %u)\n", x[0], length);
2025*193032a3SAndroid Build Coastguard Worker hex_block(" ", x + 1, length);
2026*193032a3SAndroid Build Coastguard Worker data_block.clear();
2027*193032a3SAndroid Build Coastguard Worker warn("Unknown Extended CTA-861 Data Block 0x%02x.\n", x[0]);
2028*193032a3SAndroid Build Coastguard Worker return;
2029*193032a3SAndroid Build Coastguard Worker }
2030*193032a3SAndroid Build Coastguard Worker
2031*193032a3SAndroid Build Coastguard Worker switch (x[0]) {
2032*193032a3SAndroid Build Coastguard Worker case 0x00:
2033*193032a3SAndroid Build Coastguard Worker case 0x02:
2034*193032a3SAndroid Build Coastguard Worker case 0x05:
2035*193032a3SAndroid Build Coastguard Worker case 0x06:
2036*193032a3SAndroid Build Coastguard Worker case 0x0d:
2037*193032a3SAndroid Build Coastguard Worker case 0x0f:
2038*193032a3SAndroid Build Coastguard Worker case 0x12:
2039*193032a3SAndroid Build Coastguard Worker case 0x13:
2040*193032a3SAndroid Build Coastguard Worker case 0x78:
2041*193032a3SAndroid Build Coastguard Worker case 0x79:
2042*193032a3SAndroid Build Coastguard Worker if (duplicate)
2043*193032a3SAndroid Build Coastguard Worker fail("Only one instance of this Data Block is allowed.\n");
2044*193032a3SAndroid Build Coastguard Worker break;
2045*193032a3SAndroid Build Coastguard Worker }
2046*193032a3SAndroid Build Coastguard Worker
2047*193032a3SAndroid Build Coastguard Worker
2048*193032a3SAndroid Build Coastguard Worker // See Table 52 of CTA-861-G for a description of Byte 3
2049*193032a3SAndroid Build Coastguard Worker if (audio_block && !(cta.byte3 & 0x40))
2050*193032a3SAndroid Build Coastguard Worker fail("audio information is present, but bit 6 of Byte 3 of the CTA-861 Extension header indicates no Basic Audio support.\n");
2051*193032a3SAndroid Build Coastguard Worker
2052*193032a3SAndroid Build Coastguard Worker if (data_block.length())
2053*193032a3SAndroid Build Coastguard Worker printf(" %s:\n", data_block.c_str());
2054*193032a3SAndroid Build Coastguard Worker
2055*193032a3SAndroid Build Coastguard Worker switch (x[0]) {
2056*193032a3SAndroid Build Coastguard Worker case 0x00: cta_vcdb(x + 1, length); return;
2057*193032a3SAndroid Build Coastguard Worker case 0x01:
2058*193032a3SAndroid Build Coastguard Worker if (length < 3) {
2059*193032a3SAndroid Build Coastguard Worker data_block = std::string("Vendor-Specific Video Data Block");
2060*193032a3SAndroid Build Coastguard Worker fail("Invalid length %u < 3.\n", length);
2061*193032a3SAndroid Build Coastguard Worker return;
2062*193032a3SAndroid Build Coastguard Worker }
2063*193032a3SAndroid Build Coastguard Worker oui = (x[3] << 16) + (x[2] << 8) + x[1];
2064*193032a3SAndroid Build Coastguard Worker name = oui_name(oui);
2065*193032a3SAndroid Build Coastguard Worker if (!name) {
2066*193032a3SAndroid Build Coastguard Worker name = oui_name(oui, true);
2067*193032a3SAndroid Build Coastguard Worker if (name)
2068*193032a3SAndroid Build Coastguard Worker reverse = true;
2069*193032a3SAndroid Build Coastguard Worker }
2070*193032a3SAndroid Build Coastguard Worker if (!name) {
2071*193032a3SAndroid Build Coastguard Worker printf(" Vendor-Specific Video Data Block, OUI %s:\n",
2072*193032a3SAndroid Build Coastguard Worker ouitohex(oui).c_str());
2073*193032a3SAndroid Build Coastguard Worker hex_block(" ", x + 4, length - 3);
2074*193032a3SAndroid Build Coastguard Worker data_block.clear();
2075*193032a3SAndroid Build Coastguard Worker warn("Unknown Extended Vendor-Specific Video Data Block, OUI %s.\n",
2076*193032a3SAndroid Build Coastguard Worker ouitohex(oui).c_str());
2077*193032a3SAndroid Build Coastguard Worker return;
2078*193032a3SAndroid Build Coastguard Worker }
2079*193032a3SAndroid Build Coastguard Worker data_block = std::string("Vendor-Specific Video Data Block (") + name + ")";
2080*193032a3SAndroid Build Coastguard Worker if (reverse)
2081*193032a3SAndroid Build Coastguard Worker fail((std::string("OUI ") + ouitohex(oui) + " is in the wrong byte order\n").c_str());
2082*193032a3SAndroid Build Coastguard Worker printf(" %s, OUI %s:\n", data_block.c_str(), ouitohex(oui).c_str());
2083*193032a3SAndroid Build Coastguard Worker if (oui == 0x90848b)
2084*193032a3SAndroid Build Coastguard Worker cta_hdr10plus(x + 4, length - 3);
2085*193032a3SAndroid Build Coastguard Worker else if (oui == 0x00d046)
2086*193032a3SAndroid Build Coastguard Worker cta_dolby_video(x + 4, length - 3);
2087*193032a3SAndroid Build Coastguard Worker else
2088*193032a3SAndroid Build Coastguard Worker hex_block(" ", x + 4, length - 3);
2089*193032a3SAndroid Build Coastguard Worker return;
2090*193032a3SAndroid Build Coastguard Worker case 0x02: cta_vesa_vdddb(x + 1, length); return;
2091*193032a3SAndroid Build Coastguard Worker case 0x05: cta_colorimetry_block(x + 1, length); return;
2092*193032a3SAndroid Build Coastguard Worker case 0x06: cta_hdr_static_metadata_block(x + 1, length); return;
2093*193032a3SAndroid Build Coastguard Worker case 0x07: cta_hdr_dyn_metadata_block(x + 1, length); return;
2094*193032a3SAndroid Build Coastguard Worker case 0x0d: cta_vfpdb(x + 1, length); return;
2095*193032a3SAndroid Build Coastguard Worker case 0x0e: cta_svd(x + 1, length, true); return;
2096*193032a3SAndroid Build Coastguard Worker case 0x0f: cta_y420cmdb(x + 1, length); return;
2097*193032a3SAndroid Build Coastguard Worker case 0x11:
2098*193032a3SAndroid Build Coastguard Worker if (length < 3) {
2099*193032a3SAndroid Build Coastguard Worker data_block = std::string("Vendor-Specific Audio Data Block");
2100*193032a3SAndroid Build Coastguard Worker fail("Invalid length %u < 3.\n", length);
2101*193032a3SAndroid Build Coastguard Worker return;
2102*193032a3SAndroid Build Coastguard Worker }
2103*193032a3SAndroid Build Coastguard Worker oui = (x[3] << 16) + (x[2] << 8) + x[1];
2104*193032a3SAndroid Build Coastguard Worker name = oui_name(oui);
2105*193032a3SAndroid Build Coastguard Worker if (!name) {
2106*193032a3SAndroid Build Coastguard Worker name = oui_name(oui, true);
2107*193032a3SAndroid Build Coastguard Worker if (name)
2108*193032a3SAndroid Build Coastguard Worker reverse = true;
2109*193032a3SAndroid Build Coastguard Worker }
2110*193032a3SAndroid Build Coastguard Worker if (!name) {
2111*193032a3SAndroid Build Coastguard Worker printf(" Vendor-Specific Audio Data Block, OUI %s:\n",
2112*193032a3SAndroid Build Coastguard Worker ouitohex(oui).c_str());
2113*193032a3SAndroid Build Coastguard Worker hex_block(" ", x + 4, length - 3);
2114*193032a3SAndroid Build Coastguard Worker data_block.clear();
2115*193032a3SAndroid Build Coastguard Worker warn("Unknown Extended Vendor-Specific Audio Data Block, OUI %s.\n",
2116*193032a3SAndroid Build Coastguard Worker ouitohex(oui).c_str());
2117*193032a3SAndroid Build Coastguard Worker return;
2118*193032a3SAndroid Build Coastguard Worker }
2119*193032a3SAndroid Build Coastguard Worker data_block = std::string("Vendor-Specific Audio Data Block (") + name + ")";
2120*193032a3SAndroid Build Coastguard Worker if (reverse)
2121*193032a3SAndroid Build Coastguard Worker fail((std::string("OUI ") + ouitohex(oui) + " is in the wrong byte order\n").c_str());
2122*193032a3SAndroid Build Coastguard Worker printf(" %s, OUI %s:\n", data_block.c_str(), ouitohex(oui).c_str());
2123*193032a3SAndroid Build Coastguard Worker if (oui == 0x00d046)
2124*193032a3SAndroid Build Coastguard Worker cta_dolby_audio(x + 4, length - 3);
2125*193032a3SAndroid Build Coastguard Worker else
2126*193032a3SAndroid Build Coastguard Worker hex_block(" ", x + 4, length - 3);
2127*193032a3SAndroid Build Coastguard Worker return;
2128*193032a3SAndroid Build Coastguard Worker case 0x12: cta_hdmi_audio_block(x + 1, length); return;
2129*193032a3SAndroid Build Coastguard Worker case 0x13: cta_rcdb(x + 1, length); return;
2130*193032a3SAndroid Build Coastguard Worker case 0x14: cta_sldb(x + 1, length); return;
2131*193032a3SAndroid Build Coastguard Worker case 0x20: cta_ifdb(x + 1, length); return;
2132*193032a3SAndroid Build Coastguard Worker case 0x34: cta_displayid_type_7(x + 1, length); return;
2133*193032a3SAndroid Build Coastguard Worker case 0x35: cta_displayid_type_8(x + 1, length); return;
2134*193032a3SAndroid Build Coastguard Worker case 0x42: cta_displayid_type_10(x + 1, length); return;
2135*193032a3SAndroid Build Coastguard Worker case 0x78:
2136*193032a3SAndroid Build Coastguard Worker cta_hf_eeodb(x + 1, length);
2137*193032a3SAndroid Build Coastguard Worker // This must be the first CTA-861 block
2138*193032a3SAndroid Build Coastguard Worker if (!cta.first_block)
2139*193032a3SAndroid Build Coastguard Worker fail("Block starts at a wrong offset.\n");
2140*193032a3SAndroid Build Coastguard Worker return;
2141*193032a3SAndroid Build Coastguard Worker case 0x79:
2142*193032a3SAndroid Build Coastguard Worker if (!cta.last_block_was_hdmi_vsdb)
2143*193032a3SAndroid Build Coastguard Worker fail("HDMI Forum SCDB did not immediately follow the HDMI VSDB.\n");
2144*193032a3SAndroid Build Coastguard Worker if (cta.have_hf_scdb || cta.have_hf_vsdb)
2145*193032a3SAndroid Build Coastguard Worker fail("Duplicate HDMI Forum VSDB/SCDB.\n");
2146*193032a3SAndroid Build Coastguard Worker if (length < 2) {
2147*193032a3SAndroid Build Coastguard Worker data_block = std::string("HDMI Forum SCDB");
2148*193032a3SAndroid Build Coastguard Worker fail("Invalid length %u < 2.\n", length);
2149*193032a3SAndroid Build Coastguard Worker return;
2150*193032a3SAndroid Build Coastguard Worker }
2151*193032a3SAndroid Build Coastguard Worker if (x[1] || x[2])
2152*193032a3SAndroid Build Coastguard Worker printf(" Non-zero SCDB reserved fields!\n");
2153*193032a3SAndroid Build Coastguard Worker cta_hf_scdb(x + 3, length - 2);
2154*193032a3SAndroid Build Coastguard Worker cta.have_hf_scdb = 1;
2155*193032a3SAndroid Build Coastguard Worker return;
2156*193032a3SAndroid Build Coastguard Worker }
2157*193032a3SAndroid Build Coastguard Worker
2158*193032a3SAndroid Build Coastguard Worker hex_block(" ", x + 1, length);
2159*193032a3SAndroid Build Coastguard Worker }
2160*193032a3SAndroid Build Coastguard Worker
cta_block(const unsigned char * x,bool duplicate)2161*193032a3SAndroid Build Coastguard Worker void edid_state::cta_block(const unsigned char *x, bool duplicate)
2162*193032a3SAndroid Build Coastguard Worker {
2163*193032a3SAndroid Build Coastguard Worker unsigned length = x[0] & 0x1f;
2164*193032a3SAndroid Build Coastguard Worker const char *name;
2165*193032a3SAndroid Build Coastguard Worker unsigned oui;
2166*193032a3SAndroid Build Coastguard Worker bool reverse = false;
2167*193032a3SAndroid Build Coastguard Worker bool audio_block = false;
2168*193032a3SAndroid Build Coastguard Worker
2169*193032a3SAndroid Build Coastguard Worker switch ((x[0] & 0xe0) >> 5) {
2170*193032a3SAndroid Build Coastguard Worker case 0x01:
2171*193032a3SAndroid Build Coastguard Worker data_block = "Audio Data Block";
2172*193032a3SAndroid Build Coastguard Worker printf(" %s:\n", data_block.c_str());
2173*193032a3SAndroid Build Coastguard Worker cta_audio_block(x + 1, length);
2174*193032a3SAndroid Build Coastguard Worker audio_block = true;
2175*193032a3SAndroid Build Coastguard Worker break;
2176*193032a3SAndroid Build Coastguard Worker case 0x02:
2177*193032a3SAndroid Build Coastguard Worker data_block = "Video Data Block";
2178*193032a3SAndroid Build Coastguard Worker printf(" %s:\n", data_block.c_str());
2179*193032a3SAndroid Build Coastguard Worker cta_svd(x + 1, length, false);
2180*193032a3SAndroid Build Coastguard Worker break;
2181*193032a3SAndroid Build Coastguard Worker case 0x03:
2182*193032a3SAndroid Build Coastguard Worker oui = (x[3] << 16) + (x[2] << 8) + x[1];
2183*193032a3SAndroid Build Coastguard Worker name = oui_name(oui);
2184*193032a3SAndroid Build Coastguard Worker if (!name) {
2185*193032a3SAndroid Build Coastguard Worker name = oui_name(oui, true);
2186*193032a3SAndroid Build Coastguard Worker if (name)
2187*193032a3SAndroid Build Coastguard Worker reverse = true;
2188*193032a3SAndroid Build Coastguard Worker }
2189*193032a3SAndroid Build Coastguard Worker if (!name) {
2190*193032a3SAndroid Build Coastguard Worker printf(" Vendor-Specific Data Block, OUI %s:\n", ouitohex(oui).c_str());
2191*193032a3SAndroid Build Coastguard Worker hex_block(" ", x + 4, length - 3);
2192*193032a3SAndroid Build Coastguard Worker data_block.clear();
2193*193032a3SAndroid Build Coastguard Worker warn("Unknown Vendor-Specific Data Block, OUI %s.\n",
2194*193032a3SAndroid Build Coastguard Worker ouitohex(oui).c_str());
2195*193032a3SAndroid Build Coastguard Worker return;
2196*193032a3SAndroid Build Coastguard Worker }
2197*193032a3SAndroid Build Coastguard Worker data_block = std::string("Vendor-Specific Data Block (") + name + ")";
2198*193032a3SAndroid Build Coastguard Worker if (reverse)
2199*193032a3SAndroid Build Coastguard Worker fail((std::string("OUI ") + ouitohex(oui) + " is in the wrong byte order\n").c_str());
2200*193032a3SAndroid Build Coastguard Worker printf(" %s, OUI %s:\n", data_block.c_str(), ouitohex(oui).c_str());
2201*193032a3SAndroid Build Coastguard Worker if (oui == 0x000c03) {
2202*193032a3SAndroid Build Coastguard Worker cta_hdmi_block(x + 1, length);
2203*193032a3SAndroid Build Coastguard Worker cta.last_block_was_hdmi_vsdb = 1;
2204*193032a3SAndroid Build Coastguard Worker cta.first_block = 0;
2205*193032a3SAndroid Build Coastguard Worker // The HDMI OUI is present, so this EDID represents an HDMI
2206*193032a3SAndroid Build Coastguard Worker // interface. And HDMI interfaces must use EDID version 1.3
2207*193032a3SAndroid Build Coastguard Worker // according to the HDMI Specification, so check for this.
2208*193032a3SAndroid Build Coastguard Worker if (base.edid_minor != 3)
2209*193032a3SAndroid Build Coastguard Worker fail("The HDMI Specification requires EDID 1.3 instead of 1.%u.\n",
2210*193032a3SAndroid Build Coastguard Worker base.edid_minor);
2211*193032a3SAndroid Build Coastguard Worker return;
2212*193032a3SAndroid Build Coastguard Worker }
2213*193032a3SAndroid Build Coastguard Worker if (oui == 0xc45dd8) {
2214*193032a3SAndroid Build Coastguard Worker if (!cta.last_block_was_hdmi_vsdb)
2215*193032a3SAndroid Build Coastguard Worker fail("HDMI Forum VSDB did not immediately follow the HDMI VSDB.\n");
2216*193032a3SAndroid Build Coastguard Worker if (cta.have_hf_scdb || cta.have_hf_vsdb)
2217*193032a3SAndroid Build Coastguard Worker fail("Duplicate HDMI Forum VSDB/SCDB.\n");
2218*193032a3SAndroid Build Coastguard Worker cta_hf_scdb(x + 4, length - 3);
2219*193032a3SAndroid Build Coastguard Worker cta.have_hf_vsdb = 1;
2220*193032a3SAndroid Build Coastguard Worker break;
2221*193032a3SAndroid Build Coastguard Worker }
2222*193032a3SAndroid Build Coastguard Worker if (oui == 0x00001a) {
2223*193032a3SAndroid Build Coastguard Worker cta_amd(x + 4, length - 3);
2224*193032a3SAndroid Build Coastguard Worker break;
2225*193032a3SAndroid Build Coastguard Worker }
2226*193032a3SAndroid Build Coastguard Worker if (oui == 0xca125c && length == 0x15) {
2227*193032a3SAndroid Build Coastguard Worker cta_microsoft(x + 4, length - 3);
2228*193032a3SAndroid Build Coastguard Worker break;
2229*193032a3SAndroid Build Coastguard Worker }
2230*193032a3SAndroid Build Coastguard Worker hex_block(" ", x + 4, length - 3);
2231*193032a3SAndroid Build Coastguard Worker break;
2232*193032a3SAndroid Build Coastguard Worker case 0x04:
2233*193032a3SAndroid Build Coastguard Worker data_block = "Speaker Allocation Data Block";
2234*193032a3SAndroid Build Coastguard Worker printf(" %s:\n", data_block.c_str());
2235*193032a3SAndroid Build Coastguard Worker cta_sadb(x + 1, length);
2236*193032a3SAndroid Build Coastguard Worker audio_block = true;
2237*193032a3SAndroid Build Coastguard Worker if (duplicate)
2238*193032a3SAndroid Build Coastguard Worker fail("Only one instance of this Data Block is allowed.\n");
2239*193032a3SAndroid Build Coastguard Worker break;
2240*193032a3SAndroid Build Coastguard Worker case 0x05:
2241*193032a3SAndroid Build Coastguard Worker data_block = "VESA Display Transfer Characteristics Data Block";
2242*193032a3SAndroid Build Coastguard Worker printf(" %s:\n", data_block.c_str());
2243*193032a3SAndroid Build Coastguard Worker cta_vesa_dtcdb(x + 1, length);
2244*193032a3SAndroid Build Coastguard Worker if (duplicate)
2245*193032a3SAndroid Build Coastguard Worker fail("Only one instance of this Data Block is allowed.\n");
2246*193032a3SAndroid Build Coastguard Worker break;
2247*193032a3SAndroid Build Coastguard Worker case 0x07:
2248*193032a3SAndroid Build Coastguard Worker cta_ext_block(x + 1, length - 1, duplicate);
2249*193032a3SAndroid Build Coastguard Worker break;
2250*193032a3SAndroid Build Coastguard Worker default: {
2251*193032a3SAndroid Build Coastguard Worker unsigned tag = (*x & 0xe0) >> 5;
2252*193032a3SAndroid Build Coastguard Worker unsigned length = *x & 0x1f;
2253*193032a3SAndroid Build Coastguard Worker
2254*193032a3SAndroid Build Coastguard Worker printf(" Unknown CTA-861 tag 0x%02x, length %u\n", tag, length);
2255*193032a3SAndroid Build Coastguard Worker hex_block(" ", x + 1, length);
2256*193032a3SAndroid Build Coastguard Worker data_block.clear();
2257*193032a3SAndroid Build Coastguard Worker warn("Unknown CTA-861 Data Block %u.\n", tag);
2258*193032a3SAndroid Build Coastguard Worker break;
2259*193032a3SAndroid Build Coastguard Worker }
2260*193032a3SAndroid Build Coastguard Worker }
2261*193032a3SAndroid Build Coastguard Worker
2262*193032a3SAndroid Build Coastguard Worker // See Table 52 of CTA-861-G for a description of Byte 3
2263*193032a3SAndroid Build Coastguard Worker if (audio_block && !(cta.byte3 & 0x40))
2264*193032a3SAndroid Build Coastguard Worker fail("audio information is present, but bit 6 of Byte 3 of the CTA-861 Extension header indicates no Basic Audio support.\n");
2265*193032a3SAndroid Build Coastguard Worker cta.first_block = 0;
2266*193032a3SAndroid Build Coastguard Worker cta.last_block_was_hdmi_vsdb = 0;
2267*193032a3SAndroid Build Coastguard Worker }
2268*193032a3SAndroid Build Coastguard Worker
preparse_cta_block(const unsigned char * x)2269*193032a3SAndroid Build Coastguard Worker void edid_state::preparse_cta_block(const unsigned char *x)
2270*193032a3SAndroid Build Coastguard Worker {
2271*193032a3SAndroid Build Coastguard Worker unsigned version = x[1];
2272*193032a3SAndroid Build Coastguard Worker unsigned offset = x[2];
2273*193032a3SAndroid Build Coastguard Worker
2274*193032a3SAndroid Build Coastguard Worker if (offset >= 4) {
2275*193032a3SAndroid Build Coastguard Worker const unsigned char *detailed;
2276*193032a3SAndroid Build Coastguard Worker
2277*193032a3SAndroid Build Coastguard Worker for (detailed = x + offset; detailed + 17 < x + 127; detailed += 18) {
2278*193032a3SAndroid Build Coastguard Worker if (memchk(detailed, 18))
2279*193032a3SAndroid Build Coastguard Worker break;
2280*193032a3SAndroid Build Coastguard Worker if (detailed[0] || detailed[1])
2281*193032a3SAndroid Build Coastguard Worker cta.preparsed_total_dtds++;
2282*193032a3SAndroid Build Coastguard Worker }
2283*193032a3SAndroid Build Coastguard Worker }
2284*193032a3SAndroid Build Coastguard Worker
2285*193032a3SAndroid Build Coastguard Worker if (version < 3)
2286*193032a3SAndroid Build Coastguard Worker return;
2287*193032a3SAndroid Build Coastguard Worker
2288*193032a3SAndroid Build Coastguard Worker for (unsigned i = 4; i < offset; i += (x[i] & 0x1f) + 1) {
2289*193032a3SAndroid Build Coastguard Worker bool for_ycbcr420 = false;
2290*193032a3SAndroid Build Coastguard Worker unsigned oui;
2291*193032a3SAndroid Build Coastguard Worker
2292*193032a3SAndroid Build Coastguard Worker switch ((x[i] & 0xe0) >> 5) {
2293*193032a3SAndroid Build Coastguard Worker case 0x03:
2294*193032a3SAndroid Build Coastguard Worker oui = (x[i + 3] << 16) + (x[i + 2] << 8) + x[i + 1];
2295*193032a3SAndroid Build Coastguard Worker if (oui == 0x000c03) {
2296*193032a3SAndroid Build Coastguard Worker cta.has_hdmi = true;
2297*193032a3SAndroid Build Coastguard Worker cta.preparsed_phys_addr = (x[i + 4] << 8) | x[i + 5];
2298*193032a3SAndroid Build Coastguard Worker }
2299*193032a3SAndroid Build Coastguard Worker break;
2300*193032a3SAndroid Build Coastguard Worker case 0x07:
2301*193032a3SAndroid Build Coastguard Worker if (x[i + 1] == 0x0d)
2302*193032a3SAndroid Build Coastguard Worker cta.has_vfpdb = true;
2303*193032a3SAndroid Build Coastguard Worker if (x[i + 1] == 0x13 && (x[i + 2] & 0x40)) {
2304*193032a3SAndroid Build Coastguard Worker cta.preparsed_speaker_count = 1 + (x[i + 2] & 0x1f);
2305*193032a3SAndroid Build Coastguard Worker cta.preparsed_sld = x[i + 2] & 0x20;
2306*193032a3SAndroid Build Coastguard Worker }
2307*193032a3SAndroid Build Coastguard Worker if (x[i + 1] == 0x14)
2308*193032a3SAndroid Build Coastguard Worker cta_preparse_sldb(x + i + 2, (x[i] & 0x1f) - 1);
2309*193032a3SAndroid Build Coastguard Worker if (x[i + 1] == 0x22)
2310*193032a3SAndroid Build Coastguard Worker cta.preparsed_total_vtdbs++;
2311*193032a3SAndroid Build Coastguard Worker if (x[i + 1] == 0x23)
2312*193032a3SAndroid Build Coastguard Worker cta.preparsed_has_t8vtdb = true;
2313*193032a3SAndroid Build Coastguard Worker if (x[i + 1] == 0x32)
2314*193032a3SAndroid Build Coastguard Worker cta.preparsed_total_vtdbs +=
2315*193032a3SAndroid Build Coastguard Worker ((x[i] & 0x1f) - 2) / (6 + ((x[i + 2] & 0x70) >> 4));
2316*193032a3SAndroid Build Coastguard Worker if (x[i + 1] != 0x0e)
2317*193032a3SAndroid Build Coastguard Worker continue;
2318*193032a3SAndroid Build Coastguard Worker for_ycbcr420 = true;
2319*193032a3SAndroid Build Coastguard Worker /* fall-through */
2320*193032a3SAndroid Build Coastguard Worker case 0x02:
2321*193032a3SAndroid Build Coastguard Worker for (unsigned j = 1 + for_ycbcr420; j <= (x[i] & 0x1f); j++) {
2322*193032a3SAndroid Build Coastguard Worker unsigned char vic = x[i + j];
2323*193032a3SAndroid Build Coastguard Worker
2324*193032a3SAndroid Build Coastguard Worker if ((vic & 0x7f) <= 64)
2325*193032a3SAndroid Build Coastguard Worker vic &= 0x7f;
2326*193032a3SAndroid Build Coastguard Worker cta.preparsed_svds[for_ycbcr420].push_back(vic);
2327*193032a3SAndroid Build Coastguard Worker cta.preparsed_has_vic[for_ycbcr420][vic] = true;
2328*193032a3SAndroid Build Coastguard Worker }
2329*193032a3SAndroid Build Coastguard Worker break;
2330*193032a3SAndroid Build Coastguard Worker }
2331*193032a3SAndroid Build Coastguard Worker }
2332*193032a3SAndroid Build Coastguard Worker }
2333*193032a3SAndroid Build Coastguard Worker
parse_cta_block(const unsigned char * x)2334*193032a3SAndroid Build Coastguard Worker void edid_state::parse_cta_block(const unsigned char *x)
2335*193032a3SAndroid Build Coastguard Worker {
2336*193032a3SAndroid Build Coastguard Worker unsigned version = x[1];
2337*193032a3SAndroid Build Coastguard Worker unsigned offset = x[2];
2338*193032a3SAndroid Build Coastguard Worker const unsigned char *detailed;
2339*193032a3SAndroid Build Coastguard Worker
2340*193032a3SAndroid Build Coastguard Worker // See Table 52 of CTA-861-G for a description of Byte 3
2341*193032a3SAndroid Build Coastguard Worker
2342*193032a3SAndroid Build Coastguard Worker printf(" Revision: %u\n", version);
2343*193032a3SAndroid Build Coastguard Worker if (version == 0)
2344*193032a3SAndroid Build Coastguard Worker fail("Invalid CTA-861 Extension revision 0.\n");
2345*193032a3SAndroid Build Coastguard Worker if (version == 2)
2346*193032a3SAndroid Build Coastguard Worker fail("Deprecated CTA-861 Extension revision 2.\n");
2347*193032a3SAndroid Build Coastguard Worker if (cta.has_hdmi && version != 3)
2348*193032a3SAndroid Build Coastguard Worker fail("The HDMI Specification requires CTA Extension revision 3.\n");
2349*193032a3SAndroid Build Coastguard Worker if (version > 3)
2350*193032a3SAndroid Build Coastguard Worker warn("Unknown CTA-861 Extension revision %u.\n", version);
2351*193032a3SAndroid Build Coastguard Worker
2352*193032a3SAndroid Build Coastguard Worker if (version >= 1) do {
2353*193032a3SAndroid Build Coastguard Worker if (version == 1 && x[3] != 0)
2354*193032a3SAndroid Build Coastguard Worker fail("Non-zero byte 3.\n");
2355*193032a3SAndroid Build Coastguard Worker
2356*193032a3SAndroid Build Coastguard Worker if (offset < 4)
2357*193032a3SAndroid Build Coastguard Worker break;
2358*193032a3SAndroid Build Coastguard Worker
2359*193032a3SAndroid Build Coastguard Worker if (version < 3 && ((offset - 4) / 8)) {
2360*193032a3SAndroid Build Coastguard Worker printf(" 8-byte timing descriptors: %u\n", (offset - 4) / 8);
2361*193032a3SAndroid Build Coastguard Worker fail("8-byte descriptors were never used.\n");
2362*193032a3SAndroid Build Coastguard Worker }
2363*193032a3SAndroid Build Coastguard Worker
2364*193032a3SAndroid Build Coastguard Worker if (version >= 2) {
2365*193032a3SAndroid Build Coastguard Worker if (x[3] & 0x80)
2366*193032a3SAndroid Build Coastguard Worker printf(" Underscans IT Video Formats by default\n");
2367*193032a3SAndroid Build Coastguard Worker else
2368*193032a3SAndroid Build Coastguard Worker warn("IT Video Formats are overscanned by default, but normally this should be underscanned.\n");
2369*193032a3SAndroid Build Coastguard Worker if (x[3] & 0x40)
2370*193032a3SAndroid Build Coastguard Worker printf(" Basic audio support\n");
2371*193032a3SAndroid Build Coastguard Worker if (x[3] & 0x20)
2372*193032a3SAndroid Build Coastguard Worker printf(" Supports YCbCr 4:4:4\n");
2373*193032a3SAndroid Build Coastguard Worker if (x[3] & 0x10)
2374*193032a3SAndroid Build Coastguard Worker printf(" Supports YCbCr 4:2:2\n");
2375*193032a3SAndroid Build Coastguard Worker // Disable this test: this fails a lot of EDIDs, and there are
2376*193032a3SAndroid Build Coastguard Worker // also some corner cases where you only want to receive 4:4:4
2377*193032a3SAndroid Build Coastguard Worker // and refuse a fallback to 4:2:2.
2378*193032a3SAndroid Build Coastguard Worker // if ((x[3] & 0x30) && (x[3] & 0x30) != 0x30)
2379*193032a3SAndroid Build Coastguard Worker // msg(!cta.has_hdmi, "If YCbCr support is indicated, then both 4:2:2 and 4:4:4 %s be supported.\n",
2380*193032a3SAndroid Build Coastguard Worker // cta.has_hdmi ? "shall" : "should");
2381*193032a3SAndroid Build Coastguard Worker printf(" Native detailed modes: %u\n", x[3] & 0x0f);
2382*193032a3SAndroid Build Coastguard Worker if (cta.first_block)
2383*193032a3SAndroid Build Coastguard Worker cta.byte3 = x[3];
2384*193032a3SAndroid Build Coastguard Worker else if (x[3] != cta.byte3)
2385*193032a3SAndroid Build Coastguard Worker fail("Byte 3 must be the same for all CTA-861 Extension Blocks.\n");
2386*193032a3SAndroid Build Coastguard Worker if (cta.first_block) {
2387*193032a3SAndroid Build Coastguard Worker unsigned native_dtds = x[3] & 0x0f;
2388*193032a3SAndroid Build Coastguard Worker
2389*193032a3SAndroid Build Coastguard Worker cta.native_timings.clear();
2390*193032a3SAndroid Build Coastguard Worker if (!native_dtds && !cta.has_vfpdb) {
2391*193032a3SAndroid Build Coastguard Worker cta.first_svd_might_be_preferred = true;
2392*193032a3SAndroid Build Coastguard Worker } else if (native_dtds > cta.preparsed_total_dtds) {
2393*193032a3SAndroid Build Coastguard Worker fail("There are more Native DTDs (%u) than DTDs (%u).\n",
2394*193032a3SAndroid Build Coastguard Worker native_dtds, cta.preparsed_total_dtds);
2395*193032a3SAndroid Build Coastguard Worker }
2396*193032a3SAndroid Build Coastguard Worker if (native_dtds > cta.preparsed_total_dtds)
2397*193032a3SAndroid Build Coastguard Worker native_dtds = cta.preparsed_total_dtds;
2398*193032a3SAndroid Build Coastguard Worker for (unsigned i = 0; i < native_dtds; i++) {
2399*193032a3SAndroid Build Coastguard Worker char type[16];
2400*193032a3SAndroid Build Coastguard Worker
2401*193032a3SAndroid Build Coastguard Worker sprintf(type, "DTD %3u", i + 1);
2402*193032a3SAndroid Build Coastguard Worker cta.native_timings.push_back(timings_ext(i + 129, type));
2403*193032a3SAndroid Build Coastguard Worker }
2404*193032a3SAndroid Build Coastguard Worker if (cta.has_hdmi && block_nr != (block_map.saw_block_1 ? 2 : 1))
2405*193032a3SAndroid Build Coastguard Worker fail("The HDMI Specification requires that the first Extension Block (that is not a Block Map) is an CTA-861 Extension Block.\n");
2406*193032a3SAndroid Build Coastguard Worker }
2407*193032a3SAndroid Build Coastguard Worker }
2408*193032a3SAndroid Build Coastguard Worker if (version >= 3) {
2409*193032a3SAndroid Build Coastguard Worker unsigned i;
2410*193032a3SAndroid Build Coastguard Worker
2411*193032a3SAndroid Build Coastguard Worker for (i = 4; i < offset; i += (x[i] & 0x1f) + 1) {
2412*193032a3SAndroid Build Coastguard Worker unsigned tag = (x[i] & 0xe0) << 3;
2413*193032a3SAndroid Build Coastguard Worker
2414*193032a3SAndroid Build Coastguard Worker if (tag == 0x700)
2415*193032a3SAndroid Build Coastguard Worker tag |= x[i + 1];
2416*193032a3SAndroid Build Coastguard Worker bool duplicate = cta.found_tags.find(tag) != cta.found_tags.end();
2417*193032a3SAndroid Build Coastguard Worker
2418*193032a3SAndroid Build Coastguard Worker cta_block(x + i, duplicate);
2419*193032a3SAndroid Build Coastguard Worker if (!duplicate)
2420*193032a3SAndroid Build Coastguard Worker cta.found_tags.insert(tag);
2421*193032a3SAndroid Build Coastguard Worker }
2422*193032a3SAndroid Build Coastguard Worker
2423*193032a3SAndroid Build Coastguard Worker data_block.clear();
2424*193032a3SAndroid Build Coastguard Worker if (i != offset)
2425*193032a3SAndroid Build Coastguard Worker fail("Offset is %u, but should be %u.\n", offset, i);
2426*193032a3SAndroid Build Coastguard Worker }
2427*193032a3SAndroid Build Coastguard Worker
2428*193032a3SAndroid Build Coastguard Worker data_block = "Detailed Timing Descriptors";
2429*193032a3SAndroid Build Coastguard Worker base.seen_non_detailed_descriptor = false;
2430*193032a3SAndroid Build Coastguard Worker bool first = true;
2431*193032a3SAndroid Build Coastguard Worker for (detailed = x + offset; detailed + 17 < x + 127; detailed += 18) {
2432*193032a3SAndroid Build Coastguard Worker if (memchk(detailed, 18))
2433*193032a3SAndroid Build Coastguard Worker break;
2434*193032a3SAndroid Build Coastguard Worker if (first) {
2435*193032a3SAndroid Build Coastguard Worker first = false;
2436*193032a3SAndroid Build Coastguard Worker printf(" %s:\n", data_block.c_str());
2437*193032a3SAndroid Build Coastguard Worker }
2438*193032a3SAndroid Build Coastguard Worker detailed_block(detailed);
2439*193032a3SAndroid Build Coastguard Worker }
2440*193032a3SAndroid Build Coastguard Worker if (!memchk(detailed, x + 127 - detailed)) {
2441*193032a3SAndroid Build Coastguard Worker data_block = "Padding";
2442*193032a3SAndroid Build Coastguard Worker fail("CTA-861 padding contains non-zero bytes.\n");
2443*193032a3SAndroid Build Coastguard Worker }
2444*193032a3SAndroid Build Coastguard Worker } while (0);
2445*193032a3SAndroid Build Coastguard Worker
2446*193032a3SAndroid Build Coastguard Worker data_block.clear();
2447*193032a3SAndroid Build Coastguard Worker if (base.has_serial_number && base.has_serial_string)
2448*193032a3SAndroid Build Coastguard Worker warn("Display Product Serial Number is set, so the Serial Number in the Base EDID should be 0.\n");
2449*193032a3SAndroid Build Coastguard Worker if (!cta.has_vic_1 && !base.has_640x480p60_est_timing)
2450*193032a3SAndroid Build Coastguard Worker fail("Required 640x480p60 timings are missing in the established timings"
2451*193032a3SAndroid Build Coastguard Worker " and the SVD list (VIC 1).\n");
2452*193032a3SAndroid Build Coastguard Worker if ((cta.supported_hdmi_vic_vsb_codes & cta.supported_hdmi_vic_codes) !=
2453*193032a3SAndroid Build Coastguard Worker cta.supported_hdmi_vic_codes)
2454*193032a3SAndroid Build Coastguard Worker fail("HDMI VIC Codes must have their CTA-861 VIC equivalents in the VSB.\n");
2455*193032a3SAndroid Build Coastguard Worker if (!cta.has_vcdb)
2456*193032a3SAndroid Build Coastguard Worker fail("Missing VCDB, needed for Set Selectable RGB Quantization to avoid interop issues.\n");
2457*193032a3SAndroid Build Coastguard Worker }
2458*193032a3SAndroid Build Coastguard Worker
cta_resolve_svr(vec_timings_ext::iterator iter)2459*193032a3SAndroid Build Coastguard Worker void edid_state::cta_resolve_svr(vec_timings_ext::iterator iter)
2460*193032a3SAndroid Build Coastguard Worker {
2461*193032a3SAndroid Build Coastguard Worker if (iter->svr() == 254) {
2462*193032a3SAndroid Build Coastguard Worker iter->flags = cta.t8vtdb.flags;
2463*193032a3SAndroid Build Coastguard Worker iter->t = cta.t8vtdb.t;
2464*193032a3SAndroid Build Coastguard Worker } else if (iter->svr() <= 144) {
2465*193032a3SAndroid Build Coastguard Worker iter->flags = cta.vec_dtds[iter->svr() - 129].flags;
2466*193032a3SAndroid Build Coastguard Worker iter->t = cta.vec_dtds[iter->svr() - 129].t;
2467*193032a3SAndroid Build Coastguard Worker } else {
2468*193032a3SAndroid Build Coastguard Worker iter->flags = cta.vec_vtdbs[iter->svr() - 145].flags;
2469*193032a3SAndroid Build Coastguard Worker iter->t = cta.vec_vtdbs[iter->svr() - 145].t;
2470*193032a3SAndroid Build Coastguard Worker }
2471*193032a3SAndroid Build Coastguard Worker }
2472*193032a3SAndroid Build Coastguard Worker
cta_resolve_svrs()2473*193032a3SAndroid Build Coastguard Worker void edid_state::cta_resolve_svrs()
2474*193032a3SAndroid Build Coastguard Worker {
2475*193032a3SAndroid Build Coastguard Worker for (vec_timings_ext::iterator iter = cta.preferred_timings.begin();
2476*193032a3SAndroid Build Coastguard Worker iter != cta.preferred_timings.end(); ++iter) {
2477*193032a3SAndroid Build Coastguard Worker if (iter->has_svr())
2478*193032a3SAndroid Build Coastguard Worker cta_resolve_svr(iter);
2479*193032a3SAndroid Build Coastguard Worker }
2480*193032a3SAndroid Build Coastguard Worker
2481*193032a3SAndroid Build Coastguard Worker for (vec_timings_ext::iterator iter = cta.native_timings.begin();
2482*193032a3SAndroid Build Coastguard Worker iter != cta.native_timings.end(); ++iter) {
2483*193032a3SAndroid Build Coastguard Worker if (iter->has_svr())
2484*193032a3SAndroid Build Coastguard Worker cta_resolve_svr(iter);
2485*193032a3SAndroid Build Coastguard Worker }
2486*193032a3SAndroid Build Coastguard Worker }
2487*193032a3SAndroid Build Coastguard Worker
check_cta_blocks()2488*193032a3SAndroid Build Coastguard Worker void edid_state::check_cta_blocks()
2489*193032a3SAndroid Build Coastguard Worker {
2490*193032a3SAndroid Build Coastguard Worker unsigned max_pref_prog_hact = 0;
2491*193032a3SAndroid Build Coastguard Worker unsigned max_pref_prog_vact = 0;
2492*193032a3SAndroid Build Coastguard Worker unsigned max_pref_ilace_hact = 0;
2493*193032a3SAndroid Build Coastguard Worker unsigned max_pref_ilace_vact = 0;
2494*193032a3SAndroid Build Coastguard Worker
2495*193032a3SAndroid Build Coastguard Worker data_block = "CTA-861";
2496*193032a3SAndroid Build Coastguard Worker for (vec_timings_ext::iterator iter = cta.preferred_timings.begin();
2497*193032a3SAndroid Build Coastguard Worker iter != cta.preferred_timings.end(); ++iter) {
2498*193032a3SAndroid Build Coastguard Worker if (iter->t.interlaced &&
2499*193032a3SAndroid Build Coastguard Worker (iter->t.vact > max_pref_ilace_vact ||
2500*193032a3SAndroid Build Coastguard Worker (iter->t.vact == max_pref_ilace_vact && iter->t.hact >= max_pref_ilace_hact))) {
2501*193032a3SAndroid Build Coastguard Worker max_pref_ilace_hact = iter->t.hact;
2502*193032a3SAndroid Build Coastguard Worker max_pref_ilace_vact = iter->t.vact;
2503*193032a3SAndroid Build Coastguard Worker }
2504*193032a3SAndroid Build Coastguard Worker if (!iter->t.interlaced &&
2505*193032a3SAndroid Build Coastguard Worker (iter->t.vact > max_pref_prog_vact ||
2506*193032a3SAndroid Build Coastguard Worker (iter->t.vact == max_pref_prog_vact && iter->t.hact >= max_pref_prog_hact))) {
2507*193032a3SAndroid Build Coastguard Worker max_pref_prog_hact = iter->t.hact;
2508*193032a3SAndroid Build Coastguard Worker max_pref_prog_vact = iter->t.vact;
2509*193032a3SAndroid Build Coastguard Worker }
2510*193032a3SAndroid Build Coastguard Worker }
2511*193032a3SAndroid Build Coastguard Worker
2512*193032a3SAndroid Build Coastguard Worker unsigned native_prog = 0;
2513*193032a3SAndroid Build Coastguard Worker unsigned native_prog_hact = 0;
2514*193032a3SAndroid Build Coastguard Worker unsigned native_prog_vact = 0;
2515*193032a3SAndroid Build Coastguard Worker bool native_prog_mixed_resolutions = false;
2516*193032a3SAndroid Build Coastguard Worker unsigned native_ilace = 0;
2517*193032a3SAndroid Build Coastguard Worker unsigned native_ilace_hact = 0;
2518*193032a3SAndroid Build Coastguard Worker unsigned native_ilace_vact = 0;
2519*193032a3SAndroid Build Coastguard Worker bool native_ilace_mixed_resolutions = false;
2520*193032a3SAndroid Build Coastguard Worker
2521*193032a3SAndroid Build Coastguard Worker for (vec_timings_ext::iterator iter = cta.native_timings.begin();
2522*193032a3SAndroid Build Coastguard Worker iter != cta.native_timings.end(); ++iter) {
2523*193032a3SAndroid Build Coastguard Worker if (iter->t.interlaced) {
2524*193032a3SAndroid Build Coastguard Worker native_ilace++;
2525*193032a3SAndroid Build Coastguard Worker if (!native_ilace_hact) {
2526*193032a3SAndroid Build Coastguard Worker native_ilace_hact = iter->t.hact;
2527*193032a3SAndroid Build Coastguard Worker native_ilace_vact = iter->t.vact;
2528*193032a3SAndroid Build Coastguard Worker } else if (native_ilace_hact != iter->t.hact ||
2529*193032a3SAndroid Build Coastguard Worker native_ilace_vact != iter->t.vact) {
2530*193032a3SAndroid Build Coastguard Worker native_ilace_mixed_resolutions = true;
2531*193032a3SAndroid Build Coastguard Worker }
2532*193032a3SAndroid Build Coastguard Worker } else {
2533*193032a3SAndroid Build Coastguard Worker native_prog++;
2534*193032a3SAndroid Build Coastguard Worker if (!native_prog_hact) {
2535*193032a3SAndroid Build Coastguard Worker native_prog_hact = iter->t.hact;
2536*193032a3SAndroid Build Coastguard Worker native_prog_vact = iter->t.vact;
2537*193032a3SAndroid Build Coastguard Worker } else if (native_prog_hact != iter->t.hact ||
2538*193032a3SAndroid Build Coastguard Worker native_prog_vact != iter->t.vact) {
2539*193032a3SAndroid Build Coastguard Worker native_prog_mixed_resolutions = true;
2540*193032a3SAndroid Build Coastguard Worker }
2541*193032a3SAndroid Build Coastguard Worker }
2542*193032a3SAndroid Build Coastguard Worker }
2543*193032a3SAndroid Build Coastguard Worker
2544*193032a3SAndroid Build Coastguard Worker if (native_prog_mixed_resolutions)
2545*193032a3SAndroid Build Coastguard Worker fail("Native progressive timings are a mix of several resolutions.\n");
2546*193032a3SAndroid Build Coastguard Worker if (native_ilace_mixed_resolutions)
2547*193032a3SAndroid Build Coastguard Worker fail("Native interlaced timings are a mix of several resolutions.\n");
2548*193032a3SAndroid Build Coastguard Worker if (native_ilace && !native_prog)
2549*193032a3SAndroid Build Coastguard Worker fail("A native interlaced timing is present, but not a native progressive timing.\n");
2550*193032a3SAndroid Build Coastguard Worker if (!native_prog_mixed_resolutions && native_prog > 1)
2551*193032a3SAndroid Build Coastguard Worker warn("Multiple native progressive timings are defined.\n");
2552*193032a3SAndroid Build Coastguard Worker if (!native_ilace_mixed_resolutions && native_ilace > 1)
2553*193032a3SAndroid Build Coastguard Worker warn("Multiple native interlaced timings are defined.\n");
2554*193032a3SAndroid Build Coastguard Worker
2555*193032a3SAndroid Build Coastguard Worker if (!native_prog_mixed_resolutions && native_prog_vact &&
2556*193032a3SAndroid Build Coastguard Worker (max_pref_prog_vact > native_prog_vact ||
2557*193032a3SAndroid Build Coastguard Worker (max_pref_prog_vact == native_prog_vact && max_pref_prog_hact > native_prog_hact)))
2558*193032a3SAndroid Build Coastguard Worker warn("Native progressive resolution of %ux%u is smaller than the max preferred progressive resolution %ux%u.\n",
2559*193032a3SAndroid Build Coastguard Worker native_prog_hact, native_prog_vact,
2560*193032a3SAndroid Build Coastguard Worker max_pref_prog_hact, max_pref_prog_vact);
2561*193032a3SAndroid Build Coastguard Worker if (!native_ilace_mixed_resolutions && native_ilace_vact &&
2562*193032a3SAndroid Build Coastguard Worker (max_pref_ilace_vact > native_ilace_vact ||
2563*193032a3SAndroid Build Coastguard Worker (max_pref_ilace_vact == native_ilace_vact && max_pref_ilace_hact > native_ilace_hact)))
2564*193032a3SAndroid Build Coastguard Worker warn("Native interlaced resolution of %ux%u is smaller than the max preferred interlaced resolution %ux%u.\n",
2565*193032a3SAndroid Build Coastguard Worker native_ilace_hact, native_ilace_vact,
2566*193032a3SAndroid Build Coastguard Worker max_pref_ilace_hact, max_pref_ilace_vact);
2567*193032a3SAndroid Build Coastguard Worker
2568*193032a3SAndroid Build Coastguard Worker if (dispid.native_width && native_prog_hact &&
2569*193032a3SAndroid Build Coastguard Worker !native_prog_mixed_resolutions) {
2570*193032a3SAndroid Build Coastguard Worker if (dispid.native_width != native_prog_hact ||
2571*193032a3SAndroid Build Coastguard Worker dispid.native_height != native_prog_vact)
2572*193032a3SAndroid Build Coastguard Worker fail("Mismatch between CTA-861 and DisplayID native progressive resolution.\n");
2573*193032a3SAndroid Build Coastguard Worker }
2574*193032a3SAndroid Build Coastguard Worker }
2575