| 1 | /* |
| 2 | * Copyright 1998 by Egbert Eich <Egbert.Eich@Physik.TU-Darmstadt.DE> |
| 3 | * Copyright 2007 Red Hat, Inc. |
| 4 | * |
| 5 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 6 | * copy of this software and associated documentation files (the "Software"), |
| 7 | * to deal in the Software without restriction, including without limitation |
| 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| 9 | * and/or sell copies of the Software, and to permit persons to whom the |
| 10 | * Software is furnished to do so, subject to the following conditions: |
| 11 | * |
| 12 | * The above copyright notice and this permission notice (including the next |
| 13 | * paragraph) shall be included in all copies or substantial portions of the |
| 14 | * Software. |
| 15 | * |
| 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| 21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
| 22 | * DEALINGS IN THE SOFTWARE. |
| 23 | * |
| 24 | * print_edid.c: print out all information retrieved from display device |
| 25 | */ |
| 26 | |
| 27 | #ifdef HAVE_XORG_CONFIG_H |
| 28 | #include <xorg-config.h> |
| 29 | #endif |
| 30 | |
| 31 | /* XXX kinda gross */ |
| 32 | #define _PARSE_EDID_ |
| 33 | |
| 34 | #include "misc.h" |
| 35 | #include "xf86.h" |
| 36 | #include "xf86_OSproc.h" |
| 37 | #include "xf86DDC.h" |
| 38 | #include "edid.h" |
| 39 | |
| 40 | #define EDID_WIDTH 16 |
| 41 | |
| 42 | static void |
| 43 | print_vendor(int scrnIndex, struct vendor *c) |
| 44 | { |
| 45 | xf86DrvMsg(scrnIndex, X_INFO, "Manufacturer: %s Model: %x Serial#: %u\n", |
| 46 | (char *) &c->name, c->prod_id, c->serial); |
| 47 | xf86DrvMsg(scrnIndex, X_INFO, "Year: %u Week: %u\n", c->year, c->week); |
| 48 | } |
| 49 | |
| 50 | static void |
| 51 | print_version(int scrnIndex, struct edid_version *c) |
| 52 | { |
| 53 | xf86DrvMsg(scrnIndex, X_INFO, "EDID Version: %u.%u\n", c->version, |
| 54 | c->revision); |
| 55 | } |
| 56 | |
| 57 | static const char *digital_interfaces[] = { |
| 58 | "undefined", |
| 59 | "DVI", |
| 60 | "HDMI-a", |
| 61 | "HDMI-b", |
| 62 | "MDDI", |
| 63 | "DisplayPort", |
| 64 | "unknown" |
| 65 | }; |
| 66 | |
| 67 | static void |
| 68 | print_input_features(int scrnIndex, struct disp_features *c, |
| 69 | struct edid_version *v) |
| 70 | { |
| 71 | if (DIGITAL(c->input_type)) { |
| 72 | xf86DrvMsg(scrnIndex, X_INFO, "Digital Display Input\n"); |
| 73 | if (v->revision == 2 || v->revision == 3) { |
| 74 | if (DFP1(c->input_dfp)) |
| 75 | xf86DrvMsg(scrnIndex, X_INFO, "DFP 1.x compatible TMDS\n"); |
| 76 | } |
| 77 | else if (v->revision >= 4) { |
| 78 | int interface = c->input_interface; |
| 79 | int bpc = c->input_bpc; |
| 80 | |
| 81 | if (interface > 6) |
| 82 | interface = 6; /* unknown */ |
| 83 | if (bpc == 0 || bpc == 7) |
| 84 | xf86DrvMsg(scrnIndex, X_INFO, "Undefined color depth\n"); |
| 85 | else |
| 86 | xf86DrvMsg(scrnIndex, X_INFO, "%d bits per channel\n", |
| 87 | bpc * 2 + 4); |
| 88 | xf86DrvMsg(scrnIndex, X_INFO, "Digital interface is %s\n", |
| 89 | digital_interfaces[interface]); |
| 90 | } |
| 91 | } |
| 92 | else { |
| 93 | xf86DrvMsg(scrnIndex, X_INFO, "Analog Display Input, "); |
| 94 | xf86ErrorF("Input Voltage Level: "); |
| 95 | switch (c->input_voltage) { |
| 96 | case V070: |
| 97 | xf86ErrorF("0.700/0.300 V\n"); |
| 98 | break; |
| 99 | case V071: |
| 100 | xf86ErrorF("0.714/0.286 V\n"); |
| 101 | break; |
| 102 | case V100: |
| 103 | xf86ErrorF("1.000/0.400 V\n"); |
| 104 | break; |
| 105 | case V007: |
| 106 | xf86ErrorF("0.700/0.700 V\n"); |
| 107 | break; |
| 108 | default: |
| 109 | xf86ErrorF("undefined\n"); |
| 110 | } |
| 111 | if (SIG_SETUP(c->input_setup)) |
| 112 | xf86DrvMsg(scrnIndex, X_INFO, "Signal levels configurable\n"); |
| 113 | xf86DrvMsg(scrnIndex, X_INFO, "Sync:"); |
| 114 | if (SEP_SYNC(c->input_sync)) |
| 115 | xf86ErrorF(" Separate"); |
| 116 | if (COMP_SYNC(c->input_sync)) |
| 117 | xf86ErrorF(" Composite"); |
| 118 | if (SYNC_O_GREEN(c->input_sync)) |
| 119 | xf86ErrorF(" SyncOnGreen"); |
| 120 | if (SYNC_SERR(c->input_sync)) |
| 121 | xf86ErrorF("Serration on. " |
| 122 | "V.Sync Pulse req. if CompSync or SyncOnGreen\n"); |
| 123 | else |
| 124 | xf86ErrorF("\n"); |
| 125 | } |
| 126 | } |
| 127 | |
| 128 | static void |
| 129 | print_dpms_features(int scrnIndex, struct disp_features *c, |
| 130 | struct edid_version *v) |
| 131 | { |
| 132 | if (c->dpms) { |
| 133 | xf86DrvMsg(scrnIndex, X_INFO, "DPMS capabilities:"); |
| 134 | if (DPMS_STANDBY(c->dpms)) |
| 135 | xf86ErrorF(" StandBy"); |
| 136 | if (DPMS_SUSPEND(c->dpms)) |
| 137 | xf86ErrorF(" Suspend"); |
| 138 | if (DPMS_OFF(c->dpms)) |
| 139 | xf86ErrorF(" Off"); |
| 140 | } |
| 141 | else |
| 142 | xf86DrvMsg(scrnIndex, X_INFO, "No DPMS capabilities specified"); |
| 143 | if (!c->input_type) { /* analog */ |
| 144 | switch (c->display_type) { |
| 145 | case DISP_MONO: |
| 146 | xf86ErrorF("; Monochorome/GrayScale Display\n"); |
| 147 | break; |
| 148 | case DISP_RGB: |
| 149 | xf86ErrorF("; RGB/Color Display\n"); |
| 150 | break; |
| 151 | case DISP_MULTCOLOR: |
| 152 | xf86ErrorF("; Non RGB Multicolor Display\n"); |
| 153 | break; |
| 154 | default: |
| 155 | xf86ErrorF("\n"); |
| 156 | break; |
| 157 | } |
| 158 | } |
| 159 | else { |
| 160 | int enc = c->display_type; |
| 161 | |
| 162 | xf86ErrorF("\n"); |
| 163 | xf86DrvMsg(scrnIndex, X_INFO, "Supported color encodings: " |
| 164 | "RGB 4:4:4 %s%s\n", |
| 165 | enc & DISP_YCRCB444 ? "YCrCb 4:4:4 " : "", |
| 166 | enc & DISP_YCRCB422 ? "YCrCb 4:2:2" : ""); |
| 167 | } |
| 168 | |
| 169 | if (STD_COLOR_SPACE(c->msc)) |
| 170 | xf86DrvMsg(scrnIndex, X_INFO, |
| 171 | "Default color space is primary color space\n"); |
| 172 | |
| 173 | if (PREFERRED_TIMING_MODE(c->msc) || v->revision >= 4) { |
| 174 | xf86DrvMsg(scrnIndex, X_INFO, |
| 175 | "First detailed timing is preferred mode\n"); |
| 176 | if (v->revision >= 4) |
| 177 | xf86DrvMsg(scrnIndex, X_INFO, |
| 178 | "Preferred mode is native pixel format and refresh rate\n"); |
| 179 | } |
| 180 | else if (v->revision == 3) { |
| 181 | xf86DrvMsg(scrnIndex, X_INFO, |
| 182 | "First detailed timing not preferred " |
| 183 | "mode in violation of standard!\n"); |
| 184 | } |
| 185 | |
| 186 | if (v->revision >= 4) { |
| 187 | if (GFT_SUPPORTED(c->msc)) { |
| 188 | xf86DrvMsg(scrnIndex, X_INFO, "Display is continuous-frequency\n"); |
| 189 | } |
| 190 | } |
| 191 | else { |
| 192 | if (GFT_SUPPORTED(c->msc)) |
| 193 | xf86DrvMsg(scrnIndex, X_INFO, "GTF timings supported\n"); |
| 194 | } |
| 195 | } |
| 196 | |
| 197 | static void |
| 198 | print_whitepoint(int scrnIndex, struct disp_features *disp) |
| 199 | { |
| 200 | xf86DrvMsg(scrnIndex, X_INFO, "redX: %.3f redY: %.3f ", |
| 201 | disp->redx, disp->redy); |
| 202 | xf86ErrorF("greenX: %.3f greenY: %.3f\n", disp->greenx, disp->greeny); |
| 203 | xf86DrvMsg(scrnIndex, X_INFO, "blueX: %.3f blueY: %.3f ", |
| 204 | disp->bluex, disp->bluey); |
| 205 | xf86ErrorF("whiteX: %.3f whiteY: %.3f\n", disp->whitex, disp->whitey); |
| 206 | } |
| 207 | |
| 208 | static void |
| 209 | print_display(int scrnIndex, struct disp_features *disp, struct edid_version *v) |
| 210 | { |
| 211 | print_input_features(scrnIndex, disp, v); |
| 212 | if (disp->hsize && disp->vsize) { |
| 213 | xf86DrvMsg(scrnIndex, X_INFO, "Max Image Size [cm]: "); |
| 214 | xf86ErrorF("horiz.: %i ", disp->hsize); |
| 215 | xf86ErrorF("vert.: %i\n", disp->vsize); |
| 216 | } |
| 217 | else if (v->revision >= 4 && (disp->hsize || disp->vsize)) { |
| 218 | if (disp->hsize) |
| 219 | xf86DrvMsg(scrnIndex, X_INFO, "Aspect ratio: %.2f (landscape)\n", |
| 220 | (disp->hsize + 99) / 100.0); |
| 221 | if (disp->vsize) |
| 222 | xf86DrvMsg(scrnIndex, X_INFO, "Aspect ratio: %.2f (portrait)\n", |
| 223 | 100.0 / (float) (disp->vsize + 99)); |
| 224 | |
| 225 | } |
| 226 | else { |
| 227 | xf86DrvMsg(scrnIndex, X_INFO, "Indeterminate output size\n"); |
| 228 | } |
| 229 | |
| 230 | if (!disp->gamma && v->revision >= 1.4) |
| 231 | xf86DrvMsg(scrnIndex, X_INFO, "Gamma defined in extension block\n"); |
| 232 | else |
| 233 | xf86DrvMsg(scrnIndex, X_INFO, "Gamma: %.2f\n", disp->gamma); |
| 234 | |
| 235 | print_dpms_features(scrnIndex, disp, v); |
| 236 | print_whitepoint(scrnIndex, disp); |
| 237 | } |
| 238 | |
| 239 | static void |
| 240 | print_established_timings(int scrnIndex, struct established_timings *t) |
| 241 | { |
| 242 | unsigned char c; |
| 243 | |
| 244 | if (t->t1 || t->t2 || t->t_manu) |
| 245 | xf86DrvMsg(scrnIndex, X_INFO, "Supported established timings:\n"); |
| 246 | c = t->t1; |
| 247 | if (c & 0x80) |
| 248 | xf86DrvMsg(scrnIndex, X_INFO, "720x400@70Hz\n"); |
| 249 | if (c & 0x40) |
| 250 | xf86DrvMsg(scrnIndex, X_INFO, "720x400@88Hz\n"); |
| 251 | if (c & 0x20) |
| 252 | xf86DrvMsg(scrnIndex, X_INFO, "640x480@60Hz\n"); |
| 253 | if (c & 0x10) |
| 254 | xf86DrvMsg(scrnIndex, X_INFO, "640x480@67Hz\n"); |
| 255 | if (c & 0x08) |
| 256 | xf86DrvMsg(scrnIndex, X_INFO, "640x480@72Hz\n"); |
| 257 | if (c & 0x04) |
| 258 | xf86DrvMsg(scrnIndex, X_INFO, "640x480@75Hz\n"); |
| 259 | if (c & 0x02) |
| 260 | xf86DrvMsg(scrnIndex, X_INFO, "800x600@56Hz\n"); |
| 261 | if (c & 0x01) |
| 262 | xf86DrvMsg(scrnIndex, X_INFO, "800x600@60Hz\n"); |
| 263 | c = t->t2; |
| 264 | if (c & 0x80) |
| 265 | xf86DrvMsg(scrnIndex, X_INFO, "800x600@72Hz\n"); |
| 266 | if (c & 0x40) |
| 267 | xf86DrvMsg(scrnIndex, X_INFO, "800x600@75Hz\n"); |
| 268 | if (c & 0x20) |
| 269 | xf86DrvMsg(scrnIndex, X_INFO, "832x624@75Hz\n"); |
| 270 | if (c & 0x10) |
| 271 | xf86DrvMsg(scrnIndex, X_INFO, "1024x768@87Hz (interlaced)\n"); |
| 272 | if (c & 0x08) |
| 273 | xf86DrvMsg(scrnIndex, X_INFO, "1024x768@60Hz\n"); |
| 274 | if (c & 0x04) |
| 275 | xf86DrvMsg(scrnIndex, X_INFO, "1024x768@70Hz\n"); |
| 276 | if (c & 0x02) |
| 277 | xf86DrvMsg(scrnIndex, X_INFO, "1024x768@75Hz\n"); |
| 278 | if (c & 0x01) |
| 279 | xf86DrvMsg(scrnIndex, X_INFO, "1280x1024@75Hz\n"); |
| 280 | c = t->t_manu; |
| 281 | if (c & 0x80) |
| 282 | xf86DrvMsg(scrnIndex, X_INFO, "1152x864@75Hz\n"); |
| 283 | xf86DrvMsg(scrnIndex, X_INFO, "Manufacturer's mask: %X\n", c & 0x7F); |
| 284 | } |
| 285 | |
| 286 | static void |
| 287 | print_std_timings(int scrnIndex, struct std_timings *t) |
| 288 | { |
| 289 | int i; |
| 290 | char done = 0; |
| 291 | |
| 292 | for (i = 0; i < STD_TIMINGS; i++) { |
| 293 | if (t[i].hsize > 256) { /* sanity check */ |
| 294 | if (!done) { |
| 295 | xf86DrvMsg(scrnIndex, X_INFO, "Supported standard timings:\n"); |
| 296 | done = 1; |
| 297 | } |
| 298 | xf86DrvMsg(scrnIndex, X_INFO, |
| 299 | "#%i: hsize: %i vsize %i refresh: %i vid: %i\n", |
| 300 | i, t[i].hsize, t[i].vsize, t[i].refresh, t[i].id); |
| 301 | } |
| 302 | } |
| 303 | } |
| 304 | |
| 305 | static void |
| 306 | print_cvt_timings(int si, struct cvt_timings *t) |
| 307 | { |
| 308 | int i; |
| 309 | |
| 310 | for (i = 0; i < 4; i++) { |
| 311 | if (t[i].height) { |
| 312 | xf86DrvMsg(si, X_INFO, "%dx%d @ %s%s%s%s%s Hz\n", |
| 313 | t[i].width, t[i].height, |
| 314 | t[i].rates & 0x10 ? "50," : "", |
| 315 | t[i].rates & 0x08 ? "60," : "", |
| 316 | t[i].rates & 0x04 ? "75," : "", |
| 317 | t[i].rates & 0x02 ? "85," : "", |
| 318 | t[i].rates & 0x01 ? "60RB" : ""); |
| 319 | } |
| 320 | else |
| 321 | break; |
| 322 | } |
| 323 | } |
| 324 | |
| 325 | static void |
| 326 | print_detailed_timings(int scrnIndex, struct detailed_timings *t) |
| 327 | { |
| 328 | |
| 329 | if (t->clock > 15000000) { /* sanity check */ |
| 330 | xf86DrvMsg(scrnIndex, X_INFO, "Supported detailed timing:\n"); |
| 331 | xf86DrvMsg(scrnIndex, X_INFO, "clock: %.1f MHz ", |
| 332 | t->clock / 1000000.0); |
| 333 | xf86ErrorF("Image Size: %i x %i mm\n", t->h_size, t->v_size); |
| 334 | xf86DrvMsg(scrnIndex, X_INFO, |
| 335 | "h_active: %i h_sync: %i h_sync_end %i h_blank_end %i ", |
| 336 | t->h_active, t->h_sync_off + t->h_active, |
| 337 | t->h_sync_off + t->h_sync_width + t->h_active, |
| 338 | t->h_active + t->h_blanking); |
| 339 | xf86ErrorF("h_border: %i\n", t->h_border); |
| 340 | xf86DrvMsg(scrnIndex, X_INFO, |
| 341 | "v_active: %i v_sync: %i v_sync_end %i v_blanking: %i ", |
| 342 | t->v_active, t->v_sync_off + t->v_active, |
| 343 | t->v_sync_off + t->v_sync_width + t->v_active, |
| 344 | t->v_active + t->v_blanking); |
| 345 | xf86ErrorF("v_border: %i\n", t->v_border); |
| 346 | if (IS_STEREO(t->stereo)) { |
| 347 | xf86DrvMsg(scrnIndex, X_INFO, "Stereo: "); |
| 348 | if (IS_RIGHT_STEREO(t->stereo)) { |
| 349 | if (!t->stereo_1) |
| 350 | xf86ErrorF("right channel on sync\n"); |
| 351 | else |
| 352 | xf86ErrorF("left channel on sync\n"); |
| 353 | } |
| 354 | else if (IS_LEFT_STEREO(t->stereo)) { |
| 355 | if (!t->stereo_1) |
| 356 | xf86ErrorF("right channel on even line\n"); |
| 357 | else |
| 358 | xf86ErrorF("left channel on evel line\n"); |
| 359 | } |
| 360 | if (IS_4WAY_STEREO(t->stereo)) { |
| 361 | if (!t->stereo_1) |
| 362 | xf86ErrorF("4-way interleaved\n"); |
| 363 | else |
| 364 | xf86ErrorF("side-by-side interleaved"); |
| 365 | } |
| 366 | } |
| 367 | } |
| 368 | } |
| 369 | |
| 370 | /* This function handle all detailed patchs, |
| 371 | * including EDID and EDID-extension |
| 372 | */ |
| 373 | struct det_print_parameter { |
| 374 | xf86MonPtr m; |
| 375 | int index; |
| 376 | ddc_quirk_t quirks; |
| 377 | }; |
| 378 | |
| 379 | static void |
| 380 | handle_detailed_print(struct detailed_monitor_section *det_mon, void *data) |
| 381 | { |
| 382 | int j, scrnIndex; |
| 383 | struct det_print_parameter *p; |
| 384 | |
| 385 | p = (struct det_print_parameter *) data; |
| 386 | scrnIndex = p->m->scrnIndex; |
| 387 | xf86DetTimingApplyQuirks(det_mon, p->quirks, |
| 388 | p->m->features.hsize, p->m->features.vsize); |
| 389 | |
| 390 | switch (det_mon->type) { |
| 391 | case DT: |
| 392 | print_detailed_timings(scrnIndex, &det_mon->section.d_timings); |
| 393 | break; |
| 394 | case DS_SERIAL: |
| 395 | xf86DrvMsg(scrnIndex, X_INFO, "Serial No: %s\n", |
| 396 | det_mon->section.serial); |
| 397 | break; |
| 398 | case DS_ASCII_STR: |
| 399 | xf86DrvMsg(scrnIndex, X_INFO, " %s\n", det_mon->section.ascii_data); |
| 400 | break; |
| 401 | case DS_NAME: |
| 402 | xf86DrvMsg(scrnIndex, X_INFO, "Monitor name: %s\n", |
| 403 | det_mon->section.name); |
| 404 | break; |
| 405 | case DS_RANGES: |
| 406 | { |
| 407 | struct monitor_ranges *r = &det_mon->section.ranges; |
| 408 | |
| 409 | xf86DrvMsg(scrnIndex, X_INFO, |
| 410 | "Ranges: V min: %i V max: %i Hz, H min: %i H max: %i kHz,", |
| 411 | r->min_v, r->max_v, r->min_h, r->max_h); |
| 412 | if (r->max_clock_khz != 0) { |
| 413 | xf86ErrorF(" PixClock max %i kHz\n", r->max_clock_khz); |
| 414 | if (r->maxwidth) |
| 415 | xf86DrvMsg(scrnIndex, X_INFO, "Maximum pixel width: %d\n", |
| 416 | r->maxwidth); |
| 417 | xf86DrvMsg(scrnIndex, X_INFO, "Supported aspect ratios:"); |
| 418 | if (r->supported_aspect & SUPPORTED_ASPECT_4_3) |
| 419 | xf86ErrorF(" 4:3%s", |
| 420 | r->preferred_aspect == |
| 421 | PREFERRED_ASPECT_4_3 ? "*" : ""); |
| 422 | if (r->supported_aspect & SUPPORTED_ASPECT_16_9) |
| 423 | xf86ErrorF(" 16:9%s", |
| 424 | r->preferred_aspect == |
| 425 | PREFERRED_ASPECT_16_9 ? "*" : ""); |
| 426 | if (r->supported_aspect & SUPPORTED_ASPECT_16_10) |
| 427 | xf86ErrorF(" 16:10%s", |
| 428 | r->preferred_aspect == |
| 429 | PREFERRED_ASPECT_16_10 ? "*" : ""); |
| 430 | if (r->supported_aspect & SUPPORTED_ASPECT_5_4) |
| 431 | xf86ErrorF(" 5:4%s", |
| 432 | r->preferred_aspect == |
| 433 | PREFERRED_ASPECT_5_4 ? "*" : ""); |
| 434 | if (r->supported_aspect & SUPPORTED_ASPECT_15_9) |
| 435 | xf86ErrorF(" 15:9%s", |
| 436 | r->preferred_aspect == |
| 437 | PREFERRED_ASPECT_15_9 ? "*" : ""); |
| 438 | xf86ErrorF("\n"); |
| 439 | xf86DrvMsg(scrnIndex, X_INFO, "Supported blankings:"); |
| 440 | if (r->supported_blanking & CVT_STANDARD) |
| 441 | xf86ErrorF(" standard"); |
| 442 | if (r->supported_blanking & CVT_REDUCED) |
| 443 | xf86ErrorF(" reduced"); |
| 444 | xf86ErrorF("\n"); |
| 445 | xf86DrvMsg(scrnIndex, X_INFO, "Supported scalings:"); |
| 446 | if (r->supported_scaling & SCALING_HSHRINK) |
| 447 | xf86ErrorF(" hshrink"); |
| 448 | if (r->supported_scaling & SCALING_HSTRETCH) |
| 449 | xf86ErrorF(" hstretch"); |
| 450 | if (r->supported_scaling & SCALING_VSHRINK) |
| 451 | xf86ErrorF(" vshrink"); |
| 452 | if (r->supported_scaling & SCALING_VSTRETCH) |
| 453 | xf86ErrorF(" vstretch"); |
| 454 | xf86ErrorF("\n"); |
| 455 | if (r->preferred_refresh) |
| 456 | xf86DrvMsg(scrnIndex, X_INFO, "Preferred refresh rate: %d\n", |
| 457 | r->preferred_refresh); |
| 458 | else |
| 459 | xf86DrvMsg(scrnIndex, X_INFO, "Buggy monitor, no preferred " |
| 460 | "refresh rate given\n"); |
| 461 | } |
| 462 | else if (r->max_clock != 0) { |
| 463 | xf86ErrorF(" PixClock max %i MHz\n", r->max_clock); |
| 464 | } |
| 465 | else { |
| 466 | xf86ErrorF("\n"); |
| 467 | } |
| 468 | if (r->gtf_2nd_f > 0) |
| 469 | xf86DrvMsg(scrnIndex, X_INFO, " 2nd GTF parameters: f: %i kHz " |
| 470 | "c: %i m: %i k %i j %i\n", r->gtf_2nd_f, |
| 471 | r->gtf_2nd_c, r->gtf_2nd_m, r->gtf_2nd_k, r->gtf_2nd_j); |
| 472 | break; |
| 473 | } |
| 474 | case DS_STD_TIMINGS: |
| 475 | for (j = 0; j < 5; j++) |
| 476 | xf86DrvMsg(scrnIndex, X_INFO, |
| 477 | "#%i: hsize: %i vsize %i refresh: %i " |
| 478 | "vid: %i\n", p->index, det_mon->section.std_t[j].hsize, |
| 479 | det_mon->section.std_t[j].vsize, |
| 480 | det_mon->section.std_t[j].refresh, |
| 481 | det_mon->section.std_t[j].id); |
| 482 | break; |
| 483 | case DS_WHITE_P: |
| 484 | for (j = 0; j < 2; j++) |
| 485 | if (det_mon->section.wp[j].index != 0) |
| 486 | xf86DrvMsg(scrnIndex, X_INFO, |
| 487 | "White point %i: whiteX: %f, whiteY: %f; gamma: %f\n", |
| 488 | det_mon->section.wp[j].index, |
| 489 | det_mon->section.wp[j].white_x, |
| 490 | det_mon->section.wp[j].white_y, |
| 491 | det_mon->section.wp[j].white_gamma); |
| 492 | break; |
| 493 | case DS_CMD: |
| 494 | xf86DrvMsg(scrnIndex, X_INFO, "Color management data: (not decoded)\n"); |
| 495 | break; |
| 496 | case DS_CVT: |
| 497 | xf86DrvMsg(scrnIndex, X_INFO, "CVT 3-byte-code modes:\n"); |
| 498 | print_cvt_timings(scrnIndex, det_mon->section.cvt); |
| 499 | break; |
| 500 | case DS_EST_III: |
| 501 | xf86DrvMsg(scrnIndex, X_INFO, |
| 502 | "Established timings III: (not decoded)\n"); |
| 503 | break; |
| 504 | case DS_DUMMY: |
| 505 | default: |
| 506 | break; |
| 507 | } |
| 508 | if (det_mon->type >= DS_VENDOR && det_mon->type <= DS_VENDOR_MAX) { |
| 509 | xf86DrvMsg(scrnIndex, X_INFO, |
| 510 | "Unknown vendor-specific block %hx\n", |
| 511 | det_mon->type - DS_VENDOR); |
| 512 | } |
| 513 | |
| 514 | p->index = p->index + 1; |
| 515 | } |
| 516 | |
| 517 | static void |
| 518 | print_number_sections(int scrnIndex, int num) |
| 519 | { |
| 520 | if (num) |
| 521 | xf86DrvMsg(scrnIndex, X_INFO, "Number of EDID sections to follow: %i\n", |
| 522 | num); |
| 523 | } |
| 524 | |
| 525 | xf86MonPtr |
| 526 | xf86PrintEDID(xf86MonPtr m) |
| 527 | { |
| 528 | CARD16 i, j, n; |
| 529 | char buf[EDID_WIDTH * 2 + 1]; |
| 530 | struct det_print_parameter p; |
| 531 | |
| 532 | if (!m) |
| 533 | return NULL; |
| 534 | |
| 535 | print_vendor(m->scrnIndex, &m->vendor); |
| 536 | print_version(m->scrnIndex, &m->ver); |
| 537 | print_display(m->scrnIndex, &m->features, &m->ver); |
| 538 | print_established_timings(m->scrnIndex, &m->timings1); |
| 539 | print_std_timings(m->scrnIndex, m->timings2); |
| 540 | p.m = m; |
| 541 | p.index = 0; |
| 542 | p.quirks = xf86DDCDetectQuirks(m->scrnIndex, m, FALSE); |
| 543 | xf86ForEachDetailedBlock(m, handle_detailed_print, &p); |
| 544 | print_number_sections(m->scrnIndex, m->no_sections); |
| 545 | |
| 546 | /* extension block section stuff */ |
| 547 | |
| 548 | xf86DrvMsg(m->scrnIndex, X_INFO, "EDID (in hex):\n"); |
| 549 | |
| 550 | n = 128; |
| 551 | if (m->flags & EDID_COMPLETE_RAWDATA) |
| 552 | n += m->no_sections * 128; |
| 553 | |
| 554 | for (i = 0; i < n; i += j) { |
| 555 | for (j = 0; j < EDID_WIDTH; ++j) { |
| 556 | sprintf(&buf[j * 2], "%02x", m->rawData[i + j]); |
| 557 | } |
| 558 | xf86DrvMsg(m->scrnIndex, X_INFO, "\t%s\n", buf); |
| 559 | } |
| 560 | |
| 561 | return m; |
| 562 | } |