1 // SPDX-License-Identifier: MIT
3 * Copyright 2020 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
5 * Author: Hans Verkuil <hverkuil-cisco@xs4all.nl>
8 #include "edid-decode.h"
10 void edid_state::parse_digital_interface(const unsigned char *x
)
12 data_block
= "Digital Interface";
13 printf(" %s:\n", data_block
.c_str());
15 printf(" Supported Digital Interface: ");
16 unsigned short v
= x
[2];
19 printf("Analog Video Input\n");
20 if (!memchk(x
+ 2, 12))
21 fail("Bytes 0x02-0x0d should be 0.\n");
23 case 0x01: printf("DVI\n"); break;
24 case 0x02: printf("DVI Single Link\n"); break;
25 case 0x03: printf("DVI Dual Link - High Resolution\n"); break;
26 case 0x04: printf("DVI Dual Link - High Color\n"); break;
27 case 0x05: printf("DVI - Consumer Electronics\n"); break;
28 case 0x06: printf("Plug & Display\n"); break;
29 case 0x07: printf("DFP\n"); break;
30 case 0x08: printf("Open LDI - Single Link\n"); break;
31 case 0x09: printf("Open LDI - Dual Link\n"); break;
32 case 0x0a: printf("Open LDI - Consumer Electronics\n"); break;
34 printf("Unknown (0x%02x)\n", v
);
35 fail("Unknown Digital Interface 0x%02x.\n", v
);
39 switch ((x
[3]) >> 6) {
41 if (!memchk(x
+ 3, 4))
42 fail("Bytes 0x03-0x06 should be 0.\n");
45 printf(" Version: %u.%u\n Release: %u.%u\n", x
[3] & 0x3f, x
[4], x
[5], x
[6]);
47 fail("Version number > 99.\n");
49 fail("Release number > 99.\n");
53 fail("Bits 5-0 of byte 0x03 should be 0.\n");
55 fail("Bytes 0x05-0x06 should be 0.\n");
56 printf(" Letter Designation: %c\n", x
[4]);
60 fail("Bits 5-0 of byte 0x03 should be 0.\n");
61 printf(" Date Code: Year %u Week %u Day %u\n", 1990 + x
[4], x
[5], x
[6]);
62 if (!x
[5] || x
[5] > 12)
63 fail("Bad month number.\n");
64 if (!x
[6] || x
[6] > 31)
65 fail("Bad day number.\n");
70 printf(" Data Enable Signal Usage %sAvailable\n",
71 (v
& 0x80) ? "" : "Not ");
73 printf(" Data Enable Signal %s\n",
74 (v
& 0x40) ? "High" : "Low");
76 fail("Bit 6 of byte 0x07 should be 0.\n");
77 printf(" Edge of Shift Clock: ");
78 switch ((v
>> 4) & 0x03) {
79 case 0: printf("Not specified\n"); break;
80 case 1: printf("Use rising edge of shift clock\n"); break;
81 case 2: printf("Use falling edge of shift clock\n"); break;
82 case 3: printf("Use both edges of shift clock\n"); break;
84 printf(" HDCP is %ssupported\n", (v
& 0x08) ? "" : "not ");
85 printf(" Digital Receivers %ssupport Double Clocking of Input Data\n",
86 (v
& 0x04) ? "" : "do not ");
87 printf(" Packetized Digital Video is %ssupported\n", (v
& 0x02) ? "" : "not ");
89 fail("Bit 0 of byte 0x07 should be 0.\n");
92 printf(" Data Formats: ");
94 case 0x15: printf("8-Bit Over 8-Bit RGB\n"); break;
95 case 0x19: printf("12-Bit Over 12-Bit RGB\n"); break;
96 case 0x24: printf("24-Bit MSB-Aligned RGB (Single Link)\n"); break;
97 case 0x48: printf("48-Bit MSB-Aligned RGB (Dual Link - High Resolution)\n"); break;
98 case 0x49: printf("48-Bit MSB-Aligned RGB (Dual Link - High Color)\n"); break;
100 printf("Unknown (0x%02x)\n", v
);
101 fail("Unknown Data Format 0x%02x.\n", v
);
104 if (x
[2] == 0x03 && v
!= 0x48)
105 fail("Data Format should be 0x48, not 0x%02x.\n", v
);
106 if (x
[2] == 0x04 && v
!= 0x49)
107 fail("Data Format should be 0x49, not 0x%02x.\n", v
);
111 printf(" Minimum Pixel Clock Frequency Per Link: %u MHz\n", v
);
113 fail("Invalid Min-PCF 0x%02x.\n", v
);
116 v
= x
[10] | (x
[11] << 8);
118 printf(" Maximum Pixel Clock Frequency Per Link: %u MHz\n", v
);
120 fail("Invalid Max-PCF 0x%04x.\n", v
);
123 v
= x
[12] | (x
[13] << 8);
125 printf(" Crossover Frequency: None - Single Link\n");
127 printf(" Crossover Frequency: %u MHz\n", v
);
130 void edid_state::parse_display_device(const unsigned char *x
)
132 data_block
= "Display Device";
133 printf(" %s:\n", data_block
.c_str());
135 printf(" Sub-Pixel Layout: ");
136 unsigned char v
= x
[0x0e];
138 case 0x00: printf("Not defined\n"); break;
139 case 0x01: printf("RGB\n"); break;
140 case 0x02: printf("BGR\n"); break;
141 case 0x03: printf("Quad Pixel - G at bottom left & top right\n"); break;
142 case 0x04: printf("Quad Pixel - G at bottom right & top left\n"); break;
144 printf("Unknown (0x%02x)\n", v
);
145 fail("Unknown Sub-Pixel Layout 0x%02x.\n", v
);
148 printf(" Sub-Pixel Configuration: ");
151 case 0x00: printf("Not defined\n"); break;
152 case 0x01: printf("Delta (Tri-ad)\n"); break;
153 case 0x02: printf("Stripe\n"); break;
154 case 0x03: printf("Stripe Offset\n"); break;
155 case 0x04: printf("Quad Pixel\n"); break;
157 printf("Unknown (0x%02x)\n", v
);
158 fail("Unknown Sub-Pixel Configuration 0x%02x.\n", v
);
161 printf(" Sub-Pixel Shape: ");
164 case 0x00: printf("Not defined\n"); break;
165 case 0x01: printf("Round\n"); break;
166 case 0x02: printf("Square\n"); break;
167 case 0x03: printf("Rectangular\n"); break;
168 case 0x04: printf("Oval\n"); break;
169 case 0x05: printf("Elliptical\n"); break;
171 printf("Unknown (0x%02x)\n", v
);
172 fail("Unknown Sub-Pixel Shape 0x%02x.\n", v
);
176 printf(" Horizontal Dot/Pixel Pitch: %.2f mm\n",
179 printf(" Vertical Dot/Pixel Pitch: %.2f mm\n",
182 printf(" Display Device %s a Fixed Pixel Format\n",
183 (v
& 0x80) ? "has" : "does not have");
184 printf(" View Direction: ");
185 switch ((v
& 0x60) >> 5) {
186 case 0x00: printf("Not specified\n"); break;
187 case 0x01: printf("Direct\n"); break;
188 case 0x02: printf("Reflected\n"); break;
189 case 0x03: printf("Direct & Reflected\n"); break;
191 printf(" Display Device uses %stransparent background\n",
192 (v
& 0x10) ? "" : "non-");
193 printf(" Physical Implementation: ");
194 switch ((v
& 0x0c) >> 2) {
195 case 0x00: printf("Not specified\n"); break;
196 case 0x01: printf("Large Image device for group viewing\n"); break;
197 case 0x02: printf("Desktop or personal display\n"); break;
198 case 0x03: printf("Eyepiece type personal display\n"); break;
200 printf(" Monitor/display does %ssupport DDC/CI\n",
201 (v
& 0x02) ? "" : "not ");
203 fail("Bit 0 of byte 0x13 should be 0.\n");
206 void edid_state::parse_display_caps(const unsigned char *x
)
208 data_block
= "Display Capabities & Feature Support Set";
209 printf(" %s:\n", data_block
.c_str());
211 unsigned short v
= x
[0x14];
213 printf(" Legacy Modes: %s VGA/DOS Legacy Timing Modes are supported\n",
214 (v
& 0x80) ? "All" : "Not all");
215 printf(" Stereo Video: ");
216 switch ((v
& 0x70) >> 4) {
217 case 0x00: printf("No direct stereo\n"); break;
218 case 0x01: printf("Field seq. stereo via stereo sync signal\n"); break;
219 case 0x02: printf("auto-stereoscopic, column interleave\n"); break;
220 case 0x03: printf("auto-stereoscopic, line interleave\n"); break;
222 printf("Unknown (0x%02x)\n", (v
& 0x70) >> 4);
223 fail("Unknown Stereo Video 0x%02x.\n", (v
& 0x70) >> 4);
226 printf(" Scaler On Board: %s\n", (v
& 0x08) ? "Yes" : "No");
227 printf(" Image Centering: %s\n", (v
& 0x04) ? "Yes" : "No");
228 printf(" Conditional Update: %s\n", (v
& 0x02) ? "Yes" : "No");
229 printf(" Interlaced Video: %s\n", (v
& 0x01) ? "Yes" : "No");
232 printf(" Frame Lock: %s\n", (v
& 0x80) ? "Yes" : "No");
233 printf(" Frame Rate Conversion: ");
234 switch ((v
& 0x60) >> 5) {
235 case 0x00: printf("Not supported\n"); break;
236 case 0x01: printf("Vertical is converted to a single frequency\n"); break;
237 case 0x02: printf("Horizontal is convertred to a single frequency\n"); break;
238 case 0x03: printf("Both Vertical & Horizontal are converted to single frequencies\n"); break;
241 fail("Bits 4-0 of byte 0x15 should be 0.\n");
242 v
= x
[0x16] | (x
[0x17] << 8);
243 printf(" Vertical Frequency: ");
245 printf("Not available\n");
246 } else if (v
== 0xffff) {
247 printf("Reserved\n");
248 fail("Vertical Frequency uses 0xffff (reserved value).\n");
250 printf("%.2f kHz\n", v
/ 100.0);
252 v
= x
[0x18] | (x
[0x19] << 8);
253 printf(" Horizontal Frequency: ");
255 printf("Not available\n");
256 } else if (v
== 0xffff) {
257 printf("Reserved\n");
258 fail("Horizontal Frequency uses 0xffff (reserved value).\n");
260 printf("%.2f kHz\n", v
/ 100.0);
264 printf(" Display/Scan Orientation Definition Type: ");
265 switch ((v
& 0xc0) >> 6) {
266 case 0x00: printf("Not defined\n"); break;
267 case 0x01: printf("Fixed Orientation\n"); break;
268 case 0x02: printf("Pivots: Default Orientation\n"); break;
269 case 0x03: printf("Pivots: Current Orientation (requires multiple EDID Extension Tables)\n"); break;
271 printf(" Screen Orientation: %s\n",
272 (v
& 0x20) ? "Portrait" : "Landscape");
273 printf(" Zero Pixel Location: ");
274 switch ((v
& 0x18) >> 3) {
275 case 0x00: printf("Upper Left\n"); break;
276 case 0x01: printf("Upper Right\n"); break;
277 case 0x02: printf("Lower Left\n"); break;
278 case 0x03: printf("Lower Right\n"); break;
280 printf(" Scan Direction: ");
281 switch ((v
& 0x06) >> 1) {
282 case 0x00: printf("Not defined\n"); break;
283 case 0x01: printf("Fast Scan is on the Major (Long) Axis and Slow Scan is on the Minor Axis\n"); break;
284 case 0x02: printf("Fast Scan is on the Minor (Short) Axis and Slow Scan is on the Major Axis\n"); break;
286 printf("Reserved\n");
287 fail("Scan Direction used the reserved value 0x03.\n");
290 printf(" Standalone Projector: %s\n",
291 (v
& 0x01) ? "Yes" : "No");
294 printf(" Default Color/Luminance Decoding: ");
296 case 0x00: printf("Not defined\n"); break;
297 case 0x01: printf("BGR\n"); break;
298 case 0x02: printf("Y/C (S-Video) NTSC\n"); break;
299 case 0x03: printf("Y/C (S-Video) PAL\n"); break;
300 case 0x04: printf("Y/C (S-Video) SECAM\n"); break;
301 case 0x05: printf("YCrCb 4:4:4 per SMPTE 293M & 294M\n"); break;
302 case 0x06: printf("YCrCb 4:2:2 per SMPTE 293M & 294M\n"); break;
303 case 0x07: printf("YCrCb 4:2:0 per SMPTE 293M & 294M\n"); break;
304 case 0x08: printf("YCrCb per SMPTE 260M (Legacy HDTV)\n"); break;
305 case 0x09: printf("YPbPr per SMPTE 240M (Legacy HDTV)\n"); break;
306 case 0x0a: printf("YCrCb per SMPTE 274M (Modern HDTV)\n"); break;
307 case 0x0b: printf("YPbPr per SMPTE 274M (Modern HDTV)\n"); break;
308 case 0x0c: printf("Y B-Y R-Y BetaCam (Sony)\n"); break;
309 case 0x0d: printf("Y B-Y R-Y M-2 (Matsushita)\n"); break;
310 case 0x0e: printf("Monochrome\n"); break;
312 printf("Unknown (0x%02x)\n", v
);
313 fail("Unknown Default Color/Luminance Decoding 0x%02x.\n", v
);
317 printf(" Preferred Color/Luminance Decoder: ");
319 case 0x00: printf("Uses Default Decoding\n"); break;
320 case 0x01: printf("BGR\n"); break;
321 case 0x02: printf("Y/C (S-Video)\n"); break;
322 case 0x03: printf("Yxx (SMPTE 2xxM)\n"); break;
323 case 0x04: printf("Monochrome\n"); break;
325 printf("Unknown (0x%02x)\n", v
);
326 fail("Unknown Preferred Color/Luminance Decoding 0x%02x.\n", v
);
330 if (v
&& (x
[0x1e] & 0xfc)) {
331 printf(" Color/Luminance Decoding Capabilities:\n");
332 printf(" BGR: %s\n", (v
& 0x80) ? "Yes" : "No");
333 printf(" Y/C (S-Video) NTSC: %s\n", (v
& 0x40) ? "Yes" : "No");
334 printf(" Y/C (S-Video) PAL: %s\n", (v
& 0x20) ? "Yes" : "No");
335 printf(" Y/C (S-Video) SECAM: %s\n", (v
& 0x10) ? "Yes" : "No");
336 printf(" YCrCb 4:4:4 per SMPTE 293M & 294M: %s\n", (v
& 0x08) ? "Yes" : "No");
337 printf(" YCrCb 4:2:2 per SMPTE 293M & 294M: %s\n", (v
& 0x04) ? "Yes" : "No");
338 printf(" YCrCb 4:2:0 per SMPTE 293M & 294M: %s\n", (v
& 0x02) ? "Yes" : "No");
339 printf(" YCrCb per SMPTE 260M (Legacy HDTV): %s\n", (v
& 0x01) ? "Yes" : "No");
341 printf(" YPbPr per SMPTE 240M (Legacy HDTV): %s\n", (v
& 0x80) ? "Yes" : "No");
342 printf(" YCrCb per SMPTE 274M (Modern HDTV): %s\n", (v
& 0x40) ? "Yes" : "No");
343 printf(" YPbPr per SMPTE 274M (Modern HDTV): %s\n", (v
& 0x20) ? "Yes" : "No");
344 printf(" Y B-Y R-Y BetaCam (Sony): %s\n", (v
& 0x10) ? "Yes" : "No");
345 printf(" Y B-Y R-Y M-2 (Matsushita): %s\n", (v
& 0x08) ? "Yes" : "No");
346 printf(" Monochrome: %s\n", (v
& 0x04) ? "Yes" : "No");
348 printf(" Color/Luminance Decoding Capabilities: None\n");
351 fail("Bits 1-0 of byte 0x1e should be 0.\n");
354 printf(" Dithering: %s\n", (v
& 0x80) ? "Yes" : "No");
356 fail("Bits 6-0 of byte 0x1f should be 0.\n");
358 printf(" Supported Color Bit-Depth of Sub-Channel 0 (Blue): ");
360 printf("No Information\n");
361 } else if (v
<= 16) {
364 printf("Reserved (0x%02x)\n", v
);
365 fail("Supported Color Bit-Depth of Sub-Channel Blue value is 0x%02x.\n", v
);
368 printf(" Supported Color Bit-Depth of Sub-Channel 1 (Green): ");
370 printf("No Information\n");
371 } else if (v
<= 16) {
374 printf("Reserved (0x%02x)\n", v
);
375 fail("Supported Color Bit-Depth of Sub-Channel Green value is 0x%02x.\n", v
);
378 printf(" Supported Color Bit-Depth of Sub-Channel 2 (Red): ");
380 printf("No Information\n");
381 } else if (v
<= 16) {
384 printf("Reserved (0x%02x)\n", v
);
385 fail("Supported Color Bit-Depth of Sub-Channel Red value is 0x%02x.\n", v
);
388 printf(" Supported Color Bit-Depth of Sub-Channel 0 (Cb/Pb): ");
390 printf("No Information\n");
391 } else if (v
<= 16) {
394 printf("Reserved (0x%02x)\n", v
);
395 fail("Supported Color Bit-Depth of Sub-Channel Cb/Pb value is 0x%02x.\n", v
);
398 printf(" Supported Color Bit-Depth of Sub-Channel 1 (Y): ");
400 printf("No Information\n");
401 } else if (v
<= 16) {
404 printf("Reserved (0x%02x)\n", v
);
405 fail("Supported Color Bit-Depth of Sub-Channel Y value is 0x%02x.\n", v
);
408 printf(" Supported Color Bit-Depth of Sub-Channel 2 (Cr/Pr): ");
410 printf("No Information\n");
411 } else if (v
<= 16) {
414 printf("Reserved (0x%02x)\n", v
);
415 fail("Supported Color Bit-Depth of Sub-Channel Cr/Pr value is 0x%02x.\n", v
);
419 printf(" Aspect Ratio Conversion Modes:");
424 printf(" Full Mode: %s\n", (v
& 0x80) ? "Yes" : "No");
425 printf(" Zoom Mode: %s\n", (v
& 0x40) ? "Yes" : "No");
426 printf(" Squeeze (Side Bars/Letterbox) Mode: %s\n", (v
& 0x20) ? "Yes" : "No");
427 printf(" Variable (Expand/Shrink) Mode: %s\n", (v
& 0x10) ? "Yes" : "No");
430 fail("Bits 3-0 of byte 0x26 should be 0.\n");
433 void edid_state::parse_display_xfer(const unsigned char *x
)
435 data_block
= "Display Transfer Characteristics - Gamma";
436 printf(" %s:\n", data_block
.c_str());
438 unsigned char v
= x
[0x51];
439 unsigned num_entries
= v
& 0x3f;
441 switch ((v
& 0xc0) >> 6) {
443 printf(" No Display Transfer Characteristics\n");
444 if (!memchk(x
+ 0x51, 46))
445 fail("Bytes 0x51-0x7e should be 0.\n");
448 fail("Bits 7-6 of byte 0x51 cannot be 0x03.\n");
454 if (((v
& 0xc0) >> 6) == 0x01) {
455 if (!num_entries
|| num_entries
> 45)
456 fail("White Curve with %u entries.\n", num_entries
);
457 if (num_entries
> 45)
459 if (!memchk(x
+ 0x52 + num_entries
, 45 - num_entries
))
460 fail("Bytes 0x%02x-0x7e should be 0.\n", 0x52 + num_entries
);
461 printf(" White Curve (%u entries):\n", num_entries
);
462 hex_block(" ", x
+ 0x52, num_entries
, false, 15);
464 if (!num_entries
|| num_entries
> 15)
465 fail("Sub-Channel Curve with %u entries.\n", num_entries
);
466 if (num_entries
> 15)
468 printf(" Sub-Channel 0 (Blue) Curve with %u entries:\n", num_entries
);
469 hex_block(" ", x
+ 0x52, num_entries
, false);
470 if (!memchk(x
+ 0x52 + num_entries
, 15 - num_entries
))
471 fail("Bytes 0x%02x-0x7e should be 0.\n", 0x52 + num_entries
);
472 printf(" Sub-Channel 1 (Green) Curve with %u entries:\n", num_entries
);
473 hex_block(" ", x
+ 0x52 + 15, num_entries
, false);
474 if (!memchk(x
+ 0x52 + 15 + num_entries
, 15 - num_entries
))
475 fail("Bytes 0x%02x-0x7e should be 0.\n", 0x52 + 15 + num_entries
);
476 printf(" Sub-Channel 2 (Red) Curve with %u entries:\n", num_entries
);
477 hex_block(" ", x
+ 0x52 + 30, num_entries
, false);
478 if (!memchk(x
+ 0x52 + 30 + num_entries
, 15 - num_entries
))
479 fail("Bytes 0x%02x-0x7e should be 0.\n", 0x52 + 30 + num_entries
);
483 void edid_state::parse_di_ext_block(const unsigned char *x
)
485 printf(" Version: %u\n", x
[1]);
487 fail("Invalid version 0.\n");
489 parse_digital_interface(x
);
490 parse_display_device(x
);
491 parse_display_caps(x
);
492 if (!memchk(x
+ 0x27, 16))
493 fail("Bytes 0x27-0x36 should be 0.\n");
494 if (!memchk(x
+ 0x37, 17))
495 fail("Bytes 0x37-0x47 should be 0.\n");
496 if (!memchk(x
+ 0x48, 9))
497 fail("Bytes 0x48-0x50 should be 0\n");
498 parse_display_xfer(x
);