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>
14 #include "edid-decode.h"
16 static const struct timings edid_cta_modes1
[] = {
18 { 640, 480, 4, 3, 25175, 0, false, 16, 96, 48, false, 10, 2, 33, false },
19 { 720, 480, 4, 3, 27000, 0, false, 16, 62, 60, false, 9, 6, 30, false },
20 { 720, 480, 16, 9, 27000, 0, false, 16, 62, 60, false, 9, 6, 30, false },
21 { 1280, 720, 16, 9, 74250, 0, false, 110, 40, 220, true, 5, 5, 20, true },
22 { 1920, 1080, 16, 9, 74250, 0, true, 88, 44, 148, true, 2, 5, 15, true },
23 { 1440, 480, 4, 3, 27000, 0, true, 38, 124, 114, false, 4, 3, 15, false },
24 { 1440, 480, 16, 9, 27000, 0, true, 38, 124, 114, false, 4, 3, 15, false },
25 { 1440, 240, 4, 3, 27000, 0, false, 38, 124, 114, false, 4, 3, 15, false },
26 { 1440, 240, 16, 9, 27000, 0, false, 38, 124, 114, false, 4, 3, 15, false },
27 { 2880, 480, 4, 3, 54000, 0, true, 76, 248, 228, false, 4, 3, 15, false },
29 { 2880, 480, 16, 9, 54000, 0, true, 76, 248, 228, false, 4, 3, 15, false },
30 { 2880, 240, 4, 3, 54000, 0, false, 76, 248, 228, false, 4, 3, 15, false },
31 { 2880, 240, 16, 9, 54000, 0, false, 76, 248, 228, false, 4, 3, 15, false },
32 { 1440, 480, 4, 3, 54000, 0, false, 32, 124, 120, false, 9, 6, 30, false },
33 { 1440, 480, 16, 9, 54000, 0, false, 32, 124, 120, false, 9, 6, 30, false },
34 { 1920, 1080, 16, 9, 148500, 0, false, 88, 44, 148, true, 4, 5, 36, true },
35 { 720, 576, 4, 3, 27000, 0, false, 12, 64, 68, false, 5, 5, 39, false },
36 { 720, 576, 16, 9, 27000, 0, false, 12, 64, 68, false, 5, 5, 39, false },
37 { 1280, 720, 16, 9, 74250, 0, false, 440, 40, 220, true, 5, 5, 20, true },
38 { 1920, 1080, 16, 9, 74250, 0, true, 528, 44, 148, true, 2, 5, 15, true },
40 { 1440, 576, 4, 3, 27000, 0, true, 24, 126, 138, false, 2, 3, 19, false },
41 { 1440, 576, 16, 9, 27000, 0, true, 24, 126, 138, false, 2, 3, 19, false },
42 { 1440, 288, 4, 3, 27000, 0, false, 24, 126, 138, false, 2, 3, 19, false },
43 { 1440, 288, 16, 9, 27000, 0, false, 24, 126, 138, false, 2, 3, 19, false },
44 { 2880, 576, 4, 3, 54000, 0, true, 48, 252, 276, false, 2, 3, 19, false },
45 { 2880, 576, 16, 9, 54000, 0, true, 48, 252, 276, false, 2, 3, 19, false },
46 { 2880, 288, 4, 3, 54000, 0, false, 48, 252, 276, false, 2, 3, 19, false },
47 { 2880, 288, 16, 9, 54000, 0, false, 48, 252, 276, false, 2, 3, 19, false },
48 { 1440, 576, 4, 3, 54000, 0, false, 24, 128, 136, false, 5, 5, 39, false },
49 { 1440, 576, 16, 9, 54000, 0, false, 24, 128, 136, false, 5, 5, 39, false },
51 { 1920, 1080, 16, 9, 148500, 0, false, 528, 44, 148, true, 4, 5, 36, true },
52 { 1920, 1080, 16, 9, 74250, 0, false, 638, 44, 148, true, 4, 5, 36, true },
53 { 1920, 1080, 16, 9, 74250, 0, false, 528, 44, 148, true, 4, 5, 36, true },
54 { 1920, 1080, 16, 9, 74250, 0, false, 88, 44, 148, true, 4, 5, 36, true },
55 { 2880, 480, 4, 3, 108000, 0, false, 64, 248, 240, false, 9, 6, 30, false },
56 { 2880, 480, 16, 9, 108000, 0, false, 64, 248, 240, false, 9, 6, 30, false },
57 { 2880, 576, 4, 3, 108000, 0, false, 48, 256, 272, false, 5, 5, 39, false },
58 { 2880, 576, 16, 9, 108000, 0, false, 48, 256, 272, false, 5, 5, 39, false },
59 { 1920, 1080, 16, 9, 72000, 0, true, 32, 168, 184, true, 23, 5, 57, false, 0, 0, true },
60 { 1920, 1080, 16, 9, 148500, 0, true, 528, 44, 148, true, 2, 5, 15, true },
62 { 1280, 720, 16, 9, 148500, 0, false, 440, 40, 220, true, 5, 5, 20, true },
63 { 720, 576, 4, 3, 54000, 0, false, 12, 64, 68, false, 5, 5, 39, false },
64 { 720, 576, 16, 9, 54000, 0, false, 12, 64, 68, false, 5, 5, 39, false },
65 { 1440, 576, 4, 3, 54000, 0, true, 24, 126, 138, false, 2, 3, 19, false },
66 { 1440, 576, 16, 9, 54000, 0, true, 24, 126, 138, false, 2, 3, 19, false },
67 { 1920, 1080, 16, 9, 148500, 0, true, 88, 44, 148, true, 2, 5, 15, true },
68 { 1280, 720, 16, 9, 148500, 0, false, 110, 40, 220, true, 5, 5, 20, true },
69 { 720, 480, 4, 3, 54000, 0, false, 16, 62, 60, false, 9, 6, 30, false },
70 { 720, 480, 16, 9, 54000, 0, false, 16, 62, 60, false, 9, 6, 30, false },
71 { 1440, 480, 4, 3, 54000, 0, true, 38, 124, 114, false, 4, 3, 15, false },
73 { 1440, 480, 16, 9, 54000, 0, true, 38, 124, 114, false, 4, 3, 15, false },
74 { 720, 576, 4, 3, 108000, 0, false, 12, 64, 68, false, 5, 5, 39, false },
75 { 720, 576, 16, 9, 108000, 0, false, 12, 64, 68, false, 5, 5, 39, false },
76 { 1440, 576, 4, 3, 108000, 0, true, 24, 126, 138, false, 2, 3, 19, false },
77 { 1440, 576, 16, 9, 108000, 0, true, 24, 126, 138, false, 2, 3, 19, false },
78 { 720, 480, 4, 3, 108000, 0, false, 16, 62, 60, false, 9, 6, 30, false },
79 { 720, 480, 16, 9, 108000, 0, false, 16, 62, 60, false, 9, 6, 30, false },
80 { 1440, 480, 4, 3, 108000, 0, true, 38, 124, 114, false, 4, 3, 15, false },
81 { 1440, 480, 16, 9, 108000, 0, true, 38, 124, 114, false, 4, 3, 15, false },
82 { 1280, 720, 16, 9, 59400, 0, false, 1760, 40, 220, true, 5, 5, 20, true },
84 { 1280, 720, 16, 9, 74250, 0, false, 2420, 40, 220, true, 5, 5, 20, true },
85 { 1280, 720, 16, 9, 74250, 0, false, 1760, 40, 220, true, 5, 5, 20, true },
86 { 1920, 1080, 16, 9, 297000, 0, false, 88, 44, 148, true, 4, 5, 36, true },
87 { 1920, 1080, 16, 9, 297000, 0, false, 528, 44, 148, true, 4, 5, 36, true },
88 { 1280, 720, 64, 27, 59400, 0, false, 1760, 40, 220, true, 5, 5, 20, true },
89 { 1280, 720, 64, 27, 74250, 0, false, 2420, 40, 220, true, 5, 5, 20, true },
90 { 1280, 720, 64, 27, 74250, 0, false, 1760, 40, 220, true, 5, 5, 20, true },
91 { 1280, 720, 64, 27, 74250, 0, false, 440, 40, 220, true, 5, 5, 20, true },
92 { 1280, 720, 64, 27, 74250, 0, false, 110, 40, 220, true, 5, 5, 20, true },
93 { 1280, 720, 64, 27, 148500, 0, false, 440, 40, 220, true, 5, 5, 20, true },
95 { 1280, 720, 64, 27, 148500, 0, false, 110, 40, 220, true, 5, 5, 20, true },
96 { 1920, 1080, 64, 27, 74250, 0, false, 638, 44, 148, true, 4, 5, 36, true },
97 { 1920, 1080, 64, 27, 74250, 0, false, 528, 44, 148, true, 4, 5, 36, true },
98 { 1920, 1080, 64, 27, 74250, 0, false, 88, 44, 148, true, 4, 5, 36, true },
99 { 1920, 1080, 64, 27, 148500, 0, false, 528, 44, 148, true, 4, 5, 36, true },
100 { 1920, 1080, 64, 27, 148500, 0, false, 88, 44, 148, true, 4, 5, 36, true },
101 { 1920, 1080, 64, 27, 297000, 0, false, 528, 44, 148, true, 4, 5, 36, true },
102 { 1920, 1080, 64, 27, 297000, 0, false, 88, 44, 148, true, 4, 5, 36, true },
103 { 1680, 720, 64, 27, 59400, 0, false, 1360, 40, 220, true, 5, 5, 20, true },
104 { 1680, 720, 64, 27, 59400, 0, false, 1228, 40, 220, true, 5, 5, 20, true },
106 { 1680, 720, 64, 27, 59400, 0, false, 700, 40, 220, true, 5, 5, 20, true },
107 { 1680, 720, 64, 27, 82500, 0, false, 260, 40, 220, true, 5, 5, 20, true },
108 { 1680, 720, 64, 27, 99000, 0, false, 260, 40, 220, true, 5, 5, 20, true },
109 { 1680, 720, 64, 27, 165000, 0, false, 60, 40, 220, true, 5, 5, 95, true },
110 { 1680, 720, 64, 27, 198000, 0, false, 60, 40, 220, true, 5, 5, 95, true },
111 { 2560, 1080, 64, 27, 99000, 0, false, 998, 44, 148, true, 4, 5, 11, true },
112 { 2560, 1080, 64, 27, 90000, 0, false, 448, 44, 148, true, 4, 5, 36, true },
113 { 2560, 1080, 64, 27, 118800, 0, false, 768, 44, 148, true, 4, 5, 36, true },
114 { 2560, 1080, 64, 27, 185625, 0, false, 548, 44, 148, true, 4, 5, 36, true },
115 { 2560, 1080, 64, 27, 198000, 0, false, 248, 44, 148, true, 4, 5, 11, true },
117 { 2560, 1080, 64, 27, 371250, 0, false, 218, 44, 148, true, 4, 5, 161, true },
118 { 2560, 1080, 64, 27, 495000, 0, false, 548, 44, 148, true, 4, 5, 161, true },
119 { 3840, 2160, 16, 9, 297000, 0, false, 1276, 88, 296, true, 8, 10, 72, true },
120 { 3840, 2160, 16, 9, 297000, 0, false, 1056, 88, 296, true, 8, 10, 72, true },
121 { 3840, 2160, 16, 9, 297000, 0, false, 176, 88, 296, true, 8, 10, 72, true },
122 { 3840, 2160, 16, 9, 594000, 0, false, 1056, 88, 296, true, 8, 10, 72, true },
123 { 3840, 2160, 16, 9, 594000, 0, false, 176, 88, 296, true, 8, 10, 72, true },
124 { 4096, 2160, 256, 135, 297000, 0, false, 1020, 88, 296, true, 8, 10, 72, true },
125 { 4096, 2160, 256, 135, 297000, 0, false, 968, 88, 128, true, 8, 10, 72, true },
126 { 4096, 2160, 256, 135, 297000, 0, false, 88, 88, 128, true, 8, 10, 72, true },
128 { 4096, 2160, 256, 135, 594000, 0, false, 968, 88, 128, true, 8, 10, 72, true },
129 { 4096, 2160, 256, 135, 594000, 0, false, 88, 88, 128, true, 8, 10, 72, true },
130 { 3840, 2160, 64, 27, 297000, 0, false, 1276, 88, 296, true, 8, 10, 72, true },
131 { 3840, 2160, 64, 27, 297000, 0, false, 1056, 88, 296, true, 8, 10, 72, true },
132 { 3840, 2160, 64, 27, 297000, 0, false, 176, 88, 296, true, 8, 10, 72, true },
133 { 3840, 2160, 64, 27, 594000, 0, false, 1056, 88, 296, true, 8, 10, 72, true },
134 { 3840, 2160, 64, 27, 594000, 0, false, 176, 88, 296, true, 8, 10, 72, true },
135 { 1280, 720, 16, 9, 90000, 0, false, 960, 40, 220, true, 5, 5, 20, true },
136 { 1280, 720, 64, 27, 90000, 0, false, 960, 40, 220, true, 5, 5, 20, true },
137 { 1680, 720, 64, 27, 99000, 0, false, 810, 40, 220, true, 5, 5, 20, true },
139 { 1920, 1080, 16, 9, 148500, 0, false, 638, 44, 148, true, 4, 5, 36, true },
140 { 1920, 1080, 64, 27, 148500, 0, false, 638, 44, 148, true, 4, 5, 36, true },
141 { 2560, 1080, 64, 27, 198000, 0, false, 998, 44, 148, true, 4, 5, 11, true },
142 { 3840, 2160, 16, 9, 594000, 0, false, 1276, 88, 296, true, 8, 10, 72, true },
143 { 4096, 2160, 256, 135, 594000, 0, false, 1020, 88, 296, true, 8, 10, 72, true },
144 { 3840, 2160, 64, 27, 594000, 0, false, 1276, 88, 296, true, 8, 10, 72, true },
145 { 3840, 2160, 16, 9, 1188000, 0, false, 1056, 88, 296, true, 8, 10, 72, true },
146 { 3840, 2160, 16, 9, 1188000, 0, false, 176, 88, 296, true, 8, 10, 72, true },
147 { 3840, 2160, 64, 27, 1188000, 0, false, 1056, 88, 296, true, 8, 10, 72, true },
148 { 3840, 2160, 64, 27, 1188000, 0, false, 176, 88, 296, true, 8, 10, 72, true },
150 { 5120, 2160, 64, 27, 396000, 0, false, 1996, 88, 296, true, 8, 10, 22, true },
151 { 5120, 2160, 64, 27, 396000, 0, false, 1696, 88, 296, true, 8, 10, 22, true },
152 { 5120, 2160, 64, 27, 396000, 0, false, 664, 88, 128, true, 8, 10, 22, true },
153 { 5120, 2160, 64, 27, 742500, 0, false, 746, 88, 296, true, 8, 10, 297, true },
154 { 5120, 2160, 64, 27, 742500, 0, false, 1096, 88, 296, true, 8, 10, 72, true },
155 { 5120, 2160, 64, 27, 742500, 0, false, 164, 88, 128, true, 8, 10, 72, true },
156 { 5120, 2160, 64, 27, 1485000, 0, false, 1096, 88, 296, true, 8, 10, 72, true },
159 static const struct timings edid_cta_modes2
[] = {
161 { 5120, 2160, 64, 27, 1485000, 0, false, 164, 88, 128, true, 8, 10, 72, true },
162 { 7680, 4320, 16, 9, 1188000, 0, false, 2552, 176, 592, true, 16, 20, 144, true },
163 { 7680, 4320, 16, 9, 1188000, 0, false, 2352, 176, 592, true, 16, 20, 44, true },
164 { 7680, 4320, 16, 9, 1188000, 0, false, 552, 176, 592, true, 16, 20, 44, true },
165 { 7680, 4320, 16, 9, 2376000, 0, false, 2552, 176, 592, true, 16, 20, 144, true },
166 { 7680, 4320, 16, 9, 2376000, 0, false, 2352, 176, 592, true, 16, 20, 44, true },
167 { 7680, 4320, 16, 9, 2376000, 0, false, 552, 176, 592, true, 16, 20, 44, true },
168 { 7680, 4320, 16, 9, 4752000, 0, false, 2112, 176, 592, true, 16, 20, 144, true },
170 { 7680, 4320, 16, 9, 4752000, 0, false, 352, 176, 592, true, 16, 20, 144, true },
171 { 7680, 4320, 64, 27, 1188000, 0, false, 2552, 176, 592, true, 16, 20, 144, true },
172 { 7680, 4320, 64, 27, 1188000, 0, false, 2352, 176, 592, true, 16, 20, 44, true },
173 { 7680, 4320, 64, 27, 1188000, 0, false, 552, 176, 592, true, 16, 20, 44, true },
174 { 7680, 4320, 64, 27, 2376000, 0, false, 2552, 176, 592, true, 16, 20, 144, true },
175 { 7680, 4320, 64, 27, 2376000, 0, false, 2352, 176, 592, true, 16, 20, 44, true },
176 { 7680, 4320, 64, 27, 2376000, 0, false, 552, 176, 592, true, 16, 20, 44, true },
177 { 7680, 4320, 64, 27, 4752000, 0, false, 2112, 176, 592, true, 16, 20, 144, true },
178 { 7680, 4320, 64, 27, 4752000, 0, false, 352, 176, 592, true, 16, 20, 144, true },
179 { 10240, 4320, 64, 27, 1485000, 0, false, 1492, 176, 592, true, 16, 20, 594, true },
181 { 10240, 4320, 64, 27, 1485000, 0, false, 2492, 176, 592, true, 16, 20, 44, true },
182 { 10240, 4320, 64, 27, 1485000, 0, false, 288, 176, 296, true, 16, 20, 144, true },
183 { 10240, 4320, 64, 27, 2970000, 0, false, 1492, 176, 592, true, 16, 20, 594, true },
184 { 10240, 4320, 64, 27, 2970000, 0, false, 2492, 176, 592, true, 16, 20, 44, true },
185 { 10240, 4320, 64, 27, 2970000, 0, false, 288, 176, 296, true, 16, 20, 144, true },
186 { 10240, 4320, 64, 27, 5940000, 0, false, 2192, 176, 592, true, 16, 20, 144, true },
187 { 10240, 4320, 64, 27, 5940000, 0, false, 288, 176, 296, true, 16, 20, 144, true },
188 { 4096, 2160, 256, 135, 1188000, 0, false, 800, 88, 296, true, 8, 10, 72, true },
189 { 4096, 2160, 256, 135, 1188000, 0, false, 88, 88, 128, true, 8, 10, 72, true },
192 static const cta_rid rids
[] = {
195 { 1280, 720, 16, 9 },
196 { 1280, 720, 64, 27 },
197 { 1680, 720, 64, 27 },
198 { 1920, 1080, 16, 9 },
199 { 1920, 1080, 64, 27 },
200 { 2560, 1080, 64, 27 },
201 { 3840, 1080, 32, 9 },
202 { 2560, 1440, 16, 9 },
203 { 3440, 1440, 64, 27 },
205 { 5120, 1440, 32, 9 },
206 { 3840, 2160, 16, 9 },
207 { 3840, 2160, 64, 27 },
208 { 5120, 2160, 64, 27 },
209 { 7680, 2160, 32, 9 },
210 { 5120, 2880, 16, 9 },
211 { 5120, 2880, 64, 27 },
212 { 6880, 2880, 64, 27 },
213 { 10240, 2880, 32, 9 },
214 { 7680, 4320, 16, 9 },
216 { 7680, 4320, 64, 27 },
217 { 10240, 4320, 64, 27 },
218 { 15360, 4320, 32, 9 },
219 { 11520, 6480, 16, 9 },
220 { 11520, 6480, 64, 27 },
221 { 15360, 6480, 64, 27 },
222 { 15360, 8640, 16, 9 },
223 { 15360, 8640, 64, 27 },
224 { 20480, 8640, 64, 27 },
227 static const unsigned char rid2vic
[ARRAY_SIZE(rids
)][8] = {
230 { 60, 61, 62, 108, 19, 4, 41, 47 },
231 { 65, 66, 67, 109, 68, 69, 70, 71 },
232 { 79, 80, 81, 110, 82, 83, 84, 85 },
233 { 32, 33, 34, 111, 31, 16, 64, 63 },
234 { 72, 73, 74, 112, 75, 76, 77, 78 },
235 { 86, 87, 88, 113, 89, 90, 91, 92 },
241 { 93, 94, 95, 114, 96, 97, 117, 118 },
242 { 103, 104, 105, 116, 106, 107, 119, 120 },
243 { 121, 122, 123, 124, 125, 126, 127, 193 },
249 { 194, 195, 196, 197, 198, 199, 200, 201 },
251 { 202, 203, 204, 205, 206, 207, 208, 209 },
252 { 210, 211, 212, 213, 214, 215, 216, 217 },
262 static const unsigned vf_rate_values
[] = {
264 0, 24, 25, 30, 48, 50, 60, 100,
265 /* Rate Index 8-15 */
266 120, 144, 200, 240, 300, 360, 400, 480,
269 static const unsigned char edid_hdmi_mode_map
[] = { 95, 94, 93, 98 };
271 unsigned char hdmi_vic_to_vic(unsigned char hdmi_vic
)
273 if (hdmi_vic
> 0 && hdmi_vic
<= ARRAY_SIZE(edid_hdmi_mode_map
))
274 return edid_hdmi_mode_map
[hdmi_vic
- 1];
278 const struct timings
*find_vic_id(unsigned char vic
)
280 if (vic
> 0 && vic
<= ARRAY_SIZE(edid_cta_modes1
))
281 return edid_cta_modes1
+ vic
- 1;
282 if (vic
>= 193 && vic
< ARRAY_SIZE(edid_cta_modes2
) + 193)
283 return edid_cta_modes2
+ vic
- 193;
287 const struct timings
*find_hdmi_vic_id(unsigned char hdmi_vic
)
289 if (hdmi_vic
> 0 && hdmi_vic
<= ARRAY_SIZE(edid_hdmi_mode_map
))
290 return find_vic_id(edid_hdmi_mode_map
[hdmi_vic
- 1]);
294 const struct cta_rid
*find_rid(unsigned char rid
)
296 if (rid
> 0 && rid
< ARRAY_SIZE(rids
))
301 static unsigned char rid_to_vic(unsigned char rid
, unsigned char rate_index
)
303 if (vf_rate_values
[rate_index
] > 120)
305 return rid2vic
[rid
][rate_index
- 1];
308 const struct timings
*cta_close_match_to_vic(const timings
&t
, unsigned &vic
)
310 for (vic
= 1; vic
<= ARRAY_SIZE(edid_cta_modes1
); vic
++) {
311 if (timings_close_match(t
, edid_cta_modes1
[vic
- 1]))
312 return &edid_cta_modes1
[vic
- 1];
314 for (vic
= 193; vic
< ARRAY_SIZE(edid_cta_modes2
) + 193; vic
++) {
315 if (timings_close_match(t
, edid_cta_modes1
[vic
- 193]))
316 return &edid_cta_modes1
[vic
- 193];
322 bool cta_matches_vic(const timings
&t
, unsigned &vic
)
324 for (vic
= 1; vic
<= ARRAY_SIZE(edid_cta_modes1
); vic
++) {
325 if (match_timings(t
, edid_cta_modes1
[vic
- 1]))
328 for (vic
= 193; vic
< ARRAY_SIZE(edid_cta_modes2
) + 193; vic
++) {
329 if (match_timings(t
, edid_cta_modes1
[vic
- 193]))
336 void edid_state::cta_list_vics()
339 for (unsigned vic
= 1; vic
<= ARRAY_SIZE(edid_cta_modes1
); vic
++) {
340 sprintf(type
, "VIC %3u", vic
);
341 print_timings("", &edid_cta_modes1
[vic
- 1], type
, "", false, false);
343 for (unsigned vic
= 193; vic
< ARRAY_SIZE(edid_cta_modes2
) + 193; vic
++) {
344 sprintf(type
, "VIC %3u", vic
);
345 print_timings("", &edid_cta_modes2
[vic
- 193], type
, "", false, false);
349 void edid_state::cta_list_hdmi_vics()
351 for (unsigned i
= 0; i
< ARRAY_SIZE(edid_hdmi_mode_map
); i
++) {
352 unsigned vic
= edid_hdmi_mode_map
[i
];
355 sprintf(type
, "HDMI VIC %u", i
+ 1);
356 print_timings("", find_vic_id(vic
), type
, "", false, false);
360 void edid_state::cta_list_rids()
362 for (unsigned i
= 1; i
< ARRAY_SIZE(rids
); i
++) {
363 printf("RID %2u: %5ux%-4u %2u:%-2u\n", i
,
364 rids
[i
].hact
, rids
[i
].vact
,
365 rids
[i
].hratio
, rids
[i
].vratio
);
369 void edid_state::cta_list_rid_timings(unsigned list_rid
)
371 for (unsigned rid
= 1; rid
< ARRAY_SIZE(rids
); rid
++) {
374 if (list_rid
&& rid
!= list_rid
)
377 sprintf(type
, "RID %u", rid
);
378 for (unsigned i
= 1; i
< ARRAY_SIZE(vf_rate_values
); i
++) {
379 unsigned fps
= vf_rate_values
[i
];
381 if (rid_to_vic(rid
, i
)) {
382 printf("%s: %5ux%-4u %7.3f Hz %3u:%-2u maps to VIC %u\n", type
,
383 rids
[rid
].hact
, rids
[rid
].vact
, (double)fps
,
384 rids
[rid
].hratio
, rids
[rid
].vratio
,
388 timings t
= calc_ovt_mode(rids
[rid
].hact
, rids
[rid
].vact
,
389 rids
[rid
].hratio
, rids
[rid
].vratio
, fps
);
390 print_timings("", &t
, type
, "", false, false);
395 static std::string
audio_ext_format(unsigned char x
)
397 if (x
>= 1 && x
<= 3)
398 fail("Obsolete Audio Ext Format 0x%02x.\n", x
);
400 case 1: return "HE AAC (Obsolete)";
401 case 2: return "HE AAC v2 (Obsolete)";
402 case 3: return "MPEG Surround (Obsolete)";
403 case 4: return "MPEG-4 HE AAC";
404 case 5: return "MPEG-4 HE AAC v2";
405 case 6: return "MPEG-4 AAC LC";
406 case 7: return "DRA";
407 case 8: return "MPEG-4 HE AAC + MPEG Surround";
408 case 10: return "MPEG-4 AAC LC + MPEG Surround";
409 case 11: return "MPEG-H 3D Audio";
410 case 12: return "AC-4";
411 case 13: return "L-PCM 3D Audio";
412 case 14: return "Auro-Cx";
413 case 15: return "MPEG-D USAC";
416 fail("Unknown Audio Ext Format 0x%02x.\n", x
);
417 return std::string("Unknown Audio Ext Format (") + utohex(x
) + ")";
420 static std::string
audio_format(unsigned char x
)
423 case 1: return "Linear PCM";
424 case 2: return "AC-3";
425 case 3: return "MPEG 1 (Layers 1 & 2)";
426 case 4: return "MPEG 1 Layer 3 (MP3)";
427 case 5: return "MPEG2 (multichannel)";
428 case 6: return "AAC LC";
429 case 7: return "DTS";
430 case 8: return "ATRAC";
431 case 9: return "One Bit Audio";
432 case 10: return "Enhanced AC-3 (DD+)";
433 case 11: return "DTS-HD";
434 case 12: return "MAT (MLP)";
435 case 13: return "DST";
436 case 14: return "WMA Pro";
439 fail("Unknown Audio Format 0x%02x.\n", x
);
440 return std::string("Unknown Audio Format (") + utohex(x
) + ")";
443 static std::string
mpeg_h_3d_audio_level(unsigned char x
)
446 case 0: return "Unspecified";
447 case 1: return "Level 1";
448 case 2: return "Level 2";
449 case 3: return "Level 3";
450 case 4: return "Level 4";
451 case 5: return "Level 5";
454 fail("Unknown MPEG-H 3D Audio Level 0x%02x.\n", x
);
455 return std::string("Unknown MPEG-H 3D Audio Level (") + utohex(x
) + ")";
458 static void cta_audio_block(const unsigned char *x
, unsigned length
)
460 unsigned i
, format
, ext_format
;
463 fail("Broken CTA-861 audio block length %d.\n", length
);
467 for (i
= 0; i
< length
; i
+= 3) {
468 format
= (x
[i
] & 0x78) >> 3;
470 printf(" Reserved (0x00)\n");
471 fail("Audio Format Code 0x00 is reserved.\n");
476 printf(" %s:\n", audio_format(format
).c_str());
478 ext_format
= (x
[i
+ 2] & 0xf8) >> 3;
479 printf(" %s:\n", audio_ext_format(ext_format
).c_str());
482 printf(" Max channels: %u\n", (x
[i
] & 0x07)+1);
483 else if (ext_format
== 11)
484 printf(" MPEG-H 3D Audio Level: %s\n",
485 mpeg_h_3d_audio_level(x
[i
] & 0x07).c_str());
486 else if (ext_format
== 13)
487 printf(" Max channels: %u\n",
488 (((x
[i
+ 1] & 0x80) >> 3) | ((x
[i
] & 0x80) >> 4) |
490 else if ((ext_format
== 12 || ext_format
== 14) && (x
[i
] & 0x07))
491 fail("Bits F10-F12 must be 0.\n");
493 printf(" Max channels: %u\n", (x
[i
] & 0x07)+1);
495 if ((format
== 1 || format
== 14) && (x
[i
+ 2] & 0xf8))
496 fail("Bits F33-F37 must be 0.\n");
497 if (ext_format
!= 13 && (x
[i
+1] & 0x80))
498 fail("Bit F27 must be 0.\n");
500 // Several sample rates are not supported in certain formats
501 if (ext_format
== 12 && (x
[i
+1] & 0x29))
502 fail("Bits F20, F23 and F25 must be 0.\n");
503 if (ext_format
>= 4 && ext_format
<= 6 && (x
[i
+1] & 0x60))
504 fail("Bits F25 and F26 must be 0.\n");
505 if ((ext_format
== 8 || ext_format
== 10 || ext_format
== 15) && (x
[i
+1] & 0x60))
506 fail("Bits F25 and F26 must be 0.\n");
508 printf(" Supported sample rates (kHz):%s%s%s%s%s%s%s\n",
509 (x
[i
+1] & 0x40) ? " 192" : "",
510 (x
[i
+1] & 0x20) ? " 176.4" : "",
511 (x
[i
+1] & 0x10) ? " 96" : "",
512 (x
[i
+1] & 0x08) ? " 88.2" : "",
513 (x
[i
+1] & 0x04) ? " 48" : "",
514 (x
[i
+1] & 0x02) ? " 44.1" : "",
515 (x
[i
+1] & 0x01) ? " 32" : "");
516 if (format
== 1 || ext_format
== 13) {
517 printf(" Supported sample sizes (bits):%s%s%s\n",
518 (x
[i
+2] & 0x04) ? " 24" : "",
519 (x
[i
+2] & 0x02) ? " 20" : "",
520 (x
[i
+2] & 0x01) ? " 16" : "");
521 } else if (format
<= 8) {
522 printf(" Maximum bit rate: %u kb/s\n", x
[i
+2] * 8);
523 } else if (format
== 10) {
524 // As specified by the "Dolby Audio and Dolby Atmos over HDMI"
525 // specification (v1.0).
527 printf(" Supports Joint Object Coding\n");
529 printf(" Supports Joint Object Coding with ACMOD28\n");
530 } else if (format
== 11) {
531 // Reverse engineering, see:
532 // https://www.avsforum.com/threads/lg-c9-earc-info-thread.3072900/post-61795538
534 printf(" Supports DTS:X\n");
535 // Note: I strongly suspect that bit 0 indicates DTS-HD MA support.
536 printf(" Audio Format Code dependent value: 0x%02x\n", x
[i
+2]);
537 } else if (format
== 12) {
539 printf(" Supports Dolby TrueHD, object audio PCM and channel-based PCM\n");
540 printf(" Hash calculation %srequired for object audio PCM or channel-based PCM\n",
541 (x
[i
+2] & 2) ? "not " : "");
543 printf(" Supports only Dolby TrueHD\n");
545 } else if (format
== 14) {
546 printf(" Profile: %u\n", x
[i
+2] & 7);
547 } else if (format
>= 9 && format
<= 13) {
548 printf(" Audio Format Code dependent value: 0x%02x\n", x
[i
+2]);
549 } else if (ext_format
== 11 && (x
[i
+2] & 1)) {
550 printf(" Supports MPEG-H 3D Audio Low Complexity Profile\n");
551 } else if ((ext_format
>= 4 && ext_format
<= 6) ||
552 ext_format
== 8 || ext_format
== 10) {
553 printf(" AAC audio frame lengths:%s%s\n",
554 (x
[i
+2] & 4) ? " 1024_TL" : "",
555 (x
[i
+2] & 2) ? " 960_TL" : "");
556 if (ext_format
>= 8 && (x
[i
+2] & 1))
557 printf(" Supports %s signaled MPEG Surround data\n",
558 (x
[i
+2] & 1) ? "implicitly and explicitly" : "only implicitly");
559 if (ext_format
== 6 && (x
[i
+2] & 1))
560 printf(" Supports 22.2ch System H\n");
561 } else if (ext_format
== 12 || ext_format
== 14) {
562 printf(" Audio Format Code dependent value: %u\n", x
[i
+2] & 7);
567 void edid_state::cta_svd(const unsigned char *x
, unsigned n
, bool for_ycbcr420
)
569 bool ascending
= !for_ycbcr420
;
570 unsigned char last_vic
= 0;
571 bool first_vic_is_1_to_4
= false;
572 bool have_vics_5_and_up
= false;
575 for (i
= 0; i
< n
; i
++) {
576 const struct timings
*t
= NULL
;
577 unsigned char svd
= x
[i
];
578 unsigned char native
;
581 if ((svd
& 0x7f) == 0)
584 if ((svd
- 1) & 0x40) {
593 first_vic_is_1_to_4
= vic
<= 4;
595 have_vics_5_and_up
= true;
600 t
= find_vic_id(vic
);
604 cta
.supported_hdmi_vic_vsb_codes
|= 1 << 0;
607 cta
.supported_hdmi_vic_vsb_codes
|= 1 << 1;
610 cta
.supported_hdmi_vic_vsb_codes
|= 1 << 2;
613 cta
.supported_hdmi_vic_vsb_codes
|= 1 << 3;
616 bool first_svd
= cta
.first_svd
&& !for_ycbcr420
;
617 bool override_pref
= first_svd
&& cta
.first_svd_might_be_preferred
;
620 sprintf(type
, "VIC %3u", vic
);
621 const char *flags
= native
? "native" : "";
624 struct timings tmp
= *t
;
626 print_timings(" ", &tmp
, type
, flags
);
628 print_timings(" ", t
, type
, flags
);
631 if (!cta
.preferred_timings
.empty()) {
632 if (match_timings(cta
.preferred_timings
[0].t
, *t
))
633 warn("For improved preferred timing interoperability, set 'Native detailed modes' to 1.\n");
635 warn("VIC %u is the preferred timing, overriding the first detailed timings. Is this intended?\n", vic
);
637 cta
.preferred_timings
.insert(cta
.preferred_timings
.begin(),
638 timings_ext(*t
, type
, flags
));
639 } else if (first_svd
) {
640 cta
.preferred_timings
.push_back(timings_ext(*t
, type
, flags
));
643 cta
.first_svd
= false;
644 cta
.first_svd_might_be_preferred
= false;
647 cta
.native_timings
.push_back(timings_ext(*t
, type
, flags
));
649 printf(" Unknown (VIC %3u)\n", vic
);
650 fail("Unknown VIC %u.\n", vic
);
653 if (vic
== 1 && !for_ycbcr420
)
655 if (++cta
.vics
[vic
][for_ycbcr420
] == 2)
656 fail("Duplicate %sVIC %u.\n", for_ycbcr420
? "YCbCr 4:2:0 " : "", vic
);
657 if (for_ycbcr420
&& cta
.preparsed_has_vic
[0][vic
])
658 fail("YCbCr 4:2:0-only VIC %u is also a regular VIC.\n", vic
);
660 if (n
> 1 && ascending
&& first_vic_is_1_to_4
&& have_vics_5_and_up
)
661 warn("All VICs are in ascending order, and the first (preferred) VIC <= 4, is that intended?\n");
664 cta_vfd
edid_state::cta_parse_vfd(const unsigned char *x
, unsigned lvfd
)
668 vfd
.rid
= x
[0] & 0x3f;
669 if (vfd
.rid
>= ARRAY_SIZE(rids
)) {
673 vfd
.bfr50
= !!(x
[0] & 0x80);
674 vfd
.fr24
= !!(x
[0] & 0x40);
675 vfd
.bfr60
= lvfd
> 1 ? !!(x
[1] & 0x80) : 1;
676 vfd
.fr144
= lvfd
> 1 ? !!(x
[1] & 0x40) : 0;
677 vfd
.fr_factor
= lvfd
> 1 ? (x
[1] & 0x3f) : 3;
678 vfd
.fr48
= lvfd
> 2 ? !!(x
[2] & 0x01) : 0;
682 static bool vfd_has_rate(cta_vfd
&vfd
, unsigned rate_index
)
684 static const unsigned factors
[6] = {
687 unsigned rate
= vf_rate_values
[rate_index
];
710 for (unsigned i
= 0; i
< ARRAY_SIZE(factors
); i
++)
711 if (factors
[i
] == factor
&& (vfd
.fr_factor
& (1 << i
)))
716 void edid_state::cta_vfdb(const unsigned char *x
, unsigned n
)
719 fail("Length is 0.\n");
722 unsigned char flags
= *x
++;
723 unsigned lvfd
= (flags
& 3) + 1;
726 fail("Length - 1 is not a multiple of Lvfd (%u).\n", lvfd
);
730 printf(" Supports YCbCr 4:2:0\n");
732 printf(" NTSC fractional frame rates are preferred\n");
733 for (unsigned i
= 0; i
< n
; i
+= lvfd
, x
+= lvfd
) {
734 unsigned char rid
= x
[0] & 0x3f;
735 cta_vfd vfd
= cta_parse_vfd(x
, lvfd
);
737 if (lvfd
> 2 && (x
[2] & 0xfe))
738 fail("Bits F31-F37 must be 0.\n");
739 if (lvfd
> 3 && x
[3])
740 fail("Bits F40-F47 must be 0.\n");
741 if (rid
== 0 || rid
>= ARRAY_SIZE(rids
)) {
742 fail("Unknown RID %u.\n", rid
);
745 for (unsigned rate_index
= 1; rate_index
< ARRAY_SIZE(vf_rate_values
); rate_index
++) {
746 if (!vfd_has_rate(vfd
, rate_index
))
748 struct timings t
= calc_ovt_mode(rids
[vfd
.rid
].hact
,
750 rids
[vfd
.rid
].hratio
,
751 rids
[vfd
.rid
].vratio
,
752 vf_rate_values
[rate_index
]);
754 sprintf(type
, "RID %u@%up", rid
, vf_rate_values
[rate_index
]);
755 print_timings(" ", &t
, type
);
756 if (rid_to_vic(vfd
.rid
, rate_index
))
757 fail("%s not allowed since it maps to VIC %u.\n",
758 type
, rid_to_vic(vfd
.rid
, rate_index
));
763 void edid_state::print_vic_index(const char *prefix
, unsigned idx
, const char *suffix
, bool ycbcr420
)
767 if (idx
< cta
.preparsed_svds
[0].size()) {
768 unsigned char vic
= cta
.preparsed_svds
[0][idx
];
769 const struct timings
*t
= find_vic_id(vic
);
772 sprintf(buf
, "VIC %3u", vic
);
775 struct timings tmp
= *t
;
776 tmp
.ycbcr420
= ycbcr420
;
777 print_timings(prefix
, &tmp
, buf
, suffix
);
779 printf("%sUnknown (%s%s%s)\n", prefix
, buf
,
780 *suffix
? ", " : "", suffix
);
783 // Should not happen!
784 printf("%sSVD Index %u is out of range", prefix
, idx
+ 1);
786 printf(" (%s)", suffix
);
791 void edid_state::cta_y420cmdb(const unsigned char *x
, unsigned length
)
793 unsigned max_idx
= 0;
797 printf(" All VDB SVDs\n");
801 if (memchk(x
, length
)) {
802 printf(" Empty Capability Map\n");
803 fail("Empty Capability Map.\n");
807 for (i
= 0; i
< length
; i
++) {
808 unsigned char v
= x
[i
];
811 for (j
= 0; j
< 8; j
++) {
815 print_vic_index(" ", i
* 8 + j
, "", true);
817 if (max_idx
< cta
.preparsed_svds
[0].size()) {
818 unsigned vic
= cta
.preparsed_svds
[0][max_idx
];
819 if (cta
.preparsed_has_vic
[1][vic
])
820 fail("VIC %u is also a YCbCr 4:2:0-only VIC.\n", vic
);
824 if (max_idx
>= cta
.preparsed_svds
[0].size())
825 fail("Max index %u > %u (#SVDs).\n",
826 max_idx
+ 1, cta
.preparsed_svds
[0].size());
829 void edid_state::cta_print_svr(unsigned char svr
, vec_timings_ext
&vec_tim
)
833 if ((svr
> 0 && svr
< 128) || (svr
> 192 && svr
< 254)) {
834 const struct timings
*t
;
835 unsigned char vic
= svr
;
837 sprintf(suffix
, "VIC %3u", vic
);
839 t
= find_vic_id(vic
);
841 print_timings(" ", t
, suffix
);
842 vec_tim
.push_back(timings_ext(*t
, suffix
, ""));
844 printf(" %s: Unknown\n", suffix
);
845 fail("Unknown VIC %u.\n", vic
);
848 } else if (svr
>= 129 && svr
<= 144) {
849 sprintf(suffix
, "DTD %3u", svr
- 128);
850 if (svr
>= cta
.preparsed_total_dtds
+ 129) {
851 printf(" %s: Invalid\n", suffix
);
852 fail("Invalid DTD %u.\n", svr
- 128);
854 printf(" %s\n", suffix
);
855 vec_tim
.push_back(timings_ext(svr
, suffix
));
857 } else if (svr
>= 145 && svr
<= 160) {
858 sprintf(suffix
, "VTDB %3u", svr
- 144);
859 if (svr
>= cta
.preparsed_total_vtdbs
+ 145) {
860 printf(" %s: Invalid\n", suffix
);
861 fail("Invalid VTDB %u.\n", svr
- 144);
863 printf(" %s\n", suffix
);
864 vec_tim
.push_back(timings_ext(svr
, suffix
));
866 } else if (svr
>= 161 && svr
<= 175) {
867 sprintf(suffix
, "RID %u@%up",
868 cta
.preparsed_first_vfd
.rid
, vf_rate_values
[svr
- 160]);
869 if (!vfd_has_rate(cta
.preparsed_first_vfd
, svr
- 160)) {
870 printf(" %s: Invalid\n", suffix
);
871 fail("Invalid %s.\n", suffix
);
873 printf(" %s\n", suffix
);
874 vec_tim
.push_back(timings_ext(svr
, suffix
));
876 } else if (svr
== 254) {
877 sprintf(suffix
, "T8VTDB");
878 if (!cta
.preparsed_has_t8vtdb
) {
879 printf(" %s: Invalid\n", suffix
);
880 fail("Invalid T8VTDB.\n");
882 sprintf(suffix
, "DMT 0x%02x", cta
.preparsed_t8vtdb_dmt
);
883 printf(" %s\n", suffix
);
884 vec_tim
.push_back(timings_ext(svr
, suffix
));
889 void edid_state::cta_vfpdb(const unsigned char *x
, unsigned length
)
894 fail("Empty Data Block with length %u.\n", length
);
897 cta
.preferred_timings_vfpdb
.clear();
898 for (i
= 0; i
< length
; i
++)
899 cta_print_svr(x
[i
], cta
.preferred_timings_vfpdb
);
902 void edid_state::cta_nvrdb(const unsigned char *x
, unsigned length
)
905 fail("Empty Data Block with length %u.\n", length
);
909 unsigned char flags
= length
== 1 ? 0 : x
[1];
911 cta
.native_timing_nvrdb
.clear();
912 cta_print_svr(x
[0], cta
.native_timing_nvrdb
);
913 if ((flags
& 1) && length
< 6) {
914 fail("Data Block too short for Image Size (length = %u).\n", length
);
918 fail("Bits F41-F46 must be 0.\n");
922 unsigned w
= (x
[3] << 8) | x
[2];
923 unsigned h
= (x
[5] << 8) | x
[4];
926 fail("Image Size has a zero width and/or height.\n");
929 printf(" Image Size: %ux%u mm\n", w
, h
);
931 printf(" Image Size: %.1fx%.1f mm\n", w
/ 10.0, h
/ 10.0);
934 static std::string
hdmi_latency2s(unsigned char l
, bool is_video
)
939 return is_video
? "Video not supported" : "Audio not supported";
940 return std::to_string(2 * (l
- 1)) + " ms";
943 void edid_state::hdmi_latency(unsigned char vid_lat
, unsigned char aud_lat
,
946 const char *vid
= is_ilaced
? "Interlaced video" : "Video";
947 const char *aud
= is_ilaced
? "Interlaced audio" : "Audio";
949 printf(" %s latency: %s\n", vid
, hdmi_latency2s(vid_lat
, true).c_str());
950 printf(" %s latency: %s\n", aud
, hdmi_latency2s(aud_lat
, false).c_str());
952 if (vid_lat
> 251 && vid_lat
!= 0xff)
953 fail("Invalid %s latency value %u.\n", vid
, vid_lat
);
954 if (aud_lat
> 251 && aud_lat
!= 0xff)
955 fail("Invalid %s latency value %u.\n", aud
, aud_lat
);
957 if (!vid_lat
|| vid_lat
> 251)
959 if (!aud_lat
|| aud_lat
> 251)
962 unsigned vid_ms
= 2 * (vid_lat
- 1);
963 unsigned aud_ms
= 2 * (aud_lat
- 1);
965 // HDMI 2.0 latency checks for devices without HDMI output
967 warn("%s latency < %s latency (%u ms < %u ms). This is discouraged for devices without HDMI output.\n",
968 aud
, vid
, aud_ms
, vid_ms
);
969 else if (vid_ms
+ 20 < aud_ms
)
970 warn("%s latency + 20 < %s latency (%u + 20 ms < %u ms). This is forbidden for devices without HDMI output.\n",
971 vid
, aud
, vid_ms
, aud_ms
);
972 else if (vid_ms
< aud_ms
)
973 warn("%s latency < %s latency (%u ms < %u ms). This is discouraged for devices without HDMI output.\n",
974 vid
, aud
, vid_ms
, aud_ms
);
977 void edid_state::cta_hdmi_block(const unsigned char *x
, unsigned length
)
979 unsigned len_vic
, len_3d
;
982 fail("Empty Data Block with length %u.\n", length
);
985 printf(" Source physical address: %x.%x.%x.%x\n", x
[0] >> 4, x
[0] & 0x0f,
986 x
[1] >> 4, x
[1] & 0x0f);
992 printf(" Supports_AI\n");
994 printf(" DC_48bit\n");
996 printf(" DC_36bit\n");
998 printf(" DC_30bit\n");
1000 printf(" DC_Y444\n");
1001 /* two reserved bits */
1003 printf(" DVI_Dual\n");
1008 printf(" Maximum TMDS clock: %u MHz\n", x
[3] * 5);
1010 fail("HDMI VSDB Max TMDS rate is > 340.\n");
1016 printf(" Supported Content Types:\n");
1018 printf(" Graphics\n");
1022 printf(" Cinema\n");
1029 hdmi_latency(x
[b
], x
[b
+ 1], false);
1032 if (x
[b
] == x
[b
+ 2] &&
1033 x
[b
+ 1] == x
[b
+ 3])
1034 warn("Progressive and Interlaced latency values are identical, no need for both.\n");
1036 hdmi_latency(x
[b
], x
[b
+ 1], true);
1045 bool formats
= false;
1047 printf(" Extended HDMI video details:\n");
1049 printf(" 3D present\n");
1050 if ((x
[b
] & 0x60) == 0x20) {
1051 printf(" All advertised VICs are 3D-capable\n");
1054 if ((x
[b
] & 0x60) == 0x40) {
1055 printf(" 3D-capable-VIC mask present\n");
1059 switch (x
[b
] & 0x18) {
1062 printf(" Base EDID image size is aspect ratio\n");
1065 printf(" Base EDID image size is in units of 1 cm\n");
1068 printf(" Base EDID image size is in units of 5 cm\n");
1069 base
.max_display_width_mm
*= 5;
1070 base
.max_display_height_mm
*= 5;
1071 printf(" Recalculated image size: %u cm x %u cm\n",
1072 base
.max_display_width_mm
/ 10, base
.max_display_height_mm
/ 10);
1076 len_vic
= (x
[b
] & 0xe0) >> 5;
1077 len_3d
= (x
[b
] & 0x1f) >> 0;
1083 printf(" HDMI VICs:\n");
1084 for (i
= 0; i
< len_vic
; i
++) {
1085 unsigned char vic
= x
[b
+ i
];
1086 const struct timings
*t
;
1088 if (vic
&& vic
<= ARRAY_SIZE(edid_hdmi_mode_map
)) {
1089 std::string suffix
= "HDMI VIC " + std::to_string(vic
);
1090 cta
.supported_hdmi_vic_codes
|= 1 << (vic
- 1);
1091 t
= find_vic_id(edid_hdmi_mode_map
[vic
- 1]);
1092 print_timings(" ", t
, suffix
.c_str());
1094 printf(" Unknown (HDMI VIC %u)\n", vic
);
1095 fail("Unknown HDMI VIC %u.\n", vic
);
1106 /* 3D_Structure_ALL_15..8 */
1108 printf(" 3D: Side-by-side (half, quincunx)\n");
1110 printf(" 3D: Side-by-side (half, horizontal)\n");
1111 /* 3D_Structure_ALL_7..0 */
1114 printf(" 3D: Top-and-bottom\n");
1116 printf(" 3D: L + depth + gfx + gfx-depth\n");
1118 printf(" 3D: L + depth\n");
1120 printf(" 3D: Side-by-side (full)\n");
1122 printf(" 3D: Line-alternative\n");
1124 printf(" 3D: Field-alternative\n");
1126 printf(" 3D: Frame-packing\n");
1135 printf(" 3D VIC indices that support these capabilities:\n");
1136 /* worst bit ordering ever */
1137 for (i
= 0; i
< 8; i
++)
1138 if (x
[b
+ 1] & (1 << i
)) {
1139 print_vic_index(" ", i
, "");
1142 for (i
= 0; i
< 8; i
++)
1143 if (x
[b
] & (1 << i
)) {
1144 print_vic_index(" ", i
+ 8, "");
1149 if (max_idx
>= (int)cta
.preparsed_svds
[0].size())
1150 fail("HDMI 3D VIC indices max index %d > %u (#SVDs).\n",
1151 max_idx
+ 1, cta
.preparsed_svds
[0].size());
1158 * (optionally: 3D_Detail_X and reserved)
1163 unsigned end
= b
+ len_3d
;
1166 printf(" 3D VIC indices with specific capabilities:\n");
1168 unsigned char idx
= x
[b
] >> 4;
1173 switch (x
[b
] & 0x0f) {
1174 case 0: s
= "frame packing"; break;
1175 case 1: s
= "field alternative"; break;
1176 case 2: s
= "line alternative"; break;
1177 case 3: s
= "side-by-side (full)"; break;
1178 case 4: s
= "L + depth"; break;
1179 case 5: s
= "L + depth + gfx + gfx-depth"; break;
1180 case 6: s
= "top-and-bottom"; break;
1183 switch (x
[b
+ 1] >> 4) {
1184 case 0x00: s
+= ", any subsampling"; break;
1185 case 0x01: s
+= ", horizontal"; break;
1186 case 0x02: case 0x03: case 0x04: case 0x05:
1187 s
+= ", not in use";
1188 fail("not-in-use 3D_Detail_X value 0x%02x.\n",
1191 case 0x06: s
+= ", all quincunx combinations"; break;
1192 case 0x07: s
+= ", quincunx odd/left, odd/right"; break;
1193 case 0x08: s
+= ", quincunx odd/left, even/right"; break;
1194 case 0x09: s
+= ", quincunx even/left, odd/right"; break;
1195 case 0x0a: s
+= ", quincunx even/left, even/right"; break;
1198 fail("reserved 3D_Detail_X value 0x%02x.\n",
1205 s
+= utohex(x
[b
] & 0x0f) + ")";
1206 fail("Unknown 3D_Structure_X value 0x%02x.\n", x
[b
] & 0x0f);
1209 print_vic_index(" ", idx
, s
.c_str());
1210 if ((x
[b
] & 0x0f) >= 8)
1214 if (max_idx
>= (int)cta
.preparsed_svds
[0].size())
1215 fail("HDMI 2D VIC indices max index %d > %u (#SVDs).\n",
1216 max_idx
+ 1, cta
.preparsed_svds
[0].size());
1219 static const char *max_frl_rates
[] = {
1221 "3 Gbps per lane on 3 lanes",
1222 "3 and 6 Gbps per lane on 3 lanes",
1223 "3 and 6 Gbps per lane on 3 lanes, 6 Gbps on 4 lanes",
1224 "3 and 6 Gbps per lane on 3 lanes, 6 and 8 Gbps on 4 lanes",
1225 "3 and 6 Gbps per lane on 3 lanes, 6, 8 and 10 Gbps on 4 lanes",
1226 "3 and 6 Gbps per lane on 3 lanes, 6, 8, 10 and 12 Gbps on 4 lanes",
1229 static const char *dsc_max_slices
[] = {
1231 "up to 1 slice and up to (340 MHz/Ksliceadjust) pixel clock per slice",
1232 "up to 2 slices and up to (340 MHz/Ksliceadjust) pixel clock per slice",
1233 "up to 4 slices and up to (340 MHz/Ksliceadjust) pixel clock per slice",
1234 "up to 8 slices and up to (340 MHz/Ksliceadjust) pixel clock per slice",
1235 "up to 8 slices and up to (400 MHz/Ksliceadjust) pixel clock per slice",
1236 "up to 12 slices and up to (400 MHz/Ksliceadjust) pixel clock per slice",
1237 "up to 12 slices and up to (600 MHz/Ksliceadjust) pixel clock per slice",
1240 static void cta_hf_eeodb(const unsigned char *x
, unsigned length
)
1242 printf(" EDID Extension Block Count: %u\n", x
[0]);
1244 fail("Block is too long.\n");
1246 fail("Extension Block Count == %u.\n", x
[0]);
1249 static void cta_hf_scdb(const unsigned char *x
, unsigned length
)
1251 unsigned rate
= x
[1] * 5;
1254 printf(" Version: %u\n", x
[0]);
1256 printf(" Maximum TMDS Character Rate: %u MHz\n", rate
);
1257 if (rate
<= 340 || rate
> 600)
1258 fail("Max TMDS rate is > 0 and <= 340 or > 600.\n");
1261 printf(" SCDC Present\n");
1263 printf(" SCDC Read Request Capable\n");
1265 printf(" Supports Cable Status\n");
1267 printf(" Supports Color Content Bits Per Component Indication\n");
1269 printf(" Supports scrambling for <= 340 Mcsc\n");
1271 printf(" Supports 3D Independent View signaling\n");
1273 printf(" Supports 3D Dual View signaling\n");
1275 printf(" Supports 3D OSD Disparity signaling\n");
1277 unsigned max_frl_rate
= x
[3] >> 4;
1279 printf(" Max Fixed Rate Link: ");
1280 if (max_frl_rate
< ARRAY_SIZE(max_frl_rates
)) {
1281 printf("%s\n", max_frl_rates
[max_frl_rate
]);
1283 printf("Unknown (0x%02x)\n", max_frl_rate
);
1284 fail("Unknown Max Fixed Rate Link (0x%02x).\n", max_frl_rate
);
1286 if (max_frl_rate
== 1 && rate
< 300)
1287 fail("Max Fixed Rate Link is 1, but Max TMDS rate < 300.\n");
1288 else if (max_frl_rate
>= 2 && rate
< 600)
1289 fail("Max Fixed Rate Link is >= 2, but Max TMDS rate < 600.\n");
1292 printf(" Supports UHD VIC\n");
1294 printf(" Supports 16-bits/component Deep Color 4:2:0 Pixel Encoding\n");
1296 printf(" Supports 12-bits/component Deep Color 4:2:0 Pixel Encoding\n");
1298 printf(" Supports 10-bits/component Deep Color 4:2:0 Pixel Encoding\n");
1304 printf(" Supports FAPA End Extended\n");
1306 printf(" Supports QMS\n");
1308 printf(" Supports Mdelta\n");
1310 printf(" Supports media rates below VRRmin (CinemaVRR)\n");
1312 printf(" Supports negative Mvrr values\n");
1314 printf(" Supports Fast Vactive\n");
1316 printf(" Supports Auto Low-Latency Mode\n");
1318 printf(" Supports a FAPA in blanking after first active video line\n");
1325 printf(" VRRmin: %u Hz\n", v
);
1327 fail("VRRmin > 48.\n");
1329 v
= (x
[5] & 0xc0) << 2 | x
[6];
1331 printf(" VRRmax: %u Hz\n", v
);
1333 fail("VRRmin == 0, but VRRmax isn't.\n");
1335 fail("VRRmax < 100.\n");
1342 printf(" Supports VESA DSC 1.2a compression\n");
1344 printf(" Supports Compressed Video Transport for 4:2:0 Pixel Encoding\n");
1346 printf(" Supports QMS TFRmax\n");
1348 printf(" Supports QMS TFRmin\n");
1350 printf(" Supports Compressed Video Transport at any valid 1/16th bit bpp\n");
1352 printf(" Supports 16 bpc Compressed Video Transport\n");
1354 printf(" Supports 12 bpc Compressed Video Transport\n");
1356 printf(" Supports 10 bpc Compressed Video Transport\n");
1358 unsigned max_slices
= x
[8] & 0xf;
1360 printf(" DSC Max Slices: ");
1361 if (max_slices
< ARRAY_SIZE(dsc_max_slices
)) {
1362 printf("%s\n", dsc_max_slices
[max_slices
]);
1364 printf("Unknown (%u), interpreted as: %s\n", max_slices
,
1366 warn("Unknown DSC Max Slices (%u).\n", max_slices
);
1370 unsigned max_frl_rate
= x
[8] >> 4;
1372 printf(" DSC Max Fixed Rate Link: ");
1373 if (max_frl_rate
< ARRAY_SIZE(max_frl_rates
)) {
1374 printf("%s\n", max_frl_rates
[max_frl_rate
]);
1376 printf("Unknown (0x%02x)\n", max_frl_rate
);
1377 fail("Unknown DSC Max Fixed Rate Link (0x%02x).\n", max_frl_rate
);
1381 printf(" Maximum number of bytes in a line of chunks: %u\n",
1382 1024 * (1 + (x
[9] & 0x3f)));
1385 // Convert a PQ value (0-1) to cd/m^2 aka nits (0-10000)
1386 static double pq2nits(double pq
)
1388 const double m1
= 2610.0 / 16384.0;
1389 const double m2
= 128.0 * (2523.0 / 4096.0);
1390 const double c1
= 3424.0 / 4096.0;
1391 const double c2
= 32.0 * (2413.0 / 4096.0);
1392 const double c3
= 32.0 * (2392.0 / 4096.0);
1393 double e
= pow(pq
, 1.0 / m2
);
1399 v
= pow(v
, 1.0 / m1
);
1403 static double chrom2d(const unsigned char *x
)
1405 unsigned v
= x
[0] + (x
[1] << 8);
1410 static double perc2d(unsigned char x
)
1415 return 100.0 * (m
/ 64.0) * pow(10, -e
);
1418 static void cta_hf_sbtmdb(const unsigned char *x
, unsigned length
)
1423 fail("Block is too short.\n");
1424 printf(" Version: %d\n", x
[0] & 0xf);
1425 switch ((x
[0] >> 5) & 3) {
1427 printf(" Does not support a General RDM format\n");
1430 printf(" Supports an SDR-range General RDM format\n");
1433 printf(" Supports an HDR-range General RDM format\n");
1436 fail("Invalid GRDM Support value.\n");
1442 bool uses_hgig_drdm
= true;
1444 printf(" Supports a D-RDM format\n");
1446 printf(" Use HGIG D-RDM\n");
1449 printf(" HGIG D-RDM is not used\n");
1450 uses_hgig_drdm
= false;
1453 printf(" PBnits[0] = 600 cd/m^2\n");
1456 printf(" PBnits[0] = 1000 cd/m^2\n");
1459 printf(" PBnits[0] = 4000 cd/m^2\n");
1462 printf(" PBnits[0] = 10000 cd/m^2\n");
1465 fail("Invalid HGIG D-DRM value.\n");
1469 bool has_chromaticities
= false;
1472 printf(" MaxRGB\n");
1473 switch (x
[1] >> 6) {
1475 printf(" Gamut is explicit\n");
1476 has_chromaticities
= true;
1479 printf(" Gamut is Rec. ITU-R BT.709\n");
1482 printf(" Gamut is SMPTE ST 2113\n");
1485 printf(" Gamut is Rec. ITU-R BT.2020\n");
1490 if (has_chromaticities
) {
1491 printf(" Red: (%.5f, %.5f)\n", chrom2d(x
), chrom2d(x
+ 2));
1492 printf(" Green: (%.5f, %.5f)\n", chrom2d(x
+ 4), chrom2d(x
+ 6));
1493 printf(" Blue: (%.5f, %.5f)\n", chrom2d(x
+ 8), chrom2d(x
+ 10));
1494 printf(" White: (%.5f, %.5f)\n", chrom2d(x
+ 12), chrom2d(x
+ 14));
1500 printf(" Min Brightness 10: %.8f cd/m^2\n", pq2nits((x
[0] << 1) / 4095.0));
1501 printf(" Peak Brightness 100: %u cd/m^2\n", (unsigned)pq2nits((x
[1] << 4) / 4095.0));
1506 printf(" Percentage of Peak Brightness P0: %.2f%%\n", perc2d(x
[0]));
1507 printf(" Peak Brightness P0: %.8f cd/m^2\n", pq2nits((x
[1] << 1) / 4095.0));
1512 printf(" Percentage of Peak Brightness P1: %.2f%%\n", perc2d(x
[0]));
1513 printf(" Peak Brightness P1: %.8f cd/m^2\n", pq2nits((x
[1] << 1) / 4095.0));
1518 printf(" Percentage of Peak Brightness P2: %.2f%%\n", perc2d(x
[0]));
1519 printf(" Peak Brightness P2: %.8f cd/m^2\n", pq2nits((x
[1] << 1) / 4095.0));
1524 printf(" Percentage of Peak Brightness P3: %.2f%%\n", perc2d(x
[0]));
1525 printf(" Peak Brightness P3: %.8f cd/m^2\n", pq2nits((x
[1] << 1) / 4095.0));
1528 static void cta_amd(const unsigned char *x
, unsigned length
)
1530 // These Freesync values are reversed engineered by looking
1531 // at existing EDIDs.
1532 printf(" Version: %u.%u\n", x
[0], x
[1]);
1533 printf(" Minimum Refresh Rate: %u Hz\n", x
[2]);
1534 printf(" Maximum Refresh Rate: %u Hz\n", x
[3]);
1535 // Freesync 1.x flags
1536 // One or more of the 0xe6 bits signal that the VESA MCCS
1537 // protocol is used to switch the Freesync range
1538 printf(" Flags 1.x: 0x%02x%s\n", x
[4],
1539 (x
[4] & 0xe6) ? " (MCCS)" : "");
1541 // Freesync 2.x flags
1542 // Bit 2 no doubt indicates if the monitor supports Local Dimming
1543 // There are probably also bits to signal support of the
1544 // FreeSync2_scRGB and FreeSync2_Gamma22 HDR display modes.
1545 // I suspect bits 0 and 1.
1546 printf(" Flags 2.x: 0x%02x\n", x
[5]);
1547 // The AMD tone mapping tutorial referred to in the URL below
1548 // mentions that the Freesync HDR info reports max/min
1549 // luminance of the monitor with and without local dimming.
1551 // https://gpuopen.com/learn/using-amd-freesync-premium-pro-hdr-code-samples/
1553 // So I assume that the first two luminance values are
1554 // the max/min luminance of the display and the next two
1555 // luminance values are the max/min luminance values when
1556 // local dimming is disabled. The values I get seem to
1558 printf(" Maximum luminance: %u (%.3f cd/m^2)\n",
1559 x
[6], 50.0 * pow(2, x
[6] / 32.0));
1560 printf(" Minimum luminance: %u (%.3f cd/m^2)\n",
1561 x
[7], (50.0 * pow(2, x
[6] / 32.0)) * pow(x
[7] / 255.0, 2) / 100.0);
1563 // One or both bytes can be 0. The meaning of that
1565 printf(" Maximum luminance (without local dimming): %u (%.3f cd/m^2)\n",
1566 x
[8], 50.0 * pow(2, x
[8] / 32.0));
1567 printf(" Minimum luminance (without local dimming): %u (%.3f cd/m^2)\n",
1568 x
[9], (50.0 * pow(2, x
[8] / 32.0)) * pow(x
[9] / 255.0, 2) / 100.0);
1570 // These bytes are always 0x08 0x2f. If these values
1571 // represent max/min luminance as well, then these
1572 // would map to 59.460 and 0.020 cd/m^2 respectively.
1573 // I wonder if this somehow relates to SDR.
1574 printf(" Unknown: 0x%02x 0x%02x\n", x
[8], x
[9]);
1579 static std::string
display_use_case(unsigned char x
)
1582 case 1: return "Test equipment";
1583 case 2: return "Generic display";
1584 case 3: return "Television display";
1585 case 4: return "Desktop productivity display";
1586 case 5: return "Desktop gaming display";
1587 case 6: return "Presentation display";
1588 case 7: return "Virtual reality headset";
1589 case 8: return "Augmented reality";
1590 case 16: return "Video wall display";
1591 case 17: return "Medical imaging display";
1592 case 18: return "Dedicated gaming display";
1593 case 19: return "Dedicated video monitor display";
1594 case 20: return "Accessory display";
1597 fail("Unknown Display product primary use case 0x%02x.\n", x
);
1598 return std::string("Unknown display use case (") + utohex(x
) + ")";
1601 static void cta_microsoft(const unsigned char *x
, unsigned length
)
1603 // This VSDB is documented at:
1604 // https://docs.microsoft.com/en-us/windows-hardware/drivers/display/specialized-monitors-edid-extension
1605 printf(" Version: %u\n", x
[0]);
1607 // In version 1 and 2 these bits should always be set to 0.
1608 printf(" Desktop Usage: %u\n", (x
[1] >> 6) & 1);
1609 printf(" Third-Party Usage: %u\n", (x
[1] >> 5) & 1);
1611 printf(" Display Product Primary Use Case: %u (%s)\n", x
[1] & 0x1f,
1612 display_use_case(x
[1] & 0x1f).c_str());
1613 printf(" Container ID: %s\n", containerid2s(x
+ 2).c_str());
1616 static void cta_hdr10plus(const unsigned char *x
, unsigned length
)
1619 fail("Empty Data Block with length %u.\n", length
);
1622 printf(" Application Version: %u\n", x
[0] & 3);
1623 printf(" Full Frame Peak Luminance Index: %u\n", (x
[0] >> 2) & 3);
1624 printf(" Peak Luminance Index: %u\n", x
[0] >> 4);
1625 hex_block(" ", x
+ 1, length
- 1);
1628 static void cta_dolby_video(const unsigned char *x
, unsigned length
)
1630 unsigned char version
= (x
[0] >> 5) & 0x07;
1632 printf(" Version: %u (%u bytes)\n", version
, length
+ 5);
1634 printf(" Supports YUV422 12 bit\n");
1638 printf(" Supports 2160p60\n");
1640 printf(" Supports global dimming\n");
1641 unsigned char dm_version
= x
[16];
1642 printf(" DM Version: %u.%u\n", dm_version
>> 4, dm_version
& 0xf);
1643 unsigned pq
= (x
[14] << 4) | (x
[13] >> 4);
1644 printf(" Target Min PQ: %u (%.8f cd/m^2)\n", pq
, pq2nits(pq
/ 4095.0));
1645 pq
= (x
[15] << 4) | (x
[13] & 0xf);
1646 printf(" Target Max PQ: %u (%u cd/m^2)\n", pq
, (unsigned)pq2nits(pq
/ 4095.0));
1647 printf(" Rx, Ry: %.8f, %.8f\n",
1648 ((x
[1] >> 4) | (x
[2] << 4)) / 4096.0,
1649 ((x
[1] & 0xf) | (x
[3] << 4)) / 4096.0);
1650 printf(" Gx, Gy: %.8f, %.8f\n",
1651 ((x
[4] >> 4) | (x
[5] << 4)) / 4096.0,
1652 ((x
[4] & 0xf) | (x
[6] << 4)) / 4096.0);
1653 printf(" Bx, By: %.8f, %.8f\n",
1654 ((x
[7] >> 4) | (x
[8] << 4)) / 4096.0,
1655 ((x
[7] & 0xf) | (x
[9] << 4)) / 4096.0);
1656 printf(" Wx, Wy: %.8f, %.8f\n",
1657 ((x
[10] >> 4) | (x
[11] << 4)) / 4096.0,
1658 ((x
[10] & 0xf) | (x
[12] << 4)) / 4096.0);
1664 printf(" Supports 2160p60\n");
1666 printf(" Supports global dimming\n");
1667 unsigned char dm_version
= (x
[0] >> 2) & 0x07;
1668 printf(" DM Version: %u.x\n", dm_version
+ 2);
1669 printf(" Colorimetry: %s\n", (x
[2] & 0x01) ? "P3-D65" : "ITU-R BT.709");
1670 printf(" Low Latency: %s\n", (x
[3] & 0x01) ? "Standard + Low Latency" : "Only Standard");
1671 double lm
= (x
[2] >> 1) / 127.0;
1672 printf(" Target Min Luminance: %.8f cd/m^2\n", lm
* lm
);
1673 printf(" Target Max Luminance: %u cd/m^2\n", 100 + (x
[1] >> 1) * 50);
1675 printf(" Rx, Ry: %.8f, %.8f\n", x
[4] / 256.0, x
[5] / 256.0);
1676 printf(" Gx, Gy: %.8f, %.8f\n", x
[6] / 256.0, x
[7] / 256.0);
1677 printf(" Bx, By: %.8f, %.8f\n", x
[8] / 256.0, x
[9] / 256.0);
1679 double xmin
= 0.625;
1680 double xstep
= (0.74609375 - xmin
) / 31.0;
1682 double ystep
= (0.37109375 - ymin
) / 31.0;
1684 printf(" Unique Rx, Ry: %.8f, %.8f\n",
1685 xmin
+ xstep
* (x
[6] >> 3),
1686 ymin
+ ystep
* (((x
[6] & 0x7) << 2) | (x
[4] & 0x01) | ((x
[5] & 0x01) << 1)));
1687 xstep
= 0.49609375 / 127.0;
1689 ystep
= (0.99609375 - ymin
) / 127.0;
1690 printf(" Unique Gx, Gy: %.8f, %.8f\n",
1691 xstep
* (x
[4] >> 1), ymin
+ ystep
* (x
[5] >> 1));
1693 xstep
= (0.15234375 - xmin
) / 7.0;
1695 ystep
= (0.05859375 - ymin
) / 7.0;
1696 printf(" Unique Bx, By: %.8f, %.8f\n",
1697 xmin
+ xstep
* (x
[3] >> 5),
1698 ymin
+ ystep
* ((x
[3] >> 2) & 0x07));
1705 printf(" Supports Backlight Control\n");
1707 printf(" Supports global dimming\n");
1708 unsigned char dm_version
= (x
[0] >> 2) & 0x07;
1709 printf(" DM Version: %u.x\n", dm_version
+ 2);
1710 printf(" Backlt Min Luma: %u cd/m^2\n", 25 + (x
[1] & 0x03) * 25);
1711 printf(" Interface: ");
1712 switch (x
[2] & 0x03) {
1713 case 0: printf("Low-Latency\n"); break;
1714 case 1: printf("Low-Latency + Low-Latency-HDMI\n"); break;
1715 case 2: printf("Standard + Low-Latency\n"); break;
1716 case 3: printf("Standard + Low-Latency + Low-Latency-HDMI\n"); break;
1718 printf(" Supports 10b 12b 444: ");
1719 switch ((x
[3] & 0x01) << 1 | (x
[4] & 0x01)) {
1720 case 0: printf("Not supported\n"); break;
1721 case 1: printf("10 bit\n"); break;
1722 case 2: printf("12 bit\n"); break;
1723 case 3: printf("Reserved\n"); break;
1726 unsigned pq
= 20 * (x
[1] >> 3);
1727 printf(" Target Min PQ v2: %u (%.8f cd/m^2)\n", pq
, pq2nits(pq
/ 4095.0));
1728 pq
= 2055 + 65 * (x
[2] >> 3);
1729 printf(" Target Max PQ v2: %u (%u cd/m^2)\n", pq
, (unsigned)pq2nits(pq
/ 4095.0));
1731 printf(" Unique Rx, Ry: %.8f, %.8f\n",
1732 0.625 + (x
[5] >> 3) / 256.0,
1733 0.25 + (x
[6] >> 3) / 256.0);
1734 printf(" Unique Gx, Gy: %.8f, %.8f\n",
1735 (x
[3] >> 1) / 256.0,
1736 0.5 + (x
[4] >> 1) / 256.0);
1737 printf(" Unique Bx, By: %.8f, %.8f\n",
1738 0.125 + (x
[5] & 0x07) / 256.0,
1739 0.03125 + (x
[6] & 0x07) / 256.0);
1743 static void cta_dolby_audio(const unsigned char *x
, unsigned length
)
1745 unsigned char version
= 1 + (x
[0] & 0x07);
1747 printf(" Version: %u (%u bytes)\n", version
, length
+ 5);
1749 printf(" Headphone playback only\n");
1751 printf(" Height speaker zone present\n");
1753 printf(" Surround speaker zone present\n");
1755 printf(" Center speaker zone present\n");
1757 printf(" Supports Dolby MAT PCM decoding at 48 kHz only, does not support TrueHD\n");
1760 static void cta_uhda_fmm(const unsigned char *x
, unsigned length
)
1762 printf(" Filmmaker Mode Content Type: %u\n", x
[0]);
1763 printf(" Filmmaker Mode Content Subtype: %u\n", x
[1]);
1766 static const char *speaker_map
[] = {
1767 "FL/FR - Front Left/Right",
1768 "LFE1 - Low Frequency Effects 1",
1769 "FC - Front Center",
1770 "BL/BR - Back Left/Right",
1772 "FLc/FRc - Front Left/Right of Center",
1773 "RLC/RRC - Rear Left/Right of Center (Deprecated)",
1774 "FLw/FRw - Front Left/Right Wide",
1775 "TpFL/TpFR - Top Front Left/Right",
1777 "TpFC - Top Front Center",
1778 "LS/RS - Left/Right Surround",
1779 "LFE2 - Low Frequency Effects 2",
1780 "TpBC - Top Back Center",
1781 "SiL/SiR - Side Left/Right",
1782 "TpSiL/TpSiR - Top Side Left/Right",
1783 "TpBL/TpBR - Top Back Left/Right",
1784 "BtFC - Bottom Front Center",
1785 "BtFL/BtFR - Bottom Front Left/Right",
1786 "TpLS/TpRS - Top Left/Right Surround (Deprecated for CTA-861)",
1787 "LSd/RSd - Left/Right Surround Direct (HDMI only)",
1790 static void cta_sadb(const unsigned char *x
, unsigned length
)
1796 fail("Empty Data Block with length %u.\n", length
);
1800 sad
= ((x
[2] << 16) | (x
[1] << 8) | x
[0]);
1802 for (i
= 0; i
< ARRAY_SIZE(speaker_map
); i
++) {
1804 printf(" %s\n", speaker_map
[i
]);
1808 static void cta_vesa_dtcdb(const unsigned char *x
, unsigned length
)
1810 if (length
!= 7 && length
!= 15 && length
!= 31) {
1811 fail("Invalid length %u.\n", length
);
1815 switch (x
[0] >> 6) {
1816 case 0: printf(" White"); break;
1817 case 1: printf(" Red"); break;
1818 case 2: printf(" Green"); break;
1819 case 3: printf(" Blue"); break;
1821 unsigned v
= x
[0] & 0x3f;
1822 printf(" transfer characteristics: %u", v
);
1823 for (unsigned i
= 1; i
< length
; i
++)
1824 printf(" %u", v
+= x
[i
]);
1828 static void cta_vesa_vdddb(const unsigned char *x
, unsigned length
)
1831 fail("Invalid length %u.\n", length
);
1835 printf(" Interface Type: ");
1836 unsigned char v
= x
[0];
1838 case 0: printf("Analog (");
1840 case 0: printf("15HD/VGA"); break;
1841 case 1: printf("VESA NAVI-V (15HD)"); break;
1842 case 2: printf("VESA NAVI-D"); break;
1843 default: printf("Reserved"); break;
1847 case 1: printf("LVDS %u lanes", v
& 0xf); break;
1848 case 2: printf("RSDS %u lanes", v
& 0xf); break;
1849 case 3: printf("DVI-D %u channels", v
& 0xf); break;
1850 case 4: printf("DVI-I analog"); break;
1851 case 5: printf("DVI-I digital %u channels", v
& 0xf); break;
1852 case 6: printf("HDMI-A"); break;
1853 case 7: printf("HDMI-B"); break;
1854 case 8: printf("MDDI %u channels", v
& 0xf); break;
1855 case 9: printf("DisplayPort %u channels", v
& 0xf); break;
1856 case 10: printf("IEEE-1394"); break;
1857 case 11: printf("M1 analog"); break;
1858 case 12: printf("M1 digital %u channels", v
& 0xf); break;
1859 default: printf("Reserved"); break;
1863 printf(" Interface Standard Version: %u.%u\n", x
[1] >> 4, x
[1] & 0xf);
1864 printf(" Content Protection Support: ");
1866 case 0: printf("None\n"); break;
1867 case 1: printf("HDCP\n"); break;
1868 case 2: printf("DTCP\n"); break;
1869 case 3: printf("DPCP\n"); break;
1870 default: printf("Reserved\n"); break;
1873 printf(" Minimum Clock Frequency: %u MHz\n", x
[3] >> 2);
1874 printf(" Maximum Clock Frequency: %u MHz\n", ((x
[3] & 0x03) << 8) | x
[4]);
1875 printf(" Device Native Pixel Format: %ux%u\n",
1876 x
[5] | (x
[6] << 8), x
[7] | (x
[8] << 8));
1877 printf(" Aspect Ratio: %.2f\n", (100 + x
[9]) / 100.0);
1879 printf(" Default Orientation: ");
1880 switch ((v
& 0xc0) >> 6) {
1881 case 0x00: printf("Landscape\n"); break;
1882 case 0x01: printf("Portrait\n"); break;
1883 case 0x02: printf("Not Fixed\n"); break;
1884 case 0x03: printf("Undefined\n"); break;
1886 printf(" Rotation Capability: ");
1887 switch ((v
& 0x30) >> 4) {
1888 case 0x00: printf("None\n"); break;
1889 case 0x01: printf("Can rotate 90 degrees clockwise\n"); break;
1890 case 0x02: printf("Can rotate 90 degrees counterclockwise\n"); break;
1891 case 0x03: printf("Can rotate 90 degrees in either direction)\n"); break;
1893 printf(" Zero Pixel Location: ");
1894 switch ((v
& 0x0c) >> 2) {
1895 case 0x00: printf("Upper Left\n"); break;
1896 case 0x01: printf("Upper Right\n"); break;
1897 case 0x02: printf("Lower Left\n"); break;
1898 case 0x03: printf("Lower Right\n"); break;
1900 printf(" Scan Direction: ");
1902 case 0x00: printf("Not defined\n"); break;
1903 case 0x01: printf("Fast Scan is on the Major (Long) Axis and Slow Scan is on the Minor Axis\n"); break;
1904 case 0x02: printf("Fast Scan is on the Minor (Short) Axis and Slow Scan is on the Major Axis\n"); break;
1905 case 0x03: printf("Reserved\n");
1906 fail("Scan Direction used the reserved value 0x03.\n");
1909 printf(" Subpixel Information: ");
1911 case 0x00: printf("Not defined\n"); break;
1912 case 0x01: printf("RGB vertical stripes\n"); break;
1913 case 0x02: printf("RGB horizontal stripes\n"); break;
1914 case 0x03: printf("Vertical stripes using primary order\n"); break;
1915 case 0x04: printf("Horizontal stripes using primary order\n"); break;
1916 case 0x05: printf("Quad sub-pixels, red at top left\n"); break;
1917 case 0x06: printf("Quad sub-pixels, red at bottom left\n"); break;
1918 case 0x07: printf("Delta (triad) RGB sub-pixels\n"); break;
1919 case 0x08: printf("Mosaic\n"); break;
1920 case 0x09: printf("Quad sub-pixels, RGB + 1 additional color\n"); break;
1921 case 0x0a: printf("Five sub-pixels, RGB + 2 additional colors\n"); break;
1922 case 0x0b: printf("Six sub-pixels, RGB + 3 additional colors\n"); break;
1923 case 0x0c: printf("Clairvoyante, Inc. PenTile Matrix (tm) layout\n"); break;
1924 default: printf("Reserved\n"); break;
1926 printf(" Horizontal and vertical dot/pixel pitch: %.2f x %.2f mm\n",
1927 (double)(x
[0x0c]) / 100.0, (double)(x
[0x0d]) / 100.0);
1929 printf(" Dithering: ");
1931 case 0: printf("None\n"); break;
1932 case 1: printf("Spatial\n"); break;
1933 case 2: printf("Temporal\n"); break;
1934 case 3: printf("Spatial and Temporal\n"); break;
1936 printf(" Direct Drive: %s\n", (v
& 0x20) ? "Yes" : "No");
1937 printf(" Overdrive %srecommended\n", (v
& 0x10) ? "not " : "");
1938 printf(" Deinterlacing: %s\n", (v
& 0x08) ? "Yes" : "No");
1941 printf(" Audio Support: %s\n", (v
& 0x80) ? "Yes" : "No");
1942 printf(" Separate Audio Inputs Provided: %s\n", (v
& 0x40) ? "Yes" : "No");
1943 printf(" Audio Input Override: %s\n", (v
& 0x20) ? "Yes" : "No");
1946 printf(" Audio Delay: %s%u ms\n", (v
& 0x80) ? "" : "-", (v
& 0x7f) * 2);
1948 printf(" Audio Delay: no information provided\n");
1950 printf(" Frame Rate/Mode Conversion: ");
1952 case 0: printf("None\n"); break;
1953 case 1: printf("Single Buffering\n"); break;
1954 case 2: printf("Double Buffering\n"); break;
1955 case 3: printf("Advanced Frame Rate Conversion\n"); break;
1958 printf(" Frame Rate Range: %u fps +/- %u fps\n",
1961 printf(" Nominal Frame Rate: %u fps\n", x
[0x12]);
1962 printf(" Color Bit Depth: %u @ interface, %u @ display\n",
1963 (x
[0x13] >> 4) + 1, (x
[0x13] & 0xf) + 1);
1966 printf(" Additional Primary Chromaticities:\n");
1967 unsigned col_x
= (x
[0x16] << 2) | (x
[0x14] >> 6);
1968 unsigned col_y
= (x
[0x17] << 2) | ((x
[0x14] >> 4) & 3);
1969 printf(" Primary 4: 0.%04u, 0.%04u\n",
1970 (col_x
* 10000) / 1024, (col_y
* 10000) / 1024);
1972 col_x
= (x
[0x18] << 2) | ((x
[0x14] >> 2) & 3);
1973 col_y
= (x
[0x19] << 2) | (x
[0x14] & 3);
1974 printf(" Primary 5: 0.%04u, 0.%04u\n",
1975 (col_x
* 10000) / 1024, (col_y
* 10000) / 1024);
1977 col_x
= (x
[0x1a] << 2) | (x
[0x15] >> 6);
1978 col_y
= (x
[0x1b] << 2) | ((x
[0x15] >> 4) & 3);
1979 printf(" Primary 6: 0.%04u, 0.%04u\n",
1980 (col_x
* 10000) / 1024, (col_y
* 10000) / 1024);
1986 printf(" Response Time %s: %u ms\n",
1987 (v
& 0x80) ? "White -> Black" : "Black -> White", v
& 0x7f);
1989 printf(" Overscan: %u%% x %u%%\n", v
>> 4, v
& 0xf);
1992 static double decode_uchar_as_double(unsigned char x
)
1994 signed char s
= (signed char)x
;
1999 void edid_state::cta_rcdb(const unsigned char *x
, unsigned length
)
2001 unsigned spm
= ((x
[3] << 16) | (x
[2] << 8) | x
[1]);
2005 fail("Empty Data Block with length %u.\n", length
);
2009 if ((x
[0] & 0x20) && !cta
.has_sldb
)
2010 fail("'SLD' flag is 1, but no Speaker Location Data Block is found.\n");
2011 else if (!(x
[0] & 0x20) && cta
.has_sldb
)
2012 fail("'SLD' flag is 0, but a Speaker Location Data Block is present.\n");
2015 printf(" Speaker count: %u\n", (x
[0] & 0x1f) + 1);
2018 fail("'Speaker' flag is 0, but 'Speaker Count' is != 0.\n");
2020 fail("'SLD' flag is 1, but 'Speaker' is 0.\n");
2023 printf(" Speaker Presence Mask:\n");
2024 for (i
= 0; i
< ARRAY_SIZE(speaker_map
); i
++) {
2026 printf(" %s\n", speaker_map
[i
]);
2029 if ((x
[0] & 0xa0) == 0x80)
2030 fail("'Display' flag set, but not the 'SLD' flag.\n");
2032 bool valid_max
= cta
.preparsed_sld_has_coord
|| (x
[0] & 0x80);
2034 if (valid_max
&& length
>= 7) {
2035 printf(" Xmax: %u dm\n", x
[4]);
2036 printf(" Ymax: %u dm\n", x
[5]);
2037 printf(" Zmax: %u dm\n", x
[6]);
2038 } else if (!valid_max
&& length
>= 7) {
2039 // The RCDB should have been truncated.
2040 warn("'Display' flag is 0 and 'Coord' is 0 for all SLDs, but the Max coordinates are still present.\n");
2042 if ((x
[0] & 0x80) && length
>= 10) {
2043 printf(" DisplayX: %.3f * Xmax\n", decode_uchar_as_double(x
[7]));
2044 printf(" DisplayY: %.3f * Ymax\n", decode_uchar_as_double(x
[8]));
2045 printf(" DisplayZ: %.3f * Zmax\n", decode_uchar_as_double(x
[9]));
2046 } else if (!(x
[0] & 0x80) && length
>= 10) {
2047 // The RCDB should have been truncated.
2048 warn("'Display' flag is 0, but the Display coordinates are still present.\n");
2052 static const struct {
2055 } speaker_location
[] = {
2056 { "FL - Front Left", -1, 1, 0 },
2057 { "FR - Front Right", 1, 1, 0 },
2058 { "FC - Front Center", 0, 1, 0 },
2059 { "LFE1 - Low Frequency Effects 1", -0.5, 1, -1 },
2060 { "BL - Back Left", -1, -1, 0 },
2061 { "BR - Back Right", 1, -1, 0 },
2062 { "FLC - Front Left of Center", -0.5, 1, 0 },
2063 { "FRC - Front Right of Center", 0.5, 1, 0 },
2064 { "BC - Back Center", 0, -1, 0 },
2065 { "LFE2 - Low Frequency Effects 2", 0.5, 1, -1 },
2066 { "SiL - Side Left", -1, 1.0/3.0, 0 },
2067 { "SiR - Side Right", 1, 1.0/3.0, 0 },
2068 { "TpFL - Top Front Left", -1, 1, 1 },
2069 { "TpFR - Top Front Right", 1, 1, 1 },
2070 { "TpFC - Top Front Center", 0, 1, 1 },
2071 { "TpC - Top Center", 0, 0, 1 },
2072 { "TpBL - Top Back Left", -1, -1, 1 },
2073 { "TpBR - Top Back Right", 1, -1, 1 },
2074 { "TpSiL - Top Side Left", -1, 0, 1 },
2075 { "TpSiR - Top Side Right", 1, 0, 1 },
2076 { "TpBC - Top Back Center", 0, -1, 1 },
2077 { "BtFC - Bottom Front Center", 0, 1, -1 },
2078 { "BtFL - Bottom Front Left", -1, 1, -1 },
2079 { "BtFR - Bottom Front Right", 1, 1, -1 },
2080 { "FLW - Front Left Wide", -1, 2.0/3.0, 0 },
2081 { "FRW - Front Right Wide", 1, 2.0/3.0, 0 },
2082 { "LS - Left Surround", -1, 0, 0 },
2083 { "RS - Right Surround", 1, 0, 0 },
2086 void edid_state::cta_sldb(const unsigned char *x
, unsigned length
)
2089 fail("Empty Data Block with length %u.\n", length
);
2093 unsigned active_cnt
= 0;
2094 unsigned channel_is_active
= 0;
2096 while (length
>= 2) {
2097 printf(" Channel: %u (%sactive)\n", x
[0] & 0x1f,
2098 (x
[0] & 0x20) ? "" : "not ");
2100 if (channel_is_active
& (1U << (x
[0] & 0x1f)))
2101 fail("Channel Index %u was already marked 'Active'.\n",
2103 channel_is_active
|= 1U << (x
[0] & 0x1f);
2106 if ((x
[1] & 0x1f) < ARRAY_SIZE(speaker_location
))
2107 printf(" Speaker: %s\n", speaker_location
[x
[1] & 0x1f].name
);
2108 if (length
>= 5 && (x
[0] & 0x40)) {
2109 printf(" X: %.3f * Xmax\n", decode_uchar_as_double(x
[2]));
2110 printf(" Y: %.3f * Ymax\n", decode_uchar_as_double(x
[3]));
2111 printf(" Z: %.3f * Zmax\n", decode_uchar_as_double(x
[4]));
2115 printf(" X: %.3f * Xmax (approximately)\n", speaker_location
[x
[1] & 0x1f].x
);
2116 printf(" Y: %.3f * Ymax (approximately)\n", speaker_location
[x
[1] & 0x1f].y
);
2117 printf(" Z: %.3f * Zmax (approximately)\n", speaker_location
[x
[1] & 0x1f].z
);
2123 if (active_cnt
!= cta
.preparsed_speaker_count
)
2124 fail("There are %u active speakers, but 'Speaker Count' is %u.\n",
2125 active_cnt
, cta
.preparsed_speaker_count
);
2128 void edid_state::cta_preparse_sldb(const unsigned char *x
, unsigned length
)
2130 cta
.has_sldb
= true;
2131 while (length
>= 2) {
2132 if (length
>= 5 && (x
[0] & 0x40)) {
2133 cta
.preparsed_sld_has_coord
= true;
2141 void edid_state::cta_vcdb(const unsigned char *x
, unsigned length
)
2143 unsigned char d
= x
[0];
2145 cta
.has_vcdb
= true;
2147 fail("Empty Data Block with length %u.\n", length
);
2150 printf(" YCbCr quantization: %s\n",
2151 (d
& 0x80) ? "Selectable (via AVI YQ)" : "No Data");
2152 printf(" RGB quantization: %s\n",
2153 (d
& 0x40) ? "Selectable (via AVI Q)" : "No Data");
2155 * If this bit is not set then that will result in interoperability
2156 * problems (specifically with PCs/laptops) that quite often do not
2157 * follow the default rules with respect to RGB Quantization Range
2160 * Starting with the CTA-861-H spec this bit is now required to be
2161 * 1 for new designs.
2164 fail("Set Selectable RGB Quantization to avoid interop issues.\n");
2166 * Since most YCbCr formats use limited range, the interop issues are
2167 * less noticable than for RGB formats.
2169 * Starting with the CTA-861-H spec this bit is now required to be
2170 * 1 for new designs, but just warn about it (for now).
2172 if ((cta
.byte3
& 0x30) && !(d
& 0x80))
2173 warn("Set Selectable YCbCr Quantization to avoid interop issues.\n");
2175 unsigned char s_pt
= (d
>> 4) & 0x03;
2176 unsigned char s_it
= (d
>> 2) & 0x03;
2177 unsigned char s_ce
= d
& 0x03;
2179 printf(" PT scan behavior: ");
2181 case 0: printf("No Data\n"); break;
2182 case 1: printf("Always Overscanned\n"); break;
2183 case 2: printf("Always Underscanned\n"); break;
2184 case 3: printf("Supports both over- and underscan\n"); break;
2186 printf(" IT scan behavior: ");
2188 case 0: printf("IT video formats not supported\n"); break;
2190 printf("Always Overscanned\n");
2191 // See Table 52 of CTA-861-G for a description of Byte 3
2192 if (cta
.byte3
& 0x80)
2193 fail("IT video formats are always overscanned, but bit 7 of Byte 3 of the CTA-861 Extension header is set to underscanned.\n");
2196 printf("Always Underscanned\n");
2197 // See Table 52 of CTA-861-G for a description of Byte 3
2198 if (!(cta
.byte3
& 0x80))
2199 fail("IT video formats are always underscanned, but bit 7 of Byte 3 of the CTA-861 Extension header is set to overscanned.\n");
2201 case 3: printf("Supports both over- and underscan\n"); break;
2204 warn("IT scan behavior is expected to support underscanned.\n");
2205 printf(" CE scan behavior: ");
2207 case 0: printf("CE video formats not supported\n"); break;
2208 case 1: printf("Always Overscanned\n"); break;
2209 case 2: printf("Always Underscanned\n"); break;
2210 case 3: printf("Supports both over- and underscan\n"); break;
2213 warn("'CE video formats not supported' makes no sense.\n");
2214 else if (s_pt
== s_it
&& s_pt
== s_ce
)
2215 warn("S_PT is equal to S_IT and S_CE, so should be set to 0 instead.\n");
2218 static const char *colorimetry1_map
[] = {
2229 static const char *colorimetry2_map
[] = {
2230 "Gamut Boundary Description Metadata Profile P0",
2231 "Reserved Gamut Boundary Description Metadata Profile P1",
2232 "Reserved Gamut Boundary Description Metadata Profile P2",
2233 "Reserved Gamut Boundary Description Metadata Profile P3",
2240 void edid_state::cta_colorimetry_block(const unsigned char *x
, unsigned length
)
2245 fail("Empty Data Block with length %u.\n", length
);
2248 for (i
= 0; i
< ARRAY_SIZE(colorimetry1_map
); i
++)
2249 if (x
[0] & (1 << i
))
2250 printf(" %s\n", colorimetry1_map
[i
]);
2251 // Bits MD0-MD3 are used to indicate which HDMI Gamut Boundary Description
2252 // Metadata Profiles are supported.
2254 // HDMI 1.3a in section 5.3.12 describes 4 possible profiles, but it marks
2255 // P3 as 'defined in a future specification'.
2257 // HDMI 1.4b, however, only specifies profile P0 in section 8.3.3. And I've
2258 // only seen P0 in practice. My assumption is that profiles P1-P3 are never
2259 // used, and so these bits should be 0.
2261 fail("Reserved bits MD1-MD3 must be 0.\n");
2262 for (i
= 0; i
< ARRAY_SIZE(colorimetry2_map
); i
++)
2263 if (x
[1] & (1 << i
))
2264 printf(" %s\n", colorimetry2_map
[i
]);
2265 // The sRGB bit (added in CTA-861.6) allows sources to explicitly
2266 // signal sRGB colorimetry. Without this the default colorimetry
2267 // of an RGB video is either sRGB or defaultRGB. It depends on the
2268 // Source which is used, and the Sink has no idea what it is getting.
2270 // For proper compatibility with PCs enabling sRGB support is
2272 if (!base
.uses_srgb
&& !(x
[1] & 0x20))
2273 warn("Set the sRGB colorimetry bit to avoid interop issues.\n");
2276 static const char *eotf_map
[] = {
2277 "Traditional gamma - SDR luminance range",
2278 "Traditional gamma - HDR luminance range",
2283 static void cta_hdr_static_metadata_block(const unsigned char *x
, unsigned length
)
2288 fail("Empty Data Block with length %u.\n", length
);
2291 printf(" Electro optical transfer functions:\n");
2292 for (i
= 0; i
< 6; i
++) {
2293 if (x
[0] & (1 << i
)) {
2294 if (i
< ARRAY_SIZE(eotf_map
)) {
2295 printf(" %s\n", eotf_map
[i
]);
2297 printf(" Unknown (%u)\n", i
);
2298 fail("Unknown EOTF (%u).\n", i
);
2302 printf(" Supported static metadata descriptors:\n");
2303 for (i
= 0; i
< 8; i
++) {
2304 if (x
[1] & (1 << i
))
2305 printf(" Static metadata type %u\n", i
+ 1);
2309 printf(" Desired content max luminance: %u (%.3f cd/m^2)\n",
2310 x
[2], 50.0 * pow(2, x
[2] / 32.0));
2313 printf(" Desired content max frame-average luminance: %u (%.3f cd/m^2)\n",
2314 x
[3], 50.0 * pow(2, x
[3] / 32.0));
2317 printf(" Desired content min luminance: %u (%.3f cd/m^2)\n",
2318 x
[4], (50.0 * pow(2, x
[2] / 32.0)) * pow(x
[4] / 255.0, 2) / 100.0);
2321 static void cta_hdr_dyn_metadata_block(const unsigned char *x
, unsigned length
)
2324 fail("Empty Data Block with length %u.\n", length
);
2327 while (length
>= 3) {
2328 unsigned type_len
= x
[0];
2329 unsigned type
= x
[1] | (x
[2] << 8);
2331 if (length
< type_len
+ 1)
2333 printf(" HDR Dynamic Metadata Type %u\n", type
);
2338 printf(" Version: %u\n", x
[3] & 0xf);
2342 unsigned version
= x
[3] & 0xf;
2343 printf(" Version: %u\n", version
);
2345 if (x
[3] & 0x10) printf(" Supports SL-HDR1 (ETSI TS 103 433-1)\n");
2346 if (x
[3] & 0x20) printf(" Supports SL-HDR2 (ETSI TS 103 433-2)\n");
2347 if (x
[3] & 0x40) printf(" Supports SL-HDR3 (ETSI TS 103 433-3)\n");
2354 length
-= type_len
+ 1;
2359 static const char *infoframe_types
[] = {
2362 "Auxiliary Video Information",
2363 "Source Product Description",
2367 "Dynamic Range and Mastering",
2370 static void cta_ifdb(const unsigned char *x
, unsigned length
)
2372 unsigned len_hdr
= x
[0] >> 5;
2375 fail("Empty Data Block with length %u.\n", length
);
2378 printf(" VSIFs: %u\n", x
[1]);
2379 if (length
< len_hdr
+ 2)
2381 length
-= len_hdr
+ 2;
2383 while (length
> 0) {
2384 int payload_len
= x
[0] >> 5;
2385 unsigned char type
= x
[0] & 0x1f;
2387 const char *name
= NULL
;
2388 if (type
< ARRAY_SIZE(infoframe_types
))
2389 name
= infoframe_types
[type
];
2392 printf(" %s InfoFrame (%u)", name
, type
);
2394 if (type
== 1 && length
>= 4) {
2395 unsigned oui
= (x
[3] << 16) | (x
[2] << 8) | x
[1];
2397 printf(", OUI %s\n", ouitohex(oui
).c_str());
2406 length
-= payload_len
;
2410 void edid_state::cta_displayid_type_7(const unsigned char *x
, unsigned length
)
2412 check_displayid_datablock_revision(x
[0], 0x00, 2);
2414 if (length
< 21U + ((x
[0] & 0x70) >> 4)) {
2415 fail("Empty Data Block with length %u.\n", length
);
2418 parse_displayid_type_1_7_timing(x
+ 1, true, 2, true);
2421 void edid_state::cta_displayid_type_8(const unsigned char *x
, unsigned length
)
2423 check_displayid_datablock_revision(x
[0], 0xe8, 1);
2424 if (length
< ((x
[0] & 0x08) ? 3 : 2)) {
2425 fail("Empty Data Block with length %u.\n", length
);
2429 unsigned sz
= (x
[0] & 0x08) ? 2 : 1;
2430 unsigned type
= x
[0] >> 6;
2433 fail("Only code type 0 is supported.\n");
2438 printf(" Also supports YCbCr 4:2:0\n");
2442 for (unsigned i
= 0; i
< length
/ sz
; i
++) {
2443 unsigned id
= x
[i
* sz
];
2446 id
|= x
[i
* sz
+ 1] << 8;
2447 parse_displayid_type_4_8_timing(type
, id
, true);
2451 void edid_state::cta_displayid_type_10(const unsigned char *x
, unsigned length
)
2453 check_displayid_datablock_revision(x
[0], 0x70);
2454 if (length
< 7U + ((x
[0] & 0x70) >> 4)) {
2455 fail("Empty Data Block with length %u.\n", length
);
2459 unsigned sz
= 6U + ((x
[0] & 0x70) >> 4);
2462 for (unsigned i
= 0; i
< length
/ sz
; i
++)
2463 parse_displayid_type_10_timing(x
+ i
* sz
, sz
, true);
2466 static void cta_hdmi_audio_block(const unsigned char *x
, unsigned length
)
2471 fail("Empty Data Block with length %u.\n", length
);
2475 printf(" Max Stream Count: %u\n", (x
[0] & 3) + 1);
2477 printf(" Supports MS NonMixed\n");
2479 num_descs
= x
[1] & 7;
2484 while (length
>= 4) {
2486 unsigned format
= x
[0] & 0xf;
2488 printf(" %s, max channels %u\n", audio_format(format
).c_str(),
2490 printf(" Supported sample rates (kHz):%s%s%s%s%s%s%s\n",
2491 (x
[2] & 0x40) ? " 192" : "",
2492 (x
[2] & 0x20) ? " 176.4" : "",
2493 (x
[2] & 0x10) ? " 96" : "",
2494 (x
[2] & 0x08) ? " 88.2" : "",
2495 (x
[2] & 0x04) ? " 48" : "",
2496 (x
[2] & 0x02) ? " 44.1" : "",
2497 (x
[2] & 0x01) ? " 32" : "");
2499 printf(" Supported sample sizes (bits):%s%s%s\n",
2500 (x
[3] & 0x04) ? " 24" : "",
2501 (x
[3] & 0x02) ? " 20" : "",
2502 (x
[3] & 0x01) ? " 16" : "");
2504 unsigned sad
= ((x
[2] << 16) | (x
[1] << 8) | x
[0]);
2507 switch (x
[3] >> 4) {
2509 printf(" Speaker Allocation for 10.2 channels:\n");
2512 printf(" Speaker Allocation for 22.2 channels:\n");
2515 printf(" Speaker Allocation for 30.2 channels:\n");
2518 printf(" Unknown Speaker Allocation (0x%02x)\n", x
[3] >> 4);
2522 for (i
= 0; i
< ARRAY_SIZE(speaker_map
); i
++) {
2524 printf(" %s\n", speaker_map
[i
]);
2532 void edid_state::cta_block(const unsigned char *x
, std::vector
<unsigned> &found_tags
)
2534 unsigned length
= x
[0] & 0x1f;
2535 unsigned tag
= (x
[0] & 0xe0) >> 5;
2536 unsigned extended
= (tag
== 0x07) ? 1 : 0;
2539 if (extended
&& length
) {
2546 bool dooutputname
= true;
2547 bool audio_block
= false;
2551 case 0x01: data_block
= "Audio Data Block"; audio_block
= true; break;
2552 case 0x02: data_block
= "Video Data Block"; break;
2553 case 0x03: data_block
= "Vendor-Specific Data Block"; break;
2554 case 0x04: data_block
= "Speaker Allocation Data Block"; audio_block
= true; break;
2555 case 0x05: data_block
= "VESA Display Transfer Characteristics Data Block"; break;
2556 case 0x06: data_block
= "Video Format Data Block"; break;
2557 case 0x07: data_block
= "Unknown CTA-861 Data Block (extended tag truncated)"; break;
2559 case 0x700: data_block
= "Video Capability Data Block"; break;
2560 case 0x701: data_block
= "Vendor-Specific Video Data Block"; break;
2561 case 0x702: data_block
= "VESA Video Display Device Data Block"; break;
2562 case 0x703: data_block
= "VESA Video Timing Block Extension"; break;
2563 case 0x704: data_block
= "Reserved for HDMI Video Data Block"; break;
2564 case 0x705: data_block
= "Colorimetry Data Block"; break;
2565 case 0x706: data_block
= "HDR Static Metadata Data Block"; break;
2566 case 0x707: data_block
= "HDR Dynamic Metadata Data Block"; break;
2567 case 0x708: data_block
= "Native Video Resolution Data Block"; break;
2569 case 0x70d: data_block
= "Video Format Preference Data Block"; break;
2570 case 0x70e: data_block
= "YCbCr 4:2:0 Video Data Block"; break;
2571 case 0x70f: data_block
= "YCbCr 4:2:0 Capability Map Data Block"; break;
2572 case 0x710: data_block
= "Reserved for CTA-861 Miscellaneous Audio Fields"; break;
2573 case 0x711: data_block
= "Vendor-Specific Audio Data Block"; audio_block
= true; break;
2574 case 0x712: data_block
= "HDMI Audio Data Block"; audio_block
= true; break;
2575 case 0x713: data_block
= "Room Configuration Data Block"; audio_block
= true; break;
2576 case 0x714: data_block
= "Speaker Location Data Block"; audio_block
= true; break;
2578 case 0x720: data_block
= "InfoFrame Data Block"; break;
2580 case 0x722: data_block
= "DisplayID Type VII Video Timing Data Block"; break;
2581 case 0x723: data_block
= "DisplayID Type VIII Video Timing Data Block"; break;
2582 case 0x72a: data_block
= "DisplayID Type X Video Timing Data Block"; break;
2584 case 0x778: data_block
= "HDMI Forum EDID Extension Override Data Block"; break;
2585 case 0x779: data_block
= "HDMI Forum Sink Capability Data Block"; break;
2586 case 0x77a: data_block
= "HDMI Forum Source-Based Tone Mapping Data Block"; break;
2589 std::string unknown_name
;
2590 if (tag
< 0x700) unknown_name
= "Unknown CTA-861 Data Block";
2591 else if (tag
< 0x70d) unknown_name
= "Unknown CTA-861 Video-Related Data Block";
2592 else if (tag
< 0x720) unknown_name
= "Unknown CTA-861 Audio-Related Data Block";
2593 else if (tag
< 0x778) unknown_name
= "Unknown CTA-861 Data Block";
2594 else if (tag
< 0x780) unknown_name
= "Unknown CTA-861 HDMI-Related Data Block";
2595 else unknown_name
= "Unknown CTA-861 Data Block";
2596 unknown_name
+= std::string(" (") + (extended
? "extended " : "") + "tag " + utohex(tag
& 0xff) + ", length " + std::to_string(length
) + ")";
2597 printf(" %s:\n", unknown_name
.c_str());
2598 warn("%s.\n", unknown_name
.c_str());
2608 data_block_oui(data_block
, x
, length
, &ouinum
);
2609 x
+= (length
< 3) ? length
: 3;
2610 length
-= (length
< 3) ? length
: 3;
2611 dooutputname
= false;
2617 if (dooutputname
&& data_block
.length())
2618 printf(" %s:\n", data_block
.c_str());
2635 if (std::find(found_tags
.begin(), found_tags
.end(), tag
) != found_tags
.end())
2636 fail("Only one instance of this Data Block is allowed.\n");
2640 // See Table 52 of CTA-861-G for a description of Byte 3
2641 if (audio_block
&& !(cta
.byte3
& 0x40))
2642 fail("Audio information is present, but bit 6 of Byte 3 of the CTA-861 Extension header indicates no Basic Audio support.\n");
2645 case 0x01: cta_audio_block(x
, length
); break;
2646 case 0x02: cta_svd(x
, length
, false); break;
2647 case 0x03|kOUI_HDMI
:
2648 cta_hdmi_block(x
, length
);
2649 // The HDMI OUI is present, so this EDID represents an HDMI
2650 // interface. And HDMI interfaces must use EDID version 1.3
2651 // according to the HDMI Specification, so check for this.
2652 if (base
.edid_minor
!= 3)
2653 fail("The HDMI Specification requires EDID 1.3 instead of 1.%u.\n",
2656 case 0x03|kOUI_HDMIForum
:
2657 if (cta
.previous_cta_tag
!= (0x03|kOUI_HDMI
))
2658 fail("HDMI Forum VSDB did not immediately follow the HDMI VSDB.\n");
2659 if (cta
.have_hf_scdb
|| cta
.have_hf_vsdb
)
2660 fail("Duplicate HDMI Forum VSDB/SCDB.\n");
2661 cta_hf_scdb(x
, length
);
2662 cta
.have_hf_vsdb
= true;
2664 case 0x03|kOUI_AMD
: cta_amd(x
, length
); break;
2665 case 0x03|kOUI_Microsoft
: if (length
!= 0x12) goto dodefault
; cta_microsoft(x
, length
); break;
2666 case 0x03|kOUI_UHDA
: cta_uhda_fmm(x
, length
); break;
2667 case 0x04: cta_sadb(x
, length
); break;
2668 case 0x05: cta_vesa_dtcdb(x
, length
); break;
2669 case 0x06: cta_vfdb(x
, length
); break;
2670 case 0x07: fail("Extended tag cannot have zero length.\n"); break;
2671 case 0x700: cta_vcdb(x
, length
); break;
2672 case 0x701|kOUI_HDR10
: cta_hdr10plus(x
, length
); break;
2673 case 0x701|kOUI_Dolby
: cta_dolby_video(x
, length
); break;
2674 // 0x701|kOUI_Apple: this almost certainly contains 'BLC Info/Corrections',
2675 // since the data (spread out over two VSDBs) is very similar to what is seen
2676 // in DisplayID blocks. Since I don't know how to parse this data, we still
2677 // default to a hex dump, but I mention this here in case data on how to
2678 // parse this becomes available.
2679 case 0x702: cta_vesa_vdddb(x
, length
); break;
2680 case 0x705: cta_colorimetry_block(x
, length
); break;
2681 case 0x706: cta_hdr_static_metadata_block(x
, length
); break;
2682 case 0x707: cta_hdr_dyn_metadata_block(x
, length
); break;
2683 case 0x708: cta_nvrdb(x
, length
); return;
2684 case 0x70d: cta_vfpdb(x
, length
); break;
2685 case 0x70e: cta_svd(x
, length
, true); break;
2686 case 0x70f: cta_y420cmdb(x
, length
); break;
2687 case 0x711|kOUI_Dolby
: cta_dolby_audio(x
, length
); break;
2688 case 0x712: cta_hdmi_audio_block(x
, length
); break;
2689 case 0x713: cta_rcdb(x
, length
); break;
2690 case 0x714: cta_sldb(x
, length
); break;
2691 case 0x720: cta_ifdb(x
, length
); break;
2692 case 0x722: cta_displayid_type_7(x
, length
); break;
2693 case 0x723: cta_displayid_type_8(x
, length
); break;
2694 case 0x72a: cta_displayid_type_10(x
, length
); break;
2696 cta_hf_eeodb(x
, length
);
2698 fail("Data Block can only be present in Block 1.\n");
2699 // This must be the first CTA-861 block
2700 if (cta
.block_number
> 0)
2701 fail("Data Block starts at a wrong offset.\n");
2704 if (cta
.previous_cta_tag
!= (0x03|kOUI_HDMI
))
2705 fail("HDMI Forum SCDB did not immediately follow the HDMI VSDB.\n");
2706 if (cta
.have_hf_scdb
|| cta
.have_hf_vsdb
)
2707 fail("Duplicate HDMI Forum VSDB/SCDB.\n");
2709 fail("Data Block can only be present in Block 1.\n");
2711 data_block
= std::string("HDMI Forum SCDB");
2712 fail("Invalid length %u < 2.\n", length
);
2716 printf(" Non-zero SCDB reserved fields!\n");
2717 cta_hf_scdb(x
+ 2, length
- 2);
2718 cta
.have_hf_scdb
= true;
2721 cta_hf_sbtmdb(x
, length
);
2725 hex_block(" ", x
, length
);
2730 cta
.previous_cta_tag
= tag
;
2731 found_tags
.push_back(tag
);
2734 void edid_state::preparse_cta_block(unsigned char *x
)
2736 unsigned version
= x
[1];
2737 unsigned offset
= x
[2];
2740 const unsigned char *detailed
;
2742 for (detailed
= x
+ offset
; detailed
+ 17 < x
+ 127; detailed
+= 18) {
2743 if (memchk(detailed
, 18))
2745 if (detailed
[0] || detailed
[1])
2746 cta
.preparsed_total_dtds
++;
2753 for (unsigned i
= 4; i
< offset
; i
+= (x
[i
] & 0x1f) + 1) {
2754 bool for_ycbcr420
= false;
2757 switch ((x
[i
] & 0xe0) >> 5) {
2759 oui
= (x
[i
+ 3] << 16) + (x
[i
+ 2] << 8) + x
[i
+ 1];
2760 if (oui
== 0x000c03) {
2761 cta
.has_hdmi
= true;
2762 cta
.preparsed_phys_addr
= (x
[i
+ 4] << 8) | x
[i
+ 5];
2763 } else if ((oui
== 0xca125c || oui
== 0x5c12ca) &&
2764 (x
[i
] & 0x1f) == 0x15 && replace_unique_ids
) {
2765 memset(x
+ i
+ 6, 0, 16);
2766 replace_checksum(x
, EDID_PAGE_SIZE
);
2770 if (!(x
[i
] & 0x1f) || cta
.preparsed_first_vfd
.rid
)
2772 cta
.preparsed_first_vfd
= cta_parse_vfd(x
+ i
+ 2, (x
[i
+ 1] & 3) + 1);
2775 if (x
[i
+ 1] == 0x0d)
2776 cta
.has_vfpdb
= true;
2777 else if (x
[i
+ 1] == 0x05)
2779 else if (x
[i
+ 1] == 0x08)
2780 cta
.has_nvrdb
= true;
2781 else if (x
[i
+ 1] == 0x13 && (x
[i
+ 2] & 0x40)) {
2782 cta
.preparsed_speaker_count
= 1 + (x
[i
+ 2] & 0x1f);
2783 cta
.preparsed_sld
= x
[i
+ 2] & 0x20;
2784 } else if (x
[i
+ 1] == 0x14)
2785 cta_preparse_sldb(x
+ i
+ 2, (x
[i
] & 0x1f) - 1);
2786 else if (x
[i
+ 1] == 0x22)
2787 cta
.preparsed_total_vtdbs
++;
2788 else if (x
[i
+ 1] == 0x23) {
2789 cta
.preparsed_has_t8vtdb
= true;
2790 cta
.preparsed_t8vtdb_dmt
= x
[i
+ 3];
2791 if (x
[i
+ 2] & 0x08)
2792 cta
.preparsed_t8vtdb_dmt
|= x
[i
+ 4] << 8;
2793 } else if (x
[i
+ 1] == 0x2a)
2794 cta
.preparsed_total_vtdbs
+=
2795 ((x
[i
] & 0x1f) - 2) / (6 + ((x
[i
+ 2] & 0x70) >> 4));
2796 else if (x
[i
+ 1] == 0x78)
2797 cta
.hf_eeodb_blocks
= x
[i
+ 2];
2798 if (x
[i
+ 1] != 0x0e)
2800 for_ycbcr420
= true;
2801 #ifdef __EMSCRIPTEN__
2802 [[clang::fallthrough
]];
2806 for (unsigned j
= 1 + for_ycbcr420
; j
<= (x
[i
] & 0x1f); j
++) {
2807 unsigned char vic
= x
[i
+ j
];
2809 if ((vic
& 0x7f) <= 64)
2811 cta
.preparsed_svds
[for_ycbcr420
].push_back(vic
);
2812 cta
.preparsed_has_vic
[for_ycbcr420
][vic
] = true;
2814 const struct timings
*t
= find_vic_id(vic
);
2816 if (!for_ycbcr420
&& t
&&
2817 t
->pixclk_khz
> cta
.preparsed_max_vic_pixclk_khz
)
2818 cta
.preparsed_max_vic_pixclk_khz
= t
->pixclk_khz
;
2825 void edid_state::parse_cta_block(const unsigned char *x
)
2827 unsigned version
= x
[1];
2828 unsigned offset
= x
[2];
2829 const unsigned char *detailed
;
2831 // See Table 52 of CTA-861-G for a description of Byte 3
2833 printf(" Revision: %u\n", version
);
2835 fail("Invalid CTA-861 Extension revision 0.\n");
2837 fail("Deprecated CTA-861 Extension revision 2.\n");
2838 if (cta
.has_hdmi
&& version
!= 3)
2839 fail("The HDMI Specification requires CTA Extension revision 3.\n");
2841 warn("Unknown CTA-861 Extension revision %u.\n", version
);
2842 if (offset
> 0 && offset
< 4)
2843 fail("Invalid CTA-861 Extension offset value (byte 2).\n");
2845 if (version
>= 1) do {
2846 if (version
== 1 && x
[3] != 0)
2847 fail("Non-zero byte 3.\n");
2849 if (version
< 3 && offset
>= 4 && ((offset
- 4) / 8)) {
2850 printf(" 8-byte timing descriptors: %u\n", (offset
- 4) / 8);
2851 fail("8-byte descriptors were never used.\n");
2856 printf(" Underscans IT Video Formats by default\n");
2858 warn("IT Video Formats are overscanned by default, but normally this should be underscanned.\n");
2860 printf(" Basic audio support\n");
2862 printf(" Supports YCbCr 4:4:4\n");
2864 printf(" Supports YCbCr 4:2:2\n");
2865 // Disable this test: this fails a lot of EDIDs, and there are
2866 // also some corner cases where you only want to receive 4:4:4
2867 // and refuse a fallback to 4:2:2.
2868 // if ((x[3] & 0x30) && (x[3] & 0x30) != 0x30)
2869 // msg(!cta.has_hdmi, "If YCbCr support is indicated, then both 4:2:2 and 4:4:4 %s be supported.\n",
2870 // cta.has_hdmi ? "shall" : "should");
2871 printf(" Native detailed modes: %u\n", x
[3] & 0x0f);
2872 if (cta
.block_number
== 0)
2874 else if (x
[3] != cta
.byte3
)
2875 fail("Byte 3 must be the same for all CTA-861 Extension Blocks.\n");
2876 if (cta
.block_number
== 0) {
2877 unsigned native_dtds
= x
[3] & 0x0f;
2879 cta
.native_timings
.clear();
2880 if (!native_dtds
&& !cta
.has_vfpdb
) {
2881 cta
.first_svd_might_be_preferred
= true;
2882 } else if (native_dtds
> cta
.preparsed_total_dtds
) {
2883 fail("There are more Native DTDs (%u) than DTDs (%u).\n",
2884 native_dtds
, cta
.preparsed_total_dtds
);
2886 if (native_dtds
> cta
.preparsed_total_dtds
)
2887 native_dtds
= cta
.preparsed_total_dtds
;
2888 for (unsigned i
= 0; i
< native_dtds
; i
++) {
2891 sprintf(type
, "DTD %3u", i
+ 1);
2892 cta
.native_timings
.push_back(timings_ext(i
+ 129, type
));
2894 if (cta
.has_hdmi
&& block_nr
!= (block_map
.saw_block_1
? 2 : 1))
2895 fail("The HDMI Specification requires that the first Extension Block (that is not a Block Map) is an CTA-861 Extension Block.\n");
2900 // Offset 0 means that there are no data blocks or DTDs,
2901 // so the remainder must be padding.
2902 if (!memchk(x
+ 4, 127 - 4)) {
2903 data_block
= "Padding";
2904 fail("Contains non-zero bytes.\n");
2912 for (i
= 4; i
< offset
; i
+= (x
[i
] & 0x1f) + 1) {
2913 cta_block(x
+ i
, cta
.found_tags
);
2918 fail("Offset is %u, but should be %u.\n", offset
, i
);
2921 data_block
= "Detailed Timing Descriptors";
2922 base
.seen_non_detailed_descriptor
= false;
2924 for (detailed
= x
+ offset
; detailed
+ 17 < x
+ 127; detailed
+= 18) {
2925 if (memchk(detailed
, 18))
2929 printf(" %s:\n", data_block
.c_str());
2931 detailed_block(detailed
);
2933 unused_bytes
= x
+ 127 - detailed
;
2934 if (!memchk(detailed
, unused_bytes
)) {
2935 data_block
= "Padding";
2936 fail("Contains non-zero bytes.\n");
2941 if (base
.serial_number
&& base
.has_serial_string
)
2942 warn("Display Product Serial Number is set, so the Serial Number in the Base EDID should be 0.\n");
2943 if (!cta
.has_vic_1
&& !base
.has_640x480p60_est_timing
)
2944 fail("Required 640x480p60 timings are missing in the established timings"
2945 " and the SVD list (VIC 1).\n");
2946 if ((cta
.supported_hdmi_vic_vsb_codes
& cta
.supported_hdmi_vic_codes
) !=
2947 cta
.supported_hdmi_vic_codes
)
2948 fail("HDMI VIC Codes must have their CTA-861 VIC equivalents in the VSB.\n");
2950 fail("Missing VCDB, needed for Set Selectable RGB Quantization to avoid interop issues.\n");
2951 if (!base
.uses_srgb
&& !cta
.has_cdb
)
2952 warn("Add a Colorimetry Data Block with the sRGB colorimetry bit set to avoid interop issues.\n");
2955 void edid_state::cta_resolve_svr(timings_ext
&t_ext
)
2957 if (t_ext
.svr() == 254) {
2958 t_ext
.flags
= cta
.t8vtdb
.flags
;
2959 add_str(t_ext
.flags
, ">=CTA-861-H");
2960 t_ext
.t
= cta
.t8vtdb
.t
;
2961 } else if (t_ext
.svr() <= 144) {
2962 t_ext
.flags
= cta
.vec_dtds
[t_ext
.svr() - 129].flags
;
2963 t_ext
.t
= cta
.vec_dtds
[t_ext
.svr() - 129].t
;
2964 } else if (t_ext
.svr() <= 160) {
2965 t_ext
.flags
= cta
.vec_vtdbs
[t_ext
.svr() - 145].flags
;
2966 add_str(t_ext
.flags
, ">=CTA-861-H");
2967 t_ext
.t
= cta
.vec_vtdbs
[t_ext
.svr() - 145].t
;
2968 } else if (t_ext
.svr() <= 175) {
2969 t_ext
.flags
.clear();
2970 unsigned char rid
= cta
.preparsed_first_vfd
.rid
;
2971 t_ext
.t
= calc_ovt_mode(rids
[rid
].hact
, rids
[rid
].vact
,
2972 rids
[rid
].hratio
, rids
[rid
].vratio
,
2973 vf_rate_values
[t_ext
.svr() - 160]);
2974 t_ext
.flags
= ">=CTA-861.6";
2978 void edid_state::cta_resolve_svrs()
2980 for (vec_timings_ext::iterator iter
= cta
.preferred_timings_vfpdb
.begin();
2981 iter
!= cta
.preferred_timings_vfpdb
.end(); ++iter
) {
2982 if (iter
->has_svr())
2983 cta_resolve_svr(*iter
);
2986 for (vec_timings_ext::iterator iter
= cta
.native_timings
.begin();
2987 iter
!= cta
.native_timings
.end(); ++iter
) {
2988 if (iter
->has_svr())
2989 cta_resolve_svr(*iter
);
2992 for (vec_timings_ext::iterator iter
= cta
.native_timing_nvrdb
.begin();
2993 iter
!= cta
.native_timing_nvrdb
.end(); ++iter
) {
2994 if (iter
->has_svr())
2995 cta_resolve_svr(*iter
);
2999 void edid_state::check_cta_blocks()
3001 unsigned max_pref_prog_hact
= 0;
3002 unsigned max_pref_prog_vact
= 0;
3003 unsigned max_pref_ilace_hact
= 0;
3004 unsigned max_pref_ilace_vact
= 0;
3006 data_block
= "CTA-861";
3008 // HDMI 1.4 goes up to 340 MHz. Dubious to have a DTD above that,
3009 // but no VICs. Displays often have a setting to turn off HDMI 2.x
3010 // support, dropping any HDMI 2.x VICs, but they sometimes forget
3011 // to replace the DTD in the base block as well.
3012 if (cta
.warn_about_hdmi_2x_dtd
)
3013 warn("DTD pixelclock indicates HDMI 2.x support, VICs indicate HDMI 1.x.\n");
3015 for (vec_timings_ext::iterator iter
= cta
.preferred_timings
.begin();
3016 iter
!= cta
.preferred_timings
.end(); ++iter
) {
3017 if (iter
->t
.interlaced
&&
3018 (iter
->t
.vact
> max_pref_ilace_vact
||
3019 (iter
->t
.vact
== max_pref_ilace_vact
&& iter
->t
.hact
>= max_pref_ilace_hact
))) {
3020 max_pref_ilace_hact
= iter
->t
.hact
;
3021 max_pref_ilace_vact
= iter
->t
.vact
;
3023 if (!iter
->t
.interlaced
&&
3024 (iter
->t
.vact
> max_pref_prog_vact
||
3025 (iter
->t
.vact
== max_pref_prog_vact
&& iter
->t
.hact
>= max_pref_prog_hact
))) {
3026 max_pref_prog_hact
= iter
->t
.hact
;
3027 max_pref_prog_vact
= iter
->t
.vact
;
3030 for (vec_timings_ext::iterator iter
= cta
.preferred_timings_vfpdb
.begin();
3031 iter
!= cta
.preferred_timings_vfpdb
.end(); ++iter
) {
3032 if (iter
->t
.interlaced
&&
3033 (iter
->t
.vact
> max_pref_ilace_vact
||
3034 (iter
->t
.vact
== max_pref_ilace_vact
&& iter
->t
.hact
>= max_pref_ilace_hact
))) {
3035 max_pref_ilace_hact
= iter
->t
.hact
;
3036 max_pref_ilace_vact
= iter
->t
.vact
;
3038 if (!iter
->t
.interlaced
&&
3039 (iter
->t
.vact
> max_pref_prog_vact
||
3040 (iter
->t
.vact
== max_pref_prog_vact
&& iter
->t
.hact
>= max_pref_prog_hact
))) {
3041 max_pref_prog_hact
= iter
->t
.hact
;
3042 max_pref_prog_vact
= iter
->t
.vact
;
3046 unsigned native_prog
= 0;
3047 unsigned native_prog_hact
= 0;
3048 unsigned native_prog_vact
= 0;
3049 bool native_prog_mixed_resolutions
= false;
3050 unsigned native_ilace
= 0;
3051 unsigned native_ilace_hact
= 0;
3052 unsigned native_ilace_vact
= 0;
3053 bool native_ilace_mixed_resolutions
= false;
3054 unsigned native_nvrdb_hact
= 0;
3055 unsigned native_nvrdb_vact
= 0;
3057 for (vec_timings_ext::iterator iter
= cta
.native_timings
.begin();
3058 iter
!= cta
.native_timings
.end(); ++iter
) {
3059 if (iter
->t
.interlaced
) {
3061 if (!native_ilace_hact
) {
3062 native_ilace_hact
= iter
->t
.hact
;
3063 native_ilace_vact
= iter
->t
.vact
;
3064 } else if (native_ilace_hact
!= iter
->t
.hact
||
3065 native_ilace_vact
!= iter
->t
.vact
) {
3066 native_ilace_mixed_resolutions
= true;
3070 if (!native_prog_hact
) {
3071 native_prog_hact
= iter
->t
.hact
;
3072 native_prog_vact
= iter
->t
.vact
;
3073 } else if (native_prog_hact
!= iter
->t
.hact
||
3074 native_prog_vact
!= iter
->t
.vact
) {
3075 native_prog_mixed_resolutions
= true;
3080 for (vec_timings_ext::iterator iter
= cta
.native_timing_nvrdb
.begin();
3081 iter
!= cta
.native_timing_nvrdb
.end(); ++iter
) {
3082 native_nvrdb_hact
= iter
->t
.hact
;
3083 native_nvrdb_vact
= iter
->t
.vact
;
3086 if (native_prog_mixed_resolutions
)
3087 fail("Native progressive timings are a mix of several resolutions.\n");
3088 if (native_ilace_mixed_resolutions
)
3089 fail("Native interlaced timings are a mix of several resolutions.\n");
3090 if (native_ilace
&& !native_prog
)
3091 fail("A native interlaced timing is present, but not a native progressive timing.\n");
3092 if (!native_prog_mixed_resolutions
&& native_prog
> 1)
3093 warn("Multiple native progressive timings are defined.\n");
3094 if (!native_ilace_mixed_resolutions
&& native_ilace
> 1)
3095 warn("Multiple native interlaced timings are defined.\n");
3097 if (native_nvrdb_vact
&&
3098 (max_pref_prog_vact
> native_nvrdb_vact
||
3099 (max_pref_prog_vact
== native_nvrdb_vact
&& max_pref_prog_hact
> native_nvrdb_hact
)))
3100 warn("Native video resolution of %ux%u is smaller than the max preferred progressive resolution %ux%u.\n",
3101 native_nvrdb_hact
, native_nvrdb_vact
,
3102 max_pref_prog_hact
, max_pref_prog_vact
);
3103 else if (!native_nvrdb_vact
&& !native_prog_mixed_resolutions
&& native_prog_vact
&&
3104 (max_pref_prog_vact
> native_prog_vact
||
3105 (max_pref_prog_vact
== native_prog_vact
&& max_pref_prog_hact
> native_prog_hact
)))
3106 warn("Native progressive resolution of %ux%u is smaller than the max preferred progressive resolution %ux%u.\n",
3107 native_prog_hact
, native_prog_vact
,
3108 max_pref_prog_hact
, max_pref_prog_vact
);
3109 if (!native_ilace_mixed_resolutions
&& native_ilace_vact
&&
3110 (max_pref_ilace_vact
> native_ilace_vact
||
3111 (max_pref_ilace_vact
== native_ilace_vact
&& max_pref_ilace_hact
> native_ilace_hact
)))
3112 warn("Native interlaced resolution of %ux%u is smaller than the max preferred interlaced resolution %ux%u.\n",
3113 native_ilace_hact
, native_ilace_vact
,
3114 max_pref_ilace_hact
, max_pref_ilace_vact
);
3116 if (dispid
.native_width
&& native_prog_hact
&&
3117 !native_prog_mixed_resolutions
) {
3118 if (dispid
.native_width
!= native_prog_hact
||
3119 dispid
.native_height
!= native_prog_vact
)
3120 fail("Mismatch between CTA-861 and DisplayID native progressive resolution.\n");