~ubuntu-branches/ubuntu/precise/xserver-xorg-video-openchrome-lts-trusty/precise-proposed

« back to all changes in this revision

Viewing changes to src/via_i2c.c

  • Committer: Package Import Robot
  • Author(s): Maarten Lankhorst
  • Date: 2014-05-15 12:47:33 UTC
  • Revision ID: package-import@ubuntu.com-20140515124733-qw5cb5dqlvejqsy3
Tags: upstream-0.3.3
ImportĀ upstreamĀ versionĀ 0.3.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
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.
 
5
 *
 
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:
 
12
 *
 
13
 * The above copyright notice and this permission notice (including the
 
14
 * next paragraph) shall be included in all copies or substantial portions
 
15
 * of the Software.
 
16
 *
 
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.
 
24
 */
 
25
 
 
26
/*
 
27
 * Implements three i2c busses through registers SR26, SR2c, and SR31.
 
28
 */
 
29
 
 
30
#ifdef HAVE_CONFIG_H
 
31
#include "config.h"
 
32
#endif
 
33
 
 
34
#include "via_driver.h"
 
35
 
 
36
#define SDA_READ  0x04
 
37
#define SCL_READ  0x08
 
38
#define SDA_WRITE 0x10
 
39
#define SCL_WRITE 0x20
 
40
 
 
41
/*
 
42
 * CRT I2C
 
43
 */
 
44
static void
 
45
ViaI2C1PutBits(I2CBusPtr Bus, int clock, int data)
 
46
{
 
47
    vgaHWPtr hwp = Bus->DriverPrivate.ptr;
 
48
    CARD8 value = 0x01; /* Enable */
 
49
 
 
50
    if (clock)
 
51
        value |= SCL_WRITE;
 
52
 
 
53
    if (data)
 
54
        value |= SDA_WRITE;
 
55
 
 
56
    ViaSeqMask(hwp, 0x26, value, 0x01 | SCL_WRITE | SDA_WRITE);
 
57
}
 
58
 
 
59
static void
 
60
ViaI2C1GetBits(I2CBusPtr Bus, int *clock, int *data)
 
61
{
 
62
    vgaHWPtr hwp = Bus->DriverPrivate.ptr;
 
63
    CARD8 value = hwp->readSeq(hwp, 0x26);
 
64
 
 
65
    *clock = (value & SCL_READ) != 0;
 
66
    *data = (value & SDA_READ) != 0;
 
67
}
 
68
 
 
69
static I2CBusPtr
 
70
ViaI2CBus1Init(ScrnInfoPtr pScrn)
 
71
{
 
72
    I2CBusPtr pI2CBus = xf86CreateI2CBusRec();
 
73
    vgaHWPtr hwp = VGAHWPTR(pScrn);
 
74
 
 
75
    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaI2CBus1Init\n"));
 
76
 
 
77
    if (!pI2CBus)
 
78
        return NULL;
 
79
 
 
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;
 
89
 
 
90
    if (!xf86I2CBusInit(pI2CBus)) {
 
91
        xf86DestroyI2CBusRec(pI2CBus, TRUE, FALSE);
 
92
        return NULL;
 
93
    }
 
94
    return pI2CBus;
 
95
}
 
96
 
 
97
/*
 
98
 * First data bus I2C: tends to have TV-encoders.
 
99
 */
 
100
static void
 
101
ViaI2C2PutBits(I2CBusPtr Bus, int clock, int data)
 
102
{
 
103
    vgaHWPtr hwp = Bus->DriverPrivate.ptr;
 
104
    CARD8 value = 0x01; /* Enable */
 
105
 
 
106
    if (clock)
 
107
        value |= SCL_WRITE;
 
108
 
 
109
    if (data)
 
110
        value |= SDA_WRITE;
 
111
 
 
112
    ViaSeqMask(hwp, 0x31, value, 0x01 | SCL_WRITE | SDA_WRITE);
 
113
}
 
114
 
 
115
static void
 
116
ViaI2C2GetBits(I2CBusPtr Bus, int *clock, int *data)
 
117
{
 
118
    vgaHWPtr hwp = Bus->DriverPrivate.ptr;
 
119
    CARD8 value = hwp->readSeq(hwp, 0x31);
 
120
 
 
121
    *clock = (value & SCL_READ) != 0;
 
122
    *data = (value & SDA_READ) != 0;
 
123
}
 
124
 
 
125
static I2CBusPtr
 
126
ViaI2CBus2Init(ScrnInfoPtr pScrn)
 
127
{
 
128
    I2CBusPtr pI2CBus = xf86CreateI2CBusRec();
 
129
    vgaHWPtr hwp = VGAHWPTR(pScrn);
 
130
 
 
131
    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaI2cBus2Init\n"));
 
132
 
 
133
    if (!pI2CBus)
 
134
        return NULL;
 
135
 
 
136
    pI2CBus->BusName = "I2C bus 2";
 
137
    pI2CBus->scrnIndex = pScrn->scrnIndex;
 
138
    pI2CBus->I2CPutBits = ViaI2C2PutBits;
 
139
    pI2CBus->I2CGetBits = ViaI2C2GetBits;
 
140
    pI2CBus->DriverPrivate.ptr = hwp;
 
141
 
 
142
    if (!xf86I2CBusInit(pI2CBus)) {
 
143
        xf86DestroyI2CBusRec(pI2CBus, TRUE, FALSE);
 
144
        return NULL;
 
145
    }
 
146
    return pI2CBus;
 
147
}
 
