~ubuntu-branches/ubuntu/hardy/linux-ubuntu-modules-2.6.24/hardy-security

« back to all changes in this revision

Viewing changes to ubuntu/media/saa7134/saa7134-i2c.c

  • Committer: Bazaar Package Importer
  • Author(s): Tim Gardner
  • Date: 2008-05-29 07:50:22 UTC
  • mfrom: (21.1.2 hardy-proposed)
  • Revision ID: james.westby@ubuntu.com-20080529075022-05i1iqrph7wpxooj
Tags: 2.6.24-18.26
security upload with ABI bump to -18

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *
3
 
 * device driver for philips saa7134 based TV cards
4
 
 * i2c interface support
5
 
 *
6
 
 * (c) 2001,02 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
7
 
 *
8
 
 *  This program is free software; you can redistribute it and/or modify
9
 
 *  it under the terms of the GNU General Public License as published by
10
 
 *  the Free Software Foundation; either version 2 of the License, or
11
 
 *  (at your option) any later version.
12
 
 *
13
 
 *  This program is distributed in the hope that it will be useful,
14
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 
 *  GNU General Public License for more details.
17
 
 *
18
 
 *  You should have received a copy of the GNU General Public License
19
 
 *  along with this program; if not, write to the Free Software
20
 
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21
 
 */
22
 
 
23
 
#include <linux/init.h>
24
 
#include <linux/list.h>
25
 
#include <linux/module.h>
26
 
#include <linux/kernel.h>
27
 
#include <linux/slab.h>
28
 
#include <linux/delay.h>
29
 
 
30
 
#include "saa7134-reg.h"
31
 
#include "saa7134.h"
32
 
#include <media/v4l2-common.h>
33
 
 
34
 
/* ----------------------------------------------------------- */
35
 
 
36
 
static unsigned int i2c_debug = 0;
37
 
module_param(i2c_debug, int, 0644);
38
 
MODULE_PARM_DESC(i2c_debug,"enable debug messages [i2c]");
39
 
 
40
 
static unsigned int i2c_scan = 0;
41
 
module_param(i2c_scan, int, 0444);
42
 
MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time");
43
 
 
44
 
#define d1printk if (1 == i2c_debug) printk
45
 
#define d2printk if (2 == i2c_debug) printk
46
 
 
47
 
#define I2C_WAIT_DELAY  32
48
 
#define I2C_WAIT_RETRY  16
49
 
 
50
 
/* ----------------------------------------------------------- */
51
 
 
52
 
static char *str_i2c_status[] = {
53
 
        "IDLE", "DONE_STOP", "BUSY", "TO_SCL", "TO_ARB", "DONE_WRITE",
54
 
        "DONE_READ", "DONE_WRITE_TO", "DONE_READ_TO", "NO_DEVICE",
55
 
        "NO_ACKN", "BUS_ERR", "ARB_LOST", "SEQ_ERR", "ST_ERR", "SW_ERR"
56
 
};
57
 
 
58
 
enum i2c_status {
59
 
        IDLE          = 0,  // no I2C command pending
60
 
        DONE_STOP     = 1,  // I2C command done and STOP executed
61
 
        BUSY          = 2,  // executing I2C command
62
 
        TO_SCL        = 3,  // executing I2C command, time out on clock stretching
63
 
        TO_ARB        = 4,  // time out on arbitration trial, still trying
64
 
        DONE_WRITE    = 5,  // I2C command done and awaiting next write command
65
 
        DONE_READ     = 6,  // I2C command done and awaiting next read command
66
 
        DONE_WRITE_TO = 7,  // see 5, and time out on status echo
67
 
        DONE_READ_TO  = 8,  // see 6, and time out on status echo
68
 
        NO_DEVICE     = 9,  // no acknowledge on device slave address
69
 
        NO_ACKN       = 10, // no acknowledge after data byte transfer
70
 
        BUS_ERR       = 11, // bus error
71
 
        ARB_LOST      = 12, // arbitration lost during transfer
72
 
        SEQ_ERR       = 13, // erroneous programming sequence
73
 
        ST_ERR        = 14, // wrong status echoing
74
 
        SW_ERR        = 15  // software error
75
 
};
76
 
 
77
 
static char *str_i2c_attr[] = {
78
 
        "NOP", "STOP", "CONTINUE", "START"
79
 
};
80
 
 
81
 
