2
* Copyright 2004 The Unichrome Project [unichrome.sf.net]
3
* Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
4
* Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
6
* Permission is hereby granted, free of charge, to any person obtaining a
7
* copy of this software and associated documentation files (the "Software"),
8
* to deal in the Software without restriction, including without limitation
9
* the rights to use, copy, modify, merge, publish, distribute, sub license,
10
* and/or sell copies of the Software, and to permit persons to whom the
11
* Software is furnished to do so, subject to the following conditions:
13
* The above copyright notice and this permission notice (including the
14
* next paragraph) shall be included in all copies or substantial portions
17
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
20
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
* DEALINGS IN THE SOFTWARE.
27
* Implements three i2c busses through registers SR26, SR2c, and SR31.
34
#include "via_driver.h"
38
#define SDA_WRITE 0x10
39
#define SCL_WRITE 0x20
45
ViaI2C1PutBits(I2CBusPtr Bus, int clock, int data)
47
vgaHWPtr hwp = Bus->DriverPrivate.ptr;
48
CARD8 value = 0x01; /* Enable */
56
ViaSeqMask(hwp, 0x26, value, 0x01 | SCL_WRITE | SDA_WRITE);
60
ViaI2C1GetBits(I2CBusPtr Bus, int *clock, int *data)
62
vgaHWPtr hwp = Bus->DriverPrivate.ptr;
63
CARD8 value = hwp->readSeq(hwp, 0x26);
65
*clock = (value & SCL_READ) != 0;
66
*data = (value & SDA_READ) != 0;
70
ViaI2CBus1Init(ScrnInfoPtr pScrn)
72
I2CBusPtr pI2CBus = xf86CreateI2CBusRec();
73
vgaHWPtr hwp = VGAHWPTR(pScrn);
75
DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaI2CBus1Init\n"));
80
pI2CBus->BusName = "I2C bus 1";
81
pI2CBus->scrnIndex = pScrn->scrnIndex;
82
pI2CBus->I2CPutBits = ViaI2C1PutBits;
83
pI2CBus->I2CGetBits = ViaI2C1GetBits;
84
pI2CBus->DriverPrivate.ptr = hwp;
85
pI2CBus->ByteTimeout = 2200;
86
pI2CBus->StartTimeout = 550;
87
pI2CBus->HoldTime = 40;
88
pI2CBus->BitTimeout = 40;
90
if (!xf86I2CBusInit(pI2CBus)) {
91
xf86DestroyI2CBusRec(pI2CBus, TRUE, FALSE);
98
* First data bus I2C: tends to have TV-encoders.
101
ViaI2C2PutBits(I2CBusPtr Bus, int clock, int data)
103
vgaHWPtr hwp = Bus->DriverPrivate.ptr;
104
CARD8 value = 0x01; /* Enable */
112
ViaSeqMask(hwp, 0x31, value, 0x01 | SCL_WRITE | SDA_WRITE);
116
ViaI2C2GetBits(I2CBusPtr Bus, int *clock, int *data)
118
vgaHWPtr hwp = Bus->DriverPrivate.ptr;
119
CARD8 value = hwp->readSeq(hwp, 0x31);
121
*clock = (value & SCL_READ) != 0;
122
*data = (value & SDA_READ) != 0;
126
ViaI2CBus2Init(ScrnInfoPtr pScrn)
128
I2CBusPtr pI2CBus = xf86CreateI2CBusRec();
129
vgaHWPtr hwp = VGAHWPTR(pScrn);
131
DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaI2cBus2Init\n"));
136
pI2CBus->BusName = "I2C bus 2";
137
pI2CBus->scrnIndex = pScrn->scrnIndex;
138
pI2CBus->I2CPutBits = ViaI2C2PutBits;
139
pI2CBus->I2CGetBits = ViaI2C2GetBits;
140
pI2CBus->DriverPrivate.ptr = hwp;
142
if (!xf86I2CBusInit(pI2CBus)) {
143
xf86DestroyI2CBusRec(pI2CBus, TRUE, FALSE);
150
* A third I2C bus is implemented by a few IO pins.
151
* Requires higher level functions to be used properly.
154
ViaI2C3Start(I2CBusPtr b, int timeout)
156
vgaHWPtr hwp = b->DriverPrivate.ptr;
158
ViaSeqMask(hwp, 0x2C, 0xF0, 0xF0);
159
b->I2CUDelay(b, b->RiseFallTime);
161
ViaSeqMask(hwp, 0x2C, 0x00, 0x10);
162
b->I2CUDelay(b, b->HoldTime);
163
ViaSeqMask(hwp, 0x2C, 0x00, 0x20);
164
b->I2CUDelay(b, b->HoldTime);
170
ViaI2C3Address(I2CDevPtr d, I2CSlaveAddr addr)
172
I2CBusPtr b = d->pI2CBus;
174
#ifdef X_NEED_I2CSTART
175
if (b->I2CStart(d->pI2CBus, d->StartTimeout)) {
177
if (ViaI2C3Start(d->pI2CBus, d->StartTimeout)) {
179
if (b->I2CPutByte(d, addr & 0xFF)) {
180
if ((addr & 0xF8) != 0xF0 && (addr & 0xFE) != 0x00)
183
if (b->I2CPutByte(d, (addr >> 8) & 0xFF))
193
ViaI2C3Stop(I2CDevPtr d)
195
I2CBusPtr b = d->pI2CBus;
196
vgaHWPtr hwp = b->DriverPrivate.ptr;
198
ViaSeqMask(hwp, 0x2C, 0xC0, 0xF0);
199
b->I2CUDelay(b, b->RiseFallTime);
201
ViaSeqMask(hwp, 0x2C, 0x20, 0x20);
202
b->I2CUDelay(b, b->HoldTime);
204
ViaSeqMask(hwp, 0x2C, 0x10, 0x10);
205
b->I2CUDelay(b, b->HoldTime);
207
ViaSeqMask(hwp, 0x2C, 0x00, 0x20);
208
b->I2CUDelay(b, b->HoldTime);
212
ViaI2C3PutBit(I2CBusPtr b, Bool sda, int timeout)
214
vgaHWPtr hwp = b->DriverPrivate.ptr;
217
ViaSeqMask(hwp, 0x2C, 0x50, 0x50);
219
ViaSeqMask(hwp, 0x2C, 0x40, 0x50);
220
b->I2CUDelay(b, b->RiseFallTime / 5);
222
ViaSeqMask(hwp, 0x2C, 0xA0, 0xA0);
223
b->I2CUDelay(b, b->HoldTime);
224
b->I2CUDelay(b, timeout);
226
ViaSeqMask(hwp, 0x2C, 0x80, 0xA0);
227
b->I2CUDelay(b, b->RiseFallTime / 5);
231
ViaI2C3PutByte(I2CDevPtr d, I2CByte data)
233
I2CBusPtr b = d->pI2CBus;
234
vgaHWPtr hwp = b->DriverPrivate.ptr;
238
for (i = 7; i >= 0; i--)
239
ViaI2C3PutBit(b, (data >> i) & 0x01, b->BitTimeout);
241
/* Raise first to avoid false positives. */
242
ViaSeqMask(hwp, 0x2C, 0x50, 0x50);
243
ViaSeqMask(hwp, 0x2C, 0x00, 0x40);
244
b->I2CUDelay(b, b->RiseFallTime);
245
ViaSeqMask(hwp, 0x2C, 0xA0, 0xA0);
247
if (hwp->readSeq(hwp, 0x2C) & 0x04)
252
ViaSeqMask(hwp, 0x2C, 0x80, 0xA0);
253
b->I2CUDelay(b, b->RiseFallTime);
259
ViaI2C3GetBit(I2CBusPtr b, int timeout)
261
vgaHWPtr hwp = b->DriverPrivate.ptr;
264
ViaSeqMask(hwp, 0x2c, 0x80, 0xC0);
265
b->I2CUDelay(b, b->RiseFallTime / 5);
266
ViaSeqMask(hwp, 0x2c, 0xA0, 0xA0);
267
b->I2CUDelay(b, 3 * b->HoldTime);
268
b->I2CUDelay(b, timeout);
270
if (hwp->readSeq(hwp, 0x2C) & 0x04)
275
ViaSeqMask(hwp, 0x2C, 0x80, 0xA0);
276
b->I2CUDelay(b, b->HoldTime);
277
b->I2CUDelay(b, b->RiseFallTime / 5);
283
ViaI2C3GetByte(I2CDevPtr d, I2CByte * data, Bool last)
285
I2CBusPtr b = d->pI2CBus;
286
vgaHWPtr hwp = b->DriverPrivate.ptr;
291
for (i = 7; i >= 0; i--)
292
if (ViaI2C3GetBit(b, b->BitTimeout))
295
if (last) /* send NACK */
296
ViaSeqMask(hwp, 0x2C, 0x50, 0x50);
298
ViaSeqMask(hwp, 0x2C, 0x40, 0x50);
300
ViaSeqMask(hwp, 0x2C, 0xA0, 0xA0);
301
b->I2CUDelay(b, b->HoldTime);
303
ViaSeqMask(hwp, 0x2C, 0x80, 0xA0);
309
ViaI2CBus3Init(ScrnInfoPtr pScrn)
311
I2CBusPtr pI2CBus = xf86CreateI2CBusRec();
312
vgaHWPtr hwp = VGAHWPTR(pScrn);
314
DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaI2CBus3Init\n"));
319
pI2CBus->BusName = "I2C bus 3";
320
pI2CBus->scrnIndex = pScrn->scrnIndex;
321
pI2CBus->I2CAddress = ViaI2C3Address;
322
#ifdef X_NEED_I2CSTART
323
pI2CBus->I2CStart = ViaI2C3Start;
325
pI2CBus->I2CStop = ViaI2C3Stop;
326
pI2CBus->I2CPutByte = ViaI2C3PutByte;
327
pI2CBus->I2CGetByte = ViaI2C3GetByte;
328
pI2CBus->DriverPrivate.ptr = hwp;
330
pI2CBus->HoldTime = 10;
331
pI2CBus->BitTimeout = 10;
332
pI2CBus->ByteTimeout = 10;
333
pI2CBus->StartTimeout = 10;
335
if (!xf86I2CBusInit(pI2CBus)) {
336
xf86DestroyI2CBusRec(pI2CBus, TRUE, FALSE);
344
ViaI2CScan(I2CBusPtr Bus)
348
xf86DrvMsg(Bus->scrnIndex, X_INFO, "ViaI2CScan: Scanning %s\n",
351
for (i = 0x10; i < 0xF0; i += 2)
352
if (xf86I2CProbeAddress(Bus, i))
353
xf86DrvMsg(Bus->scrnIndex, X_PROBED, "Found slave on %s "
354
"- 0x%02X\n", Bus->BusName, i);
356
#endif /* HAVE_DEBUG */
359
ViaI2CInit(ScrnInfoPtr pScrn)
361
VIAPtr pVia = VIAPTR(pScrn);
363
DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaI2CInit\n"));
365
if (pVia->I2CDevices & VIA_I2C_BUS1)
366
pVia->pI2CBus1 = ViaI2CBus1Init(pScrn);
367
if (pVia->I2CDevices & VIA_I2C_BUS2)
368
pVia->pI2CBus2 = ViaI2CBus2Init(pScrn);
369
if (pVia->I2CDevices & VIA_I2C_BUS3)
370
pVia->pI2CBus3 = ViaI2CBus3Init(pScrn);
375
ViaI2CScan(pVia->pI2CBus2);
377
ViaI2CScan(pVia->pI2CBus3);