14642e01fSmrg/*
205b261ecSmrg * Copyright 1998 by Egbert Eich <Egbert.Eich@Physik.TU-Darmstadt.DE>
34642e01fSmrg * Copyright 2007 Red Hat, Inc.
44642e01fSmrg *
54642e01fSmrg * Permission is hereby granted, free of charge, to any person obtaining a
66747b715Smrg * copy of this software and associated documentation files (the "Software"),
76747b715Smrg * to deal in the Software without restriction, including without limitation
86747b715Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
96747b715Smrg * and/or sell copies of the Software, and to permit persons to whom the
106747b715Smrg * Software is furnished to do so, subject to the following conditions:
114642e01fSmrg *
124642e01fSmrg * The above copyright notice and this permission notice (including the next
134642e01fSmrg * paragraph) shall be included in all copies or substantial portions of the
144642e01fSmrg * Software.
154642e01fSmrg *
164642e01fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
176747b715Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
186747b715Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
196747b715Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
206747b715Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
216747b715Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
226747b715Smrg * DEALINGS IN THE SOFTWARE.
234642e01fSmrg *
2435c4bbdfSmrg * print_edid.c: print out all information retrieved from display device
2505b261ecSmrg */
264642e01fSmrg
2705b261ecSmrg#ifdef HAVE_XORG_CONFIG_H
2805b261ecSmrg#include <xorg-config.h>
2905b261ecSmrg#endif
3005b261ecSmrg
314642e01fSmrg/* XXX kinda gross */
324642e01fSmrg#define _PARSE_EDID_
334642e01fSmrg
3405b261ecSmrg#include "misc.h"
3505b261ecSmrg#include "xf86.h"
3605b261ecSmrg#include "xf86_OSproc.h"
3705b261ecSmrg#include "xf86DDC.h"
384642e01fSmrg#include "edid.h"
3935c4bbdfSmrg
4005b261ecSmrg#define EDID_WIDTH	16
4135c4bbdfSmrg
4205b261ecSmrgstatic void
4305b261ecSmrgprint_vendor(int scrnIndex, struct vendor *c)
4405b261ecSmrg{
4505b261ecSmrg    xf86DrvMsg(scrnIndex, X_INFO, "Manufacturer: %s  Model: %x  Serial#: %u\n",
4635c4bbdfSmrg               (char *) &c->name, c->prod_id, c->serial);
4705b261ecSmrg    xf86DrvMsg(scrnIndex, X_INFO, "Year: %u  Week: %u\n", c->year, c->week);
4805b261ecSmrg}
494642e01fSmrg
5005b261ecSmrgstatic void
5105b261ecSmrgprint_version(int scrnIndex, struct edid_version *c)
5205b261ecSmrg{
5335c4bbdfSmrg    xf86DrvMsg(scrnIndex, X_INFO, "EDID Version: %u.%u\n", c->version,
5435c4bbdfSmrg               c->revision);
5505b261ecSmrg}
5635c4bbdfSmrg
574642e01fSmrgstatic const char *digital_interfaces[] = {
584642e01fSmrg    "undefined",
594642e01fSmrg    "DVI",
604642e01fSmrg    "HDMI-a",
614642e01fSmrg    "HDMI-b",
624642e01fSmrg    "MDDI",
634642e01fSmrg    "DisplayPort",
644642e01fSmrg    "unknown"
654642e01fSmrg};
664642e01fSmrg
6735c4bbdfSmrgstatic void
684642e01fSmrgprint_input_features(int scrnIndex, struct disp_features *c,
6935c4bbdfSmrg                     struct edid_version *v)
7005b261ecSmrg{
7105b261ecSmrg    if (DIGITAL(c->input_type)) {
7235c4bbdfSmrg        xf86DrvMsg(scrnIndex, X_INFO, "Digital Display Input\n");
7335c4bbdfSmrg        if (v->revision == 2 || v->revision == 3) {
7435c4bbdfSmrg            if (DFP1(c->input_dfp))
7535c4bbdfSmrg                xf86DrvMsg(scrnIndex, X_INFO, "DFP 1.x compatible TMDS\n");
7635c4bbdfSmrg        }
7735c4bbdfSmrg        else if (v->revision >= 4) {
7835c4bbdfSmrg            int interface = c->input_interface;
7935c4bbdfSmrg            int bpc = c->input_bpc;
8035c4bbdfSmrg
8135c4bbdfSmrg            if (interface > 6)
8235c4bbdfSmrg                interface = 6;  /* unknown */
8335c4bbdfSmrg            if (bpc == 0 || bpc == 7)
8435c4bbdfSmrg                xf86DrvMsg(scrnIndex, X_INFO, "Undefined color depth\n");
8535c4bbdfSmrg            else
8635c4bbdfSmrg                xf86DrvMsg(scrnIndex, X_INFO, "%d bits per channel\n",
8735c4bbdfSmrg                           bpc * 2 + 4);
8835c4bbdfSmrg            xf86DrvMsg(scrnIndex, X_INFO, "Digital interface is %s\n",
8935c4bbdfSmrg                       digital_interfaces[interface]);
9035c4bbdfSmrg        }
9135c4bbdfSmrg    }
9235c4bbdfSmrg    else {
9335c4bbdfSmrg        xf86DrvMsg(scrnIndex, X_INFO, "Analog Display Input,  ");
9435c4bbdfSmrg        xf86ErrorF("Input Voltage Level: ");
9535c4bbdfSmrg        switch (c->input_voltage) {
9635c4bbdfSmrg        case V070:
9735c4bbdfSmrg            xf86ErrorF("0.700/0.300 V\n");
9835c4bbdfSmrg            break;
9935c4bbdfSmrg        case V071:
10035c4bbdfSmrg            xf86ErrorF("0.714/0.286 V\n");
10135c4bbdfSmrg            break;
10235c4bbdfSmrg        case V100:
10335c4bbdfSmrg            xf86ErrorF("1.000/0.400 V\n");
10435c4bbdfSmrg            break;
10535c4bbdfSmrg        case V007:
10605b261ecSmrg            xf86ErrorF("0.700/0.700 V\n");
10735c4bbdfSmrg            break;
10835c4bbdfSmrg        default:
10935c4bbdfSmrg            xf86ErrorF("undefined\n");
11035c4bbdfSmrg        }
11135c4bbdfSmrg        if (SIG_SETUP(c->input_setup))
11235c4bbdfSmrg            xf86DrvMsg(scrnIndex, X_INFO, "Signal levels configurable\n");
11335c4bbdfSmrg        xf86DrvMsg(scrnIndex, X_INFO, "Sync:");
11435c4bbdfSmrg        if (SEP_SYNC(c->input_sync))
11535c4bbdfSmrg            xf86ErrorF("  Separate");
11635c4bbdfSmrg        if (COMP_SYNC(c->input_sync))
11735c4bbdfSmrg            xf86ErrorF("  Composite");
11835c4bbdfSmrg        if (SYNC_O_GREEN(c->input_sync))
11935c4bbdfSmrg            xf86ErrorF("  SyncOnGreen");
12035c4bbdfSmrg        if (SYNC_SERR(c->input_sync))
12135c4bbdfSmrg            xf86ErrorF("Serration on. "
12235c4bbdfSmrg                       "V.Sync Pulse req. if CompSync or SyncOnGreen\n");
12335c4bbdfSmrg        else
12435c4bbdfSmrg            xf86ErrorF("\n");
12505b261ecSmrg    }
12605b261ecSmrg}
12735c4bbdfSmrg
12835c4bbdfSmrgstatic void
12905b261ecSmrgprint_dpms_features(int scrnIndex, struct disp_features *c,
13035c4bbdfSmrg                    struct edid_version *v)
13105b261ecSmrg{
13235c4bbdfSmrg    if (c->dpms) {
13335c4bbdfSmrg        xf86DrvMsg(scrnIndex, X_INFO, "DPMS capabilities:");
13435c4bbdfSmrg        if (DPMS_STANDBY(c->dpms))
13535c4bbdfSmrg            xf86ErrorF(" StandBy");
13635c4bbdfSmrg        if (DPMS_SUSPEND(c->dpms))
13735c4bbdfSmrg            xf86ErrorF(" Suspend");
13835c4bbdfSmrg        if (DPMS_OFF(c->dpms))
13935c4bbdfSmrg            xf86ErrorF(" Off");
14035c4bbdfSmrg    }
14135c4bbdfSmrg    else
14235c4bbdfSmrg        xf86DrvMsg(scrnIndex, X_INFO, "No DPMS capabilities specified");
14335c4bbdfSmrg    if (!c->input_type) {       /* analog */
14435c4bbdfSmrg        switch (c->display_type) {
14535c4bbdfSmrg        case DISP_MONO:
146ed6184dfSmrg            xf86ErrorF("; Monochrome/GrayScale Display\n");
14735c4bbdfSmrg            break;
14835c4bbdfSmrg        case DISP_RGB:
14935c4bbdfSmrg            xf86ErrorF("; RGB/Color Display\n");
15035c4bbdfSmrg            break;
15135c4bbdfSmrg        case DISP_MULTCOLOR:
15235c4bbdfSmrg            xf86ErrorF("; Non RGB Multicolor Display\n");
15335c4bbdfSmrg            break;
15435c4bbdfSmrg        default:
15535c4bbdfSmrg            xf86ErrorF("\n");
15635c4bbdfSmrg            break;
15735c4bbdfSmrg        }
15835c4bbdfSmrg    }
15935c4bbdfSmrg    else {
16035c4bbdfSmrg        int enc = c->display_type;
16135c4bbdfSmrg
16235c4bbdfSmrg        xf86ErrorF("\n");
16335c4bbdfSmrg        xf86DrvMsg(scrnIndex, X_INFO, "Supported color encodings: "
16435c4bbdfSmrg                   "RGB 4:4:4 %s%s\n",
16535c4bbdfSmrg                   enc & DISP_YCRCB444 ? "YCrCb 4:4:4 " : "",
16635c4bbdfSmrg                   enc & DISP_YCRCB422 ? "YCrCb 4:2:2" : "");
16705b261ecSmrg    }
1684642e01fSmrg
16905b261ecSmrg    if (STD_COLOR_SPACE(c->msc))
17035c4bbdfSmrg        xf86DrvMsg(scrnIndex, X_INFO,
17135c4bbdfSmrg                   "Default color space is primary color space\n");
1724642e01fSmrg
1734642e01fSmrg    if (PREFERRED_TIMING_MODE(c->msc) || v->revision >= 4) {
17435c4bbdfSmrg        xf86DrvMsg(scrnIndex, X_INFO,
17535c4bbdfSmrg                   "First detailed timing is preferred mode\n");
17635c4bbdfSmrg        if (v->revision >= 4)
17735c4bbdfSmrg            xf86DrvMsg(scrnIndex, X_INFO,
17835c4bbdfSmrg                       "Preferred mode is native pixel format and refresh rate\n");
17935c4bbdfSmrg    }
18035c4bbdfSmrg    else if (v->revision == 3) {
18135c4bbdfSmrg        xf86DrvMsg(scrnIndex, X_INFO,
18235c4bbdfSmrg                   "First detailed timing not preferred "
18335c4bbdfSmrg                   "mode in violation of standard!\n");
1844642e01fSmrg    }
1854642e01fSmrg
1864642e01fSmrg    if (v->revision >= 4) {
18735c4bbdfSmrg        if (GFT_SUPPORTED(c->msc)) {
18835c4bbdfSmrg            xf86DrvMsg(scrnIndex, X_INFO, "Display is continuous-frequency\n");
18935c4bbdfSmrg        }
19035c4bbdfSmrg    }
19135c4bbdfSmrg    else {
19235c4bbdfSmrg        if (GFT_SUPPORTED(c->msc))
19335c4bbdfSmrg            xf86DrvMsg(scrnIndex, X_INFO, "GTF timings supported\n");
1944642e01fSmrg    }
19505b261ecSmrg}
19635c4bbdfSmrg
19735c4bbdfSmrgstatic void
19805b261ecSmrgprint_whitepoint(int scrnIndex, struct disp_features *disp)
19905b261ecSmrg{
20035c4bbdfSmrg    xf86DrvMsg(scrnIndex, X_INFO, "redX: %.3f redY: %.3f   ",
20135c4bbdfSmrg               disp->redx, disp->redy);
20235c4bbdfSmrg    xf86ErrorF("greenX: %.3f greenY: %.3f\n", disp->greenx, disp->greeny);
20335c4bbdfSmrg    xf86DrvMsg(scrnIndex, X_INFO, "blueX: %.3f blueY: %.3f   ",
20435c4bbdfSmrg               disp->bluex, disp->bluey);
20535c4bbdfSmrg    xf86ErrorF("whiteX: %.3f whiteY: %.3f\n", disp->whitex, disp->whitey);
20605b261ecSmrg}
2074642e01fSmrg
2084642e01fSmrgstatic void
20935c4bbdfSmrgprint_display(int scrnIndex, struct disp_features *disp, struct edid_version *v)
2104642e01fSmrg{
2114642e01fSmrg    print_input_features(scrnIndex, disp, v);
2124642e01fSmrg    if (disp->hsize && disp->vsize) {
21335c4bbdfSmrg        xf86DrvMsg(scrnIndex, X_INFO, "Max Image Size [cm]: ");
21435c4bbdfSmrg        xf86ErrorF("horiz.: %i  ", disp->hsize);
21535c4bbdfSmrg        xf86ErrorF("vert.: %i\n", disp->vsize);
21635c4bbdfSmrg    }
21735c4bbdfSmrg    else if (v->revision >= 4 && (disp->hsize || disp->vsize)) {
21835c4bbdfSmrg        if (disp->hsize)
21935c4bbdfSmrg            xf86DrvMsg(scrnIndex, X_INFO, "Aspect ratio: %.2f (landscape)\n",
22035c4bbdfSmrg                       (disp->hsize + 99) / 100.0);
22135c4bbdfSmrg        if (disp->vsize)
22235c4bbdfSmrg            xf86DrvMsg(scrnIndex, X_INFO, "Aspect ratio: %.2f (portrait)\n",
22335c4bbdfSmrg                       100.0 / (float) (disp->vsize + 99));
22435c4bbdfSmrg
22535c4bbdfSmrg    }
22635c4bbdfSmrg    else {
22735c4bbdfSmrg        xf86DrvMsg(scrnIndex, X_INFO, "Indeterminate output size\n");
2284642e01fSmrg    }
2294642e01fSmrg
2304642e01fSmrg    if (!disp->gamma && v->revision >= 1.4)
23135c4bbdfSmrg        xf86DrvMsg(scrnIndex, X_INFO, "Gamma defined in extension block\n");
2324642e01fSmrg    else
23335c4bbdfSmrg        xf86DrvMsg(scrnIndex, X_INFO, "Gamma: %.2f\n", disp->gamma);
2344642e01fSmrg
2354642e01fSmrg    print_dpms_features(scrnIndex, disp, v);
2364642e01fSmrg    print_whitepoint(scrnIndex, disp);
2374642e01fSmrg}
2384642e01fSmrg
23935c4bbdfSmrgstatic void
24005b261ecSmrgprint_established_timings(int scrnIndex, struct established_timings *t)
24105b261ecSmrg{
24205b261ecSmrg    unsigned char c;
24305b261ecSmrg
24405b261ecSmrg    if (t->t1 || t->t2 || t->t_manu)
24535c4bbdfSmrg        xf86DrvMsg(scrnIndex, X_INFO, "Supported established timings:\n");
24635c4bbdfSmrg    c = t->t1;
24735c4bbdfSmrg    if (c & 0x80)
24835c4bbdfSmrg        xf86DrvMsg(scrnIndex, X_INFO, "720x400@70Hz\n");
24935c4bbdfSmrg    if (c & 0x40)
25035c4bbdfSmrg        xf86DrvMsg(scrnIndex, X_INFO, "720x400@88Hz\n");
25135c4bbdfSmrg    if (c & 0x20)
25235c4bbdfSmrg        xf86DrvMsg(scrnIndex, X_INFO, "640x480@60Hz\n");
25335c4bbdfSmrg    if (c & 0x10)
25435c4bbdfSmrg        xf86DrvMsg(scrnIndex, X_INFO, "640x480@67Hz\n");
25535c4bbdfSmrg    if (c & 0x08)
25635c4bbdfSmrg        xf86DrvMsg(scrnIndex, X_INFO, "640x480@72Hz\n");
25735c4bbdfSmrg    if (c & 0x04)
25835c4bbdfSmrg        xf86DrvMsg(scrnIndex, X_INFO, "640x480@75Hz\n");
25935c4bbdfSmrg    if (c & 0x02)
26035c4bbdfSmrg        xf86DrvMsg(scrnIndex, X_INFO, "800x600@56Hz\n");
26135c4bbdfSmrg    if (c & 0x01)
26235c4bbdfSmrg        xf86DrvMsg(scrnIndex, X_INFO, "800x600@60Hz\n");
26335c4bbdfSmrg    c = t->t2;
26435c4bbdfSmrg    if (c & 0x80)
26535c4bbdfSmrg        xf86DrvMsg(scrnIndex, X_INFO, "800x600@72Hz\n");
26635c4bbdfSmrg    if (c & 0x40)
26735c4bbdfSmrg        xf86DrvMsg(scrnIndex, X_INFO, "800x600@75Hz\n");
26835c4bbdfSmrg    if (c & 0x20)
26935c4bbdfSmrg        xf86DrvMsg(scrnIndex, X_INFO, "832x624@75Hz\n");
27035c4bbdfSmrg    if (c & 0x10)
27135c4bbdfSmrg        xf86DrvMsg(scrnIndex, X_INFO, "1024x768@87Hz (interlaced)\n");
27235c4bbdfSmrg    if (c & 0x08)
27335c4bbdfSmrg        xf86DrvMsg(scrnIndex, X_INFO, "1024x768@60Hz\n");
27435c4bbdfSmrg    if (c & 0x04)
27535c4bbdfSmrg        xf86DrvMsg(scrnIndex, X_INFO, "1024x768@70Hz\n");
27635c4bbdfSmrg    if (c & 0x02)
27735c4bbdfSmrg        xf86DrvMsg(scrnIndex, X_INFO, "1024x768@75Hz\n");
27835c4bbdfSmrg    if (c & 0x01)
27935c4bbdfSmrg        xf86DrvMsg(scrnIndex, X_INFO, "1280x1024@75Hz\n");
28035c4bbdfSmrg    c = t->t_manu;
28135c4bbdfSmrg    if (c & 0x80)
28235c4bbdfSmrg        xf86DrvMsg(scrnIndex, X_INFO, "1152x864@75Hz\n");
28335c4bbdfSmrg    xf86DrvMsg(scrnIndex, X_INFO, "Manufacturer's mask: %X\n", c & 0x7F);
28405b261ecSmrg}
28535c4bbdfSmrg
28605b261ecSmrgstatic void
28705b261ecSmrgprint_std_timings(int scrnIndex, struct std_timings *t)
28805b261ecSmrg{
28905b261ecSmrg    int i;
29005b261ecSmrg    char done = 0;
29135c4bbdfSmrg
29235c4bbdfSmrg    for (i = 0; i < STD_TIMINGS; i++) {
29335c4bbdfSmrg        if (t[i].hsize > 256) { /* sanity check */
29435c4bbdfSmrg            if (!done) {
29535c4bbdfSmrg                xf86DrvMsg(scrnIndex, X_INFO, "Supported standard timings:\n");
29635c4bbdfSmrg                done = 1;
29735c4bbdfSmrg            }
29835c4bbdfSmrg            xf86DrvMsg(scrnIndex, X_INFO,
29935c4bbdfSmrg                       "#%i: hsize: %i  vsize %i  refresh: %i  vid: %i\n",
30035c4bbdfSmrg                       i, t[i].hsize, t[i].vsize, t[i].refresh, t[i].id);
30135c4bbdfSmrg        }
30205b261ecSmrg    }
30305b261ecSmrg}
3044642e01fSmrg
3054642e01fSmrgstatic void
3064642e01fSmrgprint_cvt_timings(int si, struct cvt_timings *t)
3074642e01fSmrg{
3084642e01fSmrg    int i;
3094642e01fSmrg
3104642e01fSmrg    for (i = 0; i < 4; i++) {
31135c4bbdfSmrg        if (t[i].height) {
31235c4bbdfSmrg            xf86DrvMsg(si, X_INFO, "%dx%d @ %s%s%s%s%s Hz\n",
31335c4bbdfSmrg                       t[i].width, t[i].height,
31435c4bbdfSmrg                       t[i].rates & 0x10 ? "50," : "",
31535c4bbdfSmrg                       t[i].rates & 0x08 ? "60," : "",
31635c4bbdfSmrg                       t[i].rates & 0x04 ? "75," : "",
31735c4bbdfSmrg                       t[i].rates & 0x02 ? "85," : "",
31835c4bbdfSmrg                       t[i].rates & 0x01 ? "60RB" : "");
31935c4bbdfSmrg        }
32035c4bbdfSmrg        else
32135c4bbdfSmrg            break;
3224642e01fSmrg    }
3234642e01fSmrg}
3244642e01fSmrg
3254642e01fSmrgstatic void
3264642e01fSmrgprint_detailed_timings(int scrnIndex, struct detailed_timings *t)
3274642e01fSmrg{
3284642e01fSmrg
3294642e01fSmrg    if (t->clock > 15000000) {  /* sanity check */
33035c4bbdfSmrg        xf86DrvMsg(scrnIndex, X_INFO, "Supported detailed timing:\n");
33135c4bbdfSmrg        xf86DrvMsg(scrnIndex, X_INFO, "clock: %.1f MHz   ",
33235c4bbdfSmrg                   t->clock / 1000000.0);
33335c4bbdfSmrg        xf86ErrorF("Image Size:  %i x %i mm\n", t->h_size, t->v_size);
33435c4bbdfSmrg        xf86DrvMsg(scrnIndex, X_INFO,
33535c4bbdfSmrg                   "h_active: %i  h_sync: %i  h_sync_end %i h_blank_end %i ",
33635c4bbdfSmrg                   t->h_active, t->h_sync_off + t->h_active,
33735c4bbdfSmrg                   t->h_sync_off + t->h_sync_width + t->h_active,
33835c4bbdfSmrg                   t->h_active + t->h_blanking);
33935c4bbdfSmrg        xf86ErrorF("h_border: %i\n", t->h_border);
34035c4bbdfSmrg        xf86DrvMsg(scrnIndex, X_INFO,
34135c4bbdfSmrg                   "v_active: %i  v_sync: %i  v_sync_end %i v_blanking: %i ",
34235c4bbdfSmrg                   t->v_active, t->v_sync_off + t->v_active,
34335c4bbdfSmrg                   t->v_sync_off + t->v_sync_width + t->v_active,
34435c4bbdfSmrg                   t->v_active + t->v_blanking);
34535c4bbdfSmrg        xf86ErrorF("v_border: %i\n", t->v_border);
34635c4bbdfSmrg        if (IS_STEREO(t->stereo)) {
34735c4bbdfSmrg            xf86DrvMsg(scrnIndex, X_INFO, "Stereo: ");
34835c4bbdfSmrg            if (IS_RIGHT_STEREO(t->stereo)) {
34935c4bbdfSmrg                if (!t->stereo_1)
35035c4bbdfSmrg                    xf86ErrorF("right channel on sync\n");
35135c4bbdfSmrg                else
35235c4bbdfSmrg                    xf86ErrorF("left channel on sync\n");
35335c4bbdfSmrg            }
35435c4bbdfSmrg            else if (IS_LEFT_STEREO(t->stereo)) {
35535c4bbdfSmrg                if (!t->stereo_1)
35635c4bbdfSmrg                    xf86ErrorF("right channel on even line\n");
35735c4bbdfSmrg                else
35835c4bbdfSmrg                    xf86ErrorF("left channel on evel line\n");
35935c4bbdfSmrg            }
36035c4bbdfSmrg            if (IS_4WAY_STEREO(t->stereo)) {
36135c4bbdfSmrg                if (!t->stereo_1)
36235c4bbdfSmrg                    xf86ErrorF("4-way interleaved\n");
36335c4bbdfSmrg                else
36435c4bbdfSmrg                    xf86ErrorF("side-by-side interleaved");
36535c4bbdfSmrg            }
36635c4bbdfSmrg        }
3674642e01fSmrg    }
3684642e01fSmrg}
3694642e01fSmrg
3706747b715Smrg/* This function handle all detailed patchs,
3716747b715Smrg * including EDID and EDID-extension
3726747b715Smrg */
37335c4bbdfSmrgstruct det_print_parameter {
37435c4bbdfSmrg    xf86MonPtr m;
37535c4bbdfSmrg    int index;
37635c4bbdfSmrg    ddc_quirk_t quirks;
3776747b715Smrg};
3786747b715Smrg
37905b261ecSmrgstatic void
38035c4bbdfSmrghandle_detailed_print(struct detailed_monitor_section *det_mon, void *data)
38105b261ecSmrg{
3826747b715Smrg    int j, scrnIndex;
3836747b715Smrg    struct det_print_parameter *p;
3846747b715Smrg
38535c4bbdfSmrg    p = (struct det_print_parameter *) data;
3866747b715Smrg    scrnIndex = p->m->scrnIndex;
38735c4bbdfSmrg    xf86DetTimingApplyQuirks(det_mon, p->quirks,
38835c4bbdfSmrg                             p->m->features.hsize, p->m->features.vsize);
3896747b715Smrg
3906747b715Smrg    switch (det_mon->type) {
3916747b715Smrg    case DT:
39235c4bbdfSmrg        print_detailed_timings(scrnIndex, &det_mon->section.d_timings);
3936747b715Smrg        break;
3946747b715Smrg    case DS_SERIAL:
39535c4bbdfSmrg        xf86DrvMsg(scrnIndex, X_INFO, "Serial No: %s\n",
39635c4bbdfSmrg                   det_mon->section.serial);
3976747b715Smrg        break;
3986747b715Smrg    case DS_ASCII_STR:
39935c4bbdfSmrg        xf86DrvMsg(scrnIndex, X_INFO, " %s\n", det_mon->section.ascii_data);
4006747b715Smrg        break;
4016747b715Smrg    case DS_NAME:
40235c4bbdfSmrg        xf86DrvMsg(scrnIndex, X_INFO, "Monitor name: %s\n",
40335c4bbdfSmrg                   det_mon->section.name);
4046747b715Smrg        break;
4056747b715Smrg    case DS_RANGES:
4066747b715Smrg    {
4076747b715Smrg        struct monitor_ranges *r = &det_mon->section.ranges;
40835c4bbdfSmrg
40935c4bbdfSmrg        xf86DrvMsg(scrnIndex, X_INFO,
4106747b715Smrg                   "Ranges: V min: %i V max: %i Hz, H min: %i H max: %i kHz,",
4116747b715Smrg                   r->min_v, r->max_v, r->min_h, r->max_h);
4126747b715Smrg        if (r->max_clock_khz != 0) {
4136747b715Smrg            xf86ErrorF(" PixClock max %i kHz\n", r->max_clock_khz);
41435c4bbdfSmrg            if (r->maxwidth)
41535c4bbdfSmrg                xf86DrvMsg(scrnIndex, X_INFO, "Maximum pixel width: %d\n",
41635c4bbdfSmrg                           r->maxwidth);
41735c4bbdfSmrg            xf86DrvMsg(scrnIndex, X_INFO, "Supported aspect ratios:");
41835c4bbdfSmrg            if (r->supported_aspect & SUPPORTED_ASPECT_4_3)
41935c4bbdfSmrg                xf86ErrorF(" 4:3%s",
42035c4bbdfSmrg                           r->preferred_aspect ==
42135c4bbdfSmrg                           PREFERRED_ASPECT_4_3 ? "*" : "");
42235c4bbdfSmrg            if (r->supported_aspect & SUPPORTED_ASPECT_16_9)
42335c4bbdfSmrg                xf86ErrorF(" 16:9%s",
42435c4bbdfSmrg                           r->preferred_aspect ==
42535c4bbdfSmrg                           PREFERRED_ASPECT_16_9 ? "*" : "");
42635c4bbdfSmrg            if (r->supported_aspect & SUPPORTED_ASPECT_16_10)
42735c4bbdfSmrg                xf86ErrorF(" 16:10%s",
42835c4bbdfSmrg                           r->preferred_aspect ==
42935c4bbdfSmrg                           PREFERRED_ASPECT_16_10 ? "*" : "");
43035c4bbdfSmrg            if (r->supported_aspect & SUPPORTED_ASPECT_5_4)
43135c4bbdfSmrg                xf86ErrorF(" 5:4%s",
43235c4bbdfSmrg                           r->preferred_aspect ==
43335c4bbdfSmrg                           PREFERRED_ASPECT_5_4 ? "*" : "");
43435c4bbdfSmrg            if (r->supported_aspect & SUPPORTED_ASPECT_15_9)
43535c4bbdfSmrg                xf86ErrorF(" 15:9%s",
43635c4bbdfSmrg                           r->preferred_aspect ==
43735c4bbdfSmrg                           PREFERRED_ASPECT_15_9 ? "*" : "");
43835c4bbdfSmrg            xf86ErrorF("\n");
43935c4bbdfSmrg            xf86DrvMsg(scrnIndex, X_INFO, "Supported blankings:");
44035c4bbdfSmrg            if (r->supported_blanking & CVT_STANDARD)
44135c4bbdfSmrg                xf86ErrorF(" standard");
44235c4bbdfSmrg            if (r->supported_blanking & CVT_REDUCED)
44335c4bbdfSmrg                xf86ErrorF(" reduced");
44435c4bbdfSmrg            xf86ErrorF("\n");
44535c4bbdfSmrg            xf86DrvMsg(scrnIndex, X_INFO, "Supported scalings:");
44635c4bbdfSmrg            if (r->supported_scaling & SCALING_HSHRINK)
44735c4bbdfSmrg                xf86ErrorF(" hshrink");
44835c4bbdfSmrg            if (r->supported_scaling & SCALING_HSTRETCH)
44935c4bbdfSmrg                xf86ErrorF(" hstretch");
45035c4bbdfSmrg            if (r->supported_scaling & SCALING_VSHRINK)
45135c4bbdfSmrg                xf86ErrorF(" vshrink");
45235c4bbdfSmrg            if (r->supported_scaling & SCALING_VSTRETCH)
45335c4bbdfSmrg                xf86ErrorF(" vstretch");
45435c4bbdfSmrg            xf86ErrorF("\n");
45535c4bbdfSmrg            if (r->preferred_refresh)
45635c4bbdfSmrg                xf86DrvMsg(scrnIndex, X_INFO, "Preferred refresh rate: %d\n",
45735c4bbdfSmrg                           r->preferred_refresh);
45835c4bbdfSmrg            else
45935c4bbdfSmrg                xf86DrvMsg(scrnIndex, X_INFO, "Buggy monitor, no preferred "
46035c4bbdfSmrg                           "refresh rate given\n");
46135c4bbdfSmrg        }
46235c4bbdfSmrg        else if (r->max_clock != 0) {
46335c4bbdfSmrg            xf86ErrorF(" PixClock max %i MHz\n", r->max_clock);
46435c4bbdfSmrg        }
46535c4bbdfSmrg        else {
46635c4bbdfSmrg            xf86ErrorF("\n");
4676747b715Smrg        }
4686747b715Smrg        if (r->gtf_2nd_f > 0)
46935c4bbdfSmrg            xf86DrvMsg(scrnIndex, X_INFO, " 2nd GTF parameters: f: %i kHz "
4706747b715Smrg                       "c: %i m: %i k %i j %i\n", r->gtf_2nd_f,
47135c4bbdfSmrg                       r->gtf_2nd_c, r->gtf_2nd_m, r->gtf_2nd_k, r->gtf_2nd_j);
4726747b715Smrg        break;
4736747b715Smrg    }
4746747b715Smrg    case DS_STD_TIMINGS:
47535c4bbdfSmrg        for (j = 0; j < 5; j++)
47635c4bbdfSmrg            xf86DrvMsg(scrnIndex, X_INFO,
47735c4bbdfSmrg                       "#%i: hsize: %i  vsize %i  refresh: %i  "
47835c4bbdfSmrg                       "vid: %i\n", p->index, det_mon->section.std_t[j].hsize,
47935c4bbdfSmrg                       det_mon->section.std_t[j].vsize,
48035c4bbdfSmrg                       det_mon->section.std_t[j].refresh,
48135c4bbdfSmrg                       det_mon->section.std_t[j].id);
4826747b715Smrg        break;
4836747b715Smrg    case DS_WHITE_P:
48435c4bbdfSmrg        for (j = 0; j < 2; j++)
48535c4bbdfSmrg            if (det_mon->section.wp[j].index != 0)
48635c4bbdfSmrg                xf86DrvMsg(scrnIndex, X_INFO,
48735c4bbdfSmrg                           "White point %i: whiteX: %f, whiteY: %f; gamma: %f\n",
48835c4bbdfSmrg                           det_mon->section.wp[j].index,
48935c4bbdfSmrg                           det_mon->section.wp[j].white_x,
49035c4bbdfSmrg                           det_mon->section.wp[j].white_y,
49135c4bbdfSmrg                           det_mon->section.wp[j].white_gamma);
4926747b715Smrg        break;
4936747b715Smrg    case DS_CMD:
49435c4bbdfSmrg        xf86DrvMsg(scrnIndex, X_INFO, "Color management data: (not decoded)\n");
4956747b715Smrg        break;
4966747b715Smrg    case DS_CVT:
49735c4bbdfSmrg        xf86DrvMsg(scrnIndex, X_INFO, "CVT 3-byte-code modes:\n");
4986747b715Smrg        print_cvt_timings(scrnIndex, det_mon->section.cvt);
4996747b715Smrg        break;
5006747b715Smrg    case DS_EST_III:
5016747b715Smrg        xf86DrvMsg(scrnIndex, X_INFO,
5026747b715Smrg                   "Established timings III: (not decoded)\n");
5036747b715Smrg        break;
5046747b715Smrg    case DS_DUMMY:
5056747b715Smrg    default:
5066747b715Smrg        break;
5076747b715Smrg    }
5086747b715Smrg    if (det_mon->type >= DS_VENDOR && det_mon->type <= DS_VENDOR_MAX) {
5096747b715Smrg        xf86DrvMsg(scrnIndex, X_INFO,
510dc61d50dSmrg                   "Unknown vendor-specific block %x\n",
5116747b715Smrg                   det_mon->type - DS_VENDOR);
51205b261ecSmrg    }
5136747b715Smrg
5146747b715Smrg    p->index = p->index + 1;
51505b261ecSmrg}
5166747b715Smrg
51705b261ecSmrgstatic void
51805b261ecSmrgprint_number_sections(int scrnIndex, int num)
51905b261ecSmrg{
52005b261ecSmrg    if (num)
52135c4bbdfSmrg        xf86DrvMsg(scrnIndex, X_INFO, "Number of EDID sections to follow: %i\n",
52235c4bbdfSmrg                   num);
52305b261ecSmrg}
52405b261ecSmrg
5254642e01fSmrgxf86MonPtr
5264642e01fSmrgxf86PrintEDID(xf86MonPtr m)
5274642e01fSmrg{
5284642e01fSmrg    CARD16 i, j, n;
5294642e01fSmrg    char buf[EDID_WIDTH * 2 + 1];
5306747b715Smrg    struct det_print_parameter p;
5314642e01fSmrg
53235c4bbdfSmrg    if (!m)
53335c4bbdfSmrg        return NULL;
5344642e01fSmrg
5354642e01fSmrg    print_vendor(m->scrnIndex, &m->vendor);
5364642e01fSmrg    print_version(m->scrnIndex, &m->ver);
5374642e01fSmrg    print_display(m->scrnIndex, &m->features, &m->ver);
5384642e01fSmrg    print_established_timings(m->scrnIndex, &m->timings1);
5394642e01fSmrg    print_std_timings(m->scrnIndex, m->timings2);
5406747b715Smrg    p.m = m;
5416747b715Smrg    p.index = 0;
5426747b715Smrg    p.quirks = xf86DDCDetectQuirks(m->scrnIndex, m, FALSE);
54335c4bbdfSmrg    xf86ForEachDetailedBlock(m, handle_detailed_print, &p);
5444642e01fSmrg    print_number_sections(m->scrnIndex, m->no_sections);
5454642e01fSmrg
5464642e01fSmrg    /* extension block section stuff */
5474642e01fSmrg
5484642e01fSmrg    xf86DrvMsg(m->scrnIndex, X_INFO, "EDID (in hex):\n");
5494642e01fSmrg
5504642e01fSmrg    n = 128;
5514642e01fSmrg    if (m->flags & EDID_COMPLETE_RAWDATA)
55235c4bbdfSmrg        n += m->no_sections * 128;
5534642e01fSmrg
5544642e01fSmrg    for (i = 0; i < n; i += j) {
55535c4bbdfSmrg        for (j = 0; j < EDID_WIDTH; ++j) {
55635c4bbdfSmrg            sprintf(&buf[j * 2], "%02x", m->rawData[i + j]);
55735c4bbdfSmrg        }
55835c4bbdfSmrg        xf86DrvMsg(m->scrnIndex, X_INFO, "\t%s\n", buf);
5594642e01fSmrg    }
5606747b715Smrg
5614642e01fSmrg    return m;
5624642e01fSmrg}
563