~ubuntu-branches/ubuntu/trusty/xserver-xorg-video-mach64-lts-xenial/trusty-proposed

« back to all changes in this revision

Viewing changes to src/atii2c.c

  • Committer: Package Import Robot
  • Author(s): Timo Aaltonen
  • Date: 2016-05-03 14:02:37 UTC
  • Revision ID: package-import@ubuntu.com-20160503140237-y946gbjc7p6fg9fn
Tags: upstream-6.9.5
ImportĀ upstreamĀ versionĀ 6.9.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright 2003 through 2004 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
 
3
 *
 
4
 * Permission to use, copy, modify, distribute, and sell this software and its
 
5
 * documentation for any purpose is hereby granted without fee, provided that
 
6
 * the above copyright notice appear in all copies and that both that copyright
 
7
 * notice and this permission notice appear in supporting documentation, and
 
8
 * that the name of Marc Aurele La France not be used in advertising or
 
9
 * publicity pertaining to distribution of the software without specific,
 
10
 * written prior permission.  Marc Aurele La France makes no representations
 
11
 * about the suitability of this software for any purpose.  It is provided
 
12
 * "as-is" without express or implied warranty.
 
13
 *
 
14
 * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 
15
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO
 
16
 * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 
17
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 
18
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 
19
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 
20
 * PERFORMANCE OF THIS SOFTWARE.
 
21
 */
 
22
 
 
23
#ifdef HAVE_CONFIG_H
 
24
#include "config.h"
 
25
#endif
 
26
 
 
27
#include "atii2c.h"
 
28
#include "atimach64i2c.h"
 
29
#include "atistruct.h"
 
30
 
 
31
#include "xf86.h"
 
32
 
 
33
/* This is derived from GATOS code, with a liberal sprinkling of bug fixes */
 
34
 
 
35
/*
 
36
 * Some local macros for use by the mid-level I2C functions.
 
37
 */
 
38
 
 
39
#define ATII2CDelay                                            \
 
40
    (*pI2CBus->I2CUDelay)(pI2CBus, pI2CBus->HoldTime)
 
41
 
 
42
 
 
43
#define ATII2CSCLDirOff                                        \
 
44
    if (pATII2C->SCLDir != 0)                                  \
 
45
        (*pATII2C->I2CSetBits)(pATII2C, pATI,                  \
 
46
            pATII2C->I2CCur & ~pATII2C->SCLDir)
 
47
 
 
48
#define ATII2CSCLDirOn                                         \
 
49
    if (pATII2C->SCLDir != 0)                                  \
 
50
        (*pATII2C->I2CSetBits)(pATII2C, pATI,                  \
 
51
            pATII2C->I2CCur | pATII2C->SCLDir)
 
52
 
 
53
#define ATII2CSDADirOff                                        \
 
54
    if (pATII2C->SDADir != 0)                                  \
 
55
        (*pATII2C->I2CSetBits)(pATII2C, pATI,                  \
 
56
            pATII2C->I2CCur & ~pATII2C->SDADir)
 
57
 
 
58
#define ATII2CSDADirOn                                         \
 
59
    if (pATII2C->SDADir != 0)                                  \
 
60
        (*pATII2C->I2CSetBits)(pATII2C, pATI,                  \
 
61
            pATII2C->I2CCur | pATII2C->SDADir)
 
62
 
 
63
 
 
64
#define ATII2CSCLBitGet                                        \
 
65
    ((*pATII2C->I2CGetBits)(pATI) & pATII2C->SCLGet)
 
66
 
 
67
#define ATII2CSCLBitOff                                        \
 
68
    do                                                         \
 
69
    {                                                          \
 
70
        (*pATII2C->I2CSetBits)(pATII2C, pATI,                  \
 
71
            pATII2C->I2CCur & ~pATII2C->SCLSet);               \
 
72
        ATII2CDelay;                                           \
 
73
    } while (0)
 
74
 
 
75
#define ATII2CSCLBitOn                                         \
 
76
    do                                                         \
 