148
 
 
149
/*
 
150
 * A third I2C bus is implemented by a few IO pins.
 
151
 * Requires higher level functions to be used properly.
 
152
 */
 
153
static Bool
 
154
ViaI2C3Start(I2CBusPtr b, int timeout)
 
155
{
 
156
    vgaHWPtr hwp = b->DriverPrivate.ptr;
 
157
 
 
158
    ViaSeqMask(hwp, 0x2C, 0xF0, 0xF0);
 
159
    b->I2CUDelay(b, b->RiseFallTime);
 
160
 
 
161
    ViaSeqMask(hwp, 0x2C, 0x00, 0x10);
 
162
    b->I2CUDelay(b, b->HoldTime);
 
163
    ViaSeqMask(hwp, 0x2C, 0x00, 0x20);
 
164
    b->I2CUDelay(b, b->HoldTime);
 
165
 
 
166
    return TRUE;
 
167
}
 
168
 
 
169
static Bool
 
170
ViaI2C3Address(I2CDevPtr d, I2CSlaveAddr addr)
 
171
{
 
172
    I2CBusPtr b = d->pI2CBus;
 
173
 
 
174
#ifdef X_NEED_I2CSTART
 
175
    if (b->I2CStart(d->pI2CBus, d->StartTimeout)) {
 
176
#else
 
177
    if (ViaI2C3Start(d->pI2CBus, d->StartTimeout)) {
 
178
#endif
 
179
        if (b->I2CPutByte(d, addr & 0xFF)) {
 
180
            if ((addr & 0xF8) != 0xF0 && (addr & 0xFE) != 0x00)
 
181
                return TRUE;
 
182
 
 
183
            if (b->I2CPutByte(d, (addr >> 8) & 0xFF))
 
184
                return TRUE;
 
185
        }
 
186
 
 
187
        b->I2CStop(d);
 
188
    }
 
189
    return FALSE;
 
190
}
 
191
 
 
192
static void
 
193
ViaI2C3Stop(I2CDevPtr d)
 
194
{
 
195
    I2CBusPtr b = d->pI2CBus;
 
196
    vgaHWPtr hwp = b->DriverPrivate.ptr;
 
197
 
 
198
    ViaSeqMask(hwp, 0x2C, 0xC0, 0xF0);
 
199
    b->I2CUDelay(b, b->RiseFallTime);
 
200
 
 
201
    ViaSeqMask(hwp, 0x2C, 0x20, 0x20);
 
202
    b->I2CUDelay(b, b->HoldTime);
 
203
 
 
204
    ViaSeqMask(hwp, 0x2C, 0x10, 0x10);
 
205
    b->I2CUDelay(b, b->HoldTime);
 
206
 
 
207
    ViaSeqMask(hwp, 0x2C, 0x00, 0x20);
 
208
    b->I2CUDelay(b, b->HoldTime);
 
209
}
 
210
 
 
211
static void
 
212
ViaI2C3PutBit(I2CBusPtr b, Bool sda, int timeout)
 
213
{
 
214
    vgaHWPtr hwp = b->DriverPrivate.ptr;
 
215
 
 
216
    if (sda)
 
217
        ViaSeqMask(hwp, 0x2C, 0x50, 0x50);
 
218
    else
 
219
        ViaSeqMask(hwp, 0x2C, 0x40, 0x50);
 
220
    b->I2CUDelay(b, b->RiseFallTime / 5);
 
221
 
 
222
    ViaSeqMask(hwp, 0x2C, 0xA0, 0xA0);
 
223
    b->I2CUDelay(b, b->HoldTime);
 
224
    b->I2CUDelay(b, timeout);
 
225
 
 
226
    ViaSeqMask(hwp, 0x2C, 0x80, 0xA0);
 
227
    b->I2CUDelay(b, b->RiseFallTime / 5);
 
228
}
 
229
 
 
230
static Bool
 
231
ViaI2C3PutByte(I2CDevPtr d, I2CByte data)
 
232
{
 
233
    I2CBusPtr b = d->pI2CBus;
 
234
    vgaHWPtr hwp = b->DriverPrivate.ptr;
 
235
    Bool ret;
 
236
    int i;
 
237
 
 
238
    for (i = 7; i >= 0; i--)
 
239
        ViaI2C3PutBit(b, (data >> i) & 0x01, b->BitTimeout);
 
240
 
 
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);
 
246
 
 
247
    if (hwp->readSeq(hwp, 0x2C) & 0x04)
 
248
        ret = FALSE;
 
249
    else
 
250
        ret = TRUE;
 
251
 
 
252
    ViaSeqMask(hwp, 0x2C, 0x80, 0xA0);
 
253
    b->I2CUDelay(b, b->RiseFallTime);
 
254
 
 
255
    return ret;
 
256
}
 
