Commit | Line | Data |
---|---|---|
a09e091a JB |
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 | } |