77
    {                                                          \
 
78
        (*pATII2C->I2CSetBits)(pATII2C, pATI,                  \
 
79
            pATII2C->I2CCur | pATII2C->SCLSet);                \
 
80
        do      /* Wait until all devices have released SCL */ \
 
81
        {                                                      \
 
82
            ATII2CDelay;                                       \
 
83
        } while (ATII2CSCLBitGet == 0);                        \
 
84
    } while (0)
 
85
 
 
86
 
 
87
#define ATII2CSDABitGet                                        \
 
88
    ((*pATII2C->I2CGetBits)(pATI) & pATII2C->SDAGet)
 
89
 
 
90
#define ATII2CSDABitOff                                        \
 
91
    do                                                         \
 
92
    {                                                          \
 
93
        (*pATII2C->I2CSetBits)(pATII2C, pATI,                  \
 
94
            pATII2C->I2CCur & ~pATII2C->SDASet);               \
 
95
        ATII2CDelay;                                           \
 
96
    } while (0)
 
97
 
 
98
#define ATII2CSDABitOn                                         \
 
99
    do                                                         \
 
100
    {                                                          \
 
101
        (*pATII2C->I2CSetBits)(pATII2C, pATI,                  \
 
102
            pATII2C->I2CCur | pATII2C->SDASet);                \
 
103
        ATII2CDelay;                                           \
 
104
    } while (0)
 
105
 
 
106
#define ATII2CSDABitSet(_flag)                                 \
 
107
    do                                                         \
 
108
    {                                                          \
 
109
        if (_flag)                                             \
 
110
            ATII2CSDABitOn;                                    \
 
111
        else                                                   \
 
112
            ATII2CSDABitOff;                                   \
 
113
    } while (0)
 
114
 
 
115
 
 
116
/*
 
117
 * ATII2CStart --
 
118
 *
 
119
 * This function puts a start signal on the I2C bus.
 
120
 */
 
121
static Bool
 
122
ATII2CStart
 
123
(
 
124
    I2CBusPtr pI2CBus,
 
125
    int       timeout
 
126
)
 
127
{
 
128
    ATII2CPtr pATII2C = pI2CBus->DriverPrivate.ptr;
 
129
    ATIPtr    pATI    = pATII2C->pATI;
 
130
 
 
131
    (void)timeout;
 
132
 
 
133
    /*
 
134
     * Set I2C line directions to out-bound.  SCL will remain out-bound until
 
135
     * next I2C Stop.
 
136
     */
 
137
    ATII2CSCLDirOn;
 
138
    ATII2CSDADirOn;
 
139
 
 
140
    /*
 
141
     * Send Start bit.  This is a pull-down of the data line while the clock
 
142
     * line is pulled up.
 
143
     */
 
144
    ATII2CSDABitOn;
 
145
    ATII2CSCLBitOn;
 
146
    ATII2CSDABitOff;
 
147
    ATII2CSCLBitOff;
 
148
 
 
149
    return TRUE;
 
150
}
 
151
 
 
152
/*
 
153
 * ATII2CAddress --
 
154
 *
 
155
 * This function puts an 8-bit address on the I2C bus.
 
156
 */
 
157
static Bool
 
158
ATII2CAddress
 
159
(
 
160
    I2CDevPtr    pI2CDev,
 
161
    I2CSlaveAddr Address
 
162
)
 
163
{
 
164
    I2CBusPtr pI2CBus = pI2CDev->pI2CBus;
 
165
 
 
166
    /* Send low byte of device address */
 
167
    if ((*pI2CBus->I2CPutByte)(pI2CDev, (I2CByte)Address))
 
168
    {
 
169
        /* Send top byte of address, if appropriate */
 
170
        if (((Address & 0x00F8U) != 0x00F0U) &&
 
171
            ((Address & 0x00FEU) != 0x0000U))
 
172
            return TRUE;
 
173
 
 
174
        if ((*pI2CBus->I2CPutByte)(pI2CDev, (I2CByte)(Address >> 8)))
 
175
            return TRUE;
 
176
    }
 
177
 
 
178
    /* Kill I2C transaction on failure */
 
179
    (*pI2CBus->I2CStop)(pI2CDev);
 
180
    return FALSE;
 
181
}
 
182
 
 
183
/*
 
184
 * ATII2CStop --
 
185
 *
 
186
 * This function puts a stop signal on the I2C bus.
 
187
 */
 