enum i2c_attr {
82
 
        NOP           = 0,  // no operation on I2C bus
83
 
        STOP          = 1,  // stop condition, no associated byte transfer
84
 
        CONTINUE      = 2,  // continue with byte transfer
85
 
        START         = 3   // start condition with byte transfer
86
 
};
87
 
 
88
 
static inline enum i2c_status i2c_get_status(struct saa7134_dev *dev)
89
 
{
90
 
        enum i2c_status status;
91
 
 
92
 
        status = saa_readb(SAA7134_I2C_ATTR_STATUS) & 0x0f;
93
 
        d2printk(KERN_DEBUG "%s: i2c stat <= %s\n",dev->name,
94
 
                 str_i2c_status[status]);
95
 
        return status;
96
 
}
97
 
 
98
 
static inline void i2c_set_status(struct saa7134_dev *dev,
99
 
                                  enum i2c_status status)
100
 
{
101
 
        d2printk(KERN_DEBUG "%s: i2c stat => %s\n",dev->name,
102
 
                 str_i2c_status[status]);
103
 
        saa_andorb(SAA7134_I2C_ATTR_STATUS,0x0f,status);
104
 
}
105
 
 
106
 
static inline void i2c_set_attr(struct saa7134_dev *dev, enum i2c_attr attr)
107
 
{
108
 
        d2printk(KERN_DEBUG "%s: i2c attr => %s\n",dev->name,
109
 
                 str_i2c_attr[attr]);
110
 
        saa_andorb(SAA7134_I2C_ATTR_STATUS,0xc0,attr << 6);
111
 
}
112
 
 
113
 
static inline int i2c_is_error(enum i2c_status status)
114
 
{
115
 
        switch (status) {
116
 
        case NO_DEVICE:
117
 
        case NO_ACKN:
118
 
        case BUS_ERR:
119
 
        case ARB_LOST:
120
 
        case SEQ_ERR:
121
 
        case ST_ERR:
122
 
                return true;
123
 
        default:
124
 
                return false;
125
 
        }
126
 
}
127
 
 
128
 
static inline int i2c_is_idle(enum i2c_status status)
129
 
{
130
 
        switch (status) {
131
 
        case IDLE:
132
 
        case DONE_STOP:
133
 
                return true;
134
 
        default:
135
 
                return false;
136
 
        }
137
 
}
138
 
 
139
 
static inline int i2c_is_busy(enum i2c_status status)
140
 
{
141
 
        switch (status) {
142
 
        case BUSY:
143
 
                return true;
144
 
        default:
145
 
                return false;
146
 
        }
147
 
}
148
 
 
149
 
static int i2c_is_busy_wait(struct saa7134_dev *dev)
150
 
{
151
 
        enum i2c_status status;
152
 
        int count;
153
 
 
154
 
        for (count = 0; count < I2C_WAIT_RETRY; count++) {
155
 
                status = i2c_get_status(dev);
156
 
                if (!i2c_is_busy(status))
157
 
                        break;
158
 
                saa_wait(I2C_WAIT_DELAY);
159
 
        }
160
 
        if (I2C_WAIT_RETRY == count)
161
 
                return false;
162
 
        return true;
163
 
}
164
 
 
165
 
static int i2c_reset(struct saa7134_dev *dev)
166
 
{
167
 
        enum i2c_status status;
168
 
        int count;
169
 
 
170
 
        d2printk(KERN_DEBUG "%s: i2c reset\n",dev->name);
171
 
        status = i2c_get_status(dev);
172
 
        if (!i2c_is_error(status))
173
 
                return true;
174
 
        i2c_set_status(dev,status);
175
 
 
176
 
        for (count = 0; count < I2C_WAIT_RETRY; count++) {
177
 
                status = i2c_get_status(dev);
178
 
                if (!i2c_is_error(status))
179
 
                        break;
180
 
                udelay(I2C_WAIT_DELAY);
181
 
        }
182
 
        if (I2C_WAIT_RETRY == count)
183
 
                return false;
184
 
 
185
 
        if (!i2c_is_idle(status))
186
 
                return false;
187
 
 
188
 
        i2c_set_attr(dev,NOP);
189
 
        return true;
190
 
}
191
 
 
192
 
static inline int i2c_send_byte(struct saa7134_dev *dev,
193
 
                                enum i2c_attr attr,
194
 
                                unsigned char data)
