xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

print_edid.c (19726B)


      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("; Monochrome/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 }