188
static void
 
189
ATII2CStop
 
190
(
 
191
    I2CDevPtr pI2CDev
 
192
)
 
193
{
 
194
    I2CBusPtr pI2CBus = pI2CDev->pI2CBus;
 
195
    ATII2CPtr pATII2C = pI2CBus->DriverPrivate.ptr;
 
196
    ATIPtr    pATI    = pATII2C->pATI;
 
197
 
 
198
    ATII2CSDADirOn;             /* Set data line direction to out-bound */
 
199
 
 
200
    /*
 
201
     * Send Stop bit.  This is a pull-up of the data line while the clock line
 
202
     * is pulled up.
 
203
     */
 
204
    ATII2CSDABitOff;
 
205
    ATII2CSCLBitOn;
 
206
    ATII2CSDABitOn;
 
207
    ATII2CSCLBitOff;
 
208
 
 
209
    /* Reset I2C line directions to in-bound */
 
210
    ATII2CSCLDirOff;
 
211
    ATII2CSDADirOff;
 
212
}
 
213
 
 
214
/*
 
215
 * ATII2CPutByte --
 
216
 *
 
217
 * This function puts an 8-bit value on the I2C bus, starting with its MSB.
 
218
 */
 
219
static Bool
 
220
ATII2CPutByte
 
221
(
 
222
    I2CDevPtr pI2CDev,
 
223
    I2CByte   Data
 
224
)
 
225
{
 
226
    I2CBusPtr pI2CBus = pI2CDev->pI2CBus;
 
227
    ATII2CPtr pATII2C = pI2CBus->DriverPrivate.ptr;
 
228
    ATIPtr    pATI    = pATII2C->pATI;
 
229
    int       i;
 
230
    Bool      Result;
 
231
 
 
232
    ATII2CSDADirOn;             /* Set data line direction to out-bound */
 
233
 
 
234
    /* Send data byte */
 
235
    for (i = 0;  i < 8;  i++)
 
236
    {
 
237
        ATII2CSDABitSet(Data & 0x80U);
 
238
        ATII2CSCLBitOn;
 
239
        ATII2CSCLBitOff;
 
240
 
 
241
        Data <<= 1;
 
242
    }
 
243
 
 
244
    ATII2CSDABitOn;             /* Release data line */
 
245
 
 
246
    ATII2CSDADirOff;            /* Set data line direction to in-bound */
 
247
 
 
248
    ATII2CSCLBitOn;             /* Start bit-read clock pulse */
 
249
 
 
250
    /* Get [N]ACK bit */
 
251
    if (ATII2CSDABitGet)
 
252
        Result = FALSE;
 
253
    else
 
254
        Result = TRUE;
 
255
 
 
256
    ATII2CSCLBitOff;            /* End clock pulse */
 
257
 
 
258
    return Result;
 
259
}
 
260
 
 
261
/*
 
262
 * ATII2CGetByte --
 
263
 *
 
264
 * This function retrieves an 8-bit value from the I2C bus.
 
265
 */
 
266
static Bool
 
267
ATII2CGetByte
 
268
(
 
269
    I2CDevPtr pI2CDev,
 
270
    I2CByte   *pData,
 
271
    Bool      Last
 
272
)
 
273
{
 
274
    I2CBusPtr     pI2CBus = pI2CDev->pI2CBus;
 
275
    ATII2CPtr     pATII2C = pI2CBus->DriverPrivate.ptr;
 
276
    ATIPtr        pATI    = pATII2C->pATI;
 
277
    unsigned long Value   = 1;
 
278
 
 
279
    do
 
280
    {
 
281
        ATII2CSCLBitOn;         /* Start bit-read clock pulse */
 
282
 
 
283
        /* Accumulate bit into byte value */
 
284
        Value <<= 1;
 
285
        if (ATII2CSDABitGet)
 
286
            Value++;
 
287
 
 
288
        ATII2CSCLBitOff;        /* End clock pulse */
 
289
    } while (Value <= (unsigned long)((I2CByte)(-1)));
 
290
 
 
291
    *pData = (I2CByte)Value;
 
292
 
 
293
    ATII2CSDADirOn;             /* Set data line direction to out-bound */
 
294
 
 
295
    /* Send [N]ACK bit */
 
296
    ATII2CSDABitSet(Last);
 
297
    ATII2CSCLBitOn;
 
298
    ATII2CSCLBitOff;
 
299
 
 
300
    if (!Last)
 
301
        ATII2CSDABitOn;         /* Release data line */
 
302
 
 
303
    ATII2CSDADirOff;            /* Set data line direction to in-bound */
 
304
 
 
305
    return TRUE;
 
306
}
 