195
 
{
196
 
        enum i2c_status status;
197
 
        __u32 dword;
198
 
 
199
 
        /* have to write both attr + data in one 32bit word */
200
 
        dword  = saa_readl(SAA7134_I2C_ATTR_STATUS >> 2);
201
 
        dword &= 0x0f;
202
 
        dword |= (attr << 6);
203
 
        dword |= ((__u32)data << 8);
204
 
        dword |= 0x00 << 16;  /* 100 kHz */
205
 
//      dword |= 0x40 << 16;  /* 400 kHz */
206
 
        dword |= 0xf0 << 24;
207
 
        saa_writel(SAA7134_I2C_ATTR_STATUS >> 2, dword);
208
 
        d2printk(KERN_DEBUG "%s: i2c data => 0x%x\n",dev->name,data);
209
 
 
210
 
        if (!i2c_is_busy_wait(dev))
211
 
                return -EIO;
212
 
        status = i2c_get_status(dev);
213
 
        if (i2c_is_error(status))
214
 
                return -EIO;
215
 
        return 0;
216
 
}
217
 
 
218
 
static inline int i2c_recv_byte(struct saa7134_dev *dev)
219
 
{
220
 
        enum i2c_status status;
221
 
        unsigned char data;
222
 
 
223
 
        i2c_set_attr(dev,CONTINUE);
224
 
        if (!i2c_is_busy_wait(dev))
225
 
                return -EIO;
226
 
        status = i2c_get_status(dev);
227
 
        if (i2c_is_error(status))
228
 
                return -EIO;
229
 
        data = saa_readb(SAA7134_I2C_DATA);
230
 
        d2printk(KERN_DEBUG "%s: i2c data <= 0x%x\n",dev->name,data);
231
 
        return data;
232
 
}
233
 
 
234
 
static int saa7134_i2c_xfer(struct i2c_adapter *i2c_adap,
235
 
                            struct i2c_msg *msgs, int num)
236
 
{
237
 
        struct saa7134_dev *dev = i2c_adap->algo_data;
238
 
        enum i2c_status status;
239
 
        unsigned char data;
240
 
        int addr,rc,i,byte;
241
 
 
242
 
        status = i2c_get_status(dev);
243
 
        if (!i2c_is_idle(status))
244
 
                if (!i2c_reset(dev))
245
 
                        return -EIO;
246
 
 
247
 
        d2printk("start xfer\n");
248
 
        d1printk(KERN_DEBUG "%s: i2c xfer:",dev->name);
249
 
        for (i = 0; i < num; i++) {
250
 
                if (!(msgs[i].flags & I2C_M_NOSTART) || 0 == i) {
251
 
                        /* send address */
252
 
                        d2printk("send address\n");
253
 
                        addr  = msgs[i].addr << 1;
254
 
                        if (msgs[i].flags & I2C_M_RD)
255
 
                                addr |= 1;
256
 
                        if (i > 0 && msgs[i].flags & I2C_M_RD) {
257
 
                                /* workaround for a saa7134 i2c bug
258
 
                                 * needed to talk to the mt352 demux
259
 
                                 * thanks to pinnacle for the hint */
260
 
                                int quirk = 0xfd;
261
 
                                d1printk(" [%02x quirk]",quirk);
262
 
                                i2c_send_byte(dev,START,quirk);
263
 
                                i2c_recv_byte(dev);
264
 
                        }
265
 
                        d1printk(" < %02x", addr);
266
 
                        rc = i2c_send_byte(dev,START,addr);
267
 
                        if (rc < 0)
268
 
                                 goto err;
269
 
                }
270
 
                if (msgs[i].flags & I2C_M_RD) {
271
 
                        /* read bytes */
272
 
                        d2printk("read bytes\n");
273
 
                        for (byte = 0; byte < msgs[i].len; byte++) {
274
 
                                d1printk(" =");
275
 
                                rc = i2c_recv_byte(dev);
276
 
                                if (rc < 0)
277
 
                                        goto err;
278
 
                                d1printk("%02x", rc);
279
 
                                msgs[i].buf[byte] = rc;
280
 
                        }
281
 
                } else {
282
 
                        /* write bytes */
283
 
                        d2printk("write bytes\n");
284
 
                        for (byte = 0; byte < msgs[i].len; byte++) {
285
 
                                data = msgs[i].buf[byte];
286
 
                                d1printk(" %02x", data);
287
 
                                rc = i2c_send_byte(dev,CONTINUE,data);
288
 
                                if (rc < 0)
289
 
                                        goto err;
290
 
                        }
291
 
                }
292
 
        }
293
 
        d2printk("xfer done\n");
294
 
        d1printk(" >");
295
 
        i2c_set_attr(dev,STOP);
296
 
        rc = -EIO;
297
 
        if (!i2c_is_busy_wait(dev))
298
 
                goto err;
299
 
        status = i2c_get_status(dev);
300
 
        if (i2c_is_error(status))
301
 
                goto err;
302
 
        /* ensure that the bus is idle for at least one bit slot */
303
 
        msleep(1);
304
 
 
305
 
        d1printk("\n");
306
 
        return num;
307
 
 err:
308
 
        if (1 == i2c_debug) {
309
 
                status = i2c_get_status(dev);
310
 
                printk(" ERROR: %s\n",str_i2c_status[status]);
311
 
        }
312
 
        return rc;
313
 
}
314
 
 
315
 
