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 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 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 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