1 #include <assert.h>
2 #include <errno.h>
3 #include <stdbool.h>
4 #include <stdlib.h>
5 #include <string.h>
6
7 #include "bits.h"
8 #include "dmt.h"
9 #include "edid.h"
10 #include "log.h"
11
12 /**
13 * The size of an EDID block, defined in section 2.2.
14 */
15 #define EDID_BLOCK_SIZE 128
16 /**
17 * The size of an EDID standard timing, defined in section 3.9.
18 */
19 #define EDID_STANDARD_TIMING_SIZE 2
20 /**
21 * The size of an EDID CVT timing code, defined in section 3.10.3.8.
22 */
23 #define EDID_CVT_TIMING_CODE_SIZE 3
24
25 /**
26 * Fixed EDID header, defined in section 3.1.
27 */
28 static const uint8_t header[] = { 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00 };
29
30 static void
add_failure(struct di_edid * edid,const char fmt[],...)31 add_failure(struct di_edid *edid, const char fmt[], ...)
32 {
33 va_list args;
34
35 va_start(args, fmt);
36 _di_logger_va_add_failure(edid->logger, fmt, args);
37 va_end(args);
38 }
39
40 static void
add_failure_until(struct di_edid * edid,int revision,const char fmt[],...)41 add_failure_until(struct di_edid *edid, int revision, const char fmt[], ...)
42 {
43 va_list args;
44
45 if (edid->revision > revision) {
46 return;
47 }
48
49 va_start(args, fmt);
50 _di_logger_va_add_failure(edid->logger, fmt, args);
51 va_end(args);
52 }
53
54 static void
parse_version_revision(const uint8_t data[static EDID_BLOCK_SIZE],int * version,int * revision)55 parse_version_revision(const uint8_t data[static EDID_BLOCK_SIZE],
56 int *version, int *revision)
57 {
58 *version = (int) data[0x12];
59 *revision = (int) data[0x13];
60 }
61
62 static size_t
parse_ext_count(const uint8_t data[static EDID_BLOCK_SIZE])63 parse_ext_count(const uint8_t data[static EDID_BLOCK_SIZE])
64 {
65 return data[0x7E];
66 }
67
68 static bool
validate_block_checksum(const uint8_t data[static EDID_BLOCK_SIZE])69 validate_block_checksum(const uint8_t data[static EDID_BLOCK_SIZE])
70 {
71 uint8_t sum = 0;
72 size_t i;
73
74 for (i = 0; i < EDID_BLOCK_SIZE; i++) {
75 sum += data[i];
76 }
77
78 return sum == 0;
79 }
80
81 static void
parse_vendor_product(struct di_edid * edid,const uint8_t data[static EDID_BLOCK_SIZE])82 parse_vendor_product(struct di_edid *edid,
83 const uint8_t data[static EDID_BLOCK_SIZE])
84 {
85 struct di_edid_vendor_product *out = &edid->vendor_product;
86 uint16_t man, raw_week, raw_year;
87 int year = 0;
88
89 /* The ASCII 3-letter manufacturer code is encoded in 5-bit codes. */
90 man = (uint16_t) ((data[0x08] << 8) | data[0x09]);
91 out->manufacturer[0] = ((man >> 10) & 0x1F) + '@';
92 out->manufacturer[1] = ((man >> 5) & 0x1F) + '@';
93 out->manufacturer[2] = ((man >> 0) & 0x1F) + '@';
94
95 out->product = (uint16_t) (data[0x0A] | (data[0x0B] << 8));
96 out->serial = (uint32_t) (data[0x0C] |
97 (data[0x0D] << 8) |
98 (data[0x0E] << 16) |
99 (data[0x0F] << 24));
100
101 raw_week = data[0x10];
102 raw_year = data[0x11];
103
104 if (raw_year >= 0x10 || edid->revision < 4) {
105 year = data[0x11] + 1990;
106 } else if (edid->revision == 4) {
107 add_failure(edid, "Year set to reserved value.");
108 }
109
110 if (raw_week == 0xFF) {
111 /* Special flag for model year */
112 out->model_year = year;
113 } else {
114 out->manufacture_year = year;
115 if (raw_week > 54) {
116 add_failure_until(edid, 4,
117 "Invalid week %u of manufacture.",
118 raw_week);
119 } else if (raw_week > 0) {
120 out->manufacture_week = raw_week;
121 }
122 }
123 }
124
125 static void
parse_video_input_digital(struct di_edid * edid,uint8_t video_input)126 parse_video_input_digital(struct di_edid *edid, uint8_t video_input)
127 {
128 uint8_t color_bit_depth, interface;
129 struct di_edid_video_input_digital *digital = &edid->video_input_digital;
130
131 if (edid->revision < 2) {
132 if (get_bit_range(video_input, 6, 0) != 0)
133 add_failure(edid, "Digital Video Interface Standard set to reserved value 0x%02x.",
134 video_input);
135 return;
136 }
137 if (edid->revision < 4) {
138 if (get_bit_range(video_input, 6, 1) != 0)
139 add_failure(edid, "Digital Video Interface Standard set to reserved value 0x%02x.",
140 video_input);
141 digital->dfp1 = has_bit(video_input, 0);
142 return;
143 }
144
145 color_bit_depth = get_bit_range(video_input, 6, 4);
146 if (color_bit_depth == 0x07) {
147 /* Reserved */
148 add_failure_until(edid, 4, "Color Bit Depth set to reserved value.");
149 } else if (color_bit_depth != 0) {
150 digital->color_bit_depth = 2 * color_bit_depth + 4;
151 }
152
153 interface = get_bit_range(video_input, 3, 0);
154 switch (interface) {
155 case DI_EDID_VIDEO_INPUT_DIGITAL_UNDEFINED:
156 case DI_EDID_VIDEO_INPUT_DIGITAL_DVI:
157 case DI_EDID_VIDEO_INPUT_DIGITAL_HDMI_A:
158 case DI_EDID_VIDEO_INPUT_DIGITAL_HDMI_B:
159 case DI_EDID_VIDEO_INPUT_DIGITAL_MDDI:
160 case DI_EDID_VIDEO_INPUT_DIGITAL_DISPLAYPORT:
161 digital->interface = interface;
162 break;
163 default:
164 add_failure_until(edid, 4,
165 "Digital Video Interface Standard set to reserved value 0x%02x.",
166 interface);
167 digital->interface = DI_EDID_VIDEO_INPUT_DIGITAL_UNDEFINED;
168 break;
169 }
170 }
171
172 static void
parse_video_input_analog(struct di_edid * edid,uint8_t video_input)173 parse_video_input_analog(struct di_edid *edid, uint8_t video_input)
174 {
175 struct di_edid_video_input_analog *analog = &edid->video_input_analog;
176
177 analog->signal_level_std = get_bit_range(video_input, 6, 5);
178 analog->video_setup = has_bit(video_input, 4);
179 analog->sync_separate = has_bit(video_input, 3);
180 analog->sync_composite = has_bit(video_input, 2);
181 analog->sync_on_green = has_bit(video_input, 1);
182 analog->sync_serrations = has_bit(video_input, 0);
183 }
184
185 static void
parse_basic_params_features(struct di_edid * edid,const uint8_t data[static EDID_BLOCK_SIZE])186 parse_basic_params_features(struct di_edid *edid,
187 const uint8_t data[static EDID_BLOCK_SIZE])
188 {
189 uint8_t video_input, width, height, features;
190 struct di_edid_screen_size *screen_size = &edid->screen_size;
191
192 video_input = data[0x14];
193 edid->is_digital = has_bit(video_input, 7);
194
195 if (edid->is_digital) {
196 parse_video_input_digital(edid, video_input);
197 } else {
198 parse_video_input_analog(edid, video_input);
199 }
200
201 /* v1.3 says screen size is undefined if either byte is zero, v1.4 says
202 * screen size and aspect ratio are undefined if both bytes are zero and
203 * encodes the aspect ratio if either byte is zero. */
204 width = data[0x15];
205 height = data[0x16];
206 if (width > 0 && height > 0) {
207 screen_size->width_cm = width;
208 screen_size->height_cm = height;
209 } else if (edid->revision >= 4) {
210 if (width > 0) {
211 screen_size->landscape_aspect_ratio = ((float) width + 99) / 100;
212 } else if (height > 0) {
213 screen_size->portait_aspect_ratio = ((float) height + 99) / 100;
214 }
215 }
216
217 if (data[0x17] != 0xFF) {
218 edid->gamma = ((float) data[0x17] + 100) / 100;
219 } else {
220 edid->gamma = 0;
221 }
222
223 features = data[0x18];
224
225 edid->dpms.standby = has_bit(features, 7);
226 edid->dpms.suspend = has_bit(features, 6);
227 edid->dpms.off = has_bit(features, 5);
228
229 if (edid->is_digital && edid->revision >= 4) {
230 edid->color_encoding_formats.rgb444 = true;
231 edid->color_encoding_formats.ycrcb444 = has_bit(features, 3);
232 edid->color_encoding_formats.ycrcb422 = has_bit(features, 4);
233 edid->display_color_type = DI_EDID_DISPLAY_COLOR_UNDEFINED;
234 } else {
235 edid->display_color_type = get_bit_range(features, 4, 3);
236 }
237
238 if (edid->revision >= 4) {
239 edid->misc_features.has_preferred_timing = true;
240 edid->misc_features.continuous_freq = has_bit(features, 0);
241 edid->misc_features.preferred_timing_is_native = has_bit(features, 1);
242 } else {
243 edid->misc_features.default_gtf = has_bit(features, 0);
244 edid->misc_features.has_preferred_timing = has_bit(features, 1);
245 }
246 edid->misc_features.srgb_is_primary = has_bit(features, 2);
247 }
248
249 static float
decode_chromaticity_coord(uint8_t hi,uint8_t lo)250 decode_chromaticity_coord(uint8_t hi, uint8_t lo)
251 {
252 uint16_t raw; /* only 10 bits are used */
253
254 raw = (uint16_t) ((hi << 2) | lo);
255 return (float) raw / 1024;
256 }
257
258 static void
parse_chromaticity_coords(struct di_edid * edid,const uint8_t data[static EDID_BLOCK_SIZE])259 parse_chromaticity_coords(struct di_edid *edid,
260 const uint8_t data[static EDID_BLOCK_SIZE])
261 {
262 uint8_t lo;
263 bool all_set, any_set;
264 struct di_edid_chromaticity_coords *coords;
265
266 coords = &edid->chromaticity_coords;
267
268 lo = data[0x19];
269 coords->red_x = decode_chromaticity_coord(data[0x1B], get_bit_range(lo, 7, 6));
270 coords->red_y = decode_chromaticity_coord(data[0x1C], get_bit_range(lo, 5, 4));
271 coords->green_x = decode_chromaticity_coord(data[0x1D], get_bit_range(lo, 3, 2));
272 coords->green_y = decode_chromaticity_coord(data[0x1E], get_bit_range(lo, 1, 0));
273
274 lo = data[0x1A];
275 coords->blue_x = decode_chromaticity_coord(data[0x1F], get_bit_range(lo, 7, 6));
276 coords->blue_y = decode_chromaticity_coord(data[0x20], get_bit_range(lo, 5, 4));
277 coords->white_x = decode_chromaticity_coord(data[0x21], get_bit_range(lo, 3, 2));
278 coords->white_y = decode_chromaticity_coord(data[0x22], get_bit_range(lo, 1, 0));
279
280 /* Either all primaries coords must be set, either none must be set */
281 any_set = coords->red_x != 0 || coords->red_y != 0
282 || coords->green_x != 0 || coords->green_y != 0
283 || coords->blue_x != 0 || coords->blue_y != 0;
284 all_set = coords->red_x != 0 && coords->red_y != 0
285 && coords->green_x != 0 && coords->green_y != 0
286 && coords->blue_x != 0 && coords->blue_y != 0;
287 if (any_set && !all_set) {
288 add_failure(edid, "Some but not all primaries coordinates are unset.");
289 }
290
291 /* Both white-point coords must be set */
292 if (coords->white_x == 0 || coords->white_y == 0) {
293 add_failure(edid, "White-point coordinates are unset.");
294 }
295 }
296
297 static void
parse_established_timings_i_ii(struct di_edid * edid,const uint8_t data[static EDID_BLOCK_SIZE])298 parse_established_timings_i_ii(struct di_edid *edid,
299 const uint8_t data[static EDID_BLOCK_SIZE])
300 {
301 struct di_edid_established_timings_i_ii *timings = &edid->established_timings_i_ii;
302
303 timings->has_720x400_70hz = has_bit(data[0x23], 7);
304 timings->has_720x400_88hz = has_bit(data[0x23], 6);
305 timings->has_640x480_60hz = has_bit(data[0x23], 5);
306 timings->has_640x480_67hz = has_bit(data[0x23], 4);
307 timings->has_640x480_72hz = has_bit(data[0x23], 3);
308 timings->has_640x480_75hz = has_bit(data[0x23], 2);
309 timings->has_800x600_56hz = has_bit(data[0x23], 1);
310 timings->has_800x600_60hz = has_bit(data[0x23], 0);
311
312 /* Established timings II */
313 timings->has_800x600_72hz = has_bit(data[0x24], 7);
314 timings->has_800x600_75hz = has_bit(data[0x24], 6);
315 timings->has_832x624_75hz = has_bit(data[0x24], 5);
316 timings->has_1024x768_87hz_interlaced = has_bit(data[0x24], 4);
317 timings->has_1024x768_60hz = has_bit(data[0x24], 3);
318 timings->has_1024x768_70hz = has_bit(data[0x24], 2);
319 timings->has_1024x768_75hz = has_bit(data[0x24], 1);
320 timings->has_1280x1024_75hz = has_bit(data[0x24], 0);
321
322 timings->has_1152x870_75hz = has_bit(data[0x25], 7);
323 /* TODO: manufacturer specified timings in bits 6:0 */
324 }
325
326 static bool
parse_standard_timing(struct di_edid * edid,const uint8_t data[static EDID_STANDARD_TIMING_SIZE],struct di_edid_standard_timing ** out)327 parse_standard_timing(struct di_edid *edid,
328 const uint8_t data[static EDID_STANDARD_TIMING_SIZE],
329 struct di_edid_standard_timing **out)
330 {
331 struct di_edid_standard_timing *t;
332
333 *out = NULL;
334
335 if (data[0] == 0x01 && data[1] == 0x01) {
336 /* Unused */
337 return true;
338 }
339 if (data[0] == 0x00) {
340 add_failure_until(edid, 4,
341 "Use 0x0101 as the invalid Standard Timings code, not 0x%02x%02x.",
342 data[0], data[1]);
343 return true;
344 }
345
346 t = calloc(1, sizeof(*t));
347 if (!t) {
348 return false;
349 }
350
351 t->horiz_video = ((int32_t) data[0] + 31) * 8;
352 t->aspect_ratio = get_bit_range(data[1], 7, 6);
353 t->refresh_rate_hz = (int32_t) get_bit_range(data[1], 5, 0) + 60;
354
355 *out = t;
356 return true;
357 }
358
359 struct di_edid_detailed_timing_def_priv *
_di_edid_parse_detailed_timing_def(const uint8_t data[static EDID_BYTE_DESCRIPTOR_SIZE])360 _di_edid_parse_detailed_timing_def(const uint8_t data[static EDID_BYTE_DESCRIPTOR_SIZE])
361 {
362 struct di_edid_detailed_timing_def_priv *priv;
363 struct di_edid_detailed_timing_def *def;
364 struct di_edid_detailed_timing_analog_composite *analog_composite;
365 struct di_edid_detailed_timing_bipolar_analog_composite *bipolar_analog_composite;
366 struct di_edid_detailed_timing_digital_composite *digital_composite;
367 struct di_edid_detailed_timing_digital_separate *digital_separate;
368 int raw;
369 uint8_t flags, stereo_hi, stereo_lo;
370
371 priv = calloc(1, sizeof(*priv));
372 if (!priv) {
373 return NULL;
374 }
375
376 def = &priv->base;
377
378 raw = (data[1] << 8) | data[0];
379 def->pixel_clock_hz = raw * 10 * 1000;
380
381 def->horiz_video = (get_bit_range(data[4], 7, 4) << 8) | data[2];
382 def->horiz_blank = (get_bit_range(data[4], 3, 0) << 8) | data[3];
383
384 def->vert_video = (get_bit_range(data[7], 7, 4) << 8) | data[5];
385 def->vert_blank = (get_bit_range(data[7], 3, 0) << 8) | data[6];
386
387 def->horiz_front_porch = (get_bit_range(data[11], 7, 6) << 8) | data[8];
388 def->horiz_sync_pulse = (get_bit_range(data[11], 5, 4) << 8) | data[9];
389 def->vert_front_porch = (get_bit_range(data[11], 3, 2) << 4)
390 | get_bit_range(data[10], 7, 4);
391 def->vert_sync_pulse = (get_bit_range(data[11], 1, 0) << 4)
392 | get_bit_range(data[10], 3, 0);
393
394 def->horiz_image_mm = (get_bit_range(data[14], 7, 4) << 8) | data[12];
395 def->vert_image_mm = (get_bit_range(data[14], 3, 0) << 8) | data[13];
396 if ((def->horiz_image_mm == 16 && def->vert_image_mm == 9)
397 || (def->horiz_image_mm == 4 && def->vert_image_mm == 3)) {
398 /* Table 3.21 note 18.2: these are special cases and define the
399 * aspect ratio rather than the size in mm.
400 * TODO: expose these values */
401 def->horiz_image_mm = def->vert_image_mm = 0;
402 }
403
404 def->horiz_border = data[15];
405 def->vert_border = data[16];
406
407 flags = data[17];
408
409 def->interlaced = has_bit(flags, 7);
410
411 stereo_hi = get_bit_range(flags, 6, 5);
412 stereo_lo = get_bit_range(flags, 0, 0);
413 if (stereo_hi == 0) {
414 def->stereo = DI_EDID_DETAILED_TIMING_DEF_STEREO_NONE;
415 } else {
416 switch ((stereo_hi << 1) | stereo_lo) {
417 case (1 << 1) | 0:
418 def->stereo = DI_EDID_DETAILED_TIMING_DEF_STEREO_FIELD_SEQ_RIGHT;
419 break;
420 case (2 << 1) | 0:
421 def->stereo = DI_EDID_DETAILED_TIMING_DEF_STEREO_FIELD_SEQ_LEFT;
422 break;
423 case (1 << 1) | 1:
424 def->stereo = DI_EDID_DETAILED_TIMING_DEF_STEREO_2_WAY_INTERLEAVED_RIGHT;
425 break;
426 case (2 << 1) | 1:
427 def->stereo = DI_EDID_DETAILED_TIMING_DEF_STEREO_2_WAY_INTERLEAVED_LEFT;
428 break;
429 case (3 << 1) | 0:
430 def->stereo = DI_EDID_DETAILED_TIMING_DEF_STEREO_4_WAY_INTERLEAVED;
431 break;
432 case (3 << 1) | 1:
433 def->stereo = DI_EDID_DETAILED_TIMING_DEF_STEREO_SIDE_BY_SIDE_INTERLEAVED;
434 break;
435 default:
436 abort(); /* unreachable */
437 }
438 }
439
440 def->signal_type = get_bit_range(flags, 4, 3);
441
442 switch (def->signal_type) {
443 case DI_EDID_DETAILED_TIMING_DEF_SIGNAL_ANALOG_COMPOSITE:
444 analog_composite = &priv->analog_composite;
445 analog_composite->sync_serrations = has_bit(flags, 2);
446 analog_composite->sync_on_green = !has_bit(flags, 1);
447 def->analog_composite = analog_composite;
448 break;
449 case DI_EDID_DETAILED_TIMING_DEF_SIGNAL_BIPOLAR_ANALOG_COMPOSITE:
450 bipolar_analog_composite = &priv->bipolar_analog_composite;
451 bipolar_analog_composite->sync_serrations = has_bit(flags, 2);
452 bipolar_analog_composite->sync_on_green = !has_bit(flags, 1);
453 def->bipolar_analog_composite = bipolar_analog_composite;
454 break;
455 case DI_EDID_DETAILED_TIMING_DEF_SIGNAL_DIGITAL_COMPOSITE:
456 digital_composite = &priv->digital_composite;
457 digital_composite->sync_serrations = has_bit(flags, 2);
458 digital_composite->sync_horiz_polarity = has_bit(flags, 1);
459 def->digital_composite = digital_composite;
460 break;
461 case DI_EDID_DETAILED_TIMING_DEF_SIGNAL_DIGITAL_SEPARATE:
462 digital_separate = &priv->digital_separate;
463 digital_separate->sync_vert_polarity = has_bit(flags, 2);
464 digital_separate->sync_horiz_polarity = has_bit(flags, 1);
465 def->digital_separate = digital_separate;
466 break;
467 }
468
469 return priv;
470 }
471
472 static bool
decode_display_range_limits_offset(struct di_edid * edid,uint8_t flags,int * max_offset,int * min_offset)473 decode_display_range_limits_offset(struct di_edid *edid, uint8_t flags,
474 int *max_offset, int *min_offset)
475 {
476 switch (flags) {
477 case 0x00:
478 /* No offset */
479 break;
480 case 0x02:
481 *max_offset = 255;
482 break;
483 case 0x03:
484 *max_offset = 255;
485 *min_offset = 255;
486 break;
487 default:
488 add_failure_until(edid, 4,
489 "Range offset flags set to reserved value 0x%02x.",
490 flags);
491 return false;
492 }
493
494 return true;
495 }
496
497 static bool
parse_display_range_limits(struct di_edid * edid,const uint8_t data[static EDID_BYTE_DESCRIPTOR_SIZE],struct di_edid_display_range_limits_priv * priv)498 parse_display_range_limits(struct di_edid *edid,
499 const uint8_t data[static EDID_BYTE_DESCRIPTOR_SIZE],
500 struct di_edid_display_range_limits_priv *priv)
501 {
502 uint8_t offset_flags, vert_offset_flags, horiz_offset_flags;
503 uint8_t support_flags, preferred_aspect_ratio;
504 int max_vert_offset = 0, min_vert_offset = 0;
505 int max_horiz_offset = 0, min_horiz_offset = 0;
506 size_t i;
507 struct di_edid_display_range_limits *base;
508 struct di_edid_display_range_limits_secondary_gtf *secondary_gtf;
509 struct di_edid_display_range_limits_cvt *cvt;
510
511 base = &priv->base;
512
513 offset_flags = data[4];
514 if (edid->revision >= 4) {
515 vert_offset_flags = get_bit_range(offset_flags, 1, 0);
516 horiz_offset_flags = get_bit_range(offset_flags, 3, 2);
517
518 if (!decode_display_range_limits_offset(edid,
519 vert_offset_flags,
520 &max_vert_offset,
521 &min_vert_offset)) {
522 return false;
523 }
524 if (!decode_display_range_limits_offset(edid,
525 horiz_offset_flags,
526 &max_horiz_offset,
527 &min_horiz_offset)) {
528 return false;
529 }
530
531 if (edid->revision <= 4 &&
532 get_bit_range(offset_flags, 7, 4) != 0) {
533 add_failure(edid, "Display Range Limits: Bits 7:4 of the range offset flags are reserved.");
534 }
535 } else if (offset_flags != 0) {
536 add_failure(edid, "Display Range Limits: Range offset flags are unsupported in EDID 1.3.");
537 }
538
539 if (edid->revision <= 4 && (data[5] == 0 || data[6] == 0 ||
540 data[7] == 0 || data[8] == 0)) {
541 add_failure(edid, "Display Range Limits: Range limits set to reserved values.");
542 return false;
543 }
544
545 base->min_vert_rate_hz = data[5] + min_vert_offset;
546 base->max_vert_rate_hz = data[6] + max_vert_offset;
547 base->min_horiz_rate_hz = (data[7] + min_horiz_offset) * 1000;
548 base->max_horiz_rate_hz = (data[8] + max_horiz_offset) * 1000;
549
550 if (base->min_vert_rate_hz > base->max_vert_rate_hz) {
551 add_failure(edid, "Display Range Limits: Min vertical rate > max vertical rate.");
552 return false;
553 }
554 if (base->min_horiz_rate_hz > base->max_horiz_rate_hz) {
555 add_failure(edid, "Display Range Limits: Min horizontal freq > max horizontal freq.");
556 return false;
557 }
558
559 base->max_pixel_clock_hz = (int64_t) data[9] * 10 * 1000 * 1000;
560 if (edid->revision == 4 && base->max_pixel_clock_hz == 0) {
561 add_failure(edid, "Display Range Limits: EDID 1.4 block does not set max dotclock.");
562 }
563
564 support_flags = data[10];
565 switch (support_flags) {
566 case 0x00:
567 /* For EDID 1.4 and later, always indicates support for default
568 * GTF. For EDID 1.3 and earlier, a misc features bit indicates
569 * support for default GTF. */
570 if (edid->revision >= 4 || edid->misc_features.default_gtf) {
571 base->type = DI_EDID_DISPLAY_RANGE_LIMITS_DEFAULT_GTF;
572 } else {
573 base->type = DI_EDID_DISPLAY_RANGE_LIMITS_BARE;
574 }
575 break;
576 case 0x01:
577 if (edid->revision < 4) {
578 /* Reserved */
579 add_failure(edid, "Display Range Limits: 'Bare Limits' is not allowed for EDID < 1.4.");
580 return false;
581 }
582 base->type = DI_EDID_DISPLAY_RANGE_LIMITS_BARE;
583 break;
584 case 0x02:
585 base->type = DI_EDID_DISPLAY_RANGE_LIMITS_SECONDARY_GTF;
586 break;
587 case 0x04:
588 if (edid->revision < 4) {
589 /* Reserved */
590 add_failure(edid, "Display Range Limits: 'CVT' is not allowed for EDID < 1.4.");
591 return false;
592 }
593 base->type = DI_EDID_DISPLAY_RANGE_LIMITS_CVT;
594 break;
595 default:
596 /* Reserved */
597 if (edid->revision <= 4) {
598 add_failure(edid,
599 "Display Range Limits: Unknown range class (0x%02x).",
600 support_flags);
601 return false;
602 }
603 base->type = DI_EDID_DISPLAY_RANGE_LIMITS_BARE;
604 break;
605 }
606
607 /* Some types require the display to support continuous frequencies, but
608 * this flag is only set for EDID 1.4 and later */
609 if (edid->revision >= 4 && !edid->misc_features.continuous_freq) {
610 switch (base->type) {
611 case DI_EDID_DISPLAY_RANGE_LIMITS_DEFAULT_GTF:
612 add_failure(edid, "Display Range Limits: GTF is supported, but the display does not support continuous frequencies.");
613 return false;
614 case DI_EDID_DISPLAY_RANGE_LIMITS_SECONDARY_GTF:
615 add_failure(edid, "Display Range Limits: Secondary GTF is supported, but the display does not support continuous frequencies.");
616 return false;
617 case DI_EDID_DISPLAY_RANGE_LIMITS_CVT:
618 add_failure(edid, "Display Range Limits: CVT is supported, but the display does not support continuous frequencies.");
619 return false;
620 default:
621 break;
622 }
623 }
624
625 switch (base->type) {
626 case DI_EDID_DISPLAY_RANGE_LIMITS_SECONDARY_GTF:
627 secondary_gtf = &priv->secondary_gtf;
628
629 if (data[11] != 0)
630 add_failure(edid,
631 "Display Range Limits: Byte 11 is 0x%02x instead of 0x00.",
632 data[11]);
633
634 secondary_gtf->start_freq_hz = data[12] * 2 * 1000;
635 secondary_gtf->c = (float) data[13] / 2;
636 secondary_gtf->m = (float) ((data[15] << 8) | data[14]);
637 secondary_gtf->k = (float) data[16];
638 secondary_gtf->j = (float) data[17] / 2;
639
640 base->secondary_gtf = secondary_gtf;
641 break;
642 case DI_EDID_DISPLAY_RANGE_LIMITS_CVT:
643 cvt = &priv->cvt;
644
645 cvt->version = get_bit_range(data[11], 7, 4);
646 cvt->revision = get_bit_range(data[11], 3, 0);
647
648 base->max_pixel_clock_hz -= get_bit_range(data[12], 7, 2) * 250 * 1000;
649 cvt->max_horiz_px = 8 * ((get_bit_range(data[12], 1, 0) << 8) | data[13]);
650
651 cvt->supported_aspect_ratio = data[14];
652 if (get_bit_range(data[14], 2, 0) != 0)
653 add_failure_until(edid, 4,
654 "Display Range Limits: Reserved bits of byte 14 are non-zero.");
655
656 preferred_aspect_ratio = get_bit_range(data[15], 7, 5);
657 switch (preferred_aspect_ratio) {
658 case 0:
659 cvt->preferred_aspect_ratio = DI_EDID_CVT_ASPECT_RATIO_4_3;
660 break;
661 case 1:
662 cvt->preferred_aspect_ratio = DI_EDID_CVT_ASPECT_RATIO_16_9;
663 break;
664 case 2:
665 cvt->preferred_aspect_ratio = DI_EDID_CVT_ASPECT_RATIO_16_10;
666 break;
667 case 3:
668 cvt->preferred_aspect_ratio = DI_EDID_CVT_ASPECT_RATIO_5_4;
669 break;
670 case 4:
671 cvt->preferred_aspect_ratio = DI_EDID_CVT_ASPECT_RATIO_15_9;
672 break;
673 default:
674 /* Reserved */
675 add_failure_until(edid, 4,
676 "Display Range Limits: Invalid preferred aspect ratio 0x%02x.",
677 preferred_aspect_ratio);
678 return false;
679 }
680
681 cvt->standard_blanking = has_bit(data[15], 3);
682 cvt->reduced_blanking = has_bit(data[15], 4);
683
684 if (get_bit_range(data[15], 2, 0) != 0)
685 add_failure_until(edid, 4,
686 "Display Range Limits: Reserved bits of byte 15 are non-zero.");
687
688 cvt->supported_scaling = data[16];
689 if (get_bit_range(data[16], 3, 0) != 0)
690 add_failure_until(edid, 4,
691 "Display Range Limits: Reserved bits of byte 16 are non-zero.");
692
693 cvt->preferred_vert_refresh_hz = data[17];
694 if (cvt->preferred_vert_refresh_hz == 0) {
695 add_failure_until(edid, 4,
696 "Display Range Limits: Preferred vertical refresh rate must be specified.");
697 return false;
698 }
699
700 base->cvt = cvt;
701 break;
702 case DI_EDID_DISPLAY_RANGE_LIMITS_BARE:
703 case DI_EDID_DISPLAY_RANGE_LIMITS_DEFAULT_GTF:
704 if (data[11] != 0x0A)
705 add_failure(edid,
706 "Display Range Limits: Byte 11 is 0x%02x instead of 0x0a.",
707 data[11]);
708 for (i = 12; i < EDID_BYTE_DESCRIPTOR_SIZE; i++) {
709 if (data[i] != 0x20) {
710 add_failure(edid,
711 "Display Range Limits: Bytes 12-17 must be 0x20.");
712 break;
713 }
714 }
715 break;
716 }
717
718 return true;
719 }
720
721 static bool
parse_standard_timings_descriptor(struct di_edid * edid,const uint8_t data[static EDID_BYTE_DESCRIPTOR_SIZE],struct di_edid_display_descriptor * desc)722 parse_standard_timings_descriptor(struct di_edid *edid,
723 const uint8_t data[static EDID_BYTE_DESCRIPTOR_SIZE],
724 struct di_edid_display_descriptor *desc)
725 {
726 struct di_edid_standard_timing *t;
727 size_t i;
728 const uint8_t *timing_data;
729
730 for (i = 0; i < EDID_MAX_DESCRIPTOR_STANDARD_TIMING_COUNT; i++) {
731 timing_data = &data[5 + i * EDID_STANDARD_TIMING_SIZE];
732 if (!parse_standard_timing(edid, timing_data, &t))
733 return false;
734 if (t) {
735 assert(desc->standard_timings_len < EDID_MAX_DESCRIPTOR_STANDARD_TIMING_COUNT);
736 desc->standard_timings[desc->standard_timings_len++] = t;
737 }
738 }
739
740 if (data[17] != 0x0A)
741 add_failure_until(edid, 4,
742 "Standard Timing Identifications: Last byte must be a line feed.");
743
744 return true;
745 }
746
747 /**
748 * Mapping table for established timings III.
749 *
750 * Contains one entry per bit, with the value set to the DMT ID.
751 */
752 static const uint8_t established_timings_iii[] = {
753 /* 0x06 */
754 0x01, /* 640 x 350 @ 85 Hz */
755 0x02, /* 640 x 400 @ 85 Hz */
756 0x03, /* 720 x 400 @ 85 Hz */
757 0x07, /* 640 x 480 @ 85 Hz */
758 0x0e, /* 848 x 480 @ 60 Hz */
759 0x0c, /* 800 x 600 @ 85 Hz */
760 0x13, /* 1024 x 768 @ 85 Hz */
761 0x15, /* 1152 x 864 @ 75 Hz */
762 /* 0x07 */
763 0x16, /* 1280 x 768 @ 60 Hz (RB) */
764 0x17, /* 1280 x 768 @ 60 Hz */
765 0x18, /* 1280 x 768 @ 75 Hz */
766 0x19, /* 1280 x 768 @ 85 Hz */
767 0x20, /* 1280 x 960 @ 60 Hz */
768 0x21, /* 1280 x 960 @ 85 Hz */
769 0x23, /* 1280 x 1024 @ 60 Hz */
770 0x25, /* 1280 x 1024 @ 85 Hz */
771 /* 0x08 */
772 0x27, /* 1360 x 768 @ 60 Hz */
773 0x2e, /* 1440 x 900 @ 60 Hz (RB) */
774 0x2f, /* 1440 x 900 @ 60 Hz */
775 0x30, /* 1440 x 900 @ 75 Hz */
776 0x31, /* 1440 x 900 @ 85 Hz */
777 0x29, /* 1400 x 1050 @ 60 Hz (RB) */
778 0x2a, /* 1400 x 1050 @ 60 Hz */
779 0x2b, /* 1400 x 1050 @ 75 Hz */
780 /* 0x09 */
781 0x2c, /* 1400 x 1050 @ 85 Hz */
782 0x39, /* 1680 x 1050 @ 60 Hz (RB) */
783 0x3a, /* 1680 x 1050 @ 60 Hz */
784 0x3b, /* 1680 x 1050 @ 75 Hz */
785 0x3c, /* 1680 x 1050 @ 85 Hz */
786 0x33, /* 1600 x 1200 @ 60 Hz */
787 0x34, /* 1600 x 1200 @ 65 Hz */
788 0x35, /* 1600 x 1200 @ 70 Hz */
789 /* 0x0a */
790 0x36, /* 1600 x 1200 @ 75 Hz */
791 0x37, /* 1600 x 1200 @ 85 Hz */
792 0x3e, /* 1792 x 1344 @ 60 Hz */
793 0x3f, /* 1792 x 1344 @ 75 Hz */
794 0x41, /* 1856 x 1392 @ 60 Hz */
795 0x42, /* 1856 x 1392 @ 75 Hz */
796 0x44, /* 1920 x 1200 @ 60 Hz (RB) */
797 0x45, /* 1920 x 1200 @ 60 Hz */
798 /* 0x0b */
799 0x46, /* 1920 x 1200 @ 75 Hz */
800 0x47, /* 1920 x 1200 @ 85 Hz */
801 0x49, /* 1920 x 1440 @ 60 Hz */
802 0x4a, /* 1920 x 1440 @ 75 Hz */
803 };
804 static_assert(EDID_MAX_DESCRIPTOR_ESTABLISHED_TIMING_III_COUNT
805 == sizeof(established_timings_iii) / sizeof(established_timings_iii[0]),
806 "Invalid number of established timings III in table");
807
808 static const struct di_dmt_timing *
get_dmt_timing(uint8_t dmt_id)809 get_dmt_timing(uint8_t dmt_id)
810 {
811 size_t i;
812 const struct di_dmt_timing *t;
813
814 for (i = 0; i < _di_dmt_timings_len; i++) {
815 t = &_di_dmt_timings[i];
816 if (t->dmt_id == dmt_id)
817 return t;
818 }
819
820 return NULL;
821 }
822
823 static void
parse_established_timings_iii_descriptor(struct di_edid * edid,const uint8_t data[static EDID_BYTE_DESCRIPTOR_SIZE],struct di_edid_display_descriptor * desc)824 parse_established_timings_iii_descriptor(struct di_edid *edid,
825 const uint8_t data[static EDID_BYTE_DESCRIPTOR_SIZE],
826 struct di_edid_display_descriptor *desc)
827 {
828 size_t i, offset, bit;
829 uint8_t dmt_id;
830 const struct di_dmt_timing *t;
831 bool has_zeroes;
832
833 if (edid->revision < 4)
834 add_failure(edid, "Established timings III: Not allowed for EDID < 1.4.");
835
836 for (i = 0; i < EDID_MAX_DESCRIPTOR_ESTABLISHED_TIMING_III_COUNT; i++) {
837 dmt_id = established_timings_iii[i];
838 offset = 0x06 + i / 8;
839 bit = 7 - i % 8;
840 assert(offset < EDID_BYTE_DESCRIPTOR_SIZE);
841 if (has_bit(data[offset], bit)) {
842 t = get_dmt_timing(dmt_id);
843 assert(t != NULL);
844 desc->established_timings_iii[desc->established_timings_iii_len++] = t;
845 }
846 }
847
848 has_zeroes = get_bit_range(data[11], 3, 0) == 0;
849 for (i = 12; i < EDID_BYTE_DESCRIPTOR_SIZE; i++) {
850 has_zeroes = has_zeroes && data[i] == 0;
851 }
852 if (!has_zeroes) {
853 add_failure_until(edid, 4,
854 "Established timings III: Reserved bits must be set to zero.");
855 }
856 }
857
858 static bool
parse_color_point_descriptor(struct di_edid * edid,const uint8_t data[static EDID_BYTE_DESCRIPTOR_SIZE],struct di_edid_display_descriptor * desc)859 parse_color_point_descriptor(struct di_edid *edid,
860 const uint8_t data[static EDID_BYTE_DESCRIPTOR_SIZE],
861 struct di_edid_display_descriptor *desc)
862 {
863 struct di_edid_color_point *c;
864
865 if (data[5] == 0) {
866 add_failure(edid, "White Point Index Number set to reserved value 0");
867 }
868
869 c = calloc(1, sizeof(*c));
870 if (!c) {
871 return false;
872 }
873
874 c->index = data[5];
875 c->white_x = decode_chromaticity_coord(data[7], get_bit_range(data[6], 3, 2));
876 c->white_y = decode_chromaticity_coord(data[8], get_bit_range(data[6], 1, 0));
877
878 if (data[9] != 0xFF) {
879 c->gamma = ((float) data[9] + 100) / 100;
880 }
881
882 desc->color_points[desc->color_points_len++] = c;
883 if (data[10] == 0) {
884 return true;
885 }
886
887 c = calloc(1, sizeof(*c));
888 if (!c) {
889 return false;
890 }
891
892 c->index = data[10];
893 c->white_x = decode_chromaticity_coord(data[12], get_bit_range(data[11], 3, 2));
894 c->white_y = decode_chromaticity_coord(data[13], get_bit_range(data[11], 1, 0));
895
896 if (data[14] != 0xFF) {
897 c->gamma = ((float) data[14] + 100) / 100;
898 }
899
900 desc->color_points[desc->color_points_len++] = c;
901 return true;
902 }
903
904 static void
parse_color_management_data_descriptor(struct di_edid * edid,const uint8_t data[static EDID_BYTE_DESCRIPTOR_SIZE],struct di_edid_display_descriptor * desc)905 parse_color_management_data_descriptor(struct di_edid *edid,
906 const uint8_t data[static EDID_BYTE_DESCRIPTOR_SIZE],
907 struct di_edid_display_descriptor *desc)
908 {
909 desc->dcm_data.version = data[5];
910
911 desc->dcm_data.red_a3 = (uint16_t)(data[6] | (data[7] << 8)) / 100.0f;
912 desc->dcm_data.red_a2 = (uint16_t)(data[8] | (data[9] << 8)) / 100.0f;
913 desc->dcm_data.green_a3 = (uint16_t)(data[10] | (data[11] << 8)) / 100.0f;
914 desc->dcm_data.green_a2 = (uint16_t)(data[12] | (data[13] << 8)) / 100.0f;
915 desc->dcm_data.blue_a3 = (uint16_t)(data[14] | (data[15] << 8)) / 100.0f;
916 desc->dcm_data.blue_a2 = (uint16_t)(data[16] | (data[17] << 8)) / 100.0f;
917
918 if (desc->dcm_data.version != 3) {
919 add_failure_until(edid, 4,
920 "Color Management Data version must be 3");
921 }
922 }
923
924 static bool
is_cvt_timing_code_preferred_vrate_supported(const struct di_edid_cvt_timing_code * t)925 is_cvt_timing_code_preferred_vrate_supported(const struct di_edid_cvt_timing_code *t)
926 {
927 switch (t->preferred_vertical_rate) {
928 case DI_EDID_CVT_TIMING_CODE_PREFERRED_VRATE_50HZ:
929 return t->supports_50hz_sb;
930 case DI_EDID_CVT_TIMING_CODE_PREFERRED_VRATE_60HZ:
931 return t->supports_60hz_sb || t->supports_60hz_rb;
932 case DI_EDID_CVT_TIMING_CODE_PREFERRED_VRATE_75HZ:
933 return t->supports_75hz_sb;
934 case DI_EDID_CVT_TIMING_CODE_PREFERRED_VRATE_85HZ:
935 return t->supports_85hz_sb;
936 }
937 abort(); /* unreachable */
938 }
939
940 static bool
parse_cvt_timing_code(struct di_edid * edid,const uint8_t data[static EDID_CVT_TIMING_CODE_SIZE],struct di_edid_cvt_timing_code ** out,bool first)941 parse_cvt_timing_code(struct di_edid *edid,
942 const uint8_t data[static EDID_CVT_TIMING_CODE_SIZE],
943 struct di_edid_cvt_timing_code **out,
944 bool first)
945 {
946 struct di_edid_cvt_timing_code *t;
947 int32_t raw;
948
949 *out = NULL;
950
951 if (!first && data[0] == 0 && data[1] == 0 && data[2] == 0) {
952 /* Unused */
953 return true;
954 }
955 if (data[0] == 0) {
956 add_failure(edid,
957 "CVT byte 0 is 0, which is a reserved value.");
958 }
959
960 t = calloc(1, sizeof(*t));
961 if (!t) {
962 return false;
963 }
964
965 raw = (int32_t)(data[0] | (get_bit_range(data[1], 7, 4) << 8));
966 t->addressable_lines_per_field = (raw + 1) * 2;
967 t->aspect_ratio = get_bit_range(data[1], 3, 2);
968
969 if (get_bit_range(data[1], 1, 0) != 0) {
970 add_failure(edid,
971 "Reserved bits of CVT byte 1 are non-zero.");
972 }
973
974 t->supports_50hz_sb = has_bit(data[2], 4);
975 t->supports_60hz_sb = has_bit(data[2], 3);
976 t->supports_75hz_sb = has_bit(data[2], 2);
977 t->supports_85hz_sb = has_bit(data[2], 1);
978 t->supports_60hz_rb = has_bit(data[2], 0);
979
980 if (get_bit_range(data[2], 4, 0) == 0) {
981 add_failure(edid,
982 "CVT byte 2 does not support any vertical rates.");
983 }
984
985 t->preferred_vertical_rate = get_bit_range(data[2], 6, 5);
986
987 if (has_bit(data[2], 7) != 0) {
988 add_failure(edid,
989 "Reserved bit of CVT byte 2 is non-zero.");
990 }
991
992 if (!is_cvt_timing_code_preferred_vrate_supported(t))
993 add_failure(edid, "The preferred CVT Vertical Rate is not supported.");
994
995 *out = t;
996 return true;
997 }
998
999 static bool
parse_cvt_timing_codes_descriptor(struct di_edid * edid,const uint8_t data[static EDID_BYTE_DESCRIPTOR_SIZE],struct di_edid_display_descriptor * desc)1000 parse_cvt_timing_codes_descriptor(struct di_edid *edid,
1001 const uint8_t data[static EDID_BYTE_DESCRIPTOR_SIZE],
1002 struct di_edid_display_descriptor *desc)
1003 {
1004 struct di_edid_cvt_timing_code *t;
1005 size_t i;
1006 const uint8_t *timing_data;
1007
1008 if (data[5] != 1) {
1009 add_failure_until(edid, 4, "Invalid version number %u.",
1010 data[5]);
1011 }
1012
1013 for (i = 0; i < EDID_MAX_DESCRIPTOR_CVT_TIMING_CODES_COUNT; i++) {
1014 timing_data = &data[6 + i * EDID_CVT_TIMING_CODE_SIZE];
1015 if (!parse_cvt_timing_code(edid, timing_data, &t, !i))
1016 return false;
1017 if (t) {
1018 assert(desc->cvt_timing_codes_len < EDID_MAX_DESCRIPTOR_CVT_TIMING_CODES_COUNT);
1019 desc->cvt_timing_codes[desc->cvt_timing_codes_len++] = t;
1020 }
1021 }
1022
1023 return true;
1024 }
1025
1026 static bool
parse_byte_descriptor(struct di_edid * edid,const uint8_t data[static EDID_BYTE_DESCRIPTOR_SIZE])1027 parse_byte_descriptor(struct di_edid *edid,
1028 const uint8_t data[static EDID_BYTE_DESCRIPTOR_SIZE])
1029 {
1030 struct di_edid_display_descriptor *desc;
1031 struct di_edid_detailed_timing_def_priv *detailed_timing_def;
1032 uint8_t tag;
1033 char *newline;
1034
1035 if (data[0] || data[1]) {
1036 if (edid->display_descriptors_len > 0) {
1037 /* A detailed timing descriptor is not allowed after a
1038 * display descriptor per note 3 of table 3.20. */
1039 add_failure(edid, "Invalid detailed timing descriptor ordering.");
1040 }
1041
1042 detailed_timing_def = _di_edid_parse_detailed_timing_def(data);
1043 if (!detailed_timing_def) {
1044 return false;
1045 }
1046
1047 assert(edid->detailed_timing_defs_len < EDID_BYTE_DESCRIPTOR_COUNT);
1048 edid->detailed_timing_defs[edid->detailed_timing_defs_len++] = detailed_timing_def;
1049 return true;
1050 }
1051
1052 if (edid->revision >= 3 && edid->revision <= 4 &&
1053 edid->detailed_timing_defs_len == 0) {
1054 /* Per section 3.10.1 */
1055 add_failure(edid,
1056 "The first byte descriptor must contain the preferred timing.");
1057 }
1058
1059 desc = calloc(1, sizeof(*desc));
1060 if (!desc) {
1061 return false;
1062 }
1063
1064 tag = data[3];
1065 switch (tag) {
1066 case DI_EDID_DISPLAY_DESCRIPTOR_PRODUCT_SERIAL:
1067 case DI_EDID_DISPLAY_DESCRIPTOR_DATA_STRING:
1068 case DI_EDID_DISPLAY_DESCRIPTOR_PRODUCT_NAME:
1069 memcpy(desc->str, &data[5], 13);
1070
1071 /* A newline (if any) indicates the end of the string. */
1072 newline = strchr(desc->str, '\n');
1073 if (newline) {
1074 newline[0] = '\0';
1075 }
1076 break;
1077 case DI_EDID_DISPLAY_DESCRIPTOR_RANGE_LIMITS:
1078 if (!parse_display_range_limits(edid, data, &desc->range_limits)) {
1079 free(desc);
1080 return true;
1081 }
1082 break;
1083 case DI_EDID_DISPLAY_DESCRIPTOR_STD_TIMING_IDS:
1084 if (!parse_standard_timings_descriptor(edid, data, desc)) {
1085 free(desc);
1086 return false;
1087 }
1088 break;
1089 case DI_EDID_DISPLAY_DESCRIPTOR_ESTABLISHED_TIMINGS_III:
1090 parse_established_timings_iii_descriptor(edid, data, desc);
1091 break;
1092 case DI_EDID_DISPLAY_DESCRIPTOR_COLOR_POINT:
1093 if (!parse_color_point_descriptor(edid, data, desc)) {
1094 free(desc);
1095 return false;
1096 }
1097 break;
1098 case DI_EDID_DISPLAY_DESCRIPTOR_DCM_DATA:
1099 parse_color_management_data_descriptor(edid, data, desc);
1100 break;
1101 case DI_EDID_DISPLAY_DESCRIPTOR_CVT_TIMING_CODES:
1102 if (!parse_cvt_timing_codes_descriptor(edid, data, desc)) {
1103 free(desc);
1104 return false;
1105 }
1106 break;
1107 case DI_EDID_DISPLAY_DESCRIPTOR_DUMMY:
1108 break; /* Ignore */
1109 default:
1110 free(desc);
1111 if (tag <= 0x0F) {
1112 /* Manufacturer-specific */
1113 } else {
1114 add_failure_until(edid, 4, "Unknown Type 0x%02hhx.", tag);
1115 }
1116 return true;
1117 }
1118
1119 desc->tag = tag;
1120 assert(edid->display_descriptors_len < EDID_BYTE_DESCRIPTOR_COUNT);
1121 edid->display_descriptors[edid->display_descriptors_len++] = desc;
1122 return true;
1123 }
1124
1125 static bool
parse_ext(struct di_edid * edid,const uint8_t data[static EDID_BLOCK_SIZE])1126 parse_ext(struct di_edid *edid, const uint8_t data[static EDID_BLOCK_SIZE])
1127 {
1128 struct di_edid_ext *ext;
1129 uint8_t tag;
1130 struct di_logger logger;
1131 char section_name[64];
1132
1133 if (!validate_block_checksum(data)) {
1134 errno = EINVAL;
1135 return false;
1136 }
1137
1138 ext = calloc(1, sizeof(*ext));
1139 if (!ext) {
1140 return false;
1141 }
1142
1143 tag = data[0x00];
1144 switch (tag) {
1145 case DI_EDID_EXT_CEA:
1146 snprintf(section_name, sizeof(section_name),
1147 "Block %zu, CTA-861 Extension Block",
1148 edid->exts_len + 1);
1149 logger = (struct di_logger) {
1150 .f = edid->logger->f,
1151 .section = section_name,
1152 };
1153
1154 if (!_di_edid_cta_parse(&ext->cta, data, EDID_BLOCK_SIZE, &logger)) {
1155 free(ext);
1156 return errno == EINVAL;
1157 }
1158 break;
1159 case DI_EDID_EXT_VTB:
1160 case DI_EDID_EXT_DI:
1161 case DI_EDID_EXT_LS:
1162 case DI_EDID_EXT_DPVL:
1163 case DI_EDID_EXT_BLOCK_MAP:
1164 case DI_EDID_EXT_VENDOR:
1165 /* Supported */
1166 break;
1167 case DI_EDID_EXT_DISPLAYID:
1168 snprintf(section_name, sizeof(section_name),
1169 "Block %zu, DisplayID Extension Block",
1170 edid->exts_len + 1);
1171 logger = (struct di_logger) {
1172 .f = edid->logger->f,
1173 .section = section_name,
1174 };
1175
1176 if (!_di_displayid_parse(&ext->displayid, &data[1],
1177 EDID_BLOCK_SIZE - 2, &logger)) {
1178 free(ext);
1179 return errno == ENOTSUP || errno == EINVAL;
1180 }
1181 break;
1182 default:
1183 /* Unsupported */
1184 free(ext);
1185 add_failure_until(edid, 4, "Unknown Extension Block.");
1186 return true;
1187 }
1188
1189 ext->tag = tag;
1190 assert(edid->exts_len < EDID_MAX_BLOCK_COUNT - 1);
1191 edid->exts[edid->exts_len++] = ext;
1192 return true;
1193 }
1194
1195 struct di_edid *
_di_edid_parse(const void * data,size_t size,FILE * failure_msg_file)1196 _di_edid_parse(const void *data, size_t size, FILE *failure_msg_file)
1197 {
1198 struct di_edid *edid;
1199 struct di_logger logger;
1200 int version, revision;
1201 size_t exts_len, parsed_ext_len, i;
1202 const uint8_t *standard_timing_data, *byte_desc_data, *ext_data;
1203 struct di_edid_standard_timing *standard_timing;
1204
1205 if (size < EDID_BLOCK_SIZE) {
1206 errno = EINVAL;
1207 return NULL;
1208 }
1209
1210 if (memcmp(data, header, sizeof(header)) != 0) {
1211 errno = EINVAL;
1212 return NULL;
1213 }
1214
1215 parse_version_revision(data, &version, &revision);
1216 if (version != 1) {
1217 /* Only EDID version 1 is supported -- as per section 2.1.7
1218 * subsequent versions break the structure */
1219 errno = ENOTSUP;
1220 return NULL;
1221 }
1222
1223 if (!validate_block_checksum(data)) {
1224 errno = EINVAL;
1225 return NULL;
1226 }
1227
1228 edid = calloc(1, sizeof(*edid));
1229 if (!edid) {
1230 return NULL;
1231 }
1232
1233 logger = (struct di_logger) {
1234 .f = failure_msg_file,
1235 .section = "Block 0, Base EDID",
1236 };
1237 edid->logger = &logger;
1238
1239 edid->version = version;
1240 edid->revision = revision;
1241
1242 if (size % EDID_BLOCK_SIZE != 0)
1243 add_failure(edid, "The data is not a multiple of the block size.");
1244 if (size > EDID_MAX_BLOCK_COUNT * EDID_BLOCK_SIZE)
1245 add_failure(edid, "The data is exceeding the maximum block count.");
1246
1247 exts_len = (size / EDID_BLOCK_SIZE) - 1;
1248 parsed_ext_len = parse_ext_count(data);
1249
1250 if (exts_len != parsed_ext_len)
1251 add_failure(edid, "The data size does not match the encoded block count.");
1252
1253 if (parsed_ext_len < exts_len)
1254 exts_len = parsed_ext_len;
1255
1256 assert(exts_len < EDID_MAX_BLOCK_COUNT);
1257
1258 parse_vendor_product(edid, data);
1259 parse_basic_params_features(edid, data);
1260 parse_chromaticity_coords(edid, data);
1261
1262 parse_established_timings_i_ii(edid, data);
1263
1264 for (i = 0; i < EDID_MAX_STANDARD_TIMING_COUNT; i++) {
1265 standard_timing_data = (const uint8_t *) data
1266 + 0x26 + i * EDID_STANDARD_TIMING_SIZE;
1267 if (!parse_standard_timing(edid, standard_timing_data,
1268 &standard_timing)) {
1269 _di_edid_destroy(edid);
1270 return NULL;
1271 }
1272 if (standard_timing) {
1273 assert(edid->standard_timings_len < EDID_MAX_STANDARD_TIMING_COUNT);
1274 edid->standard_timings[edid->standard_timings_len++] = standard_timing;
1275 }
1276 }
1277
1278 for (i = 0; i < EDID_BYTE_DESCRIPTOR_COUNT; i++) {
1279 byte_desc_data = (const uint8_t *) data
1280 + 0x36 + i * EDID_BYTE_DESCRIPTOR_SIZE;
1281 if (!parse_byte_descriptor(edid, byte_desc_data)) {
1282 _di_edid_destroy(edid);
1283 return NULL;
1284 }
1285 }
1286
1287 for (i = 0; i < exts_len; i++) {
1288 ext_data = (const uint8_t *) data + (i + 1) * EDID_BLOCK_SIZE;
1289 if (!parse_ext(edid, ext_data)) {
1290 _di_edid_destroy(edid);
1291 return NULL;
1292 }
1293 }
1294
1295 edid->logger = NULL;
1296 return edid;
1297 }
1298
1299 static void
destroy_display_descriptor(struct di_edid_display_descriptor * desc)1300 destroy_display_descriptor(struct di_edid_display_descriptor *desc)
1301 {
1302 size_t i;
1303
1304 switch (desc->tag) {
1305 case DI_EDID_DISPLAY_DESCRIPTOR_STD_TIMING_IDS:
1306 for (i = 0; i < desc->standard_timings_len; i++) {
1307 free(desc->standard_timings[i]);
1308 }
1309 break;
1310 case DI_EDID_DISPLAY_DESCRIPTOR_COLOR_POINT:
1311 for (i = 0; i < desc->color_points_len; i++) {
1312 free(desc->color_points[i]);
1313 }
1314 break;
1315 case DI_EDID_DISPLAY_DESCRIPTOR_CVT_TIMING_CODES:
1316 for (i = 0; i < desc->cvt_timing_codes_len; i++) {
1317 free(desc->cvt_timing_codes[i]);
1318 }
1319 break;
1320 default:
1321 break; /* Nothing to do */
1322 }
1323 free(desc);
1324 }
1325
1326 void
_di_edid_destroy(struct di_edid * edid)1327 _di_edid_destroy(struct di_edid *edid)
1328 {
1329 size_t i;
1330 struct di_edid_ext *ext;
1331
1332 for (i = 0; i < edid->standard_timings_len; i++) {
1333 free(edid->standard_timings[i]);
1334 }
1335
1336 for (i = 0; i < edid->detailed_timing_defs_len; i++) {
1337 free(edid->detailed_timing_defs[i]);
1338 }
1339
1340 for (i = 0; i < edid->display_descriptors_len; i++) {
1341 destroy_display_descriptor(edid->display_descriptors[i]);
1342 }
1343
1344 for (i = 0; edid->exts[i] != NULL; i++) {
1345 ext = edid->exts[i];
1346 switch (ext->tag) {
1347 case DI_EDID_EXT_CEA:
1348 _di_edid_cta_finish(&ext->cta);
1349 break;
1350 case DI_EDID_EXT_DISPLAYID:
1351 _di_displayid_finish(&ext->displayid);
1352 break;
1353 default:
1354 break; /* Nothing to do */
1355 }
1356 free(ext);
1357 }
1358
1359 free(edid);
1360 }
1361
1362 int
di_edid_get_version(const struct di_edid * edid)1363 di_edid_get_version(const struct di_edid *edid)
1364 {
1365 return edid->version;
1366 }
1367
1368 int
di_edid_get_revision(const struct di_edid * edid)1369 di_edid_get_revision(const struct di_edid *edid)
1370 {
1371 return edid->revision;
1372 }
1373
1374 const struct di_edid_vendor_product *
di_edid_get_vendor_product(const struct di_edid * edid)1375 di_edid_get_vendor_product(const struct di_edid *edid)
1376 {
1377 return &edid->vendor_product;
1378 }
1379
1380 const struct di_edid_video_input_analog *
di_edid_get_video_input_analog(const struct di_edid * edid)1381 di_edid_get_video_input_analog(const struct di_edid *edid)
1382 {
1383 return edid->is_digital ? NULL : &edid->video_input_analog;
1384 }
1385
1386 const struct di_edid_video_input_digital *
di_edid_get_video_input_digital(const struct di_edid * edid)1387 di_edid_get_video_input_digital(const struct di_edid *edid)
1388 {
1389 return edid->is_digital ? &edid->video_input_digital : NULL;
1390 }
1391
1392 const struct di_edid_screen_size *
di_edid_get_screen_size(const struct di_edid * edid)1393 di_edid_get_screen_size(const struct di_edid *edid)
1394 {
1395 return &edid->screen_size;
1396 }
1397
1398 float
di_edid_get_basic_gamma(const struct di_edid * edid)1399 di_edid_get_basic_gamma(const struct di_edid *edid)
1400 {
1401 return edid->gamma;
1402 }
1403
1404 const struct di_edid_dpms *
di_edid_get_dpms(const struct di_edid * edid)1405 di_edid_get_dpms(const struct di_edid *edid)
1406 {
1407 return &edid->dpms;
1408 }
1409
1410 enum di_edid_display_color_type
di_edid_get_display_color_type(const struct di_edid * edid)1411 di_edid_get_display_color_type(const struct di_edid *edid)
1412 {
1413 return edid->display_color_type;
1414 }
1415
1416 const struct di_edid_color_encoding_formats *
di_edid_get_color_encoding_formats(const struct di_edid * edid)1417 di_edid_get_color_encoding_formats(const struct di_edid *edid)
1418 {
1419 /* If color encoding formats are specified, RGB 4:4:4 is always
1420 * supported. */
1421 return edid->color_encoding_formats.rgb444 ? &edid->color_encoding_formats : NULL;
1422 }
1423
1424 const struct di_edid_misc_features *
di_edid_get_misc_features(const struct di_edid * edid)1425 di_edid_get_misc_features(const struct di_edid *edid)
1426 {
1427 return &edid->misc_features;
1428 }
1429
1430 const struct di_edid_chromaticity_coords *
di_edid_get_chromaticity_coords(const struct di_edid * edid)1431 di_edid_get_chromaticity_coords(const struct di_edid *edid)
1432 {
1433 return &edid->chromaticity_coords;
1434 }
1435
1436 const struct di_edid_established_timings_i_ii *
di_edid_get_established_timings_i_ii(const struct di_edid * edid)1437 di_edid_get_established_timings_i_ii(const struct di_edid *edid)
1438 {
1439 return &edid->established_timings_i_ii;
1440 }
1441
1442 int32_t
di_edid_standard_timing_get_vert_video(const struct di_edid_standard_timing * t)1443 di_edid_standard_timing_get_vert_video(const struct di_edid_standard_timing *t)
1444 {
1445 switch (t->aspect_ratio) {
1446 case DI_EDID_STANDARD_TIMING_16_10:
1447 return t->horiz_video * 10 / 16;
1448 case DI_EDID_STANDARD_TIMING_4_3:
1449 return t->horiz_video * 3 / 4;
1450 case DI_EDID_STANDARD_TIMING_5_4:
1451 return t->horiz_video * 4 / 5;
1452 case DI_EDID_STANDARD_TIMING_16_9:
1453 return t->horiz_video * 9 / 16;
1454 }
1455 abort(); /* unreachable */
1456 }
1457
1458 const struct di_dmt_timing *
di_edid_standard_timing_get_dmt(const struct di_edid_standard_timing * t)1459 di_edid_standard_timing_get_dmt(const struct di_edid_standard_timing *t)
1460 {
1461 int32_t vert_video;
1462 size_t i;
1463 const struct di_dmt_timing *dmt;
1464
1465 vert_video = di_edid_standard_timing_get_vert_video(t);
1466
1467 for (i = 0; i < _di_dmt_timings_len; i++) {
1468 dmt = &_di_dmt_timings[i];
1469
1470 if (dmt->horiz_video == t->horiz_video
1471 && dmt->vert_video == vert_video
1472 && dmt->refresh_rate_hz == (float)t->refresh_rate_hz
1473 && dmt->edid_std_id != 0) {
1474 return dmt;
1475 }
1476 }
1477
1478 return 0;
1479 }
1480
1481 const struct di_edid_standard_timing *const *
di_edid_get_standard_timings(const struct di_edid * edid)1482 di_edid_get_standard_timings(const struct di_edid *edid)
1483 {
1484 return (const struct di_edid_standard_timing *const *) &edid->standard_timings;
1485 }
1486
1487 const struct di_edid_detailed_timing_def *const *
di_edid_get_detailed_timing_defs(const struct di_edid * edid)1488 di_edid_get_detailed_timing_defs(const struct di_edid *edid)
1489 {
1490 return (const struct di_edid_detailed_timing_def *const *) &edid->detailed_timing_defs;
1491 }
1492
1493 const struct di_edid_display_descriptor *const *
di_edid_get_display_descriptors(const struct di_edid * edid)1494 di_edid_get_display_descriptors(const struct di_edid *edid)
1495 {
1496 return (const struct di_edid_display_descriptor *const *) &edid->display_descriptors;
1497 }
1498
1499 enum di_edid_display_descriptor_tag
di_edid_display_descriptor_get_tag(const struct di_edid_display_descriptor * desc)1500 di_edid_display_descriptor_get_tag(const struct di_edid_display_descriptor *desc)
1501 {
1502 return desc->tag;
1503 }
1504
1505 const char *
di_edid_display_descriptor_get_string(const struct di_edid_display_descriptor * desc)1506 di_edid_display_descriptor_get_string(const struct di_edid_display_descriptor *desc)
1507 {
1508 switch (desc->tag) {
1509 case DI_EDID_DISPLAY_DESCRIPTOR_PRODUCT_SERIAL:
1510 case DI_EDID_DISPLAY_DESCRIPTOR_DATA_STRING:
1511 case DI_EDID_DISPLAY_DESCRIPTOR_PRODUCT_NAME:
1512 return desc->str;
1513 default:
1514 return NULL;
1515 }
1516 }
1517
1518 const struct di_edid_display_range_limits *
di_edid_display_descriptor_get_range_limits(const struct di_edid_display_descriptor * desc)1519 di_edid_display_descriptor_get_range_limits(const struct di_edid_display_descriptor *desc)
1520 {
1521 if (desc->tag != DI_EDID_DISPLAY_DESCRIPTOR_RANGE_LIMITS) {
1522 return NULL;
1523 }
1524 return &desc->range_limits.base;
1525 }
1526
1527 const struct di_edid_standard_timing *const *
di_edid_display_descriptor_get_standard_timings(const struct di_edid_display_descriptor * desc)1528 di_edid_display_descriptor_get_standard_timings(const struct di_edid_display_descriptor *desc)
1529 {
1530 if (desc->tag != DI_EDID_DISPLAY_DESCRIPTOR_STD_TIMING_IDS) {
1531 return NULL;
1532 }
1533 return (const struct di_edid_standard_timing *const *) desc->standard_timings;
1534 }
1535
1536 const struct di_edid_color_point *const *
di_edid_display_descriptor_get_color_points(const struct di_edid_display_descriptor * desc)1537 di_edid_display_descriptor_get_color_points(const struct di_edid_display_descriptor *desc)
1538 {
1539 if (desc->tag != DI_EDID_DISPLAY_DESCRIPTOR_COLOR_POINT) {
1540 return NULL;
1541 }
1542 return (const struct di_edid_color_point *const *) desc->color_points;
1543 }
1544
1545 const struct di_dmt_timing *const *
di_edid_display_descriptor_get_established_timings_iii(const struct di_edid_display_descriptor * desc)1546 di_edid_display_descriptor_get_established_timings_iii(const struct di_edid_display_descriptor *desc)
1547 {
1548 if (desc->tag != DI_EDID_DISPLAY_DESCRIPTOR_ESTABLISHED_TIMINGS_III) {
1549 return NULL;
1550 }
1551 return desc->established_timings_iii;
1552 }
1553
1554 const struct di_edid_color_management_data *
di_edid_display_descriptor_get_color_management_data(const struct di_edid_display_descriptor * desc)1555 di_edid_display_descriptor_get_color_management_data(const struct di_edid_display_descriptor *desc)
1556 {
1557 if (desc->tag != DI_EDID_DISPLAY_DESCRIPTOR_DCM_DATA) {
1558 return NULL;
1559 }
1560 return &desc->dcm_data;
1561 }
1562
1563 const struct di_edid_cvt_timing_code *const *
di_edid_display_descriptor_get_cvt_timing_codes(const struct di_edid_display_descriptor * desc)1564 di_edid_display_descriptor_get_cvt_timing_codes(const struct di_edid_display_descriptor *desc)
1565 {
1566 if (desc->tag != DI_EDID_DISPLAY_DESCRIPTOR_CVT_TIMING_CODES) {
1567 return NULL;
1568 }
1569 return (const struct di_edid_cvt_timing_code *const *) desc->cvt_timing_codes;
1570 }
1571
1572 const struct di_edid_ext *const *
di_edid_get_extensions(const struct di_edid * edid)1573 di_edid_get_extensions(const struct di_edid *edid)
1574 {
1575 return (const struct di_edid_ext *const *) edid->exts;
1576 }
1577
1578 enum di_edid_ext_tag
di_edid_ext_get_tag(const struct di_edid_ext * ext)1579 di_edid_ext_get_tag(const struct di_edid_ext *ext)
1580 {
1581 return ext->tag;
1582 }
1583
1584 const struct di_edid_cta *
di_edid_ext_get_cta(const struct di_edid_ext * ext)1585 di_edid_ext_get_cta(const struct di_edid_ext *ext)
1586 {
1587 if (ext->tag != DI_EDID_EXT_CEA) {
1588 return NULL;
1589 }
1590 return &ext->cta;
1591 }
1592
1593 const struct di_displayid *
di_edid_ext_get_displayid(const struct di_edid_ext * ext)1594 di_edid_ext_get_displayid(const struct di_edid_ext *ext)
1595 {
1596 if (ext->tag != DI_EDID_EXT_DISPLAYID) {
1597 return NULL;
1598 }
1599 return &ext->displayid;
1600 }
1601