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>
10 #ifndef __EDID_DECODE_H_
11 #define __EDID_DECODE_H_
18 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
19 #define min(a, b) ((a) < (b) ? (a) : (b))
20 #define max(a, b) ((a) > (b) ? (a) : (b))
22 #define EDID_PAGE_SIZE 128U
23 #define EDID_MAX_BLOCKS 256U
25 #define RB_ALT (1U << 7)
28 #define RB_CVT_V1 (1U)
29 #define RB_CVT_V2 (2U)
30 #define RB_CVT_V3 (3U)
34 // If interlaced is true, then the vertical blanking
35 // for each field is (vfp + vsync + vbp + 0.5), except for
36 // the VIC 39 timings that doesn't have the 0.5 constant.
38 // The sequence of the various video parameters is as follows:
40 // border - front porch - sync - back porch - border - active video
42 // Note: this is slightly different from EDID 1.4 which calls
43 // 'active video' as 'addressable video' and the EDID 1.4 term
44 // 'active video' includes the borders.
46 // But since borders are rarely used, the term 'active video' will
47 // typically be the same as 'addressable video', and that's how I
50 // Active horizontal and vertical frame height, excluding any
51 // borders, if present.
52 // Note: for interlaced formats the active field height is vact / 2
54 unsigned hratio
, vratio
;
56 // 0: no reduced blanking
57 // 1: CVT reduced blanking version 1
58 // 2: CVT reduced blanking version 2
59 // 2 | RB_ALT: CVT reduced blanking version 2 video-optimized (1000/1001 fps)
60 // 3: CVT reduced blanking version 3
61 // 3 | RB_ALT: v3 with a horizontal blank of 160
62 // 4: GTF Secondary Curve
65 // The horizontal frontporch may be negative in GTF calculations,
66 // so use int instead of unsigned for hfp. Example: 292x176@76.
69 // The backporch may be negative in buggy detailed timings.
70 // So use int instead of unsigned for hbp and vbp.
73 // For interlaced formats the vertical front porch of the Even Field
74 // is actually a half-line longer.
76 // For interlaced formats the vertical back porch of the Odd Field
77 // is actually a half-line longer.
80 unsigned hborder
, vborder
;
81 bool even_vtotal
; // special for VIC 39
82 bool no_pol_vsync
; // digital composite signals have no vsync polarity
83 unsigned hsize_mm
, vsize_mm
;
84 bool ycbcr420
; // YCbCr 4:2:0 encoding
90 memset(&t
, 0, sizeof(t
));
92 timings_ext(unsigned svr
, const std::string
&_type
)
94 memset(&t
, 0, sizeof(t
));
98 timings_ext(const timings
&_t
, const std::string
&_type
, const std::string
&_flags
)
105 bool is_valid() const { return t
.hact
; }
106 bool has_svr() const { return t
.hact
&& !t
.vact
; }
107 unsigned svr() const { return t
.hact
; }
114 gtf_ip_vert_freq
= 1,
119 typedef std::vector
<timings_ext
> vec_timings_ext
;
123 unsigned hratio
, vratio
;
128 unsigned char fr_factor
;
129 unsigned int bfr50
:1;
131 unsigned int bfr60
:1;
132 unsigned int fr144
:1;
140 edid_size
= num_blocks
= block_nr
= 0;
141 max_hor_freq_hz
= max_vert_freq_hz
= max_pixclk_khz
= 0;
142 min_hor_freq_hz
= 0xffffff;
143 min_vert_freq_hz
= 0xffffffff;
144 dtd_max_vsize_mm
= dtd_max_hsize_mm
= 0;
145 warnings
= failures
= 0;
146 has_cta
= has_dispid
= false;
147 // Note: for now we do not support native DisplayID data,
148 // so this is always false. But some tests are different
149 // depending on whether it is a native DisplayID structure
150 // or an extension block, so they can use this bool.
151 native_dispid
= false;
152 hide_serial_numbers
= false;
153 replace_unique_ids
= false;
154 image_width
= image_height
= diagonal
= 0;
155 serial_string_cnt
= 0;
156 serial_strings
.clear();
160 base
.has_name_descriptor
= base
.has_display_range_descriptor
=
161 base
.supports_continuous_freq
= base
.supports_gtf
=
162 base
.supports_cvt
= base
.seen_non_detailed_descriptor
=
163 base
.has_640x480p60_est_timing
= base
.has_spwg
=
164 base
.preferred_is_also_native
= false;
165 base
.serial_number
= 0;
166 base
.week
= base
.year
= 0;
167 base
.supports_sec_gtf
= false;
168 base
.sec_gtf_start_freq
= 0;
169 base
.C
= base
.M
= base
.K
= base
.J
= 0;
170 base
.max_pos_neg_hor_freq_khz
= 0;
171 base
.uses_srgb
= false;
172 base
.detailed_block_cnt
= base
.dtd_cnt
= 0;
174 base
.min_display_hor_freq_hz
= base
.max_display_hor_freq_hz
=
175 base
.min_display_vert_freq_hz
= base
.max_display_vert_freq_hz
=
176 base
.max_display_pixclk_khz
= base
.max_display_width_mm
=
177 base
.max_display_height_mm
= 0;
179 // CTA-861 block state
180 cta
.has_vic_1
= cta
.first_svd_might_be_preferred
= cta
.has_sldb
=
181 cta
.has_hdmi
= cta
.has_vcdb
= cta
.has_vfpdb
= cta
.has_cdb
=
182 cta
.has_nvrdb
= cta
.has_pidb
= false;
183 cta
.previous_cta_tag
= 0xfff;
184 cta
.have_hf_vsdb
= cta
.have_hf_scdb
= false;
185 cta
.hdmi_max_rate
= 0;
186 cta
.hf_eeodb_blocks
= 0;
187 cta
.image_width
= cta
.image_height
= 0;
188 cta
.block_number
= 0;
189 cta
.has_svrs
= false;
190 cta
.first_svd
= true;
191 cta
.supported_hdmi_vic_codes
= cta
.supported_hdmi_vic_vsb_codes
= 0;
192 memset(cta
.vics
, 0, sizeof(cta
.vics
));
193 memset(cta
.preparsed_has_vic
, 0, sizeof(cta
.preparsed_has_vic
));
194 memset(&cta
.preparsed_first_vfd
, 0, sizeof(cta
.preparsed_first_vfd
));
195 cta
.preparsed_phys_addr
= 0xffff;
196 cta
.preparsed_speaker_count
= 0;
197 cta
.preparsed_sld
= false;
198 cta
.preparsed_sld_has_coord
= false;
199 cta
.preparsed_total_dtds
= 0;
200 cta
.preparsed_total_vtdbs
= 0;
201 cta
.preparsed_has_t8vtdb
= false;
202 cta
.preparsed_t8vtdb_dmt
= 0;
203 cta
.preparsed_max_vic_pixclk_khz
= 0;
204 cta
.warn_about_hdmi_2x_dtd
= false;
206 cta
.avi_v4_length
= 14;
207 cta
.has_ycbcr444
= false;
208 cta
.has_ycbcr422
= false;
209 cta
.has_ycbcr420
= false;
211 // DisplayID block state
213 dispid
.native_width
= dispid
.native_height
= 0;
214 dispid
.preparsed_color_ids
= dispid
.preparsed_xfer_ids
= 0;
215 dispid
.preparsed_displayid_blocks
= 0;
216 dispid
.is_base_block
= true;
217 dispid
.is_display
= dispid
.has_product_identification
=
218 dispid
.has_display_parameters
= dispid
.has_type_1_7
=
219 dispid
.has_display_interface_features
=
220 dispid
.has_tiled_display_topology
= dispid
.has_ycbcr_420
=
221 dispid
.is_arvr
= dispid
.has_arvr_hdm
= dispid
.has_arvr_layer
=
222 dispid
.has_stereo
= dispid
.has_stereo_display_interface
= false;
223 dispid
.block_number
= 0;
224 dispid
.image_width
= dispid
.image_height
= 0;
226 // Block Map block state
227 block_map
.saw_block_1
= false;
228 block_map
.saw_block_128
= false;
236 std::string data_block
;
237 unsigned unused_bytes
;
241 bool hide_serial_numbers
;
242 bool replace_unique_ids
;
243 std::vector
<std::string
> serial_strings
;
244 unsigned serial_string_cnt
;
246 unsigned min_hor_freq_hz
;
247 unsigned max_hor_freq_hz
;
248 double min_vert_freq_hz
;
249 double max_vert_freq_hz
;
250 unsigned max_pixclk_khz
;
251 unsigned dtd_max_hsize_mm
;
252 unsigned dtd_max_vsize_mm
;
255 unsigned image_width
, image_height
;
265 bool has_name_descriptor
;
266 bool has_display_range_descriptor
;
267 unsigned serial_number
;
268 unsigned char week
, year
;
269 bool supports_continuous_freq
;
271 bool supports_sec_gtf
;
272 unsigned sec_gtf_start_freq
;
277 unsigned detailed_block_cnt
;
279 bool seen_non_detailed_descriptor
;
280 bool has_640x480p60_est_timing
;
281 bool preferred_is_also_native
;
282 timings_ext preferred_timing
;
284 unsigned min_display_hor_freq_hz
;
285 unsigned max_display_hor_freq_hz
;
286 unsigned min_display_vert_freq_hz
;
287 unsigned max_display_vert_freq_hz
;
288 unsigned max_display_pixclk_khz
;
289 unsigned max_display_width_mm
;
290 unsigned max_display_height_mm
;
291 unsigned max_pos_neg_hor_freq_khz
;
294 // CTA-861 block state
296 unsigned preparsed_total_dtds
;
297 vec_timings_ext vec_dtds
;
298 unsigned preparsed_total_vtdbs
;
299 vec_timings_ext vec_vtdbs
;
300 cta_vfd preparsed_first_vfd
;
301 vec_timings_ext preferred_timings
;
302 vec_timings_ext preferred_timings_vfpdb
;
303 bool preparsed_has_t8vtdb
;
304 unsigned preparsed_t8vtdb_dmt
;
305 // Keep track of the found Tag/Extended Tag pairs.
306 // The unsigned value is equal to: (tag) | (OUI enum << 12) or (extended tag) | (tag << 8) | (OUI enum << 12)
307 std::vector
<unsigned> found_tags
;
309 vec_timings_ext native_timings
;
310 vec_timings_ext native_timing_nvrdb
;
312 unsigned image_width
, image_height
;
314 bool first_svd_might_be_preferred
;
317 unsigned hdmi_max_rate
;
322 unsigned preparsed_speaker_count
;
323 bool preparsed_sld_has_coord
;
327 unsigned short preparsed_phys_addr
;
328 unsigned previous_cta_tag
;
329 bool have_hf_vsdb
, have_hf_scdb
;
330 unsigned hf_eeodb_blocks
;
331 unsigned block_number
;
334 unsigned supported_hdmi_vic_codes
;
335 unsigned supported_hdmi_vic_vsb_codes
;
336 unsigned short vics
[256][2];
337 bool preparsed_has_vic
[2][256];
338 std::vector
<unsigned char> preparsed_svds
[2];
339 unsigned preparsed_max_vic_pixclk_khz
;
340 bool warn_about_hdmi_2x_dtd
;
341 unsigned avi_version
;
342 unsigned avi_v4_length
;
348 // DisplayID block state
350 unsigned char version
;
351 unsigned short preparsed_color_ids
;
352 unsigned short preparsed_xfer_ids
;
353 unsigned preparsed_displayid_blocks
;
357 bool has_product_identification
;
358 bool has_display_parameters
;
360 bool has_display_interface_features
;
361 bool has_tiled_display_topology
;
362 bool has_stereo_display_interface
;
367 vec_timings_ext preferred_timings
;
368 unsigned native_width
, native_height
;
370 unsigned image_width
, image_height
;
371 unsigned block_number
;
372 // Keep track of the found CTA-861 Tag/Extended Tag pairs.
373 // The unsigned value is equal to: (tag) | (OUI enum << 12) or (extended tag) | (tag << 8) | (OUI enum << 12)
374 std::vector
<unsigned> found_tags
;
377 // Block Map block state
383 std::string
dtd_type(unsigned dtd
);
384 std::string
dtd_type() { return dtd_type(base
.dtd_cnt
); }
385 bool print_timings(const char *prefix
, const struct timings
*t
,
386 const char *type
, const char *flags
= "",
387 bool detailed
= false, bool do_checks
= true,
389 bool print_timings(const char *prefix
, const struct timings_ext
&t
,
390 bool detailed
= false, bool do_checks
= true,
393 return print_timings(prefix
, &t
.t
, t
.type
.c_str(), t
.flags
.c_str(),
394 detailed
, do_checks
, ntsc
);
396 timings
calc_gtf_mode(unsigned h_pixels
, unsigned v_lines
,
397 double ip_freq_rqd
, bool int_rqd
= false,
398 enum gtf_ip_parm ip_parm
= gtf_ip_vert_freq
,
399 bool margins_rqd
= false, bool secondary
= false,
400 double C
= 40, double M
= 600, double K
= 128, double J
= 20);
401 void edid_gtf_mode(unsigned refresh
, struct timings
&t
);
402 timings
calc_cvt_mode(unsigned h_pixels
, unsigned v_lines
,
403 double ip_freq_rqd
, unsigned rb
, bool int_rqd
= false,
404 bool margins_rqd
= false, bool alt
= false,
405 unsigned rb_h_blank
= 0, unsigned rb_v_blank
= 460,
406 bool early_vsync_rqd
= false);
407 void edid_cvt_mode(unsigned refresh
, struct timings
&t
, unsigned rb_h_blank
= 0,
408 unsigned rb_v_blank
= 460, bool early_vsync_rqd
= false);
409 void detailed_cvt_descriptor(const char *prefix
, const unsigned char *x
, bool first
);
410 timings
calc_ovt_mode(unsigned hact
, unsigned vact
,
411 unsigned hratio
, unsigned vratio
,
412 unsigned frame_rate
);
413 void print_standard_timing(const char *prefix
, unsigned char b1
, unsigned char b2
,
414 bool gtf_only
= false, bool show_both
= false);
415 void detailed_display_range_limits(const unsigned char *x
);
416 void detailed_epi(const unsigned char *x
);
417 void detailed_timings(const char *prefix
, const unsigned char *x
,
418 bool base_or_cta
= true);
419 bool preparse_detailed_block(unsigned char *x
);
420 void preparse_base_block(unsigned char *x
);
421 void detailed_block(const unsigned char *x
);
422 void parse_base_block(const unsigned char *x
);
423 void check_base_block(const unsigned char *x
);
425 void list_established_timings();
427 void data_block_oui(std::string block_name
, const unsigned char *x
, unsigned length
, unsigned *ouinum
,
428 bool ignorezeros
= false, bool do_ascii
= false, bool big_endian
= false,
429 bool silent
= false);
431 void print_vic_index(const char *prefix
, unsigned idx
, const char *suffix
, bool ycbcr420
= false);
432 void hdmi_latency(unsigned char vid_lat
, unsigned char aud_lat
, bool is_ilaced
);
433 void cta_vcdb(const unsigned char *x
, unsigned length
);
434 void cta_svd(const unsigned char *x
, unsigned n
, bool for_ycbcr420
);
435 void cta_vfdb(const unsigned char *x
, unsigned n
);
436 void cta_y420cmdb(const unsigned char *x
, unsigned length
);
437 void cta_print_svr(unsigned char svr
, vec_timings_ext
&vec_tim
);
438 void cta_vfpdb(const unsigned char *x
, unsigned length
);
439 void cta_nvrdb(const unsigned char *x
, unsigned length
);
440 cta_vfd
cta_parse_vfd(const unsigned char *x
, unsigned lvfd
);
441 void cta_rcdb(const unsigned char *x
, unsigned length
);
442 void cta_sldb(const unsigned char *x
, unsigned length
);
443 void cta_pidb(const unsigned char *x
, unsigned length
);
444 void cta_preparse_sldb(const unsigned char *x
, unsigned length
);
445 void cta_colorimetry_block(const unsigned char *x
, unsigned length
);
446 void cta_hdmi_block(const unsigned char *x
, unsigned length
);
447 void cta_hf_scdb(const unsigned char *x
, unsigned length
);
448 void cta_displayid_type_7(const unsigned char *x
, unsigned length
);
449 void cta_displayid_type_8(const unsigned char *x
, unsigned length
);
450 void cta_displayid_type_10(const unsigned char *x
, unsigned length
);
451 void cta_block(const unsigned char *x
, std::vector
<unsigned> &found_tags
);
452 void preparse_cta_block(unsigned char *x
);
453 void parse_cta_block(const unsigned char *x
);
454 void cta_resolve_svr(timings_ext
&t_ext
);
455 void cta_resolve_svrs();
456 void check_cta_blocks();
457 void cta_list_vics();
458 void cta_list_hdmi_vics();
459 void cta_list_rids();
460 void cta_list_rid_timings(unsigned list_rid
= 0);
462 void set_displayid_native_res(unsigned w
, unsigned h
);
463 void parse_digital_interface(const unsigned char *x
);
464 void parse_display_device(const unsigned char *x
);
465 void parse_display_caps(const unsigned char *x
);
466 void parse_display_xfer(const unsigned char *x
);
467 void parse_di_ext_block(const unsigned char *x
);
469 void check_displayid_datablock_revision(unsigned char hdr
,
470 unsigned char valid_flags
= 0,
471 unsigned char rev
= 0);
472 void parse_displayid_product_id(const unsigned char *x
);
473 std::string
product_type(unsigned char x
, bool heading
);
474 void parse_displayid_interface_features(const unsigned char *x
);
475 void parse_displayid_parameters(const unsigned char *x
);
476 void parse_displayid_parameters_v2(const unsigned char *x
, unsigned block_rev
);
477 void parse_displayid_display_intf(const unsigned char *x
);
478 void parse_displayid_color_characteristics(const unsigned char *x
);
479 void parse_displayid_transfer_characteristics(const unsigned char *x
);
480 void parse_displayid_stereo_display_intf(const unsigned char *x
);
481 void parse_displayid_type_1_7_timing(const unsigned char *x
,
482 bool type7
, unsigned block_rev
, bool is_cta
= false);
483 void parse_displayid_type_2_timing(const unsigned char *x
);
484 void parse_displayid_type_3_timing(const unsigned char *x
);
485 void parse_displayid_type_4_8_timing(unsigned char type
, unsigned short id
, bool is_cta
= false);
486 void parse_displayid_video_timing_range_limits(const unsigned char *x
);
487 void parse_displayid_string(const unsigned char *x
);
488 void parse_displayid_display_device(const unsigned char *x
);
489 void parse_displayid_intf_power_sequencing(const unsigned char *x
);
490 void parse_displayid_type_5_timing(const unsigned char *x
);
491 void parse_displayid_tiled_display_topology(const unsigned char *x
, bool is_v2
);
492 void parse_displayid_type_6_timing(const unsigned char *x
);
493 void parse_displayid_type_9_timing(const unsigned char *x
);
494 void parse_displayid_dynamic_video_timings_range_limits(const unsigned char *x
);
495 void parse_displayid_ContainerID(const unsigned char *x
);
496 void parse_displayid_adaptive_sync(const unsigned char *x
);
497 void parse_displayid_arvr_hmd(const unsigned char *x
);
498 void parse_displayid_arvr_layer(const unsigned char *x
);
499 void parse_displayid_brightness_lum_range(const unsigned char *x
);
500 void parse_displayid_type_10_timing(const unsigned char *x
, unsigned sz
,
501 bool is_cta
= false);
502 void preparse_displayid_block(unsigned char *x
);
503 unsigned displayid_block(const unsigned version
, const unsigned char *x
, unsigned length
);
504 void parse_displayid_block(const unsigned char *x
);
505 void parse_displayid_vesa(const unsigned char *x
);
506 void parse_displayid_apple(const unsigned char *x
);
507 void parse_displayid_cta_data_block(const unsigned char *x
);
508 void check_displayid_blocks();
510 void parse_vtb_ext_block(const unsigned char *x
);
512 void parse_string_table(const unsigned char *x
);
513 void preparse_ls_ext_block(unsigned char *x
);
514 void parse_ls_ext_block(const unsigned char *x
);
516 void parse_block_map(const unsigned char *x
);
518 void preparse_extension(unsigned char *x
);
519 void parse_extension(const unsigned char *x
);
520 void print_preferred_timings();
521 void print_native_res();
524 int parse_if(const std::string
&fname
);
525 int parse_if_hdr(const unsigned char *x
, unsigned size
, unsigned char mask
= 0xff);
526 void parse_if_hdmi(const unsigned char *x
, unsigned len
);
527 void parse_if_hdmi_forum(const unsigned char *x
, unsigned len
);
528 void parse_if_vendor(const unsigned char *x
, unsigned size
);
529 void parse_if_avi(const unsigned char *x
, unsigned size
);
530 void parse_if_spd(const unsigned char *x
, unsigned size
);
531 void parse_if_audio(const unsigned char *x
, unsigned size
);
532 void parse_if_mpeg_source(const unsigned char *x
, unsigned size
);
533 void parse_if_ntsc_vbi(const unsigned char *x
, unsigned size
);
534 void parse_if_drm(const unsigned char *x
, unsigned size
);
537 static inline void add_str(std::string
&s
, const std::string
&add
)
541 else if (!add
.empty())
545 void msg(bool is_warn
, const char *fmt
, ...);
549 #define warn(fmt, ...) msg(true, fmt, __VA_ARGS__)
550 #define warn_once(fmt, ...) \
552 static bool shown_warn; \
555 msg(true, fmt, __VA_ARGS__); \
558 #define fail(fmt, ...) msg(false, fmt, __VA_ARGS__)
562 #define warn(fmt, args...) msg(true, fmt, ##args)
563 #define warn_once(fmt, args...) \
565 static bool shown_warn; \
568 msg(true, fmt, ##args); \
571 #define fail(fmt, args...) msg(false, fmt, ##args)
575 // NULL terminated array
576 extern const char *cta_speaker_map
[];
578 static inline double chrom2d(const unsigned char *x
)
580 unsigned v
= x
[0] + (x
[1] << 8);
585 std::string
utohex(unsigned char x
);
586 std::string
ouitohex(unsigned oui
);
587 std::string
containerid2s(const unsigned char *x
);
588 bool memchk(const unsigned char *x
, unsigned len
, unsigned char v
= 0);
589 void hex_block(const char *prefix
, const unsigned char *x
, unsigned length
,
590 bool show_ascii
= true, unsigned step
= 16);
591 std::string
block_name(unsigned char block
);
592 void do_checksum(const char *prefix
, const unsigned char *x
, size_t len
, size_t checksum_pos
,
593 unsigned unused_bytes
= 0);
594 void replace_checksum(unsigned char *x
, size_t len
);
595 void calc_ratio(struct timings
*t
);
596 unsigned calc_fps(const struct timings
*t
);
597 const char *oui_name(unsigned oui
, unsigned *ouinum
= NULL
);
598 unsigned gcd(unsigned a
, unsigned b
);
600 bool match_timings(const timings
&t1
, const timings
&t2
);
601 bool timings_close_match(const timings
&t1
, const timings
&t2
);
602 const struct timings
*find_dmt_id(unsigned char dmt_id
);
603 const struct timings
*close_match_to_dmt(const timings
&t
, unsigned &dmt
);
604 const struct timings
*find_vic_id(unsigned char vic
);
605 const struct cta_rid
*find_rid(unsigned char rid
);
606 unsigned char rid_fps_to_vic(unsigned char rid
, unsigned fps
);
607 const struct timings
*find_hdmi_vic_id(unsigned char hdmi_vic
);
608 const struct timings
*cta_close_match_to_vic(const timings
&t
, unsigned &vic
);
609 bool cta_matches_vic(const timings
&t
, unsigned &vic
);
610 unsigned char hdmi_vic_to_vic(unsigned char hdmi_vic
);
613 char *extract_string(const unsigned char *x
, unsigned len
, bool is_cp437
);
615 #define oneoui(c,k,n) const unsigned kOUI_##k = __LINE__<<12;