ddc.c revision 6747b715
1/* xf86DDC.c
2 *
3 * Copyright 1998,1999 by Egbert Eich <Egbert.Eich@Physik.TU-Darmstadt.DE>
4 */
5
6/*
7 * A note on terminology.  DDC1 is the original dumb serial protocol, and
8 * can only do up to 128 bytes of EDID.  DDC2 is I2C-encapsulated and
9 * introduces extension blocks.  EDID is the old display identification
10 * block, DisplayID is the new one.
11 */
12
13#ifdef HAVE_XORG_CONFIG_H
14#include <xorg-config.h>
15#endif
16
17#include "misc.h"
18#include "xf86.h"
19#include "xf86_OSproc.h"
20#include "xf86DDC.h"
21#include <string.h>
22
23#define RETRIES 4
24
25typedef enum {
26    DDCOPT_NODDC1,
27    DDCOPT_NODDC2,
28    DDCOPT_NODDC
29} DDCOpts;
30
31static const OptionInfoRec DDCOptions[] = {
32    { DDCOPT_NODDC1,	"NoDDC1",	OPTV_BOOLEAN,	{0},	FALSE },
33    { DDCOPT_NODDC2,	"NoDDC2",	OPTV_BOOLEAN,	{0},	FALSE },
34    { DDCOPT_NODDC,	"NoDDC",	OPTV_BOOLEAN,	{0},	FALSE },
35    { -1,		NULL,		OPTV_NONE,	{0},	FALSE },
36};
37
38/* DDC1 */
39
40static int
41find_start(unsigned int *ptr)
42{
43    unsigned int comp[9], test[9];
44    int i,j;
45
46    for (i=0;i<9;i++){
47	comp[i] = *(ptr++);
48	test[i] = 1;
49    }
50    for (i=0;i<127;i++){
51	for (j=0;j<9;j++){
52	    test[j] = test[j] & !(comp[j] ^ *(ptr++));
53	}
54    }
55    for (i=0;i<9;i++)
56	if (test[i]) return i+1;
57    return -1;
58}
59
60static unsigned char *
61find_header(unsigned char *block)
62{
63    unsigned char *ptr, *head_ptr, *end;
64    unsigned char header[]={0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00};
65
66    ptr = block;
67    end = block + EDID1_LEN;
68    while (ptr<end) {
69	int i;
70	head_ptr = ptr;
71	for (i=0;i<8;i++){
72	    if (header[i] != *(head_ptr++)) break;
73	    if (head_ptr == end) head_ptr = block;
74	}
75	if (i==8) break;
76	ptr++;
77    }
78    if (ptr == end) return NULL;
79    return ptr;
80}
81
82static unsigned char *
83resort(unsigned char *s_block)
84{
85    unsigned char *d_new, *d_ptr, *d_end, *s_ptr, *s_end;
86    unsigned char tmp;
87
88    s_end = s_block + EDID1_LEN;
89    d_new = malloc(EDID1_LEN);
90    if (!d_new) return NULL;
91    d_end = d_new + EDID1_LEN;
92
93    s_ptr = find_header(s_block);
94    if (!s_ptr) return NULL;
95    for (d_ptr=d_new;d_ptr<d_end;d_ptr++){
96	tmp = *(s_ptr++);
97	*d_ptr = tmp;
98	if (s_ptr == s_end) s_ptr = s_block;
99    }
100    free(s_block);
101    return d_new;
102}
103
104static int
105DDC_checksum(const unsigned char *block, int len)
106{
107    int i, result = 0;
108    int not_null = 0;
109
110    for (i=0;i<len;i++) {
111	not_null |= block[i];
112	result += block[i];
113    }
114
115#ifdef DEBUG
116    if (result & 0xFF) ErrorF("DDC checksum not correct\n");
117    if (!not_null) ErrorF("DDC read all Null\n");
118#endif
119
120    /* catch the trivial case where all bytes are 0 */
121    if (!not_null) return 1;
122
123    return result&0xFF;
124}
125
126static unsigned char *
127GetEDID_DDC1(unsigned int *s_ptr)
128{
129    unsigned char *d_block, *d_pos;
130    unsigned int *s_pos, *s_end;
131    int s_start;
132    int i,j;
133    s_start = find_start(s_ptr);
134    if (s_start==-1) return NULL;
135    s_end = s_ptr + NUM;
136    s_pos = s_ptr + s_start;
137    d_block=malloc(EDID1_LEN);
138    if (!d_block) return NULL;
139    d_pos = d_block;
140    for (i=0;i<EDID1_LEN;i++) {
141	for (j=0;j<8;j++) {
142	    *d_pos <<= 1;
143	    if (*s_pos) {
144		*d_pos |= 0x01;
145	    }
146	    s_pos++; if (s_pos == s_end) s_pos=s_ptr;
147	};
148	s_pos++; if (s_pos == s_end) s_pos=s_ptr;
149	d_pos++;
150    }
151    free(s_ptr);
152    if (d_block && DDC_checksum(d_block,EDID1_LEN)) {
153	free(d_block);
154	return NULL;
155    }
156    return (resort(d_block));
157}
158
159/* fetch entire EDID record; DDC bit needs to be masked */
160static unsigned int *
161FetchEDID_DDC1(register ScrnInfoPtr pScrn,
162	       register unsigned int (*read_DDC)(ScrnInfoPtr))
163{
164    int count = NUM;
165    unsigned int *ptr, *xp;
166
167    ptr=xp=malloc(sizeof(int)*NUM);
168
169    if (!ptr)  return NULL;
170    do {
171	/* wait for next retrace */
172	*xp = read_DDC(pScrn);
173	xp++;
174    } while(--count);
175    return ptr;
176}
177
178/* test if DDC1  return 0 if not */
179static Bool
180TestDDC1(ScrnInfoPtr pScrn, unsigned int (*read_DDC)(ScrnInfoPtr))
181{
182    int old, count;
183
184    old = read_DDC(pScrn);
185    count = HEADER * BITS_PER_BYTE;
186    do {
187	/* wait for next retrace */
188	if (old != read_DDC(pScrn)) break;
189    } while(count--);
190    return count;
191}
192
193/*
194 * read EDID record , pass it to callback function to interpret.
195 * callback function will store it for further use by calling
196 * function; it will also decide if we need to reread it
197 */
198static unsigned char *
199EDIDRead_DDC1(ScrnInfoPtr pScrn, DDC1SetSpeedProc DDCSpeed,
200              unsigned int (*read_DDC)(ScrnInfoPtr))
201{
202    unsigned char *EDID_block = NULL;
203    int count = RETRIES;
204
205    if (!read_DDC) {
206	xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
207		   "chipset doesn't support DDC1\n");
208	return NULL;
209    };
210
211    if (TestDDC1(pScrn,read_DDC)==-1) {
212	xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "No DDC signal\n");
213	return NULL;
214    };
215
216    if (DDCSpeed) DDCSpeed(pScrn,DDC_FAST);
217    do {
218	EDID_block = GetEDID_DDC1(FetchEDID_DDC1(pScrn,read_DDC));
219	count --;
220    } while (!EDID_block && count);
221    if (DDCSpeed) DDCSpeed(pScrn,DDC_SLOW);
222
223    return EDID_block;
224}
225
226/**
227 * Attempts to probe the monitor for EDID information, if NoDDC and NoDDC1 are
228 * unset.  EDID information blocks are interpreted and the results returned in
229 * an xf86MonPtr.
230 *
231 * This function does not affect the list of modes used by drivers -- it is up
232 * to the driver to decide policy on what to do with EDID information.
233 *
234 * @return pointer to a new xf86MonPtr containing the EDID information.
235 * @return NULL if no monitor attached or failure to interpret the EDID.
236 */
237xf86MonPtr
238xf86DoEDID_DDC1(
239    int scrnIndex, DDC1SetSpeedProc DDC1SetSpeed,
240    unsigned int (*DDC1Read)(ScrnInfoPtr)
241)
242{
243    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
244    unsigned char *EDID_block = NULL;
245    xf86MonPtr tmp = NULL;
246    int sigio;
247    /* Default DDC and DDC1 to enabled. */
248    Bool noddc = FALSE, noddc1 = FALSE;
249    OptionInfoPtr options;
250
251    options = xnfalloc(sizeof(DDCOptions));
252    (void)memcpy(options, DDCOptions, sizeof(DDCOptions));
253    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options);
254
255    xf86GetOptValBool(options, DDCOPT_NODDC, &noddc);
256    xf86GetOptValBool(options, DDCOPT_NODDC1, &noddc1);
257    free(options);
258
259    if (noddc || noddc1)
260	return NULL;
261
262    sigio = xf86BlockSIGIO();
263    EDID_block = EDIDRead_DDC1(pScrn,DDC1SetSpeed,DDC1Read);
264    xf86UnblockSIGIO(sigio);
265
266    if (EDID_block){
267	tmp = xf86InterpretEDID(scrnIndex,EDID_block);
268    }
269#ifdef DEBUG
270	else ErrorF("No EDID block returned\n");
271    if (!tmp)
272	ErrorF("Cannot interpret EDID block\n");
273#endif
274	return tmp;
275}
276
277/* DDC2 */
278
279static I2CDevPtr
280DDC2MakeDevice(I2CBusPtr pBus, int address, char *name)
281{
282    I2CDevPtr dev = NULL;
283
284    if (!(dev = xf86I2CFindDev(pBus, address))) {
285	dev = xf86CreateI2CDevRec();
286	dev->DevName = name;
287	dev->SlaveAddr = address;
288	dev->ByteTimeout = 2200; /* VESA DDC spec 3 p. 43 (+10 %) */
289	dev->StartTimeout = 550;
290	dev->BitTimeout = 40;
291	dev->AcknTimeout = 40;
292
293	dev->pI2CBus = pBus;
294	if (!xf86I2CDevInit(dev)) {
295	    xf86DrvMsg(pBus->scrnIndex, X_PROBED, "No DDC2 device\n");
296	    return NULL;
297	}
298    }
299
300    return dev;
301}
302
303static I2CDevPtr
304DDC2Init(int scrnIndex, I2CBusPtr pBus)
305{
306    I2CDevPtr dev = NULL;
307
308    /*
309     * Slow down the bus so that older monitors don't
310     * miss things.
311     */
312    pBus->RiseFallTime = 20;
313
314    dev = DDC2MakeDevice(pBus, 0x00A0, "ddc2");
315    if (xf86I2CProbeAddress(pBus, 0x0060))
316	DDC2MakeDevice(pBus, 0x0060, "E-EDID segment register");
317    if (xf86I2CProbeAddress(pBus, 0x0062))
318	DDC2MakeDevice(pBus, 0x0062, "EDID EEPROM interface");
319    if (xf86I2CProbeAddress(pBus, 0x006E))
320	DDC2MakeDevice(pBus, 0x006E, "DDC control interface");
321
322    return dev;
323}
324
325/* Mmmm, smell the hacks */
326static void
327EEDIDStop(I2CDevPtr d)
328{
329}
330
331/* block is the EDID block number.  a segment is two blocks. */
332static Bool
333DDC2Read(I2CDevPtr dev, int block, unsigned char *R_Buffer)
334{
335    unsigned char W_Buffer[1];
336    int i, segment;
337    I2CDevPtr seg;
338    void (*stop)(I2CDevPtr);
339
340    for (i = 0; i < RETRIES; i++) {
341	/* Stop bits reset the segment pointer to 0, so be careful here. */
342	segment = block >> 1;
343	if (segment) {
344	    Bool b;
345
346	    if (!(seg = xf86I2CFindDev(dev->pI2CBus, 0x0060)))
347		return FALSE;
348
349	    W_Buffer[0] = segment;
350
351	    stop = dev->pI2CBus->I2CStop;
352	    dev->pI2CBus->I2CStop = EEDIDStop;
353
354	    b = xf86I2CWriteRead(seg, W_Buffer, 1, NULL, 0);
355
356	    dev->pI2CBus->I2CStop = stop;
357	    if (!b) {
358		dev->pI2CBus->I2CStop(dev);
359		continue;
360	    }
361	}
362
363	W_Buffer[0] = (block & 0x01) * EDID1_LEN;
364
365	if (xf86I2CWriteRead(dev, W_Buffer, 1, R_Buffer, EDID1_LEN)) {
366	    if (!DDC_checksum(R_Buffer, EDID1_LEN))
367		return TRUE;
368	}
369    }
370
371    return FALSE;
372}
373
374/**
375 * Attempts to probe the monitor for EDID information, if NoDDC and NoDDC2 are
376 * unset.  EDID information blocks are interpreted and the results returned in
377 * an xf86MonPtr.  Unlike xf86DoEDID_DDC[12](), this function will return
378 * the complete EDID data, including all extension blocks, if the 'complete'
379 * parameter is TRUE;
380 *
381 * This function does not affect the list of modes used by drivers -- it is up
382 * to the driver to decide policy on what to do with EDID information.
383 *
384 * @return pointer to a new xf86MonPtr containing the EDID information.
385 * @return NULL if no monitor attached or failure to interpret the EDID.
386 */
387xf86MonPtr
388xf86DoEEDID(int scrnIndex, I2CBusPtr pBus, Bool complete)
389{
390    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
391    unsigned char *EDID_block = NULL;
392    xf86MonPtr tmp = NULL;
393    I2CDevPtr dev = NULL;
394    /* Default DDC and DDC2 to enabled. */
395    Bool noddc = FALSE, noddc2 = FALSE;
396    OptionInfoPtr options;
397
398    options = malloc(sizeof(DDCOptions));
399    if (!options)
400	return NULL;
401    memcpy(options, DDCOptions, sizeof(DDCOptions));
402    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options);
403
404    xf86GetOptValBool(options, DDCOPT_NODDC, &noddc);
405    xf86GetOptValBool(options, DDCOPT_NODDC2, &noddc2);
406    free(options);
407
408    if (noddc || noddc2)
409	return NULL;
410
411    if (!(dev = DDC2Init(scrnIndex, pBus)))
412	return NULL;
413
414    EDID_block = calloc(1, EDID1_LEN);
415    if (!EDID_block)
416	return NULL;
417
418    if (DDC2Read(dev, 0, EDID_block)) {
419	int i, n = EDID_block[0x7e];
420
421	if (complete && n) {
422	    EDID_block = realloc(EDID_block, EDID1_LEN * (1+n));
423
424	    for (i = 0; i < n; i++)
425		DDC2Read(dev, i+1, EDID_block + (EDID1_LEN * (1+i)));
426	}
427
428	tmp = xf86InterpretEEDID(scrnIndex, EDID_block);
429    }
430
431    if (tmp && complete)
432	tmp->flags |= MONITOR_EDID_COMPLETE_RAWDATA;
433
434    return tmp;
435}
436
437/**
438 * Attempts to probe the monitor for EDID information, if NoDDC and NoDDC2 are
439 * unset.  EDID information blocks are interpreted and the results returned in
440 * an xf86MonPtr.
441 *
442 * This function does not affect the list of modes used by drivers -- it is up
443 * to the driver to decide policy on what to do with EDID information.
444 *
445 * @return pointer to a new xf86MonPtr containing the EDID information.
446 * @return NULL if no monitor attached or failure to interpret the EDID.
447 */
448xf86MonPtr
449xf86DoEDID_DDC2(int scrnIndex, I2CBusPtr pBus)
450{
451    return xf86DoEEDID(scrnIndex, pBus, FALSE);
452}
453
454/* XXX write me */
455static void *
456DDC2ReadDisplayID(void)
457{
458    return FALSE;
459}
460
461/**
462 * Attempts to probe the monitor for DisplayID information, if NoDDC and
463 * NoDDC2 are unset.  DisplayID blocks are interpreted and the results
464 * returned in an xf86MonPtr.
465 *
466 * This function does not affect the list of modes used by drivers -- it is up
467 * to the driver to decide policy on what to do with DisplayID information.
468 *
469 * @return pointer to a new xf86MonPtr containing the DisplayID information.
470 * @return NULL if no monitor attached or failure to interpret the DisplayID.
471 */
472xf86MonPtr
473xf86DoDisplayID(int scrnIndex, I2CBusPtr pBus)
474{
475    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
476    unsigned char *did = NULL;
477    xf86MonPtr tmp = NULL;
478    I2CDevPtr dev = NULL;
479    /* Default DDC and DDC2 to enabled. */
480    Bool noddc = FALSE, noddc2 = FALSE;
481    OptionInfoPtr options;
482
483    options = malloc(sizeof(DDCOptions));
484    if (!options)
485	return NULL;
486    memcpy(options, DDCOptions, sizeof(DDCOptions));
487    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options);
488
489    xf86GetOptValBool(options, DDCOPT_NODDC, &noddc);
490    xf86GetOptValBool(options, DDCOPT_NODDC2, &noddc2);
491    free(options);
492
493    if (noddc || noddc2)
494	return NULL;
495
496    if (!(dev = DDC2Init(scrnIndex, pBus)))
497	return NULL;
498
499    if ((did = DDC2ReadDisplayID())) {
500	tmp = calloc(1, sizeof(*tmp));
501	if (!tmp)
502	    return NULL;
503
504	tmp->scrnIndex = scrnIndex;
505	tmp->flags |= MONITOR_DISPLAYID;
506	tmp->rawData = did;
507    }
508
509    return tmp;
510}
511