/* ----------------------------------------------------------- */
316
 
 
317
 
static u32 functionality(struct i2c_adapter *adap)
318
 
{
319
 
        return I2C_FUNC_SMBUS_EMUL;
320
 
}
321
 
 
322
 
static int attach_inform(struct i2c_client *client)
323
 
{
324
 
        struct saa7134_dev *dev = client->adapter->algo_data;
325
 
        int tuner = dev->tuner_type;
326
 
        int conf  = dev->tda9887_conf;
327
 
        struct tuner_setup tun_setup;
328
 
 
329
 
        d1printk( "%s i2c attach [addr=0x%x,client=%s]\n",
330
 
                client->driver->driver.name, client->addr, client->name);
331
 
 
332
 
        /* Am I an i2c remote control? */
333
 
 
334
 
        switch (client->addr) {
335
 
                case 0x7a:
336
 
                case 0x47:
337
 
                case 0x71:
338
 
                {
339
 
                        struct IR_i2c *ir = i2c_get_clientdata(client);
340
 
                        d1printk("%s i2c IR detected (%s).\n",
341
 
                                 client->driver->driver.name, ir->phys);
342
 
                        saa7134_set_i2c_ir(dev,ir);
343
 
                        break;
344
 
                }
345
 
        }
346
 
 
347
 
        if (!client->driver->command)
348
 
                return 0;
349
 
 
350
 
        if (saa7134_boards[dev->board].radio_type != UNSET) {
351
 
 
352
 
                tun_setup.type = saa7134_boards[dev->board].radio_type;
353
 
                tun_setup.addr = saa7134_boards[dev->board].radio_addr;
354
 
 
355
 
                if ((tun_setup.addr == ADDR_UNSET) || (tun_setup.addr == client->addr)) {
356
 
                        tun_setup.mode_mask = T_RADIO;
357
 
 
358
 
                        client->driver->command(client, TUNER_SET_TYPE_ADDR, &tun_setup);
359
 
                }
360
 
        }
361
 
 
362
 
        if (tuner != UNSET) {
363
 
 
364
 
                tun_setup.type = tuner;
365
 
                tun_setup.addr = saa7134_boards[dev->board].tuner_addr;
366
 
                tun_setup.config = saa7134_boards[dev->board].tuner_config;
367
 
                tun_setup.tuner_callback = saa7134_tuner_callback;
368
 
 
369
 
                if ((tun_setup.addr == ADDR_UNSET)||(tun_setup.addr == client->addr)) {
370
 
 
371
 
                        tun_setup.mode_mask = T_ANALOG_TV;
372
 
 
373
 
                        client->driver->command(client,TUNER_SET_TYPE_ADDR, &tun_setup);
374
 
                }
375
 
        }
376
 
 
377
 
        client->driver->command(client, TDA9887_SET_CONFIG, &conf);
378
 
 
379
 
        return 0;
380
 
}
381
 
 
382
 
static struct i2c_algorithm saa7134_algo = {
383
 
        .master_xfer   = saa7134_i2c_xfer,
384
 
        .functionality = functionality,
385
 
};
386
 
 
387
 
static struct i2c_adapter saa7134_adap_template = {
388
 
        .owner         = THIS_MODULE,
389
 
