edid-decode: support VTDBs in VFPDB
[edid-decode.git] / edid-decode.h
blob7e02615d05f0062afdbd74b7b14fe3ab98ba4f52
1 // SPDX-License-Identifier: MIT
2 /*
3 * Copyright 2006-2012 Red Hat, Inc.
4 * Copyright 2018-2020 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
6 * Author: Adam Jackson <ajax@nwnk.net>
7 * Maintainer: Hans Verkuil <hverkuil-cisco@xs4all.nl>
8 */
10 #ifndef __EDID_DECODE_H_
11 #define __EDID_DECODE_H_
13 #include <string>
14 #include <vector>
15 #include <string.h>
17 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
18 #define min(a, b) ((a) < (b) ? (a) : (b))
19 #define max(a, b) ((a) > (b) ? (a) : (b))
21 #define EDID_PAGE_SIZE 128U
22 #define EDID_MAX_BLOCKS 256U
24 // Video Timings
25 // If interlaced is true, then the vertical blanking
26 // for each field is (vfp + vsync + vbp + 0.5), except for
27 // the VIC 39 timings that doesn't have the 0.5 constant.
28 struct timings {
29 // Active horizontal and vertical frame height, including any
30 // borders, if present.
31 // Note: for interlaced formats the active field height is vact / 2
32 unsigned hact, vact;
33 unsigned hratio, vratio;
34 unsigned pixclk_khz;
35 unsigned rb; // 1 if CVT with reduced blanking, 2 if CVT with reduced blanking v2
36 bool interlaced;
37 // The horizontal frontporch may be negative in GTF calculations,
38 // so use int instead of unsigned for hfp. Example: 292x176@76.
39 int hfp;
40 unsigned hsync;
41 // The backporch may be negative in buggy detailed timings.
42 // So use int instead of unsigned for hbp and vbp.
43 int hbp;
44 bool pos_pol_hsync;
45 // For interlaced formats the vertical front porch of the Even Field
46 // is actually a half-line longer.
47 unsigned vfp, vsync;
48 // For interlaced formats the vertical back porch of the Odd Field
49 // is actually a half-line longer.
50 int vbp;
51 bool pos_pol_vsync;
52 unsigned hborder, vborder;
53 bool even_vtotal; // special for VIC 39
54 bool no_pol_vsync; // digital composite signals have no vsync polarity
55 unsigned hsize_mm, vsize_mm;
56 bool ycbcr420; // YCbCr 4:2:0 encoding
59 struct timings_ext {
60 timings_ext()
62 memset(&t, 0, sizeof(t));
64 timings_ext(unsigned svr, const std::string &_type)
66 memset(&t, 0, sizeof(t));
67 t.hact = svr;
68 type = _type;
70 timings_ext(const timings &_t, const std::string &_type, const std::string &_flags)
72 t = _t;
73 type = _type;
74 flags = _flags;
77 bool is_valid() const { return t.hact; }
78 bool has_svr() const { return t.hact && !t.vact; }
79 unsigned svr() const { return t.hact; }
80 timings t;
81 std::string type;
82 std::string flags;
85 typedef std::vector<timings_ext> vec_timings_ext;
87 struct edid_state {
88 edid_state()
90 // Global state
91 edid_size = num_blocks = block_nr = 0;
92 max_hor_freq_hz = max_vert_freq_hz = max_pixclk_khz = 0;
93 min_hor_freq_hz = 0xffffff;
94 min_vert_freq_hz = 0xffffffff;
95 warnings = failures = 0;
96 has_cta = has_dispid = false;
97 hide_serial_numbers = false;
99 // Base block state
100 base.edid_minor = 0;
101 base.has_name_descriptor = base.has_display_range_descriptor =
102 base.has_serial_number = base.has_serial_string =
103 base.supports_continuous_freq = base.supports_gtf =
104 base.supports_cvt = base.uses_gtf = base.uses_cvt =
105 base.has_640x480p60_est_timing = base.has_spwg =
106 base.seen_non_detailed_descriptor =
107 base.preferred_is_also_native = false;
108 base.detailed_block_cnt = base.dtd_cnt = 0;
110 base.min_display_hor_freq_hz = base.max_display_hor_freq_hz =
111 base.min_display_vert_freq_hz = base.max_display_vert_freq_hz =
112 base.max_display_pixclk_khz = base.max_display_width_mm =
113 base.max_display_height_mm = 0;
115 // CTA-861 block state
116 cta.has_vic_1 = cta.first_svd_might_be_preferred =
117 cta.has_hdmi = cta.has_vcdb = cta.has_vfpdb = false;
118 cta.last_block_was_hdmi_vsdb = cta.have_hf_vsdb = cta.have_hf_scdb = false;
119 cta.first_block = cta.first_svd = true;
120 cta.supported_hdmi_vic_codes = cta.supported_hdmi_vic_vsb_codes = 0;
121 memset(cta.vics, 0, sizeof(cta.vics));
122 memset(cta.preparsed_has_vic, 0, sizeof(cta.preparsed_has_vic));
123 cta.preparsed_phys_addr = 0xffff;
124 cta.preparse_total_dtds = 0;
125 cta.preparse_total_vtdbs = 0;
126 cta.preparse_has_t8vtdb = false;
128 // DisplayID block state
129 dispid.version = 0;
130 dispid.preparse_color_ids = dispid.preparse_xfer_ids = 0;
131 dispid.preparse_displayid_blocks = 0;
132 dispid.is_base_block = true;
133 dispid.is_display = dispid.has_product_identification =
134 dispid.has_display_parameters = dispid.has_type_1_7 =
135 dispid.has_display_interface_features = false;
137 // Block Map block state
138 block_map.saw_block_1 = false;
139 block_map.saw_block_128 = false;
142 // Global state
143 unsigned edid_size;
144 unsigned num_blocks;
145 unsigned block_nr;
146 std::string block;
147 std::string data_block;
148 bool has_cta;
149 bool has_dispid;
150 bool hide_serial_numbers;
152 unsigned min_hor_freq_hz;
153 unsigned max_hor_freq_hz;
154 double min_vert_freq_hz;
155 double max_vert_freq_hz;
156 unsigned max_pixclk_khz;
158 unsigned warnings;
159 unsigned failures;
161 // Base block state
162 struct {
163 unsigned edid_minor;
164 bool has_name_descriptor;
165 bool has_display_range_descriptor;
166 bool has_serial_number;
167 bool has_serial_string;
168 bool supports_continuous_freq;
169 bool supports_gtf;
170 bool supports_cvt;
171 bool uses_gtf;
172 bool uses_cvt;
173 bool has_spwg;
174 unsigned detailed_block_cnt;
175 unsigned dtd_cnt;
176 bool seen_non_detailed_descriptor;
177 bool has_640x480p60_est_timing;
178 bool preferred_is_also_native;
179 timings_ext preferred_timing;
181 unsigned min_display_hor_freq_hz;
182 unsigned max_display_hor_freq_hz;
183 unsigned min_display_vert_freq_hz;
184 unsigned max_display_vert_freq_hz;
185 unsigned max_display_pixclk_khz;
186 unsigned max_display_width_mm;
187 unsigned max_display_height_mm;
188 } base;
190 // CTA-861 block state
191 struct {
192 unsigned preparse_total_dtds;
193 vec_timings_ext vec_dtds;
194 unsigned preparse_total_vtdbs;
195 vec_timings_ext vec_vtdbs;
196 vec_timings_ext preferred_timings;
197 bool preparse_has_t8vtdb;
198 timings_ext t8vtdb;
199 vec_timings_ext native_timings;
200 bool has_vic_1;
201 bool first_svd_might_be_preferred;
202 unsigned char byte3;
203 bool has_hdmi;
204 bool has_vcdb;
205 bool has_vfpdb;
206 unsigned short preparsed_phys_addr;
207 bool last_block_was_hdmi_vsdb;
208 bool have_hf_vsdb, have_hf_scdb;
209 bool first_block;
210 bool first_svd;
211 unsigned supported_hdmi_vic_codes;
212 unsigned supported_hdmi_vic_vsb_codes;
213 unsigned short vics[256][2];
214 bool preparsed_has_vic[2][256];
215 std::vector<unsigned char> preparsed_svds[2];
216 } cta;
218 // DisplayID block state
219 struct {
220 unsigned char version;
221 unsigned short preparse_color_ids;
222 unsigned short preparse_xfer_ids;
223 unsigned preparse_displayid_blocks;
224 bool is_base_block;
225 bool is_display;
226 bool has_product_identification;
227 bool has_display_parameters;
228 bool has_type_1_7;
229 bool has_display_interface_features;
230 vec_timings_ext preferred_timings;
231 } dispid;
233 // Block Map block state
234 struct {
235 bool saw_block_1;
236 bool saw_block_128;
237 } block_map;
239 std::string dtd_type(unsigned dtd);
240 std::string dtd_type() { return dtd_type(base.dtd_cnt); }
241 bool print_timings(const char *prefix, const struct timings *t,
242 const char *type, const char *flags = "",
243 bool detailed = false);
244 bool print_timings(const char *prefix, const struct timings_ext &t,
245 bool detailed = false)
247 return print_timings(prefix, &t.t, t.type.c_str(), t.flags.c_str(), detailed);
249 void edid_gtf_mode(unsigned refresh, struct timings &t);
250 void edid_cvt_mode(unsigned refresh, struct timings &t);
251 void detailed_cvt_descriptor(const char *prefix, const unsigned char *x, bool first);
252 void print_standard_timing(const char *prefix, unsigned char b1, unsigned char b2,
253 bool gtf_only = false, unsigned vrefresh_offset = 60);
254 void detailed_display_range_limits(const unsigned char *x);
255 void detailed_epi(const unsigned char *x);
256 void detailed_timings(const char *prefix, const unsigned char *x,
257 bool base_or_cta = true);
258 void detailed_block(const unsigned char *x);
259 void parse_base_block(const unsigned char *x);
260 void check_base_block();
262 void print_vic_index(const char *prefix, unsigned idx, const char *suffix, bool ycbcr420 = false);
263 void cta_vcdb(const unsigned char *x, unsigned length);
264 void cta_svd(const unsigned char *x, unsigned n, bool for_ycbcr420);
265 void cta_y420cmdb(const unsigned char *x, unsigned length);
266 void cta_vfpdb(const unsigned char *x, unsigned length);
267 void cta_hdmi_block(const unsigned char *x, unsigned length);
268 void cta_displayid_type_7(const unsigned char *x, unsigned length);
269 void cta_displayid_type_8(const unsigned char *x, unsigned length);
270 void cta_displayid_type_10(const unsigned char *x, unsigned length);
271 void cta_ext_block(const unsigned char *x, unsigned length);
272 void cta_block(const unsigned char *x);
273 void preparse_cta_block(const unsigned char *x);
274 void parse_cta_block(const unsigned char *x);
275 void cta_resolve_svr(vec_timings_ext::iterator iter);
276 void cta_resolve_svrs();
277 void check_cta_blocks();
279 void parse_digital_interface(const unsigned char *x);
280 void parse_display_device(const unsigned char *x);
281 void parse_display_caps(const unsigned char *x);
282 void parse_display_xfer(const unsigned char *x);
283 void parse_di_ext_block(const unsigned char *x);
285 void check_displayid_datablock_revision(unsigned char hdr,
286 unsigned char valid_flags = 0,
287 unsigned char rev = 0);
288 void parse_displayid_product_id(const unsigned char *x);
289 std::string product_type(unsigned char x, bool heading);
290 void parse_displayid_interface_features(const unsigned char *x);
291 void parse_displayid_parameters(const unsigned char *x);
292 void parse_displayid_parameters_v2(const unsigned char *x);
293 void parse_displayid_display_intf(const unsigned char *x);
294 void parse_displayid_color_characteristics(const unsigned char *x);
295 void parse_displayid_transfer_characteristics(const unsigned char *x);
296 void parse_displayid_stereo_display_intf(const unsigned char *x);
297 void parse_displayid_type_1_7_timing(const unsigned char *x,
298 bool type7, unsigned block_rev, bool is_cta = false);
299 void parse_displayid_type_2_timing(const unsigned char *x);
300 void parse_displayid_type_3_timing(const unsigned char *x);
301 void parse_displayid_type_4_8_timing(unsigned char type, unsigned short id, bool is_cta = false);
302 void parse_displayid_video_timing_range_limits(const unsigned char *x);
303 void parse_displayid_string(const unsigned char *x);
304 void parse_displayid_display_device(const unsigned char *x);
305 void parse_displayid_intf_power_sequencing(const unsigned char *x);
306 void parse_displayid_type_5_timing(const unsigned char *x);
307 void parse_displayid_tiled_display_topology(const unsigned char *x, bool is_v2);
308 void parse_displayid_type_6_timing(const unsigned char *x);
309 void parse_displayid_type_9_timing(const unsigned char *x);
310 void parse_displayid_dynamic_video_timings_range_limits(const unsigned char *x);
311 void parse_displayid_ContainerID(const unsigned char *x);
312 void parse_displayid_type_10_timing(const unsigned char *x, bool is_cta = false);
313 void preparse_displayid_block(const unsigned char *x);
314 void parse_displayid_block(const unsigned char *x);
315 void parse_displayid_vesa(const unsigned char *x);
316 void parse_displayid_cta_data_block(const unsigned char *x);
317 void check_displayid_blocks();
319 void parse_vtb_ext_block(const unsigned char *x);
321 void parse_string_table(const unsigned char *x);
322 void parse_ls_ext_block(const unsigned char *x);
324 void parse_block_map(const unsigned char *x);
326 void preparse_extension(const unsigned char *x);
327 void parse_extension(const unsigned char *x);
328 int parse_edid();
331 static inline void add_str(std::string &s, const std::string &add)
333 if (s.empty())
334 s = add;
335 else if (!add.empty())
336 s = s + ", " + add;
339 void msg(bool is_warn, const char *fmt, ...);
341 #ifdef _WIN32
343 #define warn(fmt, ...) msg(true, fmt, __VA_ARGS__)
344 #define warn_once(fmt, ...) \
345 do { \
346 static bool shown_warn; \
347 if (!shown_warn) { \
348 shown_warn = true; \
349 msg(true, fmt, __VA_ARGS__); \
351 } while (0)
352 #define fail(fmt, ...) msg(false, fmt, __VA_ARGS__)
354 #else
356 #define warn(fmt, args...) msg(true, fmt, ##args)
357 #define warn_once(fmt, args...) \
358 do { \
359 static bool shown_warn; \
360 if (!shown_warn) { \
361 shown_warn = true; \
362 msg(true, fmt, ##args); \
364 } while (0)
365 #define fail(fmt, args...) msg(false, fmt, ##args)
367 #endif
369 void do_checksum(const char *prefix, const unsigned char *x, size_t len);
370 std::string utohex(unsigned char x);
371 std::string ouitohex(unsigned oui);
372 bool memchk(const unsigned char *x, unsigned len, unsigned char v = 0);
373 void hex_block(const char *prefix, const unsigned char *x, unsigned length,
374 bool show_ascii = true, unsigned step = 16);
375 std::string block_name(unsigned char block);
376 void calc_ratio(struct timings *t);
377 const char *oui_name(unsigned oui, bool reverse = false);
379 const struct timings *find_dmt_id(unsigned char dmt_id);
380 const struct timings *find_vic_id(unsigned char vic);
381 const struct timings *find_hdmi_vic_id(unsigned char hdmi_vic);
382 unsigned char hdmi_vic_to_vic(unsigned char hdmi_vic);
383 char *extract_string(const unsigned char *x, unsigned len);
385 #endif