257
 
 
258
static Bool
 
259
ViaI2C3GetBit(I2CBusPtr b, int timeout)
 
260
{
 
261
    vgaHWPtr hwp = b->DriverPrivate.ptr;
 
262
    Bool ret;
 
263
 
 
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);
 
269
 
 
270
    if (hwp->readSeq(hwp, 0x2C) & 0x04)
 
271
        ret = TRUE;
 
272
    else
 
273
        ret = FALSE;
 
274
 
 
275
    ViaSeqMask(hwp, 0x2C, 0x80, 0xA0);
 
276
    b->I2CUDelay(b, b->HoldTime);
 
277
    b->I2CUDelay(b, b->RiseFallTime / 5);
 
278
 
 
279
    return ret;
 
280
}
 
281
 
 
282
static Bool
 
283
ViaI2C3GetByte(I2CDevPtr d, I2CByte * data, Bool last)
 
284
{
 
285
    I2CBusPtr b = d->pI2CBus;
 
286
    vgaHWPtr hwp = b->DriverPrivate.ptr;
 
287
    int i;
 
288
 
 
289
    *data = 0x00;
 
290
 
 
291
    for (i = 7; i >= 0; i--)
 
292
        if (ViaI2C3GetBit(b, b->BitTimeout))
 
293
            *data |= 0x01 << i;
 
294
 
 
295
    if (last)   /* send NACK */
 
296
        ViaSeqMask(hwp, 0x2C, 0x50, 0x50);
 
297
    else        /* send ACK */
 
298
        ViaSeqMask(hwp, 0x2C, 0x40, 0x50);
 
299
 
 
300
    ViaSeqMask(hwp, 0x2C, 0xA0, 0xA0);
 
301
    b->I2CUDelay(b, b->HoldTime);
 
302
 
 
303
    ViaSeqMask(hwp, 0x2C, 0x80, 0xA0);
 
304
 
 
305
    return TRUE;
 
306
}
 
307
 
 
308
static I2CBusPtr
 
309
ViaI2CBus3Init(ScrnInfoPtr pScrn)
 
310
{
 
311
    I2CBusPtr pI2CBus = xf86CreateI2CBusRec();
 
312
    vgaHWPtr hwp = VGAHWPTR(pScrn);
 
313
 
 
314
    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaI2CBus3Init\n"));
 
315
 
 
316
    if (!pI2CBus)
 
317
        return NULL;
 
318
 
 
319
    pI2CBus->BusName = "I2C bus 3";
 
320
    pI2CBus->scrnIndex = pScrn->scrnIndex;
 
321
    pI2CBus->I2CAddress = ViaI2C3Address;
 
322
#ifdef X_NEED_I2CSTART
 
323
    pI2CBus->I2CStart = ViaI2C3Start;
 
324
#endif
 
325
    pI2CBus->I2CStop = ViaI2C3Stop;
 
326
    pI2CBus->I2CPutByte = ViaI2C3PutByte;
 
327
    pI2CBus->I2CGetByte = ViaI2C3GetByte;
 
328
    pI2CBus->DriverPrivate.ptr = hwp;
 
329
 
 
330
    pI2CBus->HoldTime = 10;
 
331
    pI2CBus->BitTimeout = 10;
 
332
    pI2CBus->ByteTimeout = 10;
 
333
    pI2CBus->StartTimeout = 10;
 
334
 
 
335
    if (!xf86I2CBusInit(pI2CBus)) {
 
336
        xf86DestroyI2CBusRec(pI2CBus, TRUE, FALSE);
 
337
        return NULL;
 
338
    }
 
339
    return pI2CBus;
 
340
}
 
341
 
 
342
#ifdef HAVE_DEBUG
 
343
static void
 
344
ViaI2CScan(I2CBusPtr Bus)
 
345
{
 
346
    CARD8 i;
 
347
 
 
348
    xf86DrvMsg(Bus->scrnIndex, X_INFO, "ViaI2CScan: Scanning %s\n",
 
349
               Bus->BusName);
 
350
 
 
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);
 
355
}
 
356
#endif /* HAVE_DEBUG */
 
357
 
 
358
void
 
359
ViaI2CInit(ScrnInfoPtr pScrn)
 
360
{
 
361
    VIAPtr pVia = VIAPTR(pScrn);
 
362
 
 
363
    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaI2CInit\n"));
 
364
 
 
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);
 
371
 
 
372
#ifdef HAVE_DEBUG
 
373
    if (pVia->I2CScan) {
 
374
        if (pVia->pI2CBus2)
 
375
            ViaI2CScan(pVia->pI2CBus2);
 
376
        if (pVia->pI2CBus3)
 
377
            ViaI2CScan(pVia->pI2CBus3);
 
378
    }
 
379
#endif
 
380
}