307
 
 
308
/*
 
309
 * ATICreateI2CBusRec --
 
310
 *
 
311
 * This function is called to initialise an I2CBusRec.
 
312
 */
 
313
I2CBusPtr
 
314
ATICreateI2CBusRec
 
315
(
 
316
    int    iScreen,
 
317
    ATIPtr pATI,
 
318
    char   *BusName
 
319
)
 
320
{
 
321
    I2CBusPtr pI2CBus;
 
322
    ATII2CPtr pATII2C = xnfcalloc(1, SizeOf(ATII2CRec));
 
323
 
 
324
    if (!(pI2CBus = xf86CreateI2CBusRec()))
 
325
    {
 
326
        xf86DrvMsg(iScreen, X_WARNING, "Unable to allocate I2C Bus record.\n");
 
327
        free(pATII2C);
 
328
        return NULL;
 
329
    }
 
330
 
 
331
    /* Fill in generic structure fields */
 
332
    pI2CBus->BusName           = BusName;
 
333
    pI2CBus->scrnIndex         = iScreen;
 
334
 
 
335
    pI2CBus->I2CAddress        = ATII2CAddress;
 
336
    pI2CBus->I2CStart          = ATII2CStart;
 
337
    pI2CBus->I2CStop           = ATII2CStop;
 
338
    pI2CBus->I2CPutByte        = ATII2CPutByte;
 
339
    pI2CBus->I2CGetByte        = ATII2CGetByte;
 
340
 
 
341
    pI2CBus->DriverPrivate.ptr = pATII2C;
 
342
 
 
343
    pATII2C->pATI              = pATI;
 
344
 
 
345
    if (xf86I2CBusInit(pI2CBus))
 
346
        return pI2CBus;
 
347
 
 
348
    xf86DrvMsg(iScreen, X_WARNING,
 
349
        "I2C bus %s initialisation failure.\n", BusName);
 
350
    xf86DestroyI2CBusRec(pI2CBus, TRUE, TRUE);
 
351
    free(pATII2C);
 
352
    return NULL;
 
353
}
 
354
 
 
355
/*
 
356
 * ATII2CPreInit --
 
357
 *
 
358
 * This is called by ATIPreInit() to create I2C bus record(s) for the adapter.
 
359
 */
 
360
void
 
361
ATII2CPreInit
 
362
(
 
363
    ScrnInfoPtr pScreenInfo,
 
364
    ATIPtr      pATI
 
365
)
 
366
{
 
367
            if (!xf86LoadSubModule(pScreenInfo, "i2c"))
 
368
                return;
 
369
 
 
370
            ATIMach64I2CPreInit(pScreenInfo, pATI);
 
371
}
 
372
 
 
373
/*
 
374
 * ATII2CFreeScreen --
 
375
 *
 
376
 * This is called by ATIFreeScreen() to remove the driver's I2C interface.
 
377
 */
 
378
void
 
379
ATII2CFreeScreen
 
380
(
 
381
    int iScreen
 
382
)
 
383
{
 
384
    I2CBusPtr pI2CBus, *ppI2CBus;
 
385
    ATII2CPtr pATII2C;
 
386
    int nI2CBus;
 
387
 
 
388
    nI2CBus = xf86I2CGetScreenBuses(iScreen, &ppI2CBus);
 
389
    while (--nI2CBus >= 0)
 
390
    {
 
391
        pI2CBus = ppI2CBus[nI2CBus];
 
392
        pATII2C = pI2CBus->DriverPrivate.ptr;
 
393
 
 
394
        xf86DestroyI2CBusRec(pI2CBus, TRUE, TRUE);
 
395
        free(pATII2C);
 
396
    }
 
397
 
 
398
    free(ppI2CBus);
 
399
}