aboutsummaryrefslogtreecommitdiffstats
path: root/bttv/driver/i2c.c
diff options
context:
space:
mode:
Diffstat (limited to 'bttv/driver/i2c.c')
-rw-r--r--bttv/driver/i2c.c541
1 files changed, 276 insertions, 265 deletions
diff --git a/bttv/driver/i2c.c b/bttv/driver/i2c.c
index 736ddc5..f8c8d55 100644
--- a/bttv/driver/i2c.c
+++ b/bttv/driver/i2c.c
@@ -1,7 +1,7 @@
/*
- * Generic i2c interface for linux
+ * Generic i2c interface for linux
*
- * (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de>
+ * (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de>
*
*/
@@ -23,6 +23,7 @@
static int scan = 0;
static int verbose = 1;
static int i2c_debug = 0;
+
#if LINUX_VERSION_CODE >= 0x020117
MODULE_PARM(scan,"i");
MODULE_PARM(verbose,"i");
@@ -37,221 +38,238 @@ static int bus_count = 0, driver_count = 0;
int i2c_init(void)
{
- printk(KERN_INFO "i2c: initialized%s\n",
- scan ? " (i2c bus scan enabled)" : "");
- /* anything to do here ? */
- return 0;
+ printk(KERN_INFO "i2c: initialized%s\n",
+ scan ? " (i2c bus scan enabled)" : "");
+ /* anything to do here ? */
+ return 0;
}
/* ----------------------------------------------------------------------- */
static void i2c_attach_device(struct i2c_bus *bus, struct i2c_driver *driver)
{
- unsigned long flags;
- struct i2c_device *device;
- int i,j,ack=1;
- unsigned char addr;
+ unsigned long flags;
+ struct i2c_device *device;
+ int i,j,ack=1;
+ unsigned char addr;
- /* probe for device */
- LOCK_I2C_BUS(bus);
- for (addr = driver->addr_l; addr <= driver->addr_h; addr += 2) {
- i2c_start(bus);
- ack = i2c_sendbyte(bus,addr,0);
- i2c_stop(bus);
- if (!ack)
- break;
- }
- UNLOCK_I2C_BUS(bus);
- if (ack)
- return;
-
- /* got answer */
- for (i = 0; i < I2C_DEVICE_MAX; i++)
- if (NULL == driver->devices[i])
- break;
- if (I2C_DEVICE_MAX == i)
- return;
-
- for (j = 0; j < I2C_DEVICE_MAX; j++)
- if (NULL == bus->devices[j])
- break;
- if (I2C_DEVICE_MAX == j)
- return;
-
- if (NULL == (device = kmalloc(sizeof(struct i2c_device),GFP_KERNEL)))
- return;
- device->bus = bus;
- device->driver = driver;
- device->addr = addr;
-
- /* attach */
- if (0 != driver->attach(device)) {
- kfree(device);
- return;
- }
- driver->devices[i] = device;
- driver->devcount++;
- bus->devices[j] = device;
- bus->devcount++;
-
- if (bus->attach_inform)
- bus->attach_inform(bus,driver->id);
- REGPRINT(printk("i2c: device attached: %s (addr=0x%02x, bus=%s, driver=%s)\n",device->name,addr,bus->name,driver->name));
+ /* probe for device */
+ LOCK_I2C_BUS(bus);
+ for (addr = driver->addr_l; addr <= driver->addr_h; addr += 2)
+ {
+ i2c_start(bus);
+ ack = i2c_sendbyte(bus,addr,0);
+ i2c_stop(bus);
+ if (!ack)
+ break;
+ }
+ UNLOCK_I2C_BUS(bus);
+ if (ack)
+ return;
+
+ /* got answer */
+ for (i = 0; i < I2C_DEVICE_MAX; i++)
+ if (NULL == driver->devices[i])
+ break;
+ if (I2C_DEVICE_MAX == i)
+ return;
+
+ for (j = 0; j < I2C_DEVICE_MAX; j++)
+ if (NULL == bus->devices[j])
+ break;
+ if (I2C_DEVICE_MAX == j)
+ return;
+
+ if (NULL == (device = kmalloc(sizeof(struct i2c_device),GFP_KERNEL)))
+ return;
+ device->bus = bus;
+ device->driver = driver;
+ device->addr = addr;
+
+ /* Attach */
+
+ if (driver->attach(device)!=0)
+ {
+ kfree(device);
+ return;
+ }
+ driver->devices[i] = device;
+ driver->devcount++;
+ bus->devices[j] = device;
+ bus->devcount++;
+
+ if (bus->attach_inform)
+ bus->attach_inform(bus,driver->id);
+ REGPRINT(printk("i2c: device attached: %s (addr=0x%02x, bus=%s, driver=%s)\n",device->name,addr,bus->name,driver->name));
}
static void i2c_detach_device(struct i2c_device *device)
{
- int i;
-
- if (device->bus->detach_inform)
- device->bus->detach_inform(device->bus,device->driver->id);
- device->driver->detach(device);
-
- for (i = 0; i < I2C_DEVICE_MAX; i++)
- if (device == device->driver->devices[i])
- break;
- if (I2C_DEVICE_MAX == i) {
- printk(KERN_WARNING "i2c: detach_device #1: device not found: %s\n",
- device->name);
- return;
- }
- device->driver->devices[i] = NULL;
- device->driver->devcount--;
-
- for (i = 0; i < I2C_DEVICE_MAX; i++)
- if (device == device->bus->devices[i])
- break;
- if (I2C_DEVICE_MAX == i) {
- printk(KERN_WARNING "i2c: detach_device #2: device not found: %s\n",
- device->name);
- return;
- }
- device->bus->devices[i] = NULL;
- device->bus->devcount--;
-
- REGPRINT(printk("i2c: device detached: %s (addr=0x%02x, bus=%s, driver=%s)\n",device->name,device->addr,device->bus->name,device->driver->name));
- kfree(device);
+ int i;
+
+ if (device->bus->detach_inform)
+ device->bus->detach_inform(device->bus,device->driver->id);
+ device->driver->detach(device);
+
+ for (i = 0; i < I2C_DEVICE_MAX; i++)
+ if (device == device->driver->devices[i])
+ break;
+ if (I2C_DEVICE_MAX == i)
+ {
+ printk(KERN_WARNING "i2c: detach_device #1: device not found: %s\n",
+ device->name);
+ return;
+ }
+ device->driver->devices[i] = NULL;
+ device->driver->devcount--;
+
+ for (i = 0; i < I2C_DEVICE_MAX; i++)
+ if (device == device->bus->devices[i])
+ break;
+ if (I2C_DEVICE_MAX == i)
+ {
+ printk(KERN_WARNING "i2c: detach_device #2: device not found: %s\n",
+ device->name);
+ return;
+ }
+ device->bus->devices[i] = NULL;
+ device->bus->devcount--;
+
+ REGPRINT(printk("i2c: device detached: %s (addr=0x%02x, bus=%s, driver=%s)\n",device->name,device->addr,device->bus->name,device->driver->name));
+ kfree(device);
}
/* ----------------------------------------------------------------------- */
int i2c_register_bus(struct i2c_bus *bus)
{
- unsigned long flags;
- int i,ack;
-
- memset(bus->devices,0,sizeof(bus->devices));
- bus->devcount = 0;
-
- for (i = 0; i < I2C_BUS_MAX; i++)
- if (NULL == busses[i])
- break;
- if (I2C_BUS_MAX == i)
- return -ENOMEM;
-
- busses[i] = bus;
- bus_count++;
- REGPRINT(printk("i2c: bus registered: %s\n",bus->name));
-
- LOCK_I2C_BUS(bus);
- i2c_reset(bus);
- if (scan) {
- /* scan whole i2c bus */
- for (i = 0; i < 256; i+=2) {
- i2c_start(bus);
- ack = i2c_sendbyte(bus,i,0);
- i2c_stop(bus);
- if (!ack) {
- printk("i2c: scanning bus %s: found device at addr=0x%02x\n",
- bus->name,i);
- }
+ unsigned long flags;
+ int i,ack;
+
+ memset(bus->devices,0,sizeof(bus->devices));
+ bus->devcount = 0;
+
+ for (i = 0; i < I2C_BUS_MAX; i++)
+ if (NULL == busses[i])
+ break;
+ if (I2C_BUS_MAX == i)
+ return -ENOMEM;
+
+ busses[i] = bus;
+ bus_count++;
+ REGPRINT(printk("i2c: bus registered: %s\n",bus->name));
+
+ MOD_INC_USE_COUNT;
+
+ if (scan)
+ {
+ /* scan whole i2c bus */
+ LOCK_I2C_BUS(bus);
+ for (i = 0; i < 256; i+=2)
+ {
+ i2c_start(bus);
+ ack = i2c_sendbyte(bus,i,0);
+ i2c_stop(bus);
+ if (!ack)
+ {
+ printk(KERN_INFO "i2c: scanning bus %s: found device at addr=0x%02x\n",
+ bus->name,i);
+ }
+ }
+ UNLOCK_I2C_BUS(bus);
}
- }
- UNLOCK_I2C_BUS(bus);
-
- /* probe available drivers */
- for (i = 0; i < I2C_DRIVER_MAX; i++)
- if (drivers[i])
- i2c_attach_device(bus,drivers[i]);
- return 0;
+ /* probe available drivers */
+ for (i = 0; i < I2C_DRIVER_MAX; i++)
+ if (drivers[i])
+ i2c_attach_device(bus,drivers[i]);
+ return 0;
}
int i2c_unregister_bus(struct i2c_bus *bus)
{
- int i;
-
- /* detach devices */
- for (i = 0; i < I2C_DEVICE_MAX; i++)
- if (bus->devices[i])
- i2c_detach_device(bus->devices[i]);
-
- for (i = 0; i < I2C_BUS_MAX; i++)
- if (bus == busses[i])
- break;
- if (I2C_BUS_MAX == i) {
- printk(KERN_WARNING "i2c: unregister_bus #1: bus not found: %s\n",
- bus->name);
- return -ENODEV;
- }
-
- busses[i] = NULL;
- bus_count--;
- REGPRINT(printk("i2c: bus unregistered: %s\n",bus->name));
-
- return 0;
+ int i;
+
+ /* detach devices */
+ for (i = 0; i < I2C_DEVICE_MAX; i++)
+ if (bus->devices[i])
+ i2c_detach_device(bus->devices[i]);
+
+ for (i = 0; i < I2C_BUS_MAX; i++)
+ if (bus == busses[i])
+ break;
+ if (I2C_BUS_MAX == i)
+ {
+ printk(KERN_WARNING "i2c: unregister_bus #1: bus not found: %s\n",
+ bus->name);
+ return -ENODEV;
+ }
+
+ MOD_DEC_USE_COUNT;
+
+ busses[i] = NULL;
+ bus_count--;
+ REGPRINT(printk("i2c: bus unregistered: %s\n",bus->name));
+
+ return 0;
}
/* ----------------------------------------------------------------------- */
int i2c_register_driver(struct i2c_driver *driver)
{
- int i;
-
- memset(driver->devices,0,sizeof(driver->devices));
- driver->devcount = 0;
-
- for (i = 0; i < I2C_DRIVER_MAX; i++)
- if (NULL == drivers[i])
- break;
- if (I2C_DRIVER_MAX == i)
- return -ENOMEM;
-
- drivers[i] = driver;
- driver_count++;
- REGPRINT(printk("i2c: driver registered: %s\n",driver->name));
-
- /* probe available busses */
- for (i = 0; i < I2C_BUS_MAX; i++)
- if (busses[i])
- i2c_attach_device(busses[i],driver);
-
- return 0;
+ int i;
+
+ memset(driver->devices,0,sizeof(driver->devices));
+ driver->devcount = 0;
+
+ for (i = 0; i < I2C_DRIVER_MAX; i++)
+ if (NULL == drivers[i])
+ break;
+ if (I2C_DRIVER_MAX == i)
+ return -ENOMEM;
+
+ drivers[i] = driver;
+ driver_count++;
+
+ MOD_INC_USE_COUNT;
+
+ REGPRINT(printk("i2c: driver registered: %s\n",driver->name));
+
+ /* Probe available busses */
+ for (i = 0; i < I2C_BUS_MAX; i++)
+ if (busses[i])
+ i2c_attach_device(busses[i],driver);
+
+ return 0;
}
int i2c_unregister_driver(struct i2c_driver *driver)
{
- int i;
-
- /* detach devices */
- for (i = 0; i < I2C_DEVICE_MAX; i++)
- if (driver->devices[i])
- i2c_detach_device(driver->devices[i]);
-
- for (i = 0; i < I2C_DRIVER_MAX; i++)
- if (driver == drivers[i])
- break;
- if (I2C_DRIVER_MAX == i) {
- printk(KERN_WARNING "i2c: unregister_driver: driver not found: %s\n",
- driver->name);
- return -ENODEV;
- }
-
- drivers[i] = NULL;
- driver_count--;
- REGPRINT(printk("i2c: driver unregistered: %s\n",driver->name));
-
- return 0;
+ int i;
+
+ /* detach devices */
+ for (i = 0; i < I2C_DEVICE_MAX; i++)
+ if (driver->devices[i])
+ i2c_detach_device(driver->devices[i]);
+
+ for (i = 0; i < I2C_DRIVER_MAX; i++)
+ if (driver == drivers[i])
+ break;
+ if (I2C_DRIVER_MAX == i)
+ {
+ printk(KERN_WARNING "i2c: unregister_driver: driver not found: %s\n",
+ driver->name);
+ return -ENODEV;
+ }
+
+ MOD_DEC_USE_COUNT;
+
+ drivers[i] = NULL;
+ driver_count--;
+ REGPRINT(printk("i2c: driver unregistered: %s\n",driver->name));
+
+ return 0;
}
/* ----------------------------------------------------------------------- */
@@ -259,16 +277,16 @@ int i2c_unregister_driver(struct i2c_driver *driver)
int i2c_control_device(struct i2c_bus *bus, int id,
unsigned int cmd, void *arg)
{
- int i;
-
- for (i = 0; i < I2C_DEVICE_MAX; i++)
- if (bus->devices[i] && bus->devices[i]->driver->id == id)
- break;
- if (i == I2C_DEVICE_MAX)
- return -ENODEV;
- if (NULL == bus->devices[i]->driver->command)
- return -ENODEV;
- return bus->devices[i]->driver->command(bus->devices[i],cmd,arg);
+ int i;
+
+ for (i = 0; i < I2C_DEVICE_MAX; i++)
+ if (bus->devices[i] && bus->devices[i]->driver->id == id)
+ break;
+ if (i == I2C_DEVICE_MAX)
+ return -ENODEV;
+ if (NULL == bus->devices[i]->driver->command)
+ return -ENODEV;
+ return bus->devices[i]->driver->command(bus->devices[i],cmd,arg);
}
/* ----------------------------------------------------------------------- */
@@ -276,116 +294,111 @@ int i2c_control_device(struct i2c_bus *bus, int id,
#define I2C_SET(bus,ctrl,data) (bus->i2c_setlines(bus,ctrl,data))
#define I2C_GET(bus) (bus->i2c_getdataline(bus))
-void i2c_reset(struct i2c_bus *bus)
-{
- I2C_SET(bus,1,1);
- I2C_DEBUG(printk("%s: bus reset",bus->name));
-}
-
void i2c_start(struct i2c_bus *bus)
{
- I2C_SET(bus,0,1);
- I2C_SET(bus,1,1);
- I2C_SET(bus,1,0);
- I2C_SET(bus,0,0);
- I2C_DEBUG(printk("%s: < ",bus->name));
+ I2C_SET(bus,0,1);
+ I2C_SET(bus,1,1);
+ I2C_SET(bus,1,0);
+ I2C_SET(bus,0,0);
+ I2C_DEBUG(printk("%s: < ",bus->name));
}
void i2c_stop(struct i2c_bus *bus)
{
- I2C_SET(bus,0,0);
- I2C_SET(bus,1,0);
- I2C_SET(bus,1,1);
- I2C_DEBUG(printk(">\n"));
+ I2C_SET(bus,0,0);
+ I2C_SET(bus,1,0);
+ I2C_SET(bus,1,1);
+ I2C_DEBUG(printk(">\n"));
}
void i2c_one(struct i2c_bus *bus)
{
- I2C_SET(bus,0,1);
- I2C_SET(bus,1,1);
- I2C_SET(bus,0,1);
+ I2C_SET(bus,0,1);
+ I2C_SET(bus,1,1);
+ I2C_SET(bus,0,1);
}
void i2c_zero(struct i2c_bus *bus)
{
- I2C_SET(bus,0,0);
- I2C_SET(bus,1,0);
- I2C_SET(bus,0,0);
+ I2C_SET(bus,0,0);
+ I2C_SET(bus,1,0);
+ I2C_SET(bus,0,0);
}
int i2c_ack(struct i2c_bus *bus)
{
- int ack;
+ int ack;
- I2C_SET(bus,0,1);
- I2C_SET(bus,1,1);
- ack = I2C_GET(bus);
- I2C_SET(bus,0,1);
- return ack;
+ I2C_SET(bus,0,1);
+ I2C_SET(bus,1,1);
+ ack = I2C_GET(bus);
+ I2C_SET(bus,0,1);
+ return ack;
}
int i2c_sendbyte(struct i2c_bus *bus,unsigned char data,int wait_for_ack)
{
- int i, ack;
+ int i, ack;
- I2C_SET(bus,0,0);
- for (i=7; i>=0; i--)
- (data&(1<<i)) ? i2c_one(bus) : i2c_zero(bus);
- if (wait_for_ack)
- udelay(wait_for_ack);
- ack=i2c_ack(bus);
- I2C_DEBUG(printk("%02x%c ",(int)data,ack?'-':'+'));
- return ack;
+ I2C_SET(bus,0,0);
+ for (i=7; i>=0; i--)
+ (data&(1<<i)) ? i2c_one(bus) : i2c_zero(bus);
+ if (wait_for_ack)
+ udelay(wait_for_ack);
+ ack=i2c_ack(bus);
+ I2C_DEBUG(printk("%02x%c ",(int)data,ack?'-':'+'));
+ return ack;
}
unsigned char i2c_readbyte(struct i2c_bus *bus,int last)
{
- int i;
- unsigned char data=0;
+ int i;
+ unsigned char data=0;
- I2C_SET(bus,0,1);
- for (i=7; i>=0; i--) {
- I2C_SET(bus,1,1);
- if (I2C_GET(bus))
- data |= (1<<i);
I2C_SET(bus,0,1);
- }
- last ? i2c_one(bus) : i2c_zero(bus);
- I2C_DEBUG(printk("=%02x%c ",(int)data,last?'-':'+'));
- return data;
+ for (i=7; i>=0; i--)
+ {
+ I2C_SET(bus,1,1);
+ if (I2C_GET(bus))
+ data |= (1<<i);
+ I2C_SET(bus,0,1);
+ }
+ last ? i2c_one(bus) : i2c_zero(bus);
+ I2C_DEBUG(printk("=%02x%c ",(int)data,last?'-':'+'));
+ return data;
}
/* ----------------------------------------------------------------------- */
int i2c_read(struct i2c_bus *bus, unsigned char addr)
{
- int ret;
+ int ret;
- if (bus->i2c_read)
- return bus->i2c_read(bus, addr);
-
- i2c_start(bus);
- i2c_sendbyte(bus,addr,0);
- ret = i2c_readbyte(bus,1);
- i2c_stop(bus);
- return ret;
+ if (bus->i2c_read)
+ return bus->i2c_read(bus, addr);
+
+ i2c_start(bus);
+ i2c_sendbyte(bus,addr,0);
+ ret = i2c_readbyte(bus,1);
+ i2c_stop(bus);
+ return ret;
}
int i2c_write(struct i2c_bus *bus, unsigned char addr,
unsigned char data1, unsigned char data2, int both)
{
- int ack;
-
- if (bus->i2c_write)
- return bus->i2c_write(bus, addr, data1, data2, both);
-
- i2c_start(bus);
- i2c_sendbyte(bus,addr,0);
- ack = i2c_sendbyte(bus,data1,0);
- if (both)
- ack = i2c_sendbyte(bus,data2,0);
- i2c_stop(bus);
- return ack ? -1 : 0 ;
+ int ack;
+
+ if (bus->i2c_write)
+ return bus->i2c_write(bus, addr, data1, data2, both);
+
+ i2c_start(bus);
+ i2c_sendbyte(bus,addr,0);
+ ack = i2c_sendbyte(bus,data1,0);
+ if (both)
+ ack = i2c_sendbyte(bus,data2,0);
+ i2c_stop(bus);
+ return ack ? -1 : 0 ;
}
/* ----------------------------------------------------------------------- */
@@ -398,7 +411,6 @@ EXPORT_SYMBOL(i2c_unregister_bus);
EXPORT_SYMBOL(i2c_register_driver);
EXPORT_SYMBOL(i2c_unregister_driver);
EXPORT_SYMBOL(i2c_control_device);
-EXPORT_SYMBOL(i2c_reset);
EXPORT_SYMBOL(i2c_start);
EXPORT_SYMBOL(i2c_stop);
EXPORT_SYMBOL(i2c_one);
@@ -412,11 +424,10 @@ EXPORT_SYMBOL(i2c_write);
int init_module(void)
{
- return i2c_init();
+ return i2c_init();
}
void cleanup_module(void)
{
}
-
#endif

Privacy Policy