xref: /OK3568_Linux_fs/external/xserver/hw/xfree86/ddc/print_edid.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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
print_vendor(int scrnIndex,struct vendor * c)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
print_version(int scrnIndex,struct edid_version * c)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
print_input_features(int scrnIndex,struct disp_features * c,struct edid_version * v)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
print_dpms_features(int scrnIndex,struct disp_features * c,struct edid_version * v)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
print_whitepoint(int scrnIndex,struct disp_features * disp)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
print_display(int scrnIndex,struct disp_features * disp,struct edid_version * v)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
print_established_timings(int scrnIndex,struct established_timings * t)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
print_std_timings(int scrnIndex,struct std_timings * t)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
print_cvt_timings(int si,struct cvt_timings * t)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
print_detailed_timings(int scrnIndex,struct detailed_timings * t)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
handle_detailed_print(struct detailed_monitor_section * det_mon,void * data)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
print_number_sections(int scrnIndex,int num)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
xf86PrintEDID(xf86MonPtr m)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 }
563