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_
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
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.
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
33 unsigned hratio
, vratio
;
35 unsigned rb
; // 1 if CVT with reduced blanking, 2 if CVT with reduced blanking v2
37 // The horizontal frontporch may be negative in GTF calculations,
38 // so use int instead of unsigned for hfp. Example: 292x176@76.
41 // The backporch may be negative in buggy detailed timings.
42 // So use int instead of unsigned for hbp and vbp.
45 // For interlaced formats the vertical front porch of the Even Field
46 // is actually a half-line longer.
48 // For interlaced formats the vertical back porch of the Odd Field
49 // is actually a half-line longer.
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
62 memset(&t
, 0, sizeof(t
));
64 timings_ext(unsigned svr
, const std::string
&_type
)
66 memset(&t
, 0, sizeof(t
));
70 timings_ext(const timings
&_t
, const std::string
&_type
, const std::string
&_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
; }
85 typedef std::vector
<timings_ext
> vec_timings_ext
;
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;
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
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;
147 std::string data_block
;
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
;
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
;
174 unsigned detailed_block_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
;
190 // CTA-861 block state
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
;
199 vec_timings_ext native_timings
;
201 bool first_svd_might_be_preferred
;
206 unsigned short preparsed_phys_addr
;
207 bool last_block_was_hdmi_vsdb
;
208 bool have_hf_vsdb
, have_hf_scdb
;
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];
218 // DisplayID block state
220 unsigned char version
;
221 unsigned short preparse_color_ids
;
222 unsigned short preparse_xfer_ids
;
223 unsigned preparse_displayid_blocks
;
226 bool has_product_identification
;
227 bool has_display_parameters
;
229 bool has_display_interface_features
;
230 vec_timings_ext preferred_timings
;
233 // Block Map block state
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
);
331 static inline void add_str(std::string
&s
, const std::string
&add
)
335 else if (!add
.empty())
339 void msg(bool is_warn
, const char *fmt
, ...);
343 #define warn(fmt, ...) msg(true, fmt, __VA_ARGS__)
344 #define warn_once(fmt, ...) \
346 static bool shown_warn; \
349 msg(true, fmt, __VA_ARGS__); \
352 #define fail(fmt, ...) msg(false, fmt, __VA_ARGS__)
356 #define warn(fmt, args...) msg(true, fmt, ##args)
357 #define warn_once(fmt, args...) \
359 static bool shown_warn; \
362 msg(true, fmt, ##args); \
365 #define fail(fmt, args...) msg(false, fmt, ##args)
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
);