3 * Copyright 1998,1999 by Egbert Eich <Egbert.Eich@Physik.TU-Darmstadt.DE>
5 #ifdef HAVE_XORG_CONFIG_H
6 #include <xorg-config.h>
11 #include "xf86_OSproc.h"
16 static const OptionInfoRec
*DDCAvailableOptions(void *unused
);
20 static unsigned char *EDIDRead_DDC1(
23 unsigned int (*)(ScrnInfoPtr
)
28 unsigned int (*)(ScrnInfoPtr
)
31 static unsigned int *FetchEDID_DDC1(
33 register unsigned int (*)(ScrnInfoPtr
)
36 static unsigned char* EDID1Read_DDC2(
41 static unsigned char * DDCRead_DDC2(
54 static const OptionInfoRec DDCOptions
[] = {
55 { DDCOPT_NODDC1
, "NoDDC1", OPTV_BOOLEAN
, {0}, FALSE
},
56 { DDCOPT_NODDC2
, "NoDDC2", OPTV_BOOLEAN
, {0}, FALSE
},
57 { DDCOPT_NODDC
, "NoDDC", OPTV_BOOLEAN
, {0}, FALSE
},
58 { -1, NULL
, OPTV_NONE
, {0}, FALSE
},
62 static const OptionInfoRec
*
63 DDCAvailableOptions(void *unused
)
69 * Attempts to probe the monitor for EDID information, if NoDDC and NoDDC1 are
70 * unset. EDID information blocks are interpreted and the results returned in
73 * This function does not affect the list of modes used by drivers -- it is up
74 * to the driver to decide policy on what to do with EDID information.
76 * @return pointer to a new xf86MonPtr containing the EDID information.
77 * @return NULL if no monitor attached or failure to interpret the EDID.
81 int scrnIndex
, DDC1SetSpeedProc DDC1SetSpeed
,
82 unsigned int (*DDC1Read
)(ScrnInfoPtr
)
85 ScrnInfoPtr pScrn
= xf86Screens
[scrnIndex
];
86 unsigned char *EDID_block
= NULL
;
87 xf86MonPtr tmp
= NULL
;
89 /* Default DDC and DDC1 to enabled. */
90 Bool noddc
= FALSE
, noddc1
= FALSE
;
91 OptionInfoPtr options
;
93 options
= xnfalloc(sizeof(DDCOptions
));
94 (void)memcpy(options
, DDCOptions
, sizeof(DDCOptions
));
95 xf86ProcessOptions(pScrn
->scrnIndex
, pScrn
->options
, options
);
97 xf86GetOptValBool(options
, DDCOPT_NODDC
, &noddc
);
98 xf86GetOptValBool(options
, DDCOPT_NODDC1
, &noddc1
);
104 sigio
= xf86BlockSIGIO();
105 EDID_block
= EDIDRead_DDC1(pScrn
,DDC1SetSpeed
,DDC1Read
);
106 xf86UnblockSIGIO(sigio
);
109 tmp
= xf86InterpretEDID(scrnIndex
,EDID_block
);
112 else ErrorF("No EDID block returned\n");
114 ErrorF("Cannot interpret EDID block\n");
120 * Attempts to probe the monitor for EDID information, if NoDDC and NoDDC2 are
121 * unset. EDID information blocks are interpreted and the results returned in
124 * This function does not affect the list of modes used by drivers -- it is up
125 * to the driver to decide policy on what to do with EDID information.
127 * @return pointer to a new xf86MonPtr containing the EDID information.
128 * @return NULL if no monitor attached or failure to interpret the EDID.
131 xf86DoEDID_DDC2(int scrnIndex
, I2CBusPtr pBus
)
133 ScrnInfoPtr pScrn
= xf86Screens
[scrnIndex
];
134 unsigned char *EDID_block
= NULL
;
135 xf86MonPtr tmp
= NULL
;
136 /* Default DDC and DDC2 to enabled. */
137 Bool noddc
= FALSE
, noddc2
= FALSE
;
138 OptionInfoPtr options
;
140 options
= xnfalloc(sizeof(DDCOptions
));
141 (void)memcpy(options
, DDCOptions
, sizeof(DDCOptions
));
142 xf86ProcessOptions(pScrn
->scrnIndex
, pScrn
->options
, options
);
144 xf86GetOptValBool(options
, DDCOPT_NODDC
, &noddc
);
145 xf86GetOptValBool(options
, DDCOPT_NODDC2
, &noddc2
);
151 EDID_block
= EDID1Read_DDC2(scrnIndex
,pBus
);
154 tmp
= xf86InterpretEDID(scrnIndex
,EDID_block
);
157 ErrorF("No EDID block returned\n");
163 ErrorF("Cannot interpret EDID block\n");
165 ErrorF("Sections to follow: %i\n",tmp
->no_sections
);
172 * read EDID record , pass it to callback function to interpret.
173 * callback function will store it for further use by calling
174 * function; it will also decide if we need to reread it
176 static unsigned char *
177 EDIDRead_DDC1(ScrnInfoPtr pScrn
, DDC1SetSpeedProc DDCSpeed
,
178 unsigned int (*read_DDC
)(ScrnInfoPtr
))
180 unsigned char *EDID_block
= NULL
;
184 xf86DrvMsg(pScrn
->scrnIndex
, X_PROBED
,
185 "chipset doesn't support DDC1\n");
189 if (TestDDC1(pScrn
,read_DDC
)==-1) {
190 xf86DrvMsg(pScrn
->scrnIndex
, X_PROBED
, "No DDC signal\n");
194 if (DDCSpeed
) DDCSpeed(pScrn
,DDC_FAST
);
196 EDID_block
= GetEDID_DDC1(FetchEDID_DDC1(pScrn
,read_DDC
));
198 } while (!EDID_block
&& count
);
199 if (DDCSpeed
) DDCSpeed(pScrn
,DDC_SLOW
);
204 /* test if DDC1 return 0 if not */
206 TestDDC1(ScrnInfoPtr pScrn
, unsigned int (*read_DDC
)(ScrnInfoPtr
))
210 old
= read_DDC(pScrn
);
211 count
= HEADER
* BITS_PER_BYTE
;
213 /* wait for next retrace */
214 if (old
!= read_DDC(pScrn
)) break;
219 /* fetch entire EDID record; DDC bit needs to be masked */
220 static unsigned int *
221 FetchEDID_DDC1(register ScrnInfoPtr pScrn
,
222 register unsigned int (*read_DDC
)(ScrnInfoPtr
))
225 unsigned int *ptr
, *xp
;
227 ptr
=xp
=xalloc(sizeof(int)*NUM
);
229 if (!ptr
) return NULL
;
231 /* wait for next retrace */
232 *xp
= read_DDC(pScrn
);
238 static unsigned char*
239 EDID1Read_DDC2(int scrnIndex
, I2CBusPtr pBus
)
241 return DDCRead_DDC2(scrnIndex
, pBus
, 0, EDID1_LEN
);
244 static unsigned char *
245 DDCRead_DDC2(int scrnIndex
, I2CBusPtr pBus
, int start
, int len
)
248 unsigned char W_Buffer
[2];
250 unsigned char *R_Buffer
;
254 * Slow down the bus so that older monitors don't
257 pBus
->RiseFallTime
= 20;
259 if (!(dev
= xf86I2CFindDev(pBus
, 0x00A0))) {
260 dev
= xf86CreateI2CDevRec();
261 dev
->DevName
= "ddc2";
262 dev
->SlaveAddr
= 0xA0;
263 dev
->ByteTimeout
= 2200; /* VESA DDC spec 3 p. 43 (+10 %) */
264 dev
->StartTimeout
= 550;
265 dev
->BitTimeout
= 40;
266 dev
->AcknTimeout
= 40;
269 if (!xf86I2CDevInit(dev
)) {
270 xf86DrvMsg(scrnIndex
, X_PROBED
, "No DDC2 device\n");
279 W_Buffer
[0] = start
& 0xFF;
280 W_Buffer
[1] = (start
& 0xFF00) >> 8;
282 R_Buffer
= xcalloc(1,sizeof(unsigned char)
284 for (i
=0; i
<RETRIES
; i
++) {
285 if (xf86I2CWriteRead(dev
, W_Buffer
,w_bytes
, R_Buffer
,len
)) {
286 if (!DDC_checksum(R_Buffer
,len
))
290 else ErrorF("Checksum error in EDID block\n");
294 else ErrorF("Error reading EDID block\n");
298 xf86DestroyI2CDevRec(dev
,TRUE
);