xref: /haiku/src/add-ons/accelerants/common/dump_edid.c (revision af136a21bd781f406d73682b21221102fc87b588)
1 /*
2  * Copyright 2003, Thomas Kurschel. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include "edid.h"
8 #if !defined(_KERNEL_MODE) && !defined(_BOOT_MODE)
9 #	include "ddc_int.h"
10 #endif
11 
12 #include <KernelExport.h>
13 
14 
15 const edid1_std_timing cta_mode1_timings[] = {
16 	/* VIC 1 */
17 	{  640,  480,   0, 1, 60 },
18 	{  720,  480,   0, 1, 60 },
19 	{  720,  480,   0, 3, 60 },
20 	{ 1280,  720,   0, 3, 60 },
21 	{ 1920, 1080,   0, 3, 60 },
22 	{ 1440,  480,   0, 1, 60 },
23 	{ 1440,  480,   0, 3, 60 },
24 	{ 1440,  240,   0, 1, 60 },
25 	{ 1440,  240,   0, 3, 60 },
26 	{ 2880,  480,   0, 1, 60 },
27 	/* VIC 11 */
28 	{ 2880,  480,   0, 3, 60 },
29 	{ 2880,  240,   0, 1, 60 },
30 	{ 2880,  240,   0, 3, 60 },
31 	{ 1440,  480,   0, 1, 60 },
32 	{ 1440,  480,   0, 3, 60 },
33 	{ 1920, 1080,   0, 3, 60 },
34 	{  720,  576,   0, 1, 50 },
35 	{  720,  576,   0, 3, 50 },
36 	{ 1280,  720,   0, 3, 50 },
37 	{ 1920, 1080,   0, 3, 50 },
38 	/* VIC 21 */
39 	{ 1440,  576,   0, 1, 50 },
40 	{ 1440,  576,   0, 3, 50 },
41 	{ 1440,  288,   0, 1, 50 },
42 	{ 1440,  288,   0, 3, 50 },
43 	{ 2880,  576,   0, 1, 50 },
44 	{ 2880,  576,   0, 3, 50 },
45 	{ 2880,  288,   0, 1, 50 },
46 	{ 2880,  288,   0, 3, 50 },
47 	{ 1440,  576,   0, 1, 50 },
48 	{ 1440,  576,   0, 3, 50 },
49 	/* VIC 31 */
50 	{ 1920, 1080,   0, 3, 50 },
51 	{ 1920, 1080,   0, 3, 24 },
52 	{ 1920, 1080,   0, 3, 25 },
53 	{ 1920, 1080,   0, 3, 30 },
54 	{ 2880,  480,   0, 1, 60 },
55 	{ 2880,  480,   0, 3, 60 },
56 	{ 2880,  576,   0, 1, 50 },
57 	{ 2880,  576,   0, 3, 50 },
58 	{ 1920, 1080,   0, 3, 50 },
59 	{ 1920, 1080,   0, 3, 100 },
60 	/* VIC 41 */
61 	{ 1280,  720,   0, 3, 100 },
62 	{  720,  576,   0, 1, 100 },
63 	{  720,  576,   0, 3, 100 },
64 	{ 1440,  576,   0, 1, 100 },
65 	{ 1440,  576,   0, 3, 100 },
66 	{ 1920, 1080,   0, 3, 120 },
67 	{ 1280,  720,   0, 3, 120 },
68 	{  720,  480,   0, 1, 120 },
69 	{  720,  480,   0, 3, 120 },
70 	{ 1440,  480,   0, 1, 120 },
71 	/* VIC 51 */
72 	{ 1440,  480,   0, 3, 120 },
73 	{  720,  576,   0, 1, 200 },
74 	{  720,  576,   0, 3, 200 },
75 	{ 1440,  576,   0, 1, 200 },
76 	{ 1440,  576,   0, 3, 200 },
77 	{  720,  480,   0, 1, 240 },
78 	{  720,  480,   0, 3, 240 },
79 	{ 1440,  480,   0, 1, 240 },
80 	{ 1440,  480,   0, 3, 240 },
81 	{ 1280,  720,   0, 3, 24 },
82 	/* VIC 61 */
83 	{ 1280,  720,   0, 3, 25 },
84 	{ 1280,  720,   0, 3, 30 },
85 	{ 1920, 1080,   0, 3, 120 },
86 	{ 1920, 1080,   0, 3, 100 },
87 	{ 1280,  720,   0, 4, 24 },
88 	{ 1280,  720,   0, 4, 25 },
89 	{ 1280,  720,   0, 4, 30 },
90 	{ 1280,  720,   0, 4, 50 },
91 	{ 1280,  720,   0, 4, 60 },
92 	{ 1280,  720,   0, 4, 100 },
93 	/* VIC 71 */
94 	{ 1280,  720,   0, 4, 120 },
95 	{ 1920, 1080,   0, 4, 24 },
96 	{ 1920, 1080,   0, 4, 25 },
97 	{ 1920, 1080,   0, 4, 30 },
98 	{ 1920, 1080,   0, 4, 50 },
99 	{ 1920, 1080,   0, 4, 60 },
100 	{ 1920, 1080,   0, 4, 100 },
101 	{ 1920, 1080,   0, 4, 120 },
102 	{ 1680,  720,   0, 4, 24 },
103 	{ 1680,  720,   0, 4, 25 },
104 	/* VIC 81 */
105 	{ 1680,  720,   0, 4, 30 },
106 	{ 1680,  720,   0, 4, 50 },
107 	{ 1680,  720,   0, 4, 60 },
108 	{ 1680,  720,   0, 4, 100 },
109 	{ 1680,  720,   0, 4, 120 },
110 	{ 2560, 1080,   0, 4, 24 },
111 	{ 2560, 1080,   0, 4, 25 },
112 	{ 2560, 1080,   0, 4, 30 },
113 	{ 2560, 1080,   0, 4, 50 },
114 	{ 2560, 1080,   0, 4, 60 },
115 	/* VIC 91 */
116 	{ 2560, 1080,   0, 4, 100 },
117 	{ 2560, 1080,   0, 4, 120 },
118 	{ 3840, 2160,   0, 3, 24 },
119 	{ 3840, 2160,   0, 3, 25 },
120 	{ 3840, 2160,   0, 3, 30 },
121 	{ 3840, 2160,   0, 3, 50 },
122 	{ 3840, 2160,   0, 3, 60 },
123 	{ 4096, 2160,   0, 5, 24 },
124 	{ 4096, 2160,   0, 5, 25 },
125 	{ 4096, 2160,   0, 5, 30 },
126 	/* VIC 101 */
127 	{ 4096, 2160,   0, 5, 50 },
128 	{ 4096, 2160,   0, 5, 60 },
129 	{ 3840, 2160,   0, 4, 24 },
130 	{ 3840, 2160,   0, 4, 25 },
131 	{ 3840, 2160,   0, 4, 30 },
132 	{ 3840, 2160,   0, 4, 50 },
133 	{ 3840, 2160,   0, 4, 60 },
134 	{ 1280,  720,   0, 3, 48 },
135 	{ 1280,  720,   0, 4, 48 },
136 	{ 1680,  720,   0, 4, 48 },
137 	/* VIC 111 */
138 	{ 1920, 1080,   0, 3, 48 },
139 	{ 1920, 1080,   0, 4, 48 },
140 	{ 2560, 1080,   0, 4, 48 },
141 	{ 3840, 2160,   0, 3, 48 },
142 	{ 4096, 2160,   0, 5, 48 },
143 	{ 3840, 2160,   0, 4, 48 },
144 	{ 3840, 2160,   0, 3, 100 },
145 	{ 3840, 2160,   0, 3, 120 },
146 	{ 3840, 2160,   0, 4, 100 },
147 	{ 3840, 2160,   0, 4, 120 },
148 	/* VIC 121 */
149 	{ 5120, 2160,   0, 4, 24 },
150 	{ 5120, 2160,   0, 4, 25 },
151 	{ 5120, 2160,   0, 4, 30 },
152 	{ 5120, 2160,   0, 4, 48 },
153 	{ 5120, 2160,   0, 4, 50 },
154 	{ 5120, 2160,   0, 4, 60 },
155 	{ 5120, 2160,   0, 4, 100 },
156 };
157 
158 
159 const edid1_std_timing cta_mode2_timings[] = {
160 	/* VIC 193 */
161 	{ 5120, 2160,  0, 4, 120 },
162 	{ 7680, 4320,  0, 3, 24 },
163 	{ 7680, 4320,  0, 3, 25 },
164 	{ 7680, 4320,  0, 3, 30 },
165 	{ 7680, 4320,  0, 3, 48 },
166 	{ 7680, 4320,  0, 3, 50 },
167 	{ 7680, 4320,  0, 3, 60 },
168 	{ 7680, 4320,  0, 3, 100 },
169 	/* VIC 201 */
170 	{ 7680, 4320,  0, 3, 120 },
171 	{ 7680, 4320,  0, 4, 24 },
172 	{ 7680, 4320,  0, 4, 25 },
173 	{ 7680, 4320,  0, 4, 30 },
174 	{ 7680, 4320,  0, 4, 48 },
175 	{ 7680, 4320,  0, 4, 50 },
176 	{ 7680, 4320,  0, 4, 60 },
177 	{ 7680, 4320,  0, 4, 100 },
178 	{ 7680, 4320,  0, 4, 120 },
179 	{ 10240, 4320, 0, 4, 24 },
180 	/* VIC 211 */
181 	{ 10240, 4320, 0, 4, 25 },
182 	{ 10240, 4320, 0, 4, 30 },
183 	{ 10240, 4320, 0, 4, 48 },
184 	{ 10240, 4320, 0, 4, 50 },
185 	{ 10240, 4320, 0, 4, 60 },
186 	{ 10240, 4320, 0, 4, 100 },
187 	{ 10240, 4320, 0, 4, 120 },
188 	{ 4096, 2160,  0, 5, 100 },
189 	{ 4096, 2160,  0, 5, 120 },
190 };
191 
192 
193 static void
edid_timing_dump(edid1_detailed_timing * timing,bool warnInvalid)194 edid_timing_dump(edid1_detailed_timing *timing, bool warnInvalid)
195 {
196 	if (timing->h_active + timing->h_blank == 0
197 		|| timing->v_active + timing->v_blank == 0
198 		|| timing->pixel_clock == 0) {
199 		if (warnInvalid)
200 			dprintf("Invalid video mode (%dx%d)\n", timing->h_active, timing->v_active);
201 		return;
202 	}
203 
204 	dprintf("Additional Video Mode (%dx%d@%dHz):\n",
205 		timing->h_active, timing->v_active,
206 		(timing->pixel_clock * 10000
207 			/ (timing->h_active + timing->h_blank)
208 			/ (timing->v_active + timing->v_blank)));
209 		// Refresh rate = pixel clock in MHz / Htotal / Vtotal
210 
211 	dprintf("clock=%.3f MHz\n", timing->pixel_clock / 100.0);
212 	dprintf("h: (%d, %d, %d, %d)\n",
213 		timing->h_active, timing->h_active + timing->h_sync_off,
214 		timing->h_active + timing->h_sync_off
215 			+ timing->h_sync_width,
216 		timing->h_active + timing->h_blank);
217 	dprintf("v: (%d, %d, %d, %d)\n",
218 		timing->v_active, timing->v_active + timing->v_sync_off,
219 		timing->v_active + timing->v_sync_off
220 			+ timing->v_sync_width,
221 		timing->v_active + timing->v_blank);
222 	dprintf("size: %.1f cm x %.1f cm\n",
223 		timing->h_size / 10.0, timing->v_size / 10.0);
224 	dprintf("border: %.1f cm x %.1f cm\n",
225 		timing->h_border / 10.0, timing->v_border / 10.0);
226 }
227 
228 
229 static void
edid_cta_datablock_dump(cta_data_block * dataBlock)230 edid_cta_datablock_dump(cta_data_block *dataBlock)
231 {
232 	uint16 tagCode = dataBlock->tag_code;
233 	uint8 i, j;
234 	if (tagCode == 0x7)
235 		tagCode = 0x700 | dataBlock->extended_tag_code;
236 	switch (tagCode) {
237 		case 0x1:
238 			dprintf("Audio data block\n");
239 			for (i = 0; i * 3 < dataBlock->length; i++) {
240 				const char* formatName = NULL;
241 				audio_descr* descr = &dataBlock->audio.desc0;
242 				if (i > 0)
243 					descr = &dataBlock->audio.desc[i - 1];
244 				switch (descr->descr.format_code) {
245 					case 0x1: formatName = "Linear-PCM"; break;
246 					case 0x2: formatName = "AC-3"; break;
247 					case 0x3: formatName = "MPEG 1 (Layers 1 & 2)"; break;
248 					case 0x4: formatName = "MPEG 1 Layer 3 (MP3)"; break;
249 					case 0x5: formatName = "MPEG2 (multichannel)"; break;
250 					case 0x6: formatName = "AAC LC"; break;
251 					case 0x7: formatName = "DTS"; break;
252 					case 0x8: formatName = "ATRAC"; break;
253 					case 0x9: formatName = "One Bit Audio"; break;
254 					case 0xa: formatName = "Enhanced AC-3 (DD+)"; break;
255 					case 0xb: formatName = "DTS-HD"; break;
256 					case 0xc: formatName = "MAT (MLP)"; break;
257 					case 0xd: formatName = "DST"; break;
258 					case 0xe: formatName = "WMA Pro"; break;
259 					case 0xf: formatName = "unknown"; break;
260 				}
261 				dprintf("\t%s, max channels %d\n", formatName,
262 					descr->descr_2_8.max_channels + 1);
263 				dprintf("\t\tSupported sample rates (kHz): %s%s%s%s%s%s%s\n",
264 					descr->descr_2_8.can_192khz ? "192 " : "",
265 					descr->descr_2_8.can_176khz ? "176.4 " : "",
266 					descr->descr_2_8.can_96khz ? "96 " : "",
267 					descr->descr_2_8.can_88khz ? "88.2 " : "",
268 					descr->descr_2_8.can_48khz ? "48 " : "",
269 					descr->descr_2_8.can_44khz ? "44.1 " : "",
270 					descr->descr_2_8.can_32khz ? "32 " : ""
271 				);
272 				if (descr->descr.format_code >= 2 && descr->descr.format_code <= 0x8) {
273 					dprintf("\t\tMaximum bit rate: %u kHz\n",
274 						descr->descr_2_8.maximum_bitrate * 8);
275 				} else if (descr->descr.format_code == 0x1) {
276 					dprintf("\t\tSupported sample sizes (bits): %s%s%s\n",
277 						descr->descr_1.can_24bit ? "24 " : "",
278 						descr->descr_1.can_20bit ? "20 " : "",
279 						descr->descr_1.can_16bit ? "16 " : ""
280 					);
281 				}
282 			}
283 			break;
284 		case 0x2:
285 			dprintf("Video data block:\n");
286 			for (i = 0; i < dataBlock->length; i++) {
287 				uint8 vic = dataBlock->video.vic0;
288 				bool native = false;
289 				const edid1_std_timing *timing = NULL;
290 				if (i > 0)
291 					vic = dataBlock->video.vic[i - 1];
292 				if (((vic - 1) & 0x40) == 0) {
293 					native = (vic & 0x80) != 0;
294 					vic = vic & 0x7f;
295 				}
296 				if (vic > 0 && vic < B_COUNT_OF(cta_mode1_timings)) {
297 					timing = &cta_mode1_timings[vic - 1];
298 				} else if (vic >= 193 && vic < B_COUNT_OF(cta_mode2_timings) + 193) {
299 					timing = &cta_mode2_timings[vic - 193];
300 				}
301 
302 				if (timing != NULL) {
303 					const char* ratioString = NULL;
304 					switch (timing->ratio) {
305 						case 1: ratioString = "4:3";
306 							break;
307 						case 2: ratioString = "5:4";
308 							break;
309 						case 3: ratioString = "16:9";
310 							break;
311 						case 4: ratioString = "64:27";
312 							break;
313 						case 5: ratioString = "256:135";
314 							break;
315 						default:
316 							break;
317 					}
318 					dprintf("\tVIC %3u %dx%d@%dHz %s%s\n", vic,
319 						timing->h_size, timing->v_size, timing->refresh, ratioString,
320 						native ? " (native)" : "");
321 				}
322 			}
323 			break;
324 		case 0x3:
325 		{
326 			uint32 ouinum = (dataBlock->vendor_specific.ouinum2 << 16)
327 				| (dataBlock->vendor_specific.ouinum1 << 8) | dataBlock->vendor_specific.ouinum0;
328 			const char* ouinumString = "unknown";
329 			if (ouinum == 0x000c03)
330 				ouinumString = "HDMI";
331 			if (ouinum == 0xc45dd8)
332 				ouinumString = "HDMI Forum";
333 			dprintf("Vendor specific data block, %06" B_PRIx32 " (%s)\n", ouinum, ouinumString);
334 			if (ouinum == 0x000c03) {
335 				dprintf("\tSource physical address: %u.%u.%u.%u\n",
336 					dataBlock->vendor_specific.hdmi.source_physical_address.a,
337 					dataBlock->vendor_specific.hdmi.source_physical_address.b,
338 					dataBlock->vendor_specific.hdmi.source_physical_address.c,
339 					dataBlock->vendor_specific.hdmi.source_physical_address.d);
340 #define PRINT_HDMI_FLAG(x, s)	if (dataBlock->vendor_specific.hdmi. x ) dprintf("\t" s "\n");
341 				PRINT_HDMI_FLAG(supports_ai, "Supports_AI");
342 				PRINT_HDMI_FLAG(dc_48bit, "DC_48bit");
343 				PRINT_HDMI_FLAG(dc_36bit, "DC_36bit");
344 				PRINT_HDMI_FLAG(dc_30bit, "DC_30bit");
345 				PRINT_HDMI_FLAG(dc_y444, "DC_Y444");
346 				PRINT_HDMI_FLAG(dvi_dual, "DVI_DUAL");
347 #undef PRINT_HDMI_FLAG
348 				dprintf("\tMaximum TMDS clock: %uMHz\n",
349 					dataBlock->vendor_specific.hdmi.max_tmds_clock * 5);
350 				if (dataBlock->vendor_specific.hdmi.vic_length > 0)
351 					dprintf("\tExtended HDMI video details:\n");
352 				for (i = 0; i < dataBlock->vendor_specific.hdmi.vic_length; i++) {
353 					const edid1_std_timing *timing = NULL;
354 					switch (dataBlock->vendor_specific.hdmi.vic[i]) {
355 						case 1: timing = &cta_mode1_timings[94]; break;
356 						case 2: timing = &cta_mode1_timings[93]; break;
357 						case 3: timing = &cta_mode1_timings[92]; break;
358 						case 4: timing = &cta_mode1_timings[97]; break;
359 					}
360 					if (timing != NULL) {
361 						const char* ratioString = NULL;
362 						switch (timing->ratio) {
363 							case 1: ratioString = "4:3";
364 								break;
365 							case 2: ratioString = "5:4";
366 								break;
367 							case 3: ratioString = "16:9";
368 								break;
369 							case 4: ratioString = "64:27";
370 								break;
371 							case 5: ratioString = "256:135";
372 								break;
373 							default:
374 								break;
375 						}
376 						dprintf("\tHDMI VIC %u %dx%d@%dHz %s\n", dataBlock->vendor_specific.hdmi.vic[i],
377 							timing->h_size, timing->v_size, timing->refresh, ratioString);
378 					}
379 
380 				}
381 			} else if (ouinum == 0xc45dd8) {
382 				dprintf("\tVersion: %u\n", dataBlock->vendor_specific.hdmi_forum.version);
383 				dprintf("\tMaximum TMDS character rate: %uMHz\n",
384 					dataBlock->vendor_specific.hdmi_forum.max_tmds_rate * 5);
385 #define PRINT_HDMIFORUM_FLAG(x, s)	if (dataBlock->vendor_specific.hdmi_forum. x ) dprintf("\t" s "\n");
386 				PRINT_HDMIFORUM_FLAG(scdc_present, "SCDC Present");
387 				PRINT_HDMIFORUM_FLAG(scdc_read_request_capable, "SCDC Read Request Capable");
388 				PRINT_HDMIFORUM_FLAG(supports_cable_status, "Supports Cable Status");
389 				PRINT_HDMIFORUM_FLAG(supports_color_content_bits,
390 					"Supports Color Content Bits Per Component Indication");
391 				PRINT_HDMIFORUM_FLAG(supports_scrambling, "Supports scrambling for <= 340 Mcsc");
392 				PRINT_HDMIFORUM_FLAG(supports_3d_independent, "Supports 3D Independent View signaling");
393 				PRINT_HDMIFORUM_FLAG(supports_3d_dual_view, "Supports 3D Dual View signaling");
394 				PRINT_HDMIFORUM_FLAG(supports_3d_osd_disparity, "Supports 3D OSD Disparity signaling");
395 				PRINT_HDMIFORUM_FLAG(supports_uhd_vic, "Supports UHD VIC");
396 				PRINT_HDMIFORUM_FLAG(supports_16bit_deep_color_4_2_0,
397 					"Supports 16-bits/component Deep Color 4:2:0 Pixel Encoding");
398 				PRINT_HDMIFORUM_FLAG(supports_12bit_deep_color_4_2_0,
399 					"Supports 12-bits/component Deep Color 4:2:0 Pixel Encoding");
400 				PRINT_HDMIFORUM_FLAG(supports_10bit_deep_color_4_2_0,
401 					"Supports 10-bits/component Deep Color 4:2:0 Pixel Encoding");
402 #undef PRINT_HDMIFORUM_FLAG
403 			}
404 			break;
405 		}
406 		case 0x4:
407 			dprintf("Speaker allocation data block\n");
408 #define PRINT_SPEAKER_FLAG(x, s)	if (dataBlock->speaker_allocation_map. x ) dprintf("\t" s "\n");
409 			PRINT_SPEAKER_FLAG(FL_FR, "FL/FR - Front Left/Right");
410 			PRINT_SPEAKER_FLAG(LFE, "LFE1 - Low Frequency Effects 1");
411 			PRINT_SPEAKER_FLAG(FC, "FC - Front Center");
412 			PRINT_SPEAKER_FLAG(BL_BR, "BL/BR - Back Left/Right");
413 			PRINT_SPEAKER_FLAG(BC, "BC - Back Center");
414 			PRINT_SPEAKER_FLAG(FLC_FRC, "FLC/FRC - Front Left/Right of Center");
415 			PRINT_SPEAKER_FLAG(RLC_RRC, "RLC/RRC - Rear Left/Right of Center - deprecated");
416 			PRINT_SPEAKER_FLAG(FLW_FRW, "FLW/FRW - Front Left/Right Wide");
417 			PRINT_SPEAKER_FLAG(TpFL_TpFH, "TpFL/TpFR - Top Front Left/Right");
418 			PRINT_SPEAKER_FLAG(TpC, "TpC - Top Center");
419 			PRINT_SPEAKER_FLAG(TpFC, "TpFC - Top Front Center");
420 			PRINT_SPEAKER_FLAG(LS_RS, "LS/RS - Left/Right Surround");
421 			PRINT_SPEAKER_FLAG(LFE2, "LFE2 - Low Frequency Effects 2");
422 			PRINT_SPEAKER_FLAG(TpBC, "TpBC - Top Back Center");
423 			PRINT_SPEAKER_FLAG(SiL_SiR, "SiL/SiR - Side Left/Right");
424 			PRINT_SPEAKER_FLAG(TpSiL_TpSiR, "TpSiL/TpSiR - Top Side Left/Right");
425 			PRINT_SPEAKER_FLAG(TpBL_TpBR, "TpBL/TpBR - Top Back Left/Right");
426 			PRINT_SPEAKER_FLAG(BtFC, "BtFC - Bottom Front Center");
427 			PRINT_SPEAKER_FLAG(BtFL_BtFR, "BtFL/BtFR - Bottom Front Left/Right");
428 			PRINT_SPEAKER_FLAG(TpLS_TpRS, "TpLS/TpRS - Top Left/Right Surround");
429 			PRINT_SPEAKER_FLAG(LSd_RSd, "LSd/RSd - Left/Right Surround Direct");
430 #undef PRINT_SPEAKER_FLAG
431 			break;
432 		case 0x705:
433 			dprintf("Extended tag: Colorimetry data block\n");
434 #define PRINT_COLORIMETRY(x)	if (dataBlock->colorimetry. x ) dprintf("\t" #x );
435 			PRINT_COLORIMETRY(BT2020RGB);
436 			PRINT_COLORIMETRY(BT2020YCC);
437 			PRINT_COLORIMETRY(BT2020cYCC);
438 			PRINT_COLORIMETRY(opRGB);
439 			PRINT_COLORIMETRY(opYCC601);
440 			PRINT_COLORIMETRY(sYCC601);
441 			PRINT_COLORIMETRY(xvYCC709);
442 			PRINT_COLORIMETRY(xvYCC601);
443 			PRINT_COLORIMETRY(DCIP3);
444 #undef PRINT_COLORIMETRY
445 			dprintf("\n");
446 			break;
447 		case 0x700:
448 			dprintf("Extended tag: Video capability data block\n");
449 			dprintf("\tYCbCr quantization: %s\n",
450 				dataBlock->video_capability.QY ? "Selectable (via AVI YQ)" : "No Data");
451 			dprintf("\tRGB quantization: %s\n",
452 				dataBlock->video_capability.QS ? "Selectable (via AVI Q)" : "No Data");
453 			dprintf("\tPT scan behaviour: ");
454 			switch (dataBlock->video_capability.S_PT) {
455 				case 0: dprintf("No Data\n"); break;
456 				case 1: dprintf("Always Overscanned\n"); break;
457 				case 2: dprintf("Always Underscanned\n"); break;
458 				case 3: dprintf("Supports both over- and underscan\n"); break;
459 			}
460 			dprintf("\tIT scan behaviour: ");
461 			switch (dataBlock->video_capability.S_IT) {
462 				case 0: dprintf("IT Video Formats not supported\n"); break;
463 				case 1: dprintf("Always Overscanned\n"); break;
464 				case 2: dprintf("Always Underscanned\n"); break;
465 				case 3: dprintf("Supports both over- and underscan\n"); break;
466 			}
467 			dprintf("\tCE scan behaviour: ");
468 			switch (dataBlock->video_capability.S_CE) {
469 				case 0: dprintf("CE Video Formats not supported\n"); break;
470 				case 1: dprintf("Always Overscanned\n"); break;
471 				case 2: dprintf("Always Underscanned\n"); break;
472 				case 3: dprintf("Supports both over- and underscan\n"); break;
473 			}
474 		case 0x706:
475 			dprintf("Extended tag: HDR static metadata data block\n");
476 #define PRINT_SMD_FLAG(x, s)	if (dataBlock->hdr_static_metadata. x ) dprintf("\t\t" s "\n");
477 			dprintf("\tSupported Electro-Optical Transfer Functions:\n");
478 			PRINT_SMD_FLAG(ET_0, "Traditional gamma - SDR Luminance Range");
479 			PRINT_SMD_FLAG(ET_1, "Traditional gamma - HDR Luminance Range");
480 			PRINT_SMD_FLAG(ET_2, "SMPTE ST 2084");
481 			PRINT_SMD_FLAG(ET_3, "Hybrid Log-Gamma");
482 			dprintf("\tSupported Static Metadata Descriptors:\n");
483 			PRINT_SMD_FLAG(SM_0, "Static Metadata Type 1");
484 #undef PRINT_SMD_FLAG
485 			if (dataBlock->length >= 4) {
486 				dprintf("\tDesired content max luminance: %u\n",
487 					dataBlock->hdr_static_metadata.desired_content_max_luminance);
488 			}
489 			if (dataBlock->length >= 5) {
490 				dprintf("\tDesired content max frame-average luminance: %u\n",
491 					dataBlock->hdr_static_metadata.desired_content_max_frame_average_luminance);
492 			}
493 			if (dataBlock->length >= 6) {
494 				dprintf("\tDesired content min luminance: %u\n",
495 					dataBlock->hdr_static_metadata.desired_content_min_luminance);
496 			}
497 			break;
498 		case 0x707:
499 			dprintf("Extended tag: HDR dynamic metadata data block\n");
500 			break;
501 		case 0x708:
502 			dprintf("Extended tag: Native Video Resolution data block\n");
503 			break;
504 		case 0x711:
505 			dprintf("Vendor-Specific Audio Data Block\n");
506 		case 0x70f:
507 			dprintf("Extended tag: YCbCr 4:2:0 capability map data block\n");
508 			for (i = 0; i < dataBlock->length - 1; i++) {
509 				for (j = 0; j < 8; j++) {
510 					if ((dataBlock->YCbCr_4_2_0_capability_map.bitmap[i] & (1 << j)) != 0)
511 						dprintf("\tVSD Index %u\n", i * 8 + j);
512 				}
513 			}
514 			break;
515 		default:
516 			dprintf("unknown tag 0x%x\n", tagCode);
517 			break;
518 
519 	}
520 
521 }
522 
523 
524 void
edid_dump(edid1_info * edid)525 edid_dump(edid1_info *edid)
526 {
527 	int i, j;
528 
529 	dprintf("EDID info:\n");
530 	dprintf("  EDID version: %d.%d\n", edid->version.version, edid->version.revision);
531 	dprintf("  Vendor: %s Product ID: 0x%x\n", edid->vendor.manufacturer, edid->vendor.prod_id);
532 	dprintf("  Serial #: %" B_PRIu32 "\n", edid->vendor.serial);
533 	dprintf("  Produced in week/year: %u/%u\n", edid->vendor.week, edid->vendor.year);
534 
535 
536 	dprintf("  Type: %s\n", edid->display.input_type != 0 ? "Digital" : "Analog");
537 	if (edid->display.input_type != 0 && edid->version.revision >= 4) {
538 		dprintf("  Digital Bit Depth: %d\n", edid->display.digital_params.bit_depth);
539 		switch (edid->display.digital_params.interface) {
540 			case 0x1: dprintf("  DVI interface\n"); break;
541 			case 0x2: dprintf("  HDMIa interface\n"); break;
542 			case 0x3: dprintf("  HDMIb interface\n"); break;
543 			case 0x4: dprintf("  MDDI interface\n"); break;
544 			case 0x5: dprintf("  DisplayPort interface\n"); break;
545 		}
546 	}
547 	dprintf("  Size: %d cm x %d cm\n", edid->display.h_size,
548 		edid->display.v_size);
549 	dprintf("  Gamma=%.2f\n", (edid->display.gamma + 100) / 100.0);
550 	if (edid->display.gtf_supported) {
551 		if (edid->version.revision >= 4)
552 			dprintf("  Display supports continuous frequency\n");
553 		else
554 			dprintf("  GTF Timings supported\n");
555 	}
556 	dprintf("  Red (X,Y)=(%.4f,%.4f)\n", edid->display.red_x / 1024.0,
557 		edid->display.red_y / 1024.0);
558 	dprintf("  Green (X,Y)=(%.4f,%.4f)\n", edid->display.green_x / 1024.0,
559 		edid->display.green_y / 1024.0);
560 	dprintf("  Blue (X,Y)=(%.4f,%.4f)\n", edid->display.blue_x / 1024.0,
561 		edid->display.blue_y / 1024.0);
562 	dprintf("  White (X,Y)=(%.4f,%.4f)\n", edid->display.white_x / 1024.0,
563 		edid->display.white_y / 1024.0);
564 
565 	dprintf("Supported Future Video Modes:\n");
566 	for (i = 0; i < EDID1_NUM_STD_TIMING; ++i) {
567 		if (edid->std_timing[i].h_size <= 256)
568 			continue;
569 
570 		dprintf("%dx%d@%dHz (id=%d)\n",
571 			edid->std_timing[i].h_size, edid->std_timing[i].v_size,
572 			edid->std_timing[i].refresh, edid->std_timing[i].id);
573 	}
574 
575 	dprintf("Supported VESA Video Modes:\n");
576 	if (edid->established_timing.res_720x400x70)
577 		dprintf("720x400@70Hz\n");
578 	if (edid->established_timing.res_720x400x88)
579 		dprintf("720x400@88Hz\n");
580 	if (edid->established_timing.res_640x480x60)
581 		dprintf("640x480@60Hz\n");
582 	if (edid->established_timing.res_640x480x67)
583 		dprintf("640x480@67Hz\n");
584 	if (edid->established_timing.res_640x480x72)
585 		dprintf("640x480@72Hz\n");
586 	if (edid->established_timing.res_640x480x75)
587 		dprintf("640x480@75Hz\n");
588 	if (edid->established_timing.res_800x600x56)
589 		dprintf("800x600@56Hz\n");
590 	if (edid->established_timing.res_800x600x60)
591 		dprintf("800x600@60Hz\n");
592 
593 	if (edid->established_timing.res_800x600x72)
594 		dprintf("800x600@72Hz\n");
595 	if (edid->established_timing.res_800x600x75)
596 		dprintf("800x600@75Hz\n");
597 	if (edid->established_timing.res_832x624x75)
598 		dprintf("832x624@75Hz\n");
599 	if (edid->established_timing.res_1024x768x87i)
600 		dprintf("1024x768@87Hz interlaced\n");
601 	if (edid->established_timing.res_1024x768x60)
602 		dprintf("1024x768@60Hz\n");
603 	if (edid->established_timing.res_1024x768x70)
604 		dprintf("1024x768@70Hz\n");
605 	if (edid->established_timing.res_1024x768x75)
606 		dprintf("1024x768@75Hz\n");
607 	if (edid->established_timing.res_1280x1024x75)
608 		dprintf("1280x1024@75Hz\n");
609 
610 	if (edid->established_timing.res_1152x870x75)
611 		dprintf("1152x870@75Hz\n");
612 
613 	for (i = 0; i < EDID1_NUM_DETAILED_MONITOR_DESC; ++i) {
614 		edid1_detailed_monitor *monitor = &edid->detailed_monitor[i];
615 
616 		switch(monitor->monitor_desc_type) {
617 			case EDID1_SERIAL_NUMBER:
618 				dprintf("Serial Number: %s\n", monitor->data.serial_number);
619 				break;
620 
621 			case EDID1_ASCII_DATA:
622 				dprintf("Ascii Data: %s\n", monitor->data.ascii_data);
623 				break;
624 
625 			case EDID1_MONITOR_RANGES:
626 			{
627 				edid1_monitor_range monitor_range = monitor->data.monitor_range;
628 
629 				dprintf("Horizontal frequency range = %d..%d kHz\n",
630 					monitor_range.min_h, monitor_range.max_h);
631 				dprintf("Vertical frequency range = %d..%d Hz\n",
632 					monitor_range.min_v, monitor_range.max_v);
633 				dprintf("Maximum pixel clock = %d MHz\n",
634 					(uint16)monitor_range.max_clock * 10);
635 				break;
636 			}
637 
638 			case EDID1_MONITOR_NAME:
639 				dprintf("Monitor Name: %s\n", monitor->data.monitor_name);
640 				break;
641 
642 			case EDID1_ADD_COLOUR_POINTER:
643 			{
644 				for (j = 0; j < EDID1_NUM_EXTRA_WHITEPOINTS; ++j) {
645 					edid1_whitepoint *whitepoint = &monitor->data.whitepoint[j];
646 
647 					if (whitepoint->index == 0)
648 						continue;
649 
650 					dprintf("Additional whitepoint: (X,Y)=(%f,%f) gamma=%f "
651 						"index=%i\n", whitepoint->white_x / 1024.0,
652 						whitepoint->white_y / 1024.0,
653 						(whitepoint->gamma + 100) / 100.0, whitepoint->index);
654 				}
655 				break;
656 			}
657 
658 			case EDID1_ADD_STD_TIMING:
659 			{
660 				for (j = 0; j < EDID1_NUM_EXTRA_STD_TIMING; ++j) {
661 					edid1_std_timing *timing = &monitor->data.std_timing[j];
662 
663 					if (timing->h_size <= 256)
664 						continue;
665 
666 					dprintf("%dx%d@%dHz (id=%d)\n",
667 						timing->h_size, timing->v_size,
668 						timing->refresh, timing->id);
669 				}
670 				break;
671 			}
672 
673 			case EDID1_IS_DETAILED_TIMING:
674 			{
675 				edid1_detailed_timing *timing = &monitor->data.detailed_timing;
676 				edid_timing_dump(timing, true);
677 				break;
678 			}
679 		}
680 	}
681 
682 	if (edid->num_sections > 0)
683 		dprintf("Extension blocks: %u\n", edid->num_sections);
684 	if (edid->cta_block.tag == 0x2) {
685 		dprintf("CTA extension block\n");
686 		dprintf(" Extension version: %u\n", edid->cta_block.revision);
687 		dprintf(" Number of native detailed modes: %u\n", edid->cta_block.num_native_detailed);
688 		if (edid->cta_block.ycbcr422_supported)
689 			dprintf(" Supports YCbCr 4:2:2\n");
690 		if (edid->cta_block.ycbcr444_supported)
691 			dprintf(" Supports YCbCr 4:4:4\n");
692 		if (edid->cta_block.audio_supported)
693 			dprintf(" Basic audio support\n");
694 		if (edid->cta_block.underscan)
695 			dprintf(" Underscans PC formats by default\n");
696 		if (edid->cta_block.revision >= 3) {
697 			for (i = 0; i < edid->cta_block.num_data_blocks; i++) {
698 				edid_cta_datablock_dump(&edid->cta_block.data_blocks[i]);
699 			}
700 		}
701 		for (i = 0; i < 6; i++)
702 			edid_timing_dump(&edid->cta_block.detailed_timing[i], false);
703 	}
704 	if (edid->displayid_block.tag == 0x70) {
705 		dprintf("DisplayID extension block\n");
706 		dprintf(" Extension version: %u\n", edid->displayid_block.version);
707 		dprintf(" Extension count: %u\n", edid->displayid_block.extension_count);
708 	}
709 }
710