        .class         = I2C_CLASS_TV_ANALOG,
390
 
        .name          = "saa7134",
391
 
        .id            = I2C_HW_SAA7134,
392
 
        .algo          = &saa7134_algo,
393
 
        .client_register = attach_inform,
394
 
};
395
 
 
396
 
static struct i2c_client saa7134_client_template = {
397
 
        .name   = "saa7134 internal",
398
 
};
399
 
 
400
 
/* ----------------------------------------------------------- */
401
 
 
402
 
static int
403
 
saa7134_i2c_eeprom(struct saa7134_dev *dev, unsigned char *eedata, int len)
404
 
{
405
 
        unsigned char buf;
406
 
        int i,err;
407
 
 
408
 
        dev->i2c_client.addr = 0xa0 >> 1;
409
 
        buf = 0;
410
 
        if (1 != (err = i2c_master_send(&dev->i2c_client,&buf,1))) {
411
 
                printk(KERN_INFO "%s: Huh, no eeprom present (err=%d)?\n",
412
 
                       dev->name,err);
413
 
                return -1;
414
 
        }
415
 
        if (len != (err = i2c_master_recv(&dev->i2c_client,eedata,len))) {
416
 
                printk(KERN_WARNING "%s: i2c eeprom read error (err=%d)\n",
417
 
                       dev->name,err);
418
 
                return -1;
419
 
        }
420
 
        for (i = 0; i < len; i++) {
421
 
                if (0 == (i % 16))
422
 
                        printk(KERN_INFO "%s: i2c eeprom %02x:",dev->name,i);
423
 
                printk(" %02x",eedata[i]);
424
 
                if (15 == (i % 16))
425
 
                        printk("\n");
426
 
        }
427
 
        return 0;
428
 
}
429
 
 
430
 
static char *i2c_devs[128] = {
431
 
        [ 0x20      ] = "mpeg encoder (saa6752hs)",
432
 
        [ 0xa0 >> 1 ] = "eeprom",
433
 
        [ 0xc0 >> 1 ] = "tuner (analog)",
434
 
        [ 0x86 >> 1 ] = "tda9887",
435
 
};
436
 
 
437
 
static void do_i2c_scan(char *name, struct i2c_client *c)
438
 
{
439
 
        unsigned char buf;
440
 
        int i,rc;
441
 
 
442
 
        for (i = 0; i < ARRAY_SIZE(i2c_devs); i++) {
443
 
                c->addr = i;
444
 
                rc = i2c_master_recv(c,&buf,0);
445
 
                if (rc < 0)
446
 
                        continue;
447
 
                printk("%s: i2c scan: found device @ 0x%x  [%s]\n",
448
 
                       name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
449
 
        }
450
 
}
451
 
 
452
 
void saa7134_i2c_call_clients(struct saa7134_dev *dev,
453
 
                              unsigned int cmd, void *arg)
454
 
{
455
 
        BUG_ON(NULL == dev->i2c_adap.algo_data);
456
 
        i2c_clients_command(&dev->i2c_adap, cmd, arg);
457
 
}
458
 
 
459
 
int saa7134_i2c_register(struct saa7134_dev *dev)
460
 
{
461
 
        dev->i2c_adap = saa7134_adap_template;
462
 
        dev->i2c_adap.dev.parent = &dev->pci->dev;
463
 
        strcpy(dev->i2c_adap.name,dev->name);
464
 
        dev->i2c_adap.algo_data = dev;
465
 
        i2c_add_adapter(&dev->i2c_adap);
466
 
 
467
 
        dev->i2c_client = saa7134_client_template;
468
 
        dev->i2c_client.adapter = &dev->i2c_adap;
469
 
 
470
 
        saa7134_i2c_eeprom(dev,dev->eedata,sizeof(dev->eedata));
471
 
        if (i2c_scan)
472
 
                do_i2c_scan(dev->name,&dev->i2c_client);
473
 
        return 0;
474
 
}
475
 
 
476
 
int saa7134_i2c_unregister(struct saa7134_dev *dev)
477
 
{
478
 
        i2c_del_adapter(&dev->i2c_adap);
479
 
        return 0;
480
 
}
481
 
 
482
 
/* ----------------------------------------------------------- */
483
 
/*
484
 
 * Local variables:
485
 
 * c-basic-offset: 8
486
 
 * End:
487
 
 */