ct_ddc.c revision 7a5ec427
1
2#ifdef HAVE_CONFIG_H
3#include "config.h"
4#endif
5
6/* All drivers should typically include these */
7#include "xf86.h"
8#include "xf86_OSproc.h"
9
10/* Everything using inb/outb, etc needs "compiler.h" */
11#include "compiler.h"
12
13/* Drivers that need to access the PCI config space directly need this */
14#include "xf86Pci.h"
15
16#include "ct_driver.h"
17
18static Bool chips_TestI2C(int scrnIndex);
19static Bool chips_setI2CBits(I2CBusPtr I2CPtr, ScrnInfoPtr pScrn);
20
21static unsigned int
22chips_ddc1Read(ScrnInfoPtr pScrn)
23{
24    unsigned char ddc_mask = ((CHIPSPtr)pScrn->driverPrivate)->ddc_mask;
25    CHIPSPtr cPtr = CHIPSPTR(pScrn);
26    vgaHWPtr hwp = VGAHWPTR(pScrn);
27
28    register unsigned int tmp;
29
30    while ((hwp->readST01(hwp)) & 0x08){};
31    while (!((hwp->readST01(hwp)) & 0x08)){};
32    tmp = cPtr->readXR(cPtr, 0x63);
33    return (tmp & ddc_mask);
34}
35
36static void
37chips_ddc1SetSpeed(ScrnInfoPtr pScrn, xf86ddcSpeed speed)
38{
39    vgaHWddc1SetSpeed(pScrn, speed);
40}
41
42void
43chips_ddc1(ScrnInfoPtr pScrn)
44{
45    unsigned char FR0B, FR0C, XR62;
46    unsigned char mask_c = 0x00;
47    unsigned char val, tmp_val = 0;
48    int i;
49    CHIPSPtr cPtr = CHIPSPTR(pScrn);
50
51    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Probing for DDC1\n");
52
53    FR0C = cPtr->readFR(cPtr, 0x0C);
54    XR62 = cPtr->readXR(cPtr, 0x62);
55    switch (cPtr->Chipset) {
56    case CHIPS_CT65550:
57	cPtr->ddc_mask = 0x1F;         /* GPIO 0-4 */
58	FR0B = cPtr->readFR(cPtr, 0x0B);
59	if (!(FR0B & 0x10))      /* GPIO 2 is used as 32 kHz input */
60	    cPtr->ddc_mask &= 0xFB;
61	if (cPtr->Bus == ChipsVLB) /* GPIO 3-7 are used as address bits */
62	    cPtr->ddc_mask &= 0x07;
63	break;
64    case CHIPS_CT65554:
65    case CHIPS_CT65555:
66    case CHIPS_CT68554:
67	cPtr->ddc_mask = 0x0F;        /* GPIO 0-3 */
68	break;
69    case CHIPS_CT69000:
70    case CHIPS_CT69030:
71	cPtr->ddc_mask = 0x9F;        /* GPIO 0-4,7? */
72	break;
73    default:
74	cPtr->ddc_mask = 0x0C;       /* GPIO 2,3 */
75	break;
76    }
77    if (!(FR0C & 0x80)) {       /* GPIO 1 is not available */
78	mask_c |= 0xC0;
79	cPtr->ddc_mask &= 0xFE;
80    }
81    if (!(FR0C & 0x10)) {       /* GPIO 0 is not available */
82	mask_c |= 0x18;
83	cPtr->ddc_mask &= 0xFD;
84    }
85
86    /* set GPIO 0,1 to read if available */
87    cPtr->writeFR(cPtr, 0x0C, (FR0C & mask_c) | (~mask_c & 0x90));
88    /* set remaining GPIO to read */
89    cPtr->writeXR(cPtr, 0x62, 0x00);
90
91    val = chips_ddc1Read(pScrn);
92    for (i = 0; i < 70; i++) {
93	tmp_val = chips_ddc1Read(pScrn);
94	if (tmp_val != val)
95	    break;
96    }
97    cPtr->ddc_mask = val ^ tmp_val;
98    if (cPtr->ddc_mask)
99	xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "DDC1 found\n");
100    else return;
101
102    xf86PrintEDID(xf86DoEDID_DDC1(XF86_SCRN_ARG(pScrn), chips_ddc1SetSpeed,
103				  chips_ddc1Read));
104
105    /* restore */
106    cPtr->writeFR(cPtr, 0x0C, FR0C);
107    cPtr->writeXR(cPtr, 0x62, XR62);
108}
109
110static void
111chips_I2CGetBits(I2CBusPtr b, int *clock, int *data)
112{
113    CHIPSI2CPtr pI2C_c = (CHIPSI2CPtr) (b->DriverPrivate.ptr);
114    unsigned char FR0C, XR62, val;
115
116    FR0C = pI2C_c->cPtr->readFR(pI2C_c->cPtr, 0x0C);
117    if (pI2C_c->i2cDataBit & 0x01 || pI2C_c->i2cClockBit & 0x01)
118	FR0C = (FR0C & 0xE7) | 0x10;
119    if (pI2C_c->i2cDataBit & 0x02 || pI2C_c->i2cClockBit & 0x02)
120	FR0C = (FR0C & 0x3F) | 0x80;
121    XR62 = pI2C_c->cPtr->readXR(pI2C_c->cPtr, 0x62);
122    XR62 &= (~pI2C_c->i2cDataBit) & (~pI2C_c->i2cClockBit);
123    pI2C_c->cPtr->writeFR(pI2C_c->cPtr, 0x0C, FR0C);
124    pI2C_c->cPtr->writeXR(pI2C_c->cPtr, 0x62, XR62);
125    val = pI2C_c->cPtr->readXR(pI2C_c->cPtr, 0x63);
126    *clock = (val & pI2C_c->i2cClockBit) != 0;
127    *data  = (val & pI2C_c->i2cDataBit) != 0;
128}
129
130static void
131chips_I2CPutBits(I2CBusPtr b, int clock, int data)
132{
133    CHIPSI2CPtr pI2C_c = (CHIPSI2CPtr) (b->DriverPrivate.ptr);
134    unsigned char FR0C, XR62, val;
135
136    FR0C = pI2C_c->cPtr->readFR(pI2C_c->cPtr, 0x0C);
137    if (((pI2C_c->i2cDataBit & 0x01) && data)
138	|| ((pI2C_c->i2cClockBit & 0x01) && clock))
139	FR0C |=  0x18;
140    else if ((pI2C_c->i2cDataBit & 0x01)
141	|| (pI2C_c->i2cClockBit & 0x01))
142	FR0C |=  0x10;
143    if (((pI2C_c->i2cDataBit & 0x02) && data)
144	|| ((pI2C_c->i2cClockBit & 0x02) && clock))
145	FR0C |=  0xC0;
146    else if ((pI2C_c->i2cDataBit & 0x02)
147	     || (pI2C_c->i2cClockBit & 0x02))
148	FR0C |=  0x80;
149    XR62 = pI2C_c->cPtr->readXR(pI2C_c->cPtr, 0x62);
150    XR62 = (XR62 & ~pI2C_c->i2cClockBit) | (clock ? pI2C_c->i2cClockBit : 0);
151    XR62 = (XR62 & ~pI2C_c->i2cDataBit) | (data ? pI2C_c->i2cDataBit : 0);
152    pI2C_c->cPtr->writeFR(pI2C_c->cPtr, 0x0C, FR0C);
153    pI2C_c->cPtr->writeXR(pI2C_c->cPtr, 0x62, XR62);
154    val = pI2C_c->cPtr->readXR(pI2C_c->cPtr, 0x63);
155    val = (val & ~pI2C_c->i2cClockBit) | (clock ? pI2C_c->i2cClockBit : 0);
156    val = (val & ~pI2C_c->i2cDataBit) | (data ? pI2C_c->i2cDataBit : 0);
157    pI2C_c->cPtr->writeXR(pI2C_c->cPtr, 0x63, val);
158}
159
160
161Bool
162chips_i2cInit(ScrnInfoPtr pScrn)
163{
164    CHIPSPtr cPtr = CHIPSPTR(pScrn);
165    I2CBusPtr I2CPtr;
166
167    I2CPtr = xf86CreateI2CBusRec();
168    if(!I2CPtr) return FALSE;
169
170    cPtr->I2C = I2CPtr;
171
172    I2CPtr->BusName    = "DDC";
173    I2CPtr->scrnIndex  = pScrn->scrnIndex;
174    I2CPtr->I2CPutBits = chips_I2CPutBits;
175    I2CPtr->I2CGetBits = chips_I2CGetBits;
176    I2CPtr->DriverPrivate.ptr = malloc(sizeof(CHIPSI2CRec));
177    ((CHIPSI2CPtr)(I2CPtr->DriverPrivate.ptr))->cPtr = cPtr;
178
179    if (!xf86I2CBusInit(I2CPtr))
180	return FALSE;
181
182    if (!chips_setI2CBits(I2CPtr, pScrn))
183	return FALSE;
184
185    return TRUE;
186}
187
188static Bool
189chips_setI2CBits(I2CBusPtr b, ScrnInfoPtr pScrn)
190{
191    CHIPSPtr cPtr = CHIPSPTR(pScrn);
192    CHIPSI2CPtr pI2C_c = (CHIPSI2CPtr) (b->DriverPrivate.ptr);
193    unsigned char FR0B, FR0C;
194    unsigned char bits, data_bits, clock_bits;
195    int i,j;
196
197    FR0C = cPtr->readFR(cPtr, 0x0C);
198    switch (cPtr->Chipset) {
199    case CHIPS_CT65550:
200	bits = 0x1F;         /* GPIO 0-4 */
201	FR0B = cPtr->readFR(cPtr, 0x0B);
202	if (!(FR0B & 0x10))      /* GPIO 2 is used as 32 kHz input */
203	    bits &= 0xFB;
204	pI2C_c->i2cDataBit = 0x01;
205	pI2C_c->i2cClockBit = 0x02;
206	if (cPtr->Bus == ChipsVLB) /* GPIO 3-7 are used as address bits */
207	    bits &= 0x07;
208	break;
209    case CHIPS_CT65554:
210    case CHIPS_CT65555:
211    case CHIPS_CT68554:
212	bits = 0x0F;        /* GPIO 0-3 */
213	pI2C_c->i2cDataBit = 0x04;
214	pI2C_c->i2cClockBit = 0x08;
215	break;
216    case CHIPS_CT69000:
217    case CHIPS_CT69030:
218	bits = 0x9F;        /* GPIO 0-4,7? */
219	pI2C_c->i2cDataBit = 0x04;
220	pI2C_c->i2cClockBit = 0x08;
221	break;
222    default:
223	bits = 0x0C;       /* GPIO 2,3 */
224	pI2C_c->i2cDataBit = 0x04;
225	pI2C_c->i2cClockBit = 0x08;
226	break;
227    }
228    if (!(FR0C & 0x80)) {       /* GPIO 1 is not available */
229	bits &= 0xFE;
230    }
231    if (!(FR0C & 0x10)) {       /* GPIO 0 is not available */
232	bits &= 0xFD;
233    }
234    pI2C_c->i2cClockBit &= bits;
235    pI2C_c->i2cDataBit &= bits;
236    /*
237     * first we test out the "favorite" GPIO bits ie. the ones suggested
238     * by the data book; if we don't succeed test all other combinations
239     * of possible GPIO pins as data/clock lines as the manufacturer might
240     * have its own ideas.
241     */
242    if (chips_TestI2C(pScrn->scrnIndex)) return TRUE;
243
244    data_bits = bits;
245    pI2C_c->i2cDataBit = 0x01;
246    for (i = 0; i<8; i++) {
247	if (data_bits & 0x01) {
248	    clock_bits = bits;
249	    pI2C_c->i2cClockBit = 0x01;
250	    for (j = 0; j<8; j++) {
251		if (clock_bits & 0x01)
252		    if (chips_TestI2C(pScrn->scrnIndex)) return TRUE;
253		clock_bits >>= 1;
254		pI2C_c->i2cClockBit <<= 1;
255	    }
256	}
257	data_bits >>= 1;
258	pI2C_c->i2cDataBit <<= 1;
259    }
260    /*
261     * We haven't found a valid clock/data line combination - that
262     * doesn't mean there aren't any. We just haven't received an
263     * answer from the relevant DDC I2C addresses. We'll have to wait
264     * and see, if this is too restrictive (eg one wants to use I2C
265     * for something else than DDC we might have to probe more addresses
266     * or just fall back to the "favorite" GPIO lines.
267     */
268    return FALSE;
269}
270
271static Bool
272chips_TestI2C(int scrnIndex)
273{
274    int i;
275    I2CBusPtr b;
276
277    b = xf86I2CFindBus(scrnIndex, "DDC");
278    if (b == NULL) return FALSE;
279    else {
280	for(i = 0xA0; i < 0xA8; i += 2)
281	    if(xf86I2CProbeAddress(b, i))
282		return TRUE;
283    }
284    return FALSE;
285}
286
287
288