1 // SPDX-License-Identifier: MIT
3 * Copyright 2006-2012 Red Hat, Inc.
4 * Copyright 2018-2020 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
6 * Author: Adam Jackson <ajax@nwnk.net>
7 * Maintainer: Hans Verkuil <hverkuil-cisco@xs4all.nl>
13 #include "edid-decode.h"
15 static const struct timings edid_cta_modes1
[] = {
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 },
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 },
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 },
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 },
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 },
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 },
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 },
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 },
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 },
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 },
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 },
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 },
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 },
158 static const struct timings edid_cta_modes2
[] = {
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 },
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 },
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 },
191 static const unsigned char edid_hdmi_mode_map
[] = { 95, 94, 93, 98 };
193 unsigned char hdmi_vic_to_vic(unsigned char hdmi_vic
)
195 if (hdmi_vic
> 0 && hdmi_vic
<= ARRAY_SIZE(edid_hdmi_mode_map
))
196 return edid_hdmi_mode_map
[hdmi_vic
- 1];
200 const struct timings
*find_vic_id(unsigned char vic
)
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;
209 const struct timings
*find_hdmi_vic_id(unsigned char hdmi_vic
)
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]);
216 const struct timings
*cta_close_match_to_vic(const timings
&t
, unsigned &vic
)
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];
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];
230 void edid_state::cta_list_vics()
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);
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);
243 void edid_state::cta_list_hdmi_vics()
245 for (unsigned i
= 0; i
< ARRAY_SIZE(edid_hdmi_mode_map
); i
++) {
246 unsigned vic
= edid_hdmi_mode_map
[i
];
249 sprintf(type
, "HDMI VIC %u", i
+ 1);
250 print_timings("", find_vic_id(vic
), type
, "", false, false);
254 static std::string
audio_ext_format(unsigned char x
)
256 if (x
>= 1 && x
<= 3)
257 fail("Obsolete Audio Ext Format 0x%02x.\n", 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";
273 fail("Unknown Audio Ext Format 0x%02x.\n", x
);
274 return std::string("Unknown Audio Ext Format (") + utohex(x
) + ")";
277 static std::string
audio_format(unsigned char 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";
296 fail("Unknown Audio Format 0x%02x.\n", x
);
297 return std::string("Unknown Audio Format (") + utohex(x
) + ")";
300 static std::string
mpeg_h_3d_audio_level(unsigned char 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";
311 fail("Unknown MPEG-H 3D Audio Level 0x%02x.\n", x
);
312 return std::string("Unknown MPEG-H 3D Audio Level (") + utohex(x
) + ")";
315 static void cta_audio_block(const unsigned char *x
, unsigned length
)
317 unsigned i
, format
, ext_format
;
320 fail("Broken CTA-861 audio block length %d.\n", length
);
324 for (i
= 0; i
< length
; i
+= 3) {
325 format
= (x
[i
] & 0x78) >> 3;
327 printf(" Reserved (0x00)\n");
328 fail("Audio Format Code 0x00 is reserved.\n");
333 printf(" %s:\n", audio_format(format
).c_str());
335 ext_format
= (x
[i
+ 2] & 0xf8) >> 3;
336 printf(" %s:\n", audio_ext_format(ext_format
).c_str());
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) |
348 printf(" Max channels: %u\n", (x
[i
] & 0x07)+1);
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).
369 printf(" Supports Joint Object Coding\n");
371 printf(" Supports Joint Object Coding with ACMOD28\n");
372 } else if (format
== 12) {
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 " : "");
378 printf(" Supports only Dolby TrueHD\n");
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");
400 void edid_state::cta_svd(const unsigned char *x
, unsigned n
, bool for_ycbcr420
)
404 for (i
= 0; i
< n
; i
++) {
405 const struct timings
*t
= NULL
;
406 unsigned char svd
= x
[i
];
407 unsigned char native
;
410 if ((svd
& 0x7f) == 0)
413 if ((svd
- 1) & 0x40) {
421 t
= find_vic_id(vic
);
425 cta
.supported_hdmi_vic_vsb_codes
|= 1 << 0;
428 cta
.supported_hdmi_vic_vsb_codes
|= 1 << 1;
431 cta
.supported_hdmi_vic_vsb_codes
|= 1 << 2;
434 cta
.supported_hdmi_vic_vsb_codes
|= 1 << 3;
437 bool first_svd
= cta
.first_svd
&& !for_ycbcr420
;
438 bool override_pref
= first_svd
&& cta
.first_svd_might_be_preferred
;
441 sprintf(type
, "VIC %3u", vic
);
442 const char *flags
= native
? "native" : "";
445 struct timings tmp
= *t
;
447 print_timings(" ", &tmp
, type
, flags
);
449 print_timings(" ", t
, type
, flags
);
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");
456 warn("VIC %u is the preferred timing, overriding the first detailed timings. Is this intended?\n", vic
);
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
));
464 cta
.first_svd
= false;
465 cta
.first_svd_might_be_preferred
= false;
468 cta
.native_timings
.push_back(timings_ext(*t
, type
, flags
));
470 printf(" Unknown (VIC %3u)\n", vic
);
471 fail("Unknown VIC %u.\n", vic
);
474 if (vic
== 1 && !for_ycbcr420
)
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
);
483 void edid_state::print_vic_index(const char *prefix
, unsigned idx
, const char *suffix
, bool ycbcr420
)
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
);
492 sprintf(buf
, "VIC %3u", vic
);
495 struct timings tmp
= *t
;
496 tmp
.ycbcr420
= ycbcr420
;
497 print_timings(prefix
, &tmp
, buf
, suffix
);
499 printf("%sUnknown (%s%s%s)\n", prefix
, buf
,
500 *suffix
? ", " : "", suffix
);
503 // Should not happen!
504 printf("%sSVD Index %u is out of range", prefix
, idx
+ 1);
506 printf(" (%s)", suffix
);
511 void edid_state::cta_y420cmdb(const unsigned char *x
, unsigned length
)
513 unsigned max_idx
= 0;
517 printf(" All VDB SVDs\n");
521 if (memchk(x
, length
)) {
522 printf(" Empty Capability Map\n");
523 fail("Empty Capability Map.\n");
527 for (i
= 0; i
< length
; i
++) {
528 unsigned char v
= x
[i
];
531 for (j
= 0; j
< 8; j
++) {
535 print_vic_index(" ", i
* 8 + j
, "", true);
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
);
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());
549 void edid_state::cta_vfpdb(const unsigned char *x
, unsigned length
)
554 fail("Empty Data Block with length %u.\n", length
);
557 cta
.preferred_timings
.clear();
558 for (i
= 0; i
< length
; i
++) {
559 unsigned char svr
= x
[i
];
562 if ((svr
> 0 && svr
< 128) || (svr
> 192 && svr
< 254)) {
563 const struct timings
*t
;
564 unsigned char vic
= svr
;
566 sprintf(suffix
, "VIC %3u", vic
);
568 t
= find_vic_id(vic
);
570 print_timings(" ", t
, suffix
);
571 cta
.preferred_timings
.push_back(timings_ext(*t
, suffix
, ""));
573 printf(" %s: Unknown\n", suffix
);
574 fail("Unknown VIC %u.\n", vic
);
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);
583 printf(" %s\n", suffix
);
584 cta
.preferred_timings
.push_back(timings_ext(svr
, suffix
));
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);
592 printf(" %s\n", suffix
);
593 cta
.preferred_timings
.push_back(timings_ext(svr
, suffix
));
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");
601 printf(" %s\n", suffix
);
602 cta
.preferred_timings
.push_back(timings_ext(svr
, suffix
));
608 static std::string
hdmi_latency2s(unsigned char l
, bool is_video
)
613 return is_video
? "Video not supported" : "Audio not supported";
614 return std::to_string(1 + 2 * l
) + " ms";
617 void edid_state::hdmi_latency(unsigned char vid_lat
, unsigned char aud_lat
,
620 const char *vid
= is_ilaced
? "Interlaced video" : "Video";
621 const char *aud
= is_ilaced
? "Interlaced audio" : "Audio";
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());
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
);
631 if (!vid_lat
|| vid_lat
> 251)
633 if (!aud_lat
|| aud_lat
> 251)
636 unsigned vid_ms
= 1 + 2 * vid_lat
;
637 unsigned aud_ms
= 1 + 2 * aud_lat
;
639 // HDMI 2.0 latency checks for devices without HDMI output
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
);
651 void edid_state::cta_hdmi_block(const unsigned char *x
, unsigned length
)
653 unsigned len_vic
, len_3d
;
656 fail("Empty Data Block with length %u.\n", length
);
659 printf(" Source physical address: %x.%x.%x.%x\n", x
[0] >> 4, x
[0] & 0x0f,
660 x
[1] >> 4, x
[1] & 0x0f);
666 printf(" Supports_AI\n");
668 printf(" DC_48bit\n");
670 printf(" DC_36bit\n");
672 printf(" DC_30bit\n");
674 printf(" DC_Y444\n");
675 /* two reserved bits */
677 printf(" DVI_Dual\n");
682 printf(" Maximum TMDS clock: %u MHz\n", x
[3] * 5);
684 fail("HDMI VSDB Max TMDS rate is > 340.\n");
690 printf(" Supported Content Types:\n");
692 printf(" Graphics\n");
703 hdmi_latency(x
[b
], x
[b
+ 1], false);
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");
710 hdmi_latency(x
[b
], x
[b
+ 1], true);
719 bool formats
= false;
721 printf(" Extended HDMI video details:\n");
723 printf(" 3D present\n");
724 if ((x
[b
] & 0x60) == 0x20) {
725 printf(" All advertised VICs are 3D-capable\n");
728 if ((x
[b
] & 0x60) == 0x40) {
729 printf(" 3D-capable-VIC mask present\n");
733 switch (x
[b
] & 0x18) {
736 printf(" Base EDID image size is aspect ratio\n");
739 printf(" Base EDID image size is in units of 1 cm\n");
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);
750 len_vic
= (x
[b
] & 0xe0) >> 5;
751 len_3d
= (x
[b
] & 0x1f) >> 0;
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
;
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());
768 printf(" Unknown (HDMI VIC %u)\n", vic
);
769 fail("Unknown HDMI VIC %u.\n", vic
);
780 /* 3D_Structure_ALL_15..8 */
782 printf(" 3D: Side-by-side (half, quincunx)\n");
784 printf(" 3D: Side-by-side (half, horizontal)\n");
785 /* 3D_Structure_ALL_7..0 */
788 printf(" 3D: Top-and-bottom\n");
790 printf(" 3D: L + depth + gfx + gfx-depth\n");
792 printf(" 3D: L + depth\n");
794 printf(" 3D: Side-by-side (full)\n");
796 printf(" 3D: Line-alternative\n");
798 printf(" 3D: Field-alternative\n");
800 printf(" 3D: Frame-packing\n");
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
, "");
816 for (i
= 0; i
< 8; i
++)
817 if (x
[b
] & (1 << i
)) {
818 print_vic_index(" ", i
+ 8, "");
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());
832 * (optionally: 3D_Detail_X and reserved)
837 unsigned end
= b
+ len_3d
;
840 printf(" 3D VIC indices with specific capabilities:\n");
842 unsigned char idx
= x
[b
] >> 4;
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;
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:
862 fail("not-in-use 3D_Detail_X value 0x%02x.\n",
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;
872 fail("reserved 3D_Detail_X value 0x%02x.\n",
879 s
+= utohex(x
[b
] & 0x0f) + ")";
880 fail("Unknown 3D_Structure_X value 0x%02x.\n", x
[b
] & 0x0f);
883 print_vic_index(" ", idx
, s
.c_str());
884 if ((x
[b
] & 0x0f) >= 8)
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());
893 static const char *max_frl_rates
[] = {
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",
903 static const char *dsc_max_slices
[] = {
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",
914 static void cta_hf_eeodb(const unsigned char *x
, unsigned length
)
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");
921 static void cta_hf_scdb(const unsigned char *x
, unsigned length
)
923 unsigned rate
= x
[1] * 5;
926 printf(" Version: %u\n", x
[0]);
928 printf(" Maximum TMDS Character Rate: %u MHz\n", rate
);
929 if (rate
<= 340 || rate
> 600)
930 fail("Max TMDS rate is > 0 and <= 340 or > 600.\n");
933 printf(" SCDC Present\n");
935 printf(" SCDC Read Request Capable\n");
937 printf(" Supports Color Content Bits Per Component Indication\n");
939 printf(" Supports scrambling for <= 340 Mcsc\n");
941 printf(" Supports 3D Independent View signaling\n");
943 printf(" Supports 3D Dual View signaling\n");
945 printf(" Supports 3D OSD Disparity signaling\n");
947 unsigned max_frl_rate
= x
[3] >> 4;
949 printf(" Max Fixed Rate Link: ");
950 if (max_frl_rate
< ARRAY_SIZE(max_frl_rates
)) {
951 printf("%s\n", max_frl_rates
[max_frl_rate
]);
953 printf("Unknown (0x%02x)\n", max_frl_rate
);
954 fail("Unknown Max Fixed Rate Link (0x%02x).\n", max_frl_rate
);
956 if (max_frl_rate
== 1 && rate
< 300)
957 fail("Max Fixed Rate Link is 1, but Max TMDS rate < 300.\n");
958 else if (max_frl_rate
>= 2 && rate
< 600)
959 fail("Max Fixed Rate Link is >= 2, but Max TMDS rate < 600.\n");
962 printf(" Supports UHD VIC\n");
964 printf(" Supports 16-bits/component Deep Color 4:2:0 Pixel Encoding\n");
966 printf(" Supports 12-bits/component Deep Color 4:2:0 Pixel Encoding\n");
968 printf(" Supports 10-bits/component Deep Color 4:2:0 Pixel Encoding\n");
974 printf(" Supports Mdelta\n");
976 printf(" Supports media rates below VRRmin (CinemaVRR)\n");
978 printf(" Supports negative Mvrr values\n");
980 printf(" Supports Fast Vactive\n");
982 printf(" Supports Auto Low-Latency Mode\n");
984 printf(" Supports a FAPA in blanking after first active video line\n");
991 printf(" VRRmin: %u Hz\n", v
);
993 fail("VRRmin > 48.\n");
995 v
= (x
[5] & 0xc0) << 2 | x
[6];
997 printf(" VRRmax: %u Hz\n", v
);
999 fail("VRRmin == 0, but VRRmax isn't.\n");
1001 fail("VRRmax < 100.\n");
1008 printf(" Supports VESA DSC 1.2a compression\n");
1010 printf(" Supports Compressed Video Transport for 4:2:0 Pixel Encoding\n");
1012 printf(" Supports Compressed Video Transport at any valid 1/16th bit bpp\n");
1014 printf(" Supports 16 bpc Compressed Video Transport\n");
1016 printf(" Supports 12 bpc Compressed Video Transport\n");
1018 printf(" Supports 10 bpc Compressed Video Transport\n");
1020 unsigned max_slices
= x
[8] & 0xf;
1022 printf(" DSC Max Slices: ");
1023 if (max_slices
< ARRAY_SIZE(dsc_max_slices
)) {
1024 printf("%s\n", dsc_max_slices
[max_slices
]);
1026 printf("Unknown (0x%02x)\n", max_slices
);
1027 fail("Unknown DSC Max Slices (0x%02x).\n", max_slices
);
1031 unsigned max_frl_rate
= x
[8] >> 4;
1033 printf(" DSC Max Fixed Rate Link: ");
1034 if (max_frl_rate
< ARRAY_SIZE(max_frl_rates
)) {
1035 printf("%s\n", max_frl_rates
[max_frl_rate
]);
1037 printf("Unknown (0x%02x)\n", max_frl_rate
);
1038 fail("Unknown DSC Max Fixed Rate Link (0x%02x).\n", max_frl_rate
);
1042 printf(" Maximum number of bytes in a line of chunks: %u\n",
1043 1024 * (1 + (x
[9] & 0x3f)));
1046 static void cta_amd(const unsigned char *x
, unsigned length
)
1048 // These Freesync values are reversed engineered by looking
1049 // at existing EDIDs.
1050 printf(" Version: %u.%u\n", x
[0], x
[1]);
1051 printf(" Minimum Refresh Rate: %u Hz\n", x
[2]);
1052 printf(" Maximum Refresh Rate: %u Hz\n", x
[3]);
1053 // Freesync 1.x flags
1054 // One or more of the 0xe6 bits signal that the VESA MCCS
1055 // protocol is used to switch the Freesync range
1056 printf(" Flags 1.x: 0x%02x%s\n", x
[4],
1057 (x
[4] & 0xe6) ? " (MCCS)" : "");
1059 // Freesync 2.x flags
1060 // Bit 2 no doubt indicates if the monitor supports Local Dimming
1061 // There are probably also bits to signal support of the
1062 // FreeSync2_scRGB and FreeSync2_Gamma22 HDR display modes.
1063 // I suspect bits 0 and 1.
1064 printf(" Flags 2.x: 0x%02x\n", x
[5]);
1065 // The AMD tone mapping tutorial referred to in the URL below
1066 // mentions that the Freesync HDR info reports max/min
1067 // luminance of the monitor with and without local dimming.
1069 // https://gpuopen.com/learn/using-amd-freesync-premium-pro-hdr-code-samples/
1071 // So I assume that the first two luminance values are
1072 // the max/min luminance of the display and the next two
1073 // luminance values are the max/min luminance values when
1074 // local dimming is disabled. The values I get seem to
1076 printf(" Maximum luminance: %u (%.3f cd/m^2)\n",
1077 x
[6], 50.0 * pow(2, x
[6] / 32.0));
1078 printf(" Minimum luminance: %u (%.3f cd/m^2)\n",
1079 x
[7], (50.0 * pow(2, x
[6] / 32.0)) * pow(x
[7] / 255.0, 2) / 100.0);
1081 // One or both bytes can be 0. The meaning of that
1083 printf(" Maximum luminance (without local dimming): %u (%.3f cd/m^2)\n",
1084 x
[8], 50.0 * pow(2, x
[8] / 32.0));
1085 printf(" Minimum luminance (without local dimming): %u (%.3f cd/m^2)\n",
1086 x
[9], (50.0 * pow(2, x
[8] / 32.0)) * pow(x
[9] / 255.0, 2) / 100.0);
1088 // These bytes are always 0x08 0x2f. If these values
1089 // represent max/min luminance as well, then these
1090 // would map to 59.460 and 0.020 cd/m^2 respectively.
1091 // I wonder if this somehow relates to SDR.
1092 printf(" Unknown: 0x%02x 0x%02x\n", x
[8], x
[9]);
1097 static std::string
display_use_case(unsigned char x
)
1100 case 1: return "Test equipment";
1101 case 2: return "Generic display";
1102 case 3: return "Television display";
1103 case 4: return "Desktop productivity display";
1104 case 5: return "Desktop gaming display";
1105 case 6: return "Presentation display";
1106 case 7: return "Virtual reality headset";
1107 case 8: return "Augmented reality";
1108 case 16: return "Video wall display";
1109 case 17: return "Medical imaging display";
1110 case 18: return "Dedicated gaming display";
1111 case 19: return "Dedicated video monitor display";
1112 case 20: return "Accessory display";
1115 fail("Unknown Display product primary use case 0x%02x.\n", x
);
1116 return std::string("Unknown display use case (") + utohex(x
) + ")";
1119 static void cta_microsoft(const unsigned char *x
, unsigned length
)
1121 // This VSDB is documented at:
1122 // https://docs.microsoft.com/en-us/windows-hardware/drivers/display/specialized-monitors-edid-extension
1123 printf(" Version: %u\n", x
[0]);
1125 // In version 1 and 2 these bits should always be set to 0.
1126 printf(" Desktop Usage: %u\n", (x
[1] >> 6) & 1);
1127 printf(" Third-Party Usage: %u\n", (x
[1] >> 5) & 1);
1129 printf(" Display Product Primary Use Case: %u (%s)\n", x
[1] & 0x1f,
1130 display_use_case(x
[1] & 0x1f).c_str());
1131 printf(" Container ID: %s\n", containerid2s(x
+ 2).c_str());
1134 static void cta_hdr10plus(const unsigned char *x
, unsigned length
)
1137 fail("Empty Data Block with length %u.\n", length
);
1140 printf(" Application Version: %u\n", x
[0]);
1141 hex_block(" ", x
+ 1, length
- 1);
1144 // Convert a PQ value (0-1) to cd/m^2 aka nits (0-10000)
1145 static double pq2nits(double pq
)
1147 const double m1
= 2610.0 / 16384.0;
1148 const double m2
= 128.0 * (2523.0 / 4096.0);
1149 const double c1
= 3424.0 / 4096.0;
1150 const double c2
= 32.0 * (2413.0 / 4096.0);
1151 const double c3
= 32.0 * (2392.0 / 4096.0);
1152 double e
= pow(pq
, 1.0 / m2
);
1158 v
= pow(v
, 1.0 / m1
);
1162 static void cta_dolby_video(const unsigned char *x
, unsigned length
)
1164 unsigned char version
= (x
[0] >> 5) & 0x07;
1166 printf(" Version: %u (%u bytes)\n", version
, length
+ 5);
1168 printf(" Supports YUV422 12 bit\n");
1172 printf(" Supports 2160p60\n");
1174 printf(" Supports global dimming\n");
1175 unsigned char dm_version
= x
[16];
1176 printf(" DM Version: %u.%u\n", dm_version
>> 4, dm_version
& 0xf);
1177 unsigned pq
= (x
[14] << 4) | (x
[13] >> 4);
1178 printf(" Target Min PQ: %u (%.8f cd/m^2)\n", pq
, pq2nits(pq
/ 4095.0));
1179 pq
= (x
[15] << 4) | (x
[13] & 0xf);
1180 printf(" Target Max PQ: %u (%u cd/m^2)\n", pq
, (unsigned)pq2nits(pq
/ 4095.0));
1181 printf(" Rx, Ry: %.8f, %.8f\n",
1182 ((x
[1] >> 4) | (x
[2] << 4)) / 4096.0,
1183 ((x
[1] & 0xf) | (x
[3] << 4)) / 4096.0);
1184 printf(" Gx, Gy: %.8f, %.8f\n",
1185 ((x
[4] >> 4) | (x
[5] << 4)) / 4096.0,
1186 ((x
[4] & 0xf) | (x
[6] << 4)) / 4096.0);
1187 printf(" Bx, By: %.8f, %.8f\n",
1188 ((x
[7] >> 4) | (x
[8] << 4)) / 4096.0,
1189 ((x
[7] & 0xf) | (x
[9] << 4)) / 4096.0);
1190 printf(" Wx, Wy: %.8f, %.8f\n",
1191 ((x
[10] >> 4) | (x
[11] << 4)) / 4096.0,
1192 ((x
[10] & 0xf) | (x
[12] << 4)) / 4096.0);
1198 printf(" Supports 2160p60\n");
1200 printf(" Supports global dimming\n");
1201 unsigned char dm_version
= (x
[0] >> 2) & 0x07;
1202 printf(" DM Version: %u.x\n", dm_version
+ 2);
1203 printf(" Colorimetry: %s\n", (x
[2] & 0x01) ? "P3-D65" : "ITU-R BT.709");
1204 printf(" Low Latency: %s\n", (x
[3] & 0x01) ? "Standard + Low Latency" : "Only Standard");
1205 double lm
= (x
[2] >> 1) / 127.0;
1206 printf(" Target Min Luminance: %.8f cd/m^2\n", lm
* lm
);
1207 printf(" Target Max Luminance: %u cd/m^2\n", 100 + (x
[1] >> 1) * 50);
1209 printf(" Rx, Ry: %.8f, %.8f\n", x
[4] / 256.0, x
[5] / 256.0);
1210 printf(" Gx, Gy: %.8f, %.8f\n", x
[6] / 256.0, x
[7] / 256.0);
1211 printf(" Bx, By: %.8f, %.8f\n", x
[8] / 256.0, x
[9] / 256.0);
1213 double xmin
= 0.625;
1214 double xstep
= (0.74609375 - xmin
) / 31.0;
1216 double ystep
= (0.37109375 - ymin
) / 31.0;
1218 printf(" Unique Rx, Ry: %.8f, %.8f\n",
1219 xmin
+ xstep
* (x
[6] >> 3),
1220 ymin
+ ystep
* (((x
[6] & 0x7) << 2) | (x
[4] & 0x01) | ((x
[5] & 0x01) << 1)));
1221 xstep
= 0.49609375 / 127.0;
1223 ystep
= (0.99609375 - ymin
) / 127.0;
1224 printf(" Unique Gx, Gy: %.8f, %.8f\n",
1225 xstep
* (x
[4] >> 1), ymin
+ ystep
* (x
[5] >> 1));
1227 xstep
= (0.15234375 - xmin
) / 7.0;
1229 ystep
= (0.05859375 - ymin
) / 7.0;
1230 printf(" Unique Bx, By: %.8f, %.8f\n",
1231 xmin
+ xstep
* (x
[3] >> 5),
1232 ymin
+ ystep
* ((x
[3] >> 2) & 0x07));
1239 printf(" Supports Backlight Control\n");
1241 printf(" Supports global dimming\n");
1242 unsigned char dm_version
= (x
[0] >> 2) & 0x07;
1243 printf(" DM Version: %u.x\n", dm_version
+ 2);
1244 printf(" Backlt Min Luma: %u cd/m^2\n", 25 + (x
[1] & 0x03) * 25);
1245 printf(" Interface: ");
1246 switch (x
[2] & 0x03) {
1247 case 0: printf("Low-Latency\n"); break;
1248 case 1: printf("Low-Latency + Low-Latency-HDMI\n"); break;
1249 case 2: printf("Standard + Low-Latency\n"); break;
1250 case 3: printf("Standard + Low-Latency + Low-Latency-HDMI\n"); break;
1252 printf(" Supports 10b 12b 444: ");
1253 switch ((x
[3] & 0x01) << 1 | (x
[4] & 0x01)) {
1254 case 0: printf("Not supported\n"); break;
1255 case 1: printf("10 bit\n"); break;
1256 case 2: printf("12 bit\n"); break;
1257 case 3: printf("Reserved\n"); break;
1260 // This divider constant is a guess. According to what I read
1261 // when googling for how to interpret these values, the Min PQ
1262 // maps to a range of 0-1 cd/m^2, and the Max PQ maps to a
1263 // range of 100-10000 cd/m^2. Since the maximum value for the Max PQ
1264 // is 2055 + 65 * 31 = 4070, I am guessing that that is the correct
1265 // divider, but it might well be 4095 or 4096 instead.
1267 // I'm also not sure if the divider for Min PQ is the same as for
1268 // Max PQ. To map the max value of 20 * 31 to 1 cd/m^2 you would
1269 // need a divider of 4134 or 4135, but I suspect the same divider
1271 const double dv_pq_div
= 2055 + 31 * 65;
1273 unsigned pq
= 20 * (x
[1] >> 3);
1274 printf(" Target Min PQ v2: %u (%.8f cd/m^2)\n", pq
, pq2nits(pq
/ dv_pq_div
));
1275 pq
= 2055 + 65 * (x
[2] >> 3);
1276 printf(" Target Max PQ v2: %u (%u cd/m^2)\n", pq
, (unsigned)pq2nits(pq
/ dv_pq_div
));
1278 double xmin
= 0.625;
1279 double xstep
= (0.74609375 - xmin
) / 31.0;
1281 double ystep
= (0.37109375 - ymin
) / 31.0;
1283 printf(" Unique Rx, Ry: %.8f, %.8f\n",
1284 xmin
+ xstep
* (x
[5] >> 3),
1285 ymin
+ ystep
* (x
[6] >> 3));
1286 xstep
= 0.49609375 / 127.0;
1288 ystep
= (0.99609375 - ymin
) / 127.0;
1289 printf(" Unique Gx, Gy: %.8f, %.8f\n",
1290 xstep
* (x
[3] >> 1), ymin
+ ystep
* (x
[4] >> 1));
1292 xstep
= (0.15234375 - xmin
) / 7.0;
1294 ystep
= (0.05859375 - ymin
) / 7.0;
1295 printf(" Unique Bx, By: %.8f, %.8f\n",
1296 xmin
+ xstep
* (x
[5] & 0x07),
1297 ymin
+ ystep
* (x
[6] & 0x07));
1301 static void cta_dolby_audio(const unsigned char *x
, unsigned length
)
1303 unsigned char version
= 1 + (x
[0] & 0x07);
1305 printf(" Version: %u (%u bytes)\n", version
, length
+ 5);
1307 printf(" Headphone playback only\n");
1309 printf(" Height speaker zone present\n");
1311 printf(" Surround speaker zone present\n");
1313 printf(" Center speaker zone present\n");
1315 printf(" Supports Dolby MAT PCM decoding at 48 kHz only, does not support TrueHD\n");
1318 static const char *speaker_map
[] = {
1319 "FL/FR - Front Left/Right",
1320 "LFE1 - Low Frequency Effects 1",
1321 "FC - Front Center",
1322 "BL/BR - Back Left/Right",
1324 "FLc/FRc - Front Left/Right of Center",
1325 "RLC/RRC - Rear Left/Right of Center (Deprecated)",
1326 "FLw/FRw - Front Left/Right Wide",
1327 "TpFL/TpFR - Top Front Left/Right",
1329 "TpFC - Top Front Center",
1330 "LS/RS - Left/Right Surround",
1331 "LFE2 - Low Frequency Effects 2",
1332 "TpBC - Top Back Center",
1333 "SiL/SiR - Side Left/Right",
1334 "TpSiL/TpSiR - Top Side Left/Right",
1335 "TpBL/TpBR - Top Back Left/Right",
1336 "BtFC - Bottom Front Center",
1337 "BtFL/BtFR - Bottom Front Left/Right",
1338 "TpLS/TpRS - Top Left/Right Surround (Deprecated for CTA-861)",
1339 "LSd/RSd - Left/Right Surround Direct (HDMI only)",
1342 static void cta_sadb(const unsigned char *x
, unsigned length
)
1348 fail("Empty Data Block with length %u.\n", length
);
1352 sad
= ((x
[2] << 16) | (x
[1] << 8) | x
[0]);
1354 for (i
= 0; i
< ARRAY_SIZE(speaker_map
); i
++) {
1356 printf(" %s\n", speaker_map
[i
]);
1360 static void cta_vesa_dtcdb(const unsigned char *x
, unsigned length
)
1362 if (length
!= 7 && length
!= 15 && length
!= 31) {
1363 fail("Invalid length %u.\n", length
);
1367 switch (x
[0] >> 6) {
1368 case 0: printf(" White"); break;
1369 case 1: printf(" Red"); break;
1370 case 2: printf(" Green"); break;
1371 case 3: printf(" Blue"); break;
1373 unsigned v
= x
[0] & 0x3f;
1374 printf(" transfer characteristics: %u", v
);
1375 for (unsigned i
= 1; i
< length
; i
++)
1376 printf(" %u", v
+= x
[i
]);
1380 static void cta_vesa_vdddb(const unsigned char *x
, unsigned length
)
1383 fail("Invalid length %u.\n", length
);
1387 printf(" Interface Type: ");
1388 unsigned char v
= x
[0];
1390 case 0: printf("Analog (");
1392 case 0: printf("15HD/VGA"); break;
1393 case 1: printf("VESA NAVI-V (15HD)"); break;
1394 case 2: printf("VESA NAVI-D"); break;
1395 default: printf("Reserved"); break;
1399 case 1: printf("LVDS %u lanes", v
& 0xf); break;
1400 case 2: printf("RSDS %u lanes", v
& 0xf); break;
1401 case 3: printf("DVI-D %u channels", v
& 0xf); break;
1402 case 4: printf("DVI-I analog"); break;
1403 case 5: printf("DVI-I digital %u channels", v
& 0xf); break;
1404 case 6: printf("HDMI-A"); break;
1405 case 7: printf("HDMI-B"); break;
1406 case 8: printf("MDDI %u channels", v
& 0xf); break;
1407 case 9: printf("DisplayPort %u channels", v
& 0xf); break;
1408 case 10: printf("IEEE-1394"); break;
1409 case 11: printf("M1 analog"); break;
1410 case 12: printf("M1 digital %u channels", v
& 0xf); break;
1411 default: printf("Reserved"); break;
1415 printf(" Interface Standard Version: %u.%u\n", x
[1] >> 4, x
[1] & 0xf);
1416 printf(" Content Protection Support: ");
1418 case 0: printf("None\n"); break;
1419 case 1: printf("HDCP\n"); break;
1420 case 2: printf("DTCP\n"); break;
1421 case 3: printf("DPCP\n"); break;
1422 default: printf("Reserved\n"); break;
1425 printf(" Minimum Clock Frequency: %u MHz\n", x
[3] >> 2);
1426 printf(" Maximum Clock Frequency: %u MHz\n", ((x
[3] & 0x03) << 8) | x
[4]);
1427 printf(" Device Native Pixel Format: %ux%u\n",
1428 x
[5] | (x
[6] << 8), x
[7] | (x
[8] << 8));
1429 printf(" Aspect Ratio: %.2f\n", (100 + x
[9]) / 100.0);
1431 printf(" Default Orientation: ");
1432 switch ((v
& 0xc0) >> 6) {
1433 case 0x00: printf("Landscape\n"); break;
1434 case 0x01: printf("Portrait\n"); break;
1435 case 0x02: printf("Not Fixed\n"); break;
1436 case 0x03: printf("Undefined\n"); break;
1438 printf(" Rotation Capability: ");
1439 switch ((v
& 0x30) >> 4) {
1440 case 0x00: printf("None\n"); break;
1441 case 0x01: printf("Can rotate 90 degrees clockwise\n"); break;
1442 case 0x02: printf("Can rotate 90 degrees counterclockwise\n"); break;
1443 case 0x03: printf("Can rotate 90 degrees in either direction)\n"); break;
1445 printf(" Zero Pixel Location: ");
1446 switch ((v
& 0x0c) >> 2) {
1447 case 0x00: printf("Upper Left\n"); break;
1448 case 0x01: printf("Upper Right\n"); break;
1449 case 0x02: printf("Lower Left\n"); break;
1450 case 0x03: printf("Lower Right\n"); break;
1452 printf(" Scan Direction: ");
1454 case 0x00: printf("Not defined\n"); break;
1455 case 0x01: printf("Fast Scan is on the Major (Long) Axis and Slow Scan is on the Minor Axis\n"); break;
1456 case 0x02: printf("Fast Scan is on the Minor (Short) Axis and Slow Scan is on the Major Axis\n"); break;
1457 case 0x03: printf("Reserved\n");
1458 fail("Scan Direction used the reserved value 0x03.\n");
1461 printf(" Subpixel Information: ");
1463 case 0x00: printf("Not defined\n"); break;
1464 case 0x01: printf("RGB vertical stripes\n"); break;
1465 case 0x02: printf("RGB horizontal stripes\n"); break;
1466 case 0x03: printf("Vertical stripes using primary order\n"); break;
1467 case 0x04: printf("Horizontal stripes using primary order\n"); break;
1468 case 0x05: printf("Quad sub-pixels, red at top left\n"); break;
1469 case 0x06: printf("Quad sub-pixels, red at bottom left\n"); break;
1470 case 0x07: printf("Delta (triad) RGB sub-pixels\n"); break;
1471 case 0x08: printf("Mosaic\n"); break;
1472 case 0x09: printf("Quad sub-pixels, RGB + 1 additional color\n"); break;
1473 case 0x0a: printf("Five sub-pixels, RGB + 2 additional colors\n"); break;
1474 case 0x0b: printf("Six sub-pixels, RGB + 3 additional colors\n"); break;
1475 case 0x0c: printf("Clairvoyante, Inc. PenTile Matrix (tm) layout\n"); break;
1476 default: printf("Reserved\n"); break;
1478 printf(" Horizontal and vertical dot/pixel pitch: %.2f x %.2f mm\n",
1479 (double)(x
[0x0c]) / 100.0, (double)(x
[0x0d]) / 100.0);
1481 printf(" Dithering: ");
1483 case 0: printf("None\n"); break;
1484 case 1: printf("Spatial\n"); break;
1485 case 2: printf("Temporal\n"); break;
1486 case 3: printf("Spatial and Temporal\n"); break;
1488 printf(" Direct Drive: %s\n", (v
& 0x20) ? "Yes" : "No");
1489 printf(" Overdrive %srecommended\n", (v
& 0x10) ? "not " : "");
1490 printf(" Deinterlacing: %s\n", (v
& 0x08) ? "Yes" : "No");
1493 printf(" Audio Support: %s\n", (v
& 0x80) ? "Yes" : "No");
1494 printf(" Separate Audio Inputs Provided: %s\n", (v
& 0x40) ? "Yes" : "No");
1495 printf(" Audio Input Override: %s\n", (v
& 0x20) ? "Yes" : "No");
1498 printf(" Audio Delay: %s%u ms\n", (v
& 0x80) ? "" : "-", (v
& 0x7f) * 2);
1500 printf(" Audio Delay: no information provided\n");
1502 printf(" Frame Rate/Mode Conversion: ");
1504 case 0: printf("None\n"); break;
1505 case 1: printf("Single Buffering\n"); break;
1506 case 2: printf("Double Buffering\n"); break;
1507 case 3: printf("Advanced Frame Rate Conversion\n"); break;
1510 printf(" Frame Rate Range: %u fps +/- %u fps\n",
1513 printf(" Nominal Frame Rate: %u fps\n", x
[0x12]);
1514 printf(" Color Bit Depth: %u @ interface, %u @ display\n",
1515 (x
[0x13] >> 4) + 1, (x
[0x13] & 0xf) + 1);
1518 printf(" Additional Primary Chromaticities:\n");
1519 unsigned col_x
= (x
[0x16] << 2) | (x
[0x14] >> 6);
1520 unsigned col_y
= (x
[0x17] << 2) | ((x
[0x14] >> 4) & 3);
1521 printf(" Primary 4: 0.%04u, 0.%04u\n",
1522 (col_x
* 10000) / 1024, (col_y
* 10000) / 1024);
1524 col_x
= (x
[0x18] << 2) | ((x
[0x14] >> 2) & 3);
1525 col_y
= (x
[0x19] << 2) | (x
[0x14] & 3);
1526 printf(" Primary 5: 0.%04u, 0.%04u\n",
1527 (col_x
* 10000) / 1024, (col_y
* 10000) / 1024);
1529 col_x
= (x
[0x1a] << 2) | (x
[0x15] >> 6);
1530 col_y
= (x
[0x1b] << 2) | ((x
[0x15] >> 4) & 3);
1531 printf(" Primary 6: 0.%04u, 0.%04u\n",
1532 (col_x
* 10000) / 1024, (col_y
* 10000) / 1024);
1538 printf(" Response Time %s: %u ms\n",
1539 (v
& 0x80) ? "White -> Black" : "Black -> White", v
& 0x7f);
1541 printf(" Overscan: %u%% x %u%%\n", v
>> 4, v
& 0xf);
1544 static double decode_uchar_as_double(unsigned char x
)
1546 signed char s
= (signed char)x
;
1551 void edid_state::cta_rcdb(const unsigned char *x
, unsigned length
)
1553 unsigned spm
= ((x
[3] << 16) | (x
[2] << 8) | x
[1]);
1557 fail("Empty Data Block with length %u.\n", length
);
1561 if ((x
[0] & 0x20) && !cta
.has_sldb
)
1562 fail("'SLD' flag is 1, but no Speaker Location Data Block is found.\n");
1563 else if (!(x
[0] & 0x20) && cta
.has_sldb
)
1564 fail("'SLD' flag is 0, but a Speaker Location Data Block is present.\n");
1567 printf(" Speaker count: %u\n", (x
[0] & 0x1f) + 1);
1570 fail("'Speaker' flag is 0, but 'Speaker Count' is != 0.\n");
1572 fail("'SLD' flag is 1, but 'Speaker' is 0.\n");
1575 printf(" Speaker Presence Mask:\n");
1576 for (i
= 0; i
< ARRAY_SIZE(speaker_map
); i
++) {
1578 printf(" %s\n", speaker_map
[i
]);
1581 if ((x
[0] & 0xa0) == 0x80)
1582 fail("'Display' flag set, but not the 'SLD' flag.\n");
1584 bool valid_max
= cta
.preparsed_sld_has_coord
|| (x
[0] & 0x80);
1586 if (valid_max
&& length
>= 7) {
1587 printf(" Xmax: %u dm\n", x
[4]);
1588 printf(" Ymax: %u dm\n", x
[5]);
1589 printf(" Zmax: %u dm\n", x
[6]);
1590 } else if (!valid_max
&& length
>= 7) {
1591 // The RCDB should have been truncated.
1592 warn("'Display' flag is 0 and 'Coord' is 0 for all SLDs, but the Max coordinates are still present.\n");
1594 if ((x
[0] & 0x80) && length
>= 10) {
1595 printf(" DisplayX: %.3f * Xmax\n", decode_uchar_as_double(x
[7]));
1596 printf(" DisplayY: %.3f * Ymax\n", decode_uchar_as_double(x
[8]));
1597 printf(" DisplayZ: %.3f * Zmax\n", decode_uchar_as_double(x
[9]));
1598 } else if (!(x
[0] & 0x80) && length
>= 10) {
1599 // The RCDB should have been truncated.
1600 warn("'Display' flag is 0, but the Display coordinates are still present.\n");
1604 static const char *speaker_location
[] = {
1607 "FC - Front Center",
1608 "LFE1 - Low Frequency Effects 1",
1611 "FLC - Front Left of Center",
1612 "FRC - Front Right of Center",
1614 "LFE2 - Low Frequency Effects 2",
1617 "TpFL - Top Front Left",
1618 "TpFR - Top Front Right",
1619 "TpFC - Top Front Center",
1621 "TpBL - Top Back Left",
1622 "TpBR - Top Back Right",
1623 "TpSiL - Top Side Left",
1624 "TpSiR - Top Side Right",
1625 "TpBC - Top Back Center",
1626 "BtFC - Bottom Front Center",
1627 "BtFL - Bottom Front Left",
1628 "BtFR - Bottom Front Right",
1629 "FLW - Front Left Wide",
1630 "FRW - Front Right Wide",
1631 "LS - Left Surround",
1632 "RS - Right Surround",
1635 void edid_state::cta_sldb(const unsigned char *x
, unsigned length
)
1638 fail("Empty Data Block with length %u.\n", length
);
1642 unsigned active_cnt
= 0;
1643 unsigned channel_is_active
= 0;
1645 while (length
>= 2) {
1646 printf(" Channel: %u (%sactive)\n", x
[0] & 0x1f,
1647 (x
[0] & 0x20) ? "" : "not ");
1649 if (channel_is_active
& (1U << (x
[0] & 0x1f)))
1650 fail("Channel Index %u was already marked 'Active'.\n",
1652 channel_is_active
|= 1U << (x
[0] & 0x1f);
1655 if ((x
[1] & 0x1f) < ARRAY_SIZE(speaker_location
))
1656 printf(" Speaker: %s\n", speaker_location
[x
[1] & 0x1f]);
1657 if (length
>= 5 && (x
[0] & 0x40)) {
1658 printf(" X: %.3f * Xmax\n", decode_uchar_as_double(x
[2]));
1659 printf(" Y: %.3f * Ymax\n", decode_uchar_as_double(x
[3]));
1660 printf(" Z: %.3f * Zmax\n", decode_uchar_as_double(x
[4]));
1668 if (active_cnt
!= cta
.preparsed_speaker_count
)
1669 fail("There are %u active speakers, but 'Speaker Count' is %u.\n",
1670 active_cnt
, cta
.preparsed_speaker_count
);
1673 void edid_state::cta_preparse_sldb(const unsigned char *x
, unsigned length
)
1675 cta
.has_sldb
= true;
1676 while (length
>= 2) {
1677 if (length
>= 5 && (x
[0] & 0x40)) {
1678 cta
.preparsed_sld_has_coord
= true;
1686 void edid_state::cta_vcdb(const unsigned char *x
, unsigned length
)
1688 unsigned char d
= x
[0];
1690 cta
.has_vcdb
= true;
1692 fail("Empty Data Block with length %u.\n", length
);
1695 printf(" YCbCr quantization: %s\n",
1696 (d
& 0x80) ? "Selectable (via AVI YQ)" : "No Data");
1697 printf(" RGB quantization: %s\n",
1698 (d
& 0x40) ? "Selectable (via AVI Q)" : "No Data");
1700 * If this bit is not set then that will result in interoperability
1701 * problems (specifically with PCs/laptops) that quite often do not
1702 * follow the default rules with respect to RGB Quantization Range
1705 * Starting with the CTA-861-H spec this bit is now required to be
1706 * 1 for new designs.
1709 fail("Set Selectable RGB Quantization to avoid interop issues.\n");
1711 * Since most YCbCr formats use limited range, the interop issues are
1712 * less noticable than for RGB formats.
1714 * Starting with the CTA-861-H spec this bit is now required to be
1715 * 1 for new designs, but just warn about it (for now).
1717 if ((cta
.byte3
& 0x30) && !(d
& 0x80))
1718 warn("Set Selectable YCbCr Quantization to avoid interop issues.\n");
1720 unsigned char s_pt
= (d
>> 4) & 0x03;
1721 unsigned char s_it
= (d
>> 2) & 0x03;
1722 unsigned char s_ce
= d
& 0x03;
1724 printf(" PT scan behavior: ");
1726 case 0: printf("No Data\n"); break;
1727 case 1: printf("Always Overscanned\n"); break;
1728 case 2: printf("Always Underscanned\n"); break;
1729 case 3: printf("Supports both over- and underscan\n"); break;
1731 printf(" IT scan behavior: ");
1733 case 0: printf("IT video formats not supported\n"); break;
1735 printf("Always Overscanned\n");
1736 // See Table 52 of CTA-861-G for a description of Byte 3
1737 if (cta
.byte3
& 0x80)
1738 fail("IT video formats are always overscanned, but bit 7 of Byte 3 of the CTA-861 Extension header is set to underscanned.\n");
1741 printf("Always Underscanned\n");
1742 // See Table 52 of CTA-861-G for a description of Byte 3
1743 if (!(cta
.byte3
& 0x80))
1744 fail("IT video formats are always underscanned, but bit 7 of Byte 3 of the CTA-861 Extension header is set to overscanned.\n");
1746 case 3: printf("Supports both over- and underscan\n"); break;
1749 warn("IT scan behavior is expected to support underscanned.\n");
1750 printf(" CE scan behavior: ");
1752 case 0: printf("CE video formats not supported\n"); break;
1753 case 1: printf("Always Overscanned\n"); break;
1754 case 2: printf("Always Underscanned\n"); break;
1755 case 3: printf("Supports both over- and underscan\n"); break;
1758 warn("'CE video formats not supported' makes no sense.\n");
1759 else if (s_pt
== s_it
&& s_pt
== s_ce
)
1760 warn("S_PT is equal to S_IT and S_CE, so should be set to 0 instead.\n");
1763 static const char *colorimetry_map
[] = {
1774 static void cta_colorimetry_block(const unsigned char *x
, unsigned length
)
1779 fail("Empty Data Block with length %u.\n", length
);
1782 for (i
= 0; i
< ARRAY_SIZE(colorimetry_map
); i
++) {
1783 if (x
[0] & (1 << i
))
1784 printf(" %s\n", colorimetry_map
[i
]);
1787 printf(" DCI-P3\n");
1792 static const char *eotf_map
[] = {
1793 "Traditional gamma - SDR luminance range",
1794 "Traditional gamma - HDR luminance range",
1799 static void cta_hdr_static_metadata_block(const unsigned char *x
, unsigned length
)
1804 fail("Empty Data Block with length %u.\n", length
);
1807 printf(" Electro optical transfer functions:\n");
1808 for (i
= 0; i
< 6; i
++) {
1809 if (x
[0] & (1 << i
)) {
1810 if (i
< ARRAY_SIZE(eotf_map
)) {
1811 printf(" %s\n", eotf_map
[i
]);
1813 printf(" Unknown (%u)\n", i
);
1814 fail("Unknown EOTF (%u).\n", i
);
1818 printf(" Supported static metadata descriptors:\n");
1819 for (i
= 0; i
< 8; i
++) {
1820 if (x
[1] & (1 << i
))
1821 printf(" Static metadata type %u\n", i
+ 1);
1825 printf(" Desired content max luminance: %u (%.3f cd/m^2)\n",
1826 x
[2], 50.0 * pow(2, x
[2] / 32.0));
1829 printf(" Desired content max frame-average luminance: %u (%.3f cd/m^2)\n",
1830 x
[3], 50.0 * pow(2, x
[3] / 32.0));
1833 printf(" Desired content min luminance: %u (%.3f cd/m^2)\n",
1834 x
[4], (50.0 * pow(2, x
[2] / 32.0)) * pow(x
[4] / 255.0, 2) / 100.0);
1837 static void cta_hdr_dyn_metadata_block(const unsigned char *x
, unsigned length
)
1840 fail("Empty Data Block with length %u.\n", length
);
1843 while (length
>= 3) {
1844 unsigned type_len
= x
[0];
1845 unsigned type
= x
[1] | (x
[2] << 8);
1847 if (length
< type_len
+ 1)
1849 printf(" HDR Dynamic Metadata Type %u\n", type
);
1854 printf(" Version: %u\n", x
[3] & 0xf);
1858 unsigned version
= x
[3] & 0xf;
1859 printf(" Version: %u\n", version
);
1861 if (x
[3] & 0x10) printf(" Supports SL-HDR1 (ETSI TS 103 433-1)\n");
1862 if (x
[3] & 0x20) printf(" Supports SL-HDR2 (ETSI TS 103 433-2)\n");
1863 if (x
[3] & 0x40) printf(" Supports SL-HDR3 (ETSI TS 103 433-3)\n");
1870 length
-= type_len
+ 1;
1875 static void cta_ifdb(const unsigned char *x
, unsigned length
)
1877 unsigned len_hdr
= x
[0] >> 5;
1880 fail("Empty Data Block with length %u.\n", length
);
1883 printf(" VSIFs: %u\n", x
[1]);
1884 if (length
< len_hdr
+ 2)
1886 length
-= len_hdr
+ 2;
1888 while (length
> 0) {
1889 int payload_len
= x
[0] >> 5;
1891 if ((x
[0] & 0x1f) == 1 && length
>= 4) {
1892 unsigned oui
= (x
[3] << 16) | (x
[2] << 8) | x
[1];
1894 printf(" InfoFrame Type Code %u, OUI %s\n",
1895 x
[0] & 0x1f, ouitohex(oui
).c_str());
1899 printf(" InfoFrame Type Code %u\n", x
[0] & 0x1f);
1904 length
-= payload_len
;
1908 void edid_state::cta_displayid_type_7(const unsigned char *x
, unsigned length
)
1910 check_displayid_datablock_revision(x
[0], 0x00, 2);
1912 if (length
< 21U + ((x
[0] & 0x70) >> 4)) {
1913 fail("Empty Data Block with length %u.\n", length
);
1916 parse_displayid_type_1_7_timing(x
+ 1, true, 2, true);
1919 void edid_state::cta_displayid_type_8(const unsigned char *x
, unsigned length
)
1921 check_displayid_datablock_revision(x
[0], 0xe8, 1);
1922 if (length
< ((x
[0] & 0x08) ? 3 : 2)) {
1923 fail("Empty Data Block with length %u.\n", length
);
1927 unsigned sz
= (x
[0] & 0x08) ? 2 : 1;
1928 unsigned type
= x
[0] >> 6;
1931 fail("Only code type 0 is supported.\n");
1936 printf(" Also supports YCbCr 4:2:0\n");
1940 for (unsigned i
= 0; i
< length
/ sz
; i
++) {
1941 unsigned id
= x
[i
* sz
];
1944 id
|= x
[i
* sz
+ 1] << 8;
1945 parse_displayid_type_4_8_timing(type
, id
, true);
1949 void edid_state::cta_displayid_type_10(const unsigned char *x
, unsigned length
)
1951 check_displayid_datablock_revision(x
[0], 0x70);
1952 if (length
< 7U + ((x
[0] & 0x70) >> 4)) {
1953 fail("Empty Data Block with length %u.\n", length
);
1957 unsigned sz
= 6U + ((x
[0] & 0x70) >> 4);
1960 for (unsigned i
= 0; i
< length
/ sz
; i
++)
1961 parse_displayid_type_10_timing(x
+ i
* sz
, sz
, true);
1964 static void cta_hdmi_audio_block(const unsigned char *x
, unsigned length
)
1969 fail("Empty Data Block with length %u.\n", length
);
1973 printf(" Max Stream Count: %u\n", (x
[0] & 3) + 1);
1975 printf(" Supports MS NonMixed\n");
1977 num_descs
= x
[1] & 7;
1982 while (length
>= 4) {
1984 unsigned format
= x
[0] & 0xf;
1986 printf(" %s, max channels %u\n", audio_format(format
).c_str(),
1988 printf(" Supported sample rates (kHz):%s%s%s%s%s%s%s\n",
1989 (x
[2] & 0x40) ? " 192" : "",
1990 (x
[2] & 0x20) ? " 176.4" : "",
1991 (x
[2] & 0x10) ? " 96" : "",
1992 (x
[2] & 0x08) ? " 88.2" : "",
1993 (x
[2] & 0x04) ? " 48" : "",
1994 (x
[2] & 0x02) ? " 44.1" : "",
1995 (x
[2] & 0x01) ? " 32" : "");
1997 printf(" Supported sample sizes (bits):%s%s%s\n",
1998 (x
[3] & 0x04) ? " 24" : "",
1999 (x
[3] & 0x02) ? " 20" : "",
2000 (x
[3] & 0x01) ? " 16" : "");
2002 unsigned sad
= ((x
[2] << 16) | (x
[1] << 8) | x
[0]);
2005 switch (x
[3] >> 4) {
2007 printf(" Speaker Allocation for 10.2 channels:\n");
2010 printf(" Speaker Allocation for 22.2 channels:\n");
2013 printf(" Speaker Allocation for 30.2 channels:\n");
2016 printf(" Unknown Speaker Allocation (0x%02x)\n", x
[3] >> 4);
2020 for (i
= 0; i
< ARRAY_SIZE(speaker_map
); i
++) {
2022 printf(" %s\n", speaker_map
[i
]);
2030 void edid_state::cta_ext_block(const unsigned char *x
, unsigned length
,
2035 bool reverse
= false;
2036 bool audio_block
= false;
2039 case 0x00: data_block
= "Video Capability Data Block"; break;
2040 case 0x01: data_block
.clear(); break;
2041 case 0x02: data_block
= "VESA Video Display Device Data Block"; break;
2042 case 0x03: data_block
= "VESA Video Timing Block Extension"; break;
2043 case 0x04: data_block
= "Reserved for HDMI Video Data Block"; break;
2044 case 0x05: data_block
= "Colorimetry Data Block"; break;
2045 case 0x06: data_block
= "HDR Static Metadata Data Block"; break;
2046 case 0x07: data_block
= "HDR Dynamic Metadata Data Block"; break;
2048 case 0x0d: data_block
= "Video Format Preference Data Block"; break;
2049 case 0x0e: data_block
= "YCbCr 4:2:0 Video Data Block"; break;
2050 case 0x0f: data_block
= "YCbCr 4:2:0 Capability Map Data Block"; break;
2051 case 0x10: data_block
= "Reserved for CTA-861 Miscellaneous Audio Fields"; break;
2052 case 0x11: data_block
.clear(); audio_block
= true; break;
2053 case 0x12: data_block
= "HDMI Audio Data Block"; audio_block
= true; break;
2054 case 0x13: data_block
= "Room Configuration Data Block"; audio_block
= true; break;
2055 case 0x14: data_block
= "Speaker Location Data Block"; audio_block
= true; break;
2057 case 0x20: data_block
= "InfoFrame Data Block"; break;
2059 case 0x34: data_block
= "DisplayID Type VII Video Timing Data Block"; break;
2060 case 0x35: data_block
= "DisplayID Type VIII Video Timing Data Block"; break;
2061 case 0x42: data_block
= "DisplayID Type X Video Timing Data Block"; break;
2063 case 0x78: data_block
= "HDMI Forum EDID Extension Override Data Block"; break;
2064 case 0x79: data_block
= "HDMI Forum Sink Capability Data Block"; break;
2067 printf(" Unknown CTA-861 Video-Related");
2068 else if (x
[0] <= 31)
2069 printf(" Unknown CTA-861 Audio-Related");
2070 else if (x
[0] >= 120 && x
[0] <= 127)
2071 printf(" Unknown CTA-861 HDMI-Related");
2073 printf(" Unknown CTA-861");
2074 printf(" Data Block (extended tag 0x%02x, length %u)\n", x
[0], length
);
2075 hex_block(" ", x
+ 1, length
);
2077 warn("Unknown Extended CTA-861 Data Block 0x%02x.\n", x
[0]);
2093 fail("Only one instance of this Data Block is allowed.\n");
2097 // See Table 52 of CTA-861-G for a description of Byte 3
2098 if (audio_block
&& !(cta
.byte3
& 0x40))
2099 fail("Audio information is present, but bit 6 of Byte 3 of the CTA-861 Extension header indicates no Basic Audio support.\n");
2101 if (data_block
.length())
2102 printf(" %s:\n", data_block
.c_str());
2105 case 0x00: cta_vcdb(x
+ 1, length
); break;
2108 data_block
= std::string("Vendor-Specific Video Data Block");
2109 fail("Invalid length %u < 3.\n", length
);
2112 oui
= (x
[3] << 16) + (x
[2] << 8) + x
[1];
2113 name
= oui_name(oui
);
2115 name
= oui_name(oui
, true);
2120 printf(" Vendor-Specific Video Data Block, OUI %s:\n",
2121 ouitohex(oui
).c_str());
2122 hex_block(" ", x
+ 4, length
- 3);
2124 warn("Unknown Extended Vendor-Specific Video Data Block, OUI %s.\n",
2125 ouitohex(oui
).c_str());
2128 data_block
= std::string("Vendor-Specific Video Data Block (") + name
+ ")";
2130 fail((std::string("OUI ") + ouitohex(oui
) + " is in the wrong byte order\n").c_str());
2131 printf(" %s, OUI %s:\n", data_block
.c_str(), ouitohex(oui
).c_str());
2132 if (oui
== 0x90848b)
2133 cta_hdr10plus(x
+ 4, length
- 3);
2134 else if (oui
== 0x00d046)
2135 cta_dolby_video(x
+ 4, length
- 3);
2137 hex_block(" ", x
+ 4, length
- 3);
2139 case 0x02: cta_vesa_vdddb(x
+ 1, length
); break;
2140 case 0x05: cta_colorimetry_block(x
+ 1, length
); break;
2141 case 0x06: cta_hdr_static_metadata_block(x
+ 1, length
); break;
2142 case 0x07: cta_hdr_dyn_metadata_block(x
+ 1, length
); break;
2143 case 0x0d: cta_vfpdb(x
+ 1, length
); break;
2144 case 0x0e: cta_svd(x
+ 1, length
, true); break;
2145 case 0x0f: cta_y420cmdb(x
+ 1, length
); break;
2148 data_block
= std::string("Vendor-Specific Audio Data Block");
2149 fail("Invalid length %u < 3.\n", length
);
2152 oui
= (x
[3] << 16) + (x
[2] << 8) + x
[1];
2153 name
= oui_name(oui
);
2155 name
= oui_name(oui
, true);
2160 printf(" Vendor-Specific Audio Data Block, OUI %s:\n",
2161 ouitohex(oui
).c_str());
2162 hex_block(" ", x
+ 4, length
- 3);
2164 warn("Unknown Extended Vendor-Specific Audio Data Block, OUI %s.\n",
2165 ouitohex(oui
).c_str());
2168 data_block
= std::string("Vendor-Specific Audio Data Block (") + name
+ ")";
2170 fail((std::string("OUI ") + ouitohex(oui
) + " is in the wrong byte order\n").c_str());
2171 printf(" %s, OUI %s:\n", data_block
.c_str(), ouitohex(oui
).c_str());
2172 if (oui
== 0x00d046)
2173 cta_dolby_audio(x
+ 4, length
- 3);
2175 hex_block(" ", x
+ 4, length
- 3);
2177 case 0x12: cta_hdmi_audio_block(x
+ 1, length
); break;
2178 case 0x13: cta_rcdb(x
+ 1, length
); break;
2179 case 0x14: cta_sldb(x
+ 1, length
); break;
2180 case 0x20: cta_ifdb(x
+ 1, length
); break;
2181 case 0x34: cta_displayid_type_7(x
+ 1, length
); break;
2182 case 0x35: cta_displayid_type_8(x
+ 1, length
); break;
2183 case 0x42: cta_displayid_type_10(x
+ 1, length
); break;
2185 cta_hf_eeodb(x
+ 1, length
);
2186 // This must be the first CTA-861 block
2187 if (!cta
.first_block
)
2188 fail("Block starts at a wrong offset.\n");
2191 if (!cta
.last_block_was_hdmi_vsdb
)
2192 fail("HDMI Forum SCDB did not immediately follow the HDMI VSDB.\n");
2193 if (cta
.have_hf_scdb
|| cta
.have_hf_vsdb
)
2194 fail("Duplicate HDMI Forum VSDB/SCDB.\n");
2196 data_block
= std::string("HDMI Forum SCDB");
2197 fail("Invalid length %u < 2.\n", length
);
2201 printf(" Non-zero SCDB reserved fields!\n");
2202 cta_hf_scdb(x
+ 3, length
- 2);
2203 cta
.have_hf_scdb
= 1;
2206 hex_block(" ", x
+ 1, length
);
2212 void edid_state::cta_block(const unsigned char *x
, bool duplicate
)
2214 unsigned length
= x
[0] & 0x1f;
2217 bool reverse
= false;
2218 bool audio_block
= false;
2220 switch ((x
[0] & 0xe0) >> 5) {
2222 data_block
= "Audio Data Block";
2223 printf(" %s:\n", data_block
.c_str());
2224 cta_audio_block(x
+ 1, length
);
2228 data_block
= "Video Data Block";
2229 printf(" %s:\n", data_block
.c_str());
2230 cta_svd(x
+ 1, length
, false);
2233 oui
= (x
[3] << 16) + (x
[2] << 8) + x
[1];
2234 name
= oui_name(oui
);
2236 name
= oui_name(oui
, true);
2241 printf(" Vendor-Specific Data Block, OUI %s:\n", ouitohex(oui
).c_str());
2242 hex_block(" ", x
+ 4, length
- 3);
2244 warn("Unknown Vendor-Specific Data Block, OUI %s.\n",
2245 ouitohex(oui
).c_str());
2248 data_block
= std::string("Vendor-Specific Data Block (") + name
+ ")";
2250 fail((std::string("OUI ") + ouitohex(oui
) + " is in the wrong byte order\n").c_str());
2251 printf(" %s, OUI %s:\n", data_block
.c_str(), ouitohex(oui
).c_str());
2252 if (oui
== 0x000c03) {
2253 cta_hdmi_block(x
+ 4, length
- 3);
2254 cta
.last_block_was_hdmi_vsdb
= 1;
2255 cta
.first_block
= 0;
2256 // The HDMI OUI is present, so this EDID represents an HDMI
2257 // interface. And HDMI interfaces must use EDID version 1.3
2258 // according to the HDMI Specification, so check for this.
2259 if (base
.edid_minor
!= 3)
2260 fail("The HDMI Specification requires EDID 1.3 instead of 1.%u.\n",
2264 if (oui
== 0xc45dd8) {
2265 if (!cta
.last_block_was_hdmi_vsdb
)
2266 fail("HDMI Forum VSDB did not immediately follow the HDMI VSDB.\n");
2267 if (cta
.have_hf_scdb
|| cta
.have_hf_vsdb
)
2268 fail("Duplicate HDMI Forum VSDB/SCDB.\n");
2269 cta_hf_scdb(x
+ 4, length
- 3);
2270 cta
.have_hf_vsdb
= 1;
2273 if (oui
== 0x00001a) {
2274 cta_amd(x
+ 4, length
- 3);
2277 if (oui
== 0xca125c && length
== 0x15) {
2278 cta_microsoft(x
+ 4, length
- 3);
2281 hex_block(" ", x
+ 4, length
- 3);
2284 data_block
= "Speaker Allocation Data Block";
2285 printf(" %s:\n", data_block
.c_str());
2286 cta_sadb(x
+ 1, length
);
2289 fail("Only one instance of this Data Block is allowed.\n");
2292 data_block
= "VESA Display Transfer Characteristics Data Block";
2293 printf(" %s:\n", data_block
.c_str());
2294 cta_vesa_dtcdb(x
+ 1, length
);
2296 fail("Only one instance of this Data Block is allowed.\n");
2299 cta_ext_block(x
+ 1, length
- 1, duplicate
);
2302 unsigned tag
= (*x
& 0xe0) >> 5;
2303 unsigned length
= *x
& 0x1f;
2305 printf(" Unknown CTA-861 tag 0x%02x, length %u\n", tag
, length
);
2306 hex_block(" ", x
+ 1, length
);
2308 warn("Unknown CTA-861 Data Block %u.\n", tag
);
2313 // See Table 52 of CTA-861-G for a description of Byte 3
2314 if (audio_block
&& !(cta
.byte3
& 0x40))
2315 fail("audio information is present, but bit 6 of Byte 3 of the CTA-861 Extension header indicates no Basic Audio support.\n");
2316 cta
.first_block
= 0;
2317 cta
.last_block_was_hdmi_vsdb
= 0;
2320 void edid_state::preparse_cta_block(const unsigned char *x
)
2322 unsigned version
= x
[1];
2323 unsigned offset
= x
[2];
2326 const unsigned char *detailed
;
2328 for (detailed
= x
+ offset
; detailed
+ 17 < x
+ 127; detailed
+= 18) {
2329 if (memchk(detailed
, 18))
2331 if (detailed
[0] || detailed
[1])
2332 cta
.preparsed_total_dtds
++;
2339 for (unsigned i
= 4; i
< offset
; i
+= (x
[i
] & 0x1f) + 1) {
2340 bool for_ycbcr420
= false;
2343 switch ((x
[i
] & 0xe0) >> 5) {
2345 oui
= (x
[i
+ 3] << 16) + (x
[i
+ 2] << 8) + x
[i
+ 1];
2346 if (oui
== 0x000c03) {
2347 cta
.has_hdmi
= true;
2348 cta
.preparsed_phys_addr
= (x
[i
+ 4] << 8) | x
[i
+ 5];
2352 if (x
[i
+ 1] == 0x0d)
2353 cta
.has_vfpdb
= true;
2354 if (x
[i
+ 1] == 0x13 && (x
[i
+ 2] & 0x40)) {
2355 cta
.preparsed_speaker_count
= 1 + (x
[i
+ 2] & 0x1f);
2356 cta
.preparsed_sld
= x
[i
+ 2] & 0x20;
2358 if (x
[i
+ 1] == 0x14)
2359 cta_preparse_sldb(x
+ i
+ 2, (x
[i
] & 0x1f) - 1);
2360 if (x
[i
+ 1] == 0x22)
2361 cta
.preparsed_total_vtdbs
++;
2362 if (x
[i
+ 1] == 0x23)
2363 cta
.preparsed_has_t8vtdb
= true;
2364 if (x
[i
+ 1] == 0x32)
2365 cta
.preparsed_total_vtdbs
+=
2366 ((x
[i
] & 0x1f) - 2) / (6 + ((x
[i
+ 2] & 0x70) >> 4));
2367 if (x
[i
+ 1] != 0x0e)
2369 for_ycbcr420
= true;
2372 for (unsigned j
= 1 + for_ycbcr420
; j
<= (x
[i
] & 0x1f); j
++) {
2373 unsigned char vic
= x
[i
+ j
];
2375 if ((vic
& 0x7f) <= 64)
2377 cta
.preparsed_svds
[for_ycbcr420
].push_back(vic
);
2378 cta
.preparsed_has_vic
[for_ycbcr420
][vic
] = true;
2385 void edid_state::parse_cta_block(const unsigned char *x
)
2387 unsigned version
= x
[1];
2388 unsigned offset
= x
[2];
2389 const unsigned char *detailed
;
2391 // See Table 52 of CTA-861-G for a description of Byte 3
2393 printf(" Revision: %u\n", version
);
2395 fail("Invalid CTA-861 Extension revision 0.\n");
2397 fail("Deprecated CTA-861 Extension revision 2.\n");
2398 if (cta
.has_hdmi
&& version
!= 3)
2399 fail("The HDMI Specification requires CTA Extension revision 3.\n");
2401 warn("Unknown CTA-861 Extension revision %u.\n", version
);
2403 if (version
>= 1) do {
2404 if (version
== 1 && x
[3] != 0)
2405 fail("Non-zero byte 3.\n");
2410 if (version
< 3 && ((offset
- 4) / 8)) {
2411 printf(" 8-byte timing descriptors: %u\n", (offset
- 4) / 8);
2412 fail("8-byte descriptors were never used.\n");
2417 printf(" Underscans IT Video Formats by default\n");
2419 warn("IT Video Formats are overscanned by default, but normally this should be underscanned.\n");
2421 printf(" Basic audio support\n");
2423 printf(" Supports YCbCr 4:4:4\n");
2425 printf(" Supports YCbCr 4:2:2\n");
2426 // Disable this test: this fails a lot of EDIDs, and there are
2427 // also some corner cases where you only want to receive 4:4:4
2428 // and refuse a fallback to 4:2:2.
2429 // if ((x[3] & 0x30) && (x[3] & 0x30) != 0x30)
2430 // msg(!cta.has_hdmi, "If YCbCr support is indicated, then both 4:2:2 and 4:4:4 %s be supported.\n",
2431 // cta.has_hdmi ? "shall" : "should");
2432 printf(" Native detailed modes: %u\n", x
[3] & 0x0f);
2433 if (cta
.first_block
)
2435 else if (x
[3] != cta
.byte3
)
2436 fail("Byte 3 must be the same for all CTA-861 Extension Blocks.\n");
2437 if (cta
.first_block
) {
2438 unsigned native_dtds
= x
[3] & 0x0f;
2440 cta
.native_timings
.clear();
2441 if (!native_dtds
&& !cta
.has_vfpdb
) {
2442 cta
.first_svd_might_be_preferred
= true;
2443 } else if (native_dtds
> cta
.preparsed_total_dtds
) {
2444 fail("There are more Native DTDs (%u) than DTDs (%u).\n",
2445 native_dtds
, cta
.preparsed_total_dtds
);
2447 if (native_dtds
> cta
.preparsed_total_dtds
)
2448 native_dtds
= cta
.preparsed_total_dtds
;
2449 for (unsigned i
= 0; i
< native_dtds
; i
++) {
2452 sprintf(type
, "DTD %3u", i
+ 1);
2453 cta
.native_timings
.push_back(timings_ext(i
+ 129, type
));
2455 if (cta
.has_hdmi
&& block_nr
!= (block_map
.saw_block_1
? 2 : 1))
2456 fail("The HDMI Specification requires that the first Extension Block (that is not a Block Map) is an CTA-861 Extension Block.\n");
2462 for (i
= 4; i
< offset
; i
+= (x
[i
] & 0x1f) + 1) {
2463 unsigned tag
= (x
[i
] & 0xe0) << 3;
2467 bool duplicate
= cta
.found_tags
.find(tag
) != cta
.found_tags
.end();
2469 cta_block(x
+ i
, duplicate
);
2471 cta
.found_tags
.insert(tag
);
2476 fail("Offset is %u, but should be %u.\n", offset
, i
);
2479 data_block
= "Detailed Timing Descriptors";
2480 base
.seen_non_detailed_descriptor
= false;
2482 for (detailed
= x
+ offset
; detailed
+ 17 < x
+ 127; detailed
+= 18) {
2483 if (memchk(detailed
, 18))
2487 printf(" %s:\n", data_block
.c_str());
2489 detailed_block(detailed
);
2491 if (!memchk(detailed
, x
+ 127 - detailed
)) {
2492 data_block
= "Padding";
2493 fail("CTA-861 padding contains non-zero bytes.\n");
2498 if (base
.has_serial_number
&& base
.has_serial_string
)
2499 warn("Display Product Serial Number is set, so the Serial Number in the Base EDID should be 0.\n");
2500 if (!cta
.has_vic_1
&& !base
.has_640x480p60_est_timing
)
2501 fail("Required 640x480p60 timings are missing in the established timings"
2502 " and the SVD list (VIC 1).\n");
2503 if ((cta
.supported_hdmi_vic_vsb_codes
& cta
.supported_hdmi_vic_codes
) !=
2504 cta
.supported_hdmi_vic_codes
)
2505 fail("HDMI VIC Codes must have their CTA-861 VIC equivalents in the VSB.\n");
2507 fail("Missing VCDB, needed for Set Selectable RGB Quantization to avoid interop issues.\n");
2510 void edid_state::cta_resolve_svr(vec_timings_ext::iterator iter
)
2512 if (iter
->svr() == 254) {
2513 iter
->flags
= cta
.t8vtdb
.flags
;
2514 iter
->t
= cta
.t8vtdb
.t
;
2515 } else if (iter
->svr() <= 144) {
2516 iter
->flags
= cta
.vec_dtds
[iter
->svr() - 129].flags
;
2517 iter
->t
= cta
.vec_dtds
[iter
->svr() - 129].t
;
2519 iter
->flags
= cta
.vec_vtdbs
[iter
->svr() - 145].flags
;
2520 iter
->t
= cta
.vec_vtdbs
[iter
->svr() - 145].t
;
2524 void edid_state::cta_resolve_svrs()
2526 for (vec_timings_ext::iterator iter
= cta
.preferred_timings
.begin();
2527 iter
!= cta
.preferred_timings
.end(); ++iter
) {
2528 if (iter
->has_svr())
2529 cta_resolve_svr(iter
);
2532 for (vec_timings_ext::iterator iter
= cta
.native_timings
.begin();
2533 iter
!= cta
.native_timings
.end(); ++iter
) {
2534 if (iter
->has_svr())
2535 cta_resolve_svr(iter
);
2539 void edid_state::check_cta_blocks()
2541 unsigned max_pref_prog_hact
= 0;
2542 unsigned max_pref_prog_vact
= 0;
2543 unsigned max_pref_ilace_hact
= 0;
2544 unsigned max_pref_ilace_vact
= 0;
2546 data_block
= "CTA-861";
2547 for (vec_timings_ext::iterator iter
= cta
.preferred_timings
.begin();
2548 iter
!= cta
.preferred_timings
.end(); ++iter
) {
2549 if (iter
->t
.interlaced
&&
2550 (iter
->t
.vact
> max_pref_ilace_vact
||
2551 (iter
->t
.vact
== max_pref_ilace_vact
&& iter
->t
.hact
>= max_pref_ilace_hact
))) {
2552 max_pref_ilace_hact
= iter
->t
.hact
;
2553 max_pref_ilace_vact
= iter
->t
.vact
;
2555 if (!iter
->t
.interlaced
&&
2556 (iter
->t
.vact
> max_pref_prog_vact
||
2557 (iter
->t
.vact
== max_pref_prog_vact
&& iter
->t
.hact
>= max_pref_prog_hact
))) {
2558 max_pref_prog_hact
= iter
->t
.hact
;
2559 max_pref_prog_vact
= iter
->t
.vact
;
2563 unsigned native_prog
= 0;
2564 unsigned native_prog_hact
= 0;
2565 unsigned native_prog_vact
= 0;
2566 bool native_prog_mixed_resolutions
= false;
2567 unsigned native_ilace
= 0;
2568 unsigned native_ilace_hact
= 0;
2569 unsigned native_ilace_vact
= 0;
2570 bool native_ilace_mixed_resolutions
= false;
2572 for (vec_timings_ext::iterator iter
= cta
.native_timings
.begin();
2573 iter
!= cta
.native_timings
.end(); ++iter
) {
2574 if (iter
->t
.interlaced
) {
2576 if (!native_ilace_hact
) {
2577 native_ilace_hact
= iter
->t
.hact
;
2578 native_ilace_vact
= iter
->t
.vact
;
2579 } else if (native_ilace_hact
!= iter
->t
.hact
||
2580 native_ilace_vact
!= iter
->t
.vact
) {
2581 native_ilace_mixed_resolutions
= true;
2585 if (!native_prog_hact
) {
2586 native_prog_hact
= iter
->t
.hact
;
2587 native_prog_vact
= iter
->t
.vact
;
2588 } else if (native_prog_hact
!= iter
->t
.hact
||
2589 native_prog_vact
!= iter
->t
.vact
) {
2590 native_prog_mixed_resolutions
= true;
2595 if (native_prog_mixed_resolutions
)
2596 fail("Native progressive timings are a mix of several resolutions.\n");
2597 if (native_ilace_mixed_resolutions
)
2598 fail("Native interlaced timings are a mix of several resolutions.\n");
2599 if (native_ilace
&& !native_prog
)
2600 fail("A native interlaced timing is present, but not a native progressive timing.\n");
2601 if (!native_prog_mixed_resolutions
&& native_prog
> 1)
2602 warn("Multiple native progressive timings are defined.\n");
2603 if (!native_ilace_mixed_resolutions
&& native_ilace
> 1)
2604 warn("Multiple native interlaced timings are defined.\n");
2606 if (!native_prog_mixed_resolutions
&& native_prog_vact
&&
2607 (max_pref_prog_vact
> native_prog_vact
||
2608 (max_pref_prog_vact
== native_prog_vact
&& max_pref_prog_hact
> native_prog_hact
)))
2609 warn("Native progressive resolution of %ux%u is smaller than the max preferred progressive resolution %ux%u.\n",
2610 native_prog_hact
, native_prog_vact
,
2611 max_pref_prog_hact
, max_pref_prog_vact
);
2612 if (!native_ilace_mixed_resolutions
&& native_ilace_vact
&&
2613 (max_pref_ilace_vact
> native_ilace_vact
||
2614 (max_pref_ilace_vact
== native_ilace_vact
&& max_pref_ilace_hact
> native_ilace_hact
)))
2615 warn("Native interlaced resolution of %ux%u is smaller than the max preferred interlaced resolution %ux%u.\n",
2616 native_ilace_hact
, native_ilace_vact
,
2617 max_pref_ilace_hact
, max_pref_ilace_vact
);
2619 if (dispid
.native_width
&& native_prog_hact
&&
2620 !native_prog_mixed_resolutions
) {
2621 if (dispid
.native_width
!= native_prog_hact
||
2622 dispid
.native_height
!= native_prog_vact
)
2623 fail("Mismatch between CTA-861 and DisplayID native progressive resolution.\n");