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