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