V4L/DVB (4922): Add usbvision driver
[safe/jmp/linux-2.6] / drivers / media / video / usbvision / usbvision-i2c.c
1 /* 
2  * I2C_ALGO_USB.C
3  *  i2c algorithm for USB-I2C Bridges
4  *
5  * Copyright (c) 1999-2005 Joerg Heckenbach <joerg@heckenbach-aw.de>
6  *                         Dwaine Garden <dwainegarden@rogers.com>
7  *
8  * This module is part of usbvision driver project.
9  * Updates to driver completed by Dwaine P. Garden
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24  */
25
26
27 #include <linux/kernel.h>
28 #include <linux/module.h>
29 #include <linux/delay.h>
30 #include <linux/slab.h>
31 #include <linux/version.h>
32         #include <linux/utsname.h>
33 #include <linux/init.h>
34 #include <asm/uaccess.h>
35 #include <linux/ioport.h>
36 #include <linux/errno.h>
37 #include <linux/sched.h>
38 #include <linux/usb.h>
39 #include <linux/i2c.h>
40 #include "usbvision-i2c.h"
41
42 static int debug = 0;   
43
44 #if defined(module_param)                               // Showing parameters under SYSFS
45 module_param (debug, int, 0444);                        // debug mode of the device driver
46 #else
47 MODULE_PARM(debug, "i");                                // debug mode of the device driver
48 #endif
49
50 MODULE_AUTHOR("Joerg Heckenbach");
51 MODULE_DESCRIPTION("I2C algorithm for USB-I2C-bridges");
52 MODULE_LICENSE("GPL");
53
54
55 static inline int try_write_address(struct i2c_adapter *i2c_adap,
56                                     unsigned char addr, int retries)
57 {
58         struct i2c_algo_usb_data *adap = i2c_adap->algo_data;
59         void *data;
60         int i, ret = -1;
61         char buf[4];
62
63         data = i2c_get_adapdata(i2c_adap);
64         buf[0] = 0x00;
65         for (i = 0; i <= retries; i++) {
66                 ret = (adap->outb(data, addr, buf, 1));
67                 if (ret == 1)
68                         break;  /* success! */
69                 udelay(5 /*adap->udelay */ );
70                 if (i == retries)       /* no success */
71                         break;
72                 udelay(adap->udelay);
73         }
74         if (debug) {
75                 if (i) {
76                         info("%s: Needed %d retries for address %#2x", __FUNCTION__, i, addr);
77                         info("%s: Maybe there's no device at this address", __FUNCTION__);
78                 }
79         }
80         return ret;
81 }
82
83 static inline int try_read_address(struct i2c_adapter *i2c_adap,
84                                    unsigned char addr, int retries)
85 {
86         struct i2c_algo_usb_data *adap = i2c_adap->algo_data;
87         void *data;
88         int i, ret = -1;
89         char buf[4];
90
91         data = i2c_get_adapdata(i2c_adap);
92         for (i = 0; i <= retries; i++) {
93                 ret = (adap->inb(data, addr, buf, 1));
94                 if (ret == 1)
95                         break;  /* success! */
96                 udelay(5 /*adap->udelay */ );
97                 if (i == retries)       /* no success */
98                         break;
99                 udelay(adap->udelay);
100         }
101         if (debug) {
102                 if (i) {
103                         info("%s: Needed %d retries for address %#2x", __FUNCTION__, i, addr);
104                         info("%s: Maybe there's no device at this address", __FUNCTION__);
105                 }
106         }
107         return ret;
108 }
109
110 static inline int usb_find_address(struct i2c_adapter *i2c_adap,
111                                    struct i2c_msg *msg, int retries,
112                                    unsigned char *add)
113 {
114         unsigned short flags = msg->flags;
115         
116         unsigned char addr;
117         int ret;
118         if ((flags & I2C_M_TEN)) {
119                 /* a ten bit address */
120                 addr = 0xf0 | ((msg->addr >> 7) & 0x03);
121                 /* try extended address code... */
122                 ret = try_write_address(i2c_adap, addr, retries);
123                 if (ret != 1) {
124                         err("died at extended address code, while writing");
125                         return -EREMOTEIO;
126                 }
127                 add[0] = addr;
128                 if (flags & I2C_M_RD) {
129                         /* okay, now switch into reading mode */
130                         addr |= 0x01;
131                         ret = try_read_address(i2c_adap, addr, retries);
132                         if (ret != 1) {
133                                 err("died at extended address code, while reading");
134                                 return -EREMOTEIO;
135                         }
136                 }
137
138         } else {                /* normal 7bit address  */
139                 addr = (msg->addr << 1);
140                 if (flags & I2C_M_RD)
141                         addr |= 1;
142                 if (flags & I2C_M_REV_DIR_ADDR)
143                         addr ^= 1;
144
145                 add[0] = addr;
146                 if (flags & I2C_M_RD)
147                         ret = try_read_address(i2c_adap, addr, retries);
148                 else
149                         ret = try_write_address(i2c_adap, addr, retries);
150
151                 if (ret != 1) {
152                         return -EREMOTEIO;
153                 }
154         }
155         return 0;
156 }
157
158 static int
159 usb_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num)
160 {
161         struct i2c_msg *pmsg;
162         struct i2c_algo_usb_data *adap = i2c_adap->algo_data;
163         void *data;
164         int i, ret;
165         unsigned char addr;
166
167         data = i2c_get_adapdata(i2c_adap);
168
169         for (i = 0; i < num; i++) {
170                 pmsg = &msgs[i];
171                 ret = usb_find_address(i2c_adap, pmsg, i2c_adap->retries, &addr);
172                 if (ret != 0) {
173                         if (debug) {
174                                 info("%s: got NAK from device, message #%d\n", __FUNCTION__, i);
175                         }
176                         return (ret < 0) ? ret : -EREMOTEIO;
177                 }
178
179                 if (pmsg->flags & I2C_M_RD) {
180                         /* read bytes into buffer */
181                         ret = (adap->inb(data, addr, pmsg->buf, pmsg->len));
182                         if (ret < pmsg->len) {
183                                 return (ret < 0) ? ret : -EREMOTEIO;
184                         }
185                 } else {
186                         /* write bytes from buffer */
187                         ret = (adap->outb(data, addr, pmsg->buf, pmsg->len));
188                         if (ret < pmsg->len) {
189                                 return (ret < 0) ? ret : -EREMOTEIO;
190                         }
191                 }
192         }
193         return num;
194 }
195
196 static int algo_control(struct i2c_adapter *adapter, unsigned int cmd, unsigned long arg)
197 {
198         return 0;
199 }
200
201 static u32 usb_func(struct i2c_adapter *adap)
202 {
203         return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR | I2C_FUNC_PROTOCOL_MANGLING;
204 }
205
206
207 /* -----exported algorithm data: -------------------------------------  */
208
209 static struct i2c_algorithm i2c_usb_algo = {
210         .master_xfer   = usb_xfer,
211         .smbus_xfer    = NULL,
212         .slave_send    = NULL,
213         .slave_recv    = NULL,
214         .algo_control  = algo_control,
215         .functionality = usb_func,
216 };
217
218
219 /*
220  * registering functions to load algorithms at runtime
221  */
222 int usbvision_i2c_usb_add_bus(struct i2c_adapter *adap)
223 {
224         /* register new adapter to i2c module... */
225
226         adap->algo = &i2c_usb_algo;
227
228         adap->timeout = 100;    /* default values, should       */
229         adap->retries = 3;      /* be replaced by defines       */
230
231 #ifdef MODULE
232         #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 21)
233                 MOD_INC_USE_COUNT;
234         #endif
235 #endif
236
237         i2c_add_adapter(adap);
238
239         if (debug) {
240                 info("i2c bus for %s registered", adap->name);
241         }
242
243         return 0;
244 }
245
246
247 int usbvision_i2c_usb_del_bus(struct i2c_adapter *adap)
248 {
249
250         i2c_del_adapter(adap);
251
252         if (debug) {
253                 info("i2c bus for %s unregistered", adap->name);
254         }
255 #ifdef MODULE
256         #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 21)
257                 MOD_DEC_USE_COUNT;
258         #endif
259 #endif
260
261         return 0;
262 }
263
264 EXPORT_SYMBOL(usbvision_i2c_usb_add_bus);
265 EXPORT_SYMBOL(usbvision_i2c_usb_del_bus);