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