i2c #1/3: listify i2c core
PATCH 1/1 i2c #1/3: listify i2c core
Hi,
This is the first of tree patches for i2c. Trying to get the i2c cleanups finshed before 2.6.x, so we (hopefully) don't have a ever-changing i2c subsystem in 2.7.x again (which is very annonying for driver maintainance).
Changes:
* listify i2c-core, i.e. make it use <linux/list.h> instead of statically-sized arrays, removed lots of ugly code :)
* added i2c_(get|put)_adapter, changed i2c-dev.c to use these functions instead maintaining is own adapter list.
* killed the I2C_DF_DUMMY flag which had the strange semantics to make the i2c subsystem call driver->attach_adapter on detaches. Added a detach_adapter() callback instead.
* some other minor cleanups along the way ...
Please apply,
Gerd
drivers/i2c/i2c-core.c +139 -186
@@ -38,8 +38,8 @@#define DEB (x) if (i2c_debug>=1) x;#define DEB2 (x) if (i2c_debug>=2) x; -static struct i2c_adapter *adapters[I2C_ADAP_MAX ]; -static struct i2c_driver *drivers[I2C_DRIVER_MAX ]; +static LIST_HEAD (adapters); +static LIST_HEAD (drivers);static DECLARE_MUTEX (core_lists);/**** debug level */
@@ -75,23 +75,17 @@*/ int i2c_add_adapter (struct i2c_adapter *adap) { -int res =0 , i, j; +static int nr =0 ; +struct list_head *item; +struct i2c_driver *driver;down (&core_lists); -for (i =0 ; i <I2C_ADAP_MAX ; i++) -if (NULL == adapters[i]) -break ; -if (I2C_ADAP_MAX == i) { -dev_warn (&adap->dev, -"register_adapter - enlarge I2C_ADAP_MAX.\n" ); - res = -ENOMEM ; - goto out_unlock; - } - adapters[i] = adap; - -init_MUTEX (&adap->bus); -init_MUTEX (&adap->list); + adap->nr = nr++; +init_MUTEX (&adap->bus_lock); +init_MUTEX (&adap->clist_lock); +list_add_tail (&adap->list,&adapters); +INIT_LIST_HEAD (&adap->clients);/* Add the adapter to the driver core. * If the parent pointer is not set up,
@@ -99,77 +93,65 @@*/ if (adap->dev.parent ==NULL ) adap->dev.parent = &legacy_bus; -sprintf (adap->dev.bus_id,"i2c-%d" , i); +sprintf (adap->dev.bus_id,"i2c-%d" , adap->nr); adap->dev.driver = &i2c_generic_driver;device_register (&adap->dev);/* inform drivers of new adapters */ -for (j=0 ;j<I2C_DRIVER_MAX ;j++) -if (drivers[j]!=NULL && - (drivers[j]->flags&(I2C_DF_NOTIFY |I2C_DF_DUMMY ))) +list_for_each (item,&drivers) { + driver = list_entry(item, struct i2c_driver, list); +if (driver->flags &I2C_DF_NOTIFY )/* We ignore the return code; if it fails, too bad */ - drivers[j]->attach_adapter (adap); + driver->attach_adapter (adap); + }up (&core_lists); - -DEB (dev_dbg (&adap->dev,"registered as adapter %d.\n" , i)); - out_unlock: -up (&core_lists); -return res;; +DEB (dev_dbg (&adap->dev,"registered as adapter #%d\n" , adap->nr)); +return 0 ; }int i2c_del_adapter (struct i2c_adapter *adap) { -int res =0 , i, j; +struct list_head *item; +struct i2c_driver *driver; +struct i2c_client *client; +int res =0 ;down (&core_lists); -for (i =0 ; i <I2C_ADAP_MAX ; i++) -if (adap == adapters[i]) -break ; -if (I2C_ADAP_MAX == i) { -dev_warn (&adap->dev,"unregister_adapter adap not found.\n" ); - res = -ENODEV ; - goto out_unlock; - } -/* DUMMY drivers do not register their clients, so we have to -* use a trick here: we call driver->attach_adapter to -* *detach* it! Of course, each dummy driver should know about -* this or hell will break loose... -*/ -for (j =0 ; j <I2C_DRIVER_MAX ; j++) -if (drivers[j] && (drivers[j]->flags &I2C_DF_DUMMY )) -if ((res = drivers[j]->attach_adapter (adap))) { +list_for_each (item,&drivers) { + driver = list_entry(item, struct i2c_driver, list); +if (driver->detach_adapter) +if ((res = driver->detach_adapter (adap))) {dev_warn (&adap->dev,"can't detach adapter" -"while detaching driver %s: driver not " -"detached!" , drivers[j]->name); +"while detaching driver %s: driver not " +"detached!" , driver->name); goto out_unlock; } + }/* detach any active clients. This must be done first, because * it can fail; in which case we give upp. */ -for (j=0 ;j<I2C_CLIENT_MAX ;j++) { -struct i2c_client *client = adap->clients[j]; -if (client!=NULL ) { -/* detaching devices is unconditional of the set notify -* flag, as _all_ clients that reside on the adapter -* must be deleted, as this would cause invalid states. -*/ -if ((res=client->driver->detach_client (client))) { -dev_err (&adap->dev,"adapter not " -"unregistered, because client at " -"address %02x can't be detached. " , - client->addr); - goto out_unlock; - } +list_for_each (item,&adap->clients) { + client = list_entry(item, struct i2c_client, list); + +/* detaching devices is unconditional of the set notify +* flag, as _all_ clients that reside on the adapter +* must be deleted, as this would cause invalid states. +*/ +if ((res=client->driver->detach_client (client))) { +dev_err (&adap->dev,"adapter not " +"unregistered, because client at " +"address %02x can't be detached. " , + client->addr); + goto out_unlock; } }/* clean up the sysfs representation */ device_unregister (&adap->dev); - - adapters[i] =NULL ; +list_del (&adap->list);DEB (dev_dbg (&adap->dev,"adapter unregistered\n" ));
@@ -187,24 +169,11 @@int i2c_add_driver (struct i2c_driver *driver) { -int res =0 , i; +struct list_head *item; +struct i2c_adapter *adapter; +int res =0 ;down (&core_lists); -for (i =0 ; i <I2C_DRIVER_MAX ; i++) -if (NULL == drivers[i]) -break ; -if (I2C_DRIVER_MAX == i) { -printk (KERN_WARNING -" i2c-core.o: register_driver(%s) " -"- enlarge I2C_DRIVER_MAX.\n" , - driver->name); - res = -ENOMEM ; - goto out_unlock; - } - - drivers[i] = driver; - -DEB (printk (KERN_DEBUG "i2c-core.o: driver %s registered.\n" ,driver->name));/* add the driver to the list of i2c drivers in the driver core */ driver->driver.name = driver->name;
@@ -216,13 +185,14 @@if (res) goto out_unlock; -/* now look for instances of driver on our adapters -*/ -if (driver->flags& (I2C_DF_NOTIFY |I2C_DF_DUMMY )) { -for (i=0 ;i<I2C_ADAP_MAX ;i++) { -if (adapters[i]!=NULL ) -/* Ignore errors */ - driver->attach_adapter (adapters[i]); +list_add_tail (&driver->list,&drivers); +DEB (printk (KERN_DEBUG "i2c-core.o: driver %s registered.\n" ,driver->name)); + +/* now look for instances of driver on our adapters */ +if (driver->flags &I2C_DF_NOTIFY ) { +list_for_each (item,&adapters) { + adapter = list_entry(item, struct i2c_adapter, list); + driver->attach_adapter (adapter); } }
@@ -233,44 +203,29 @@int i2c_del_driver (struct i2c_driver *driver) { -int res =0 , i, j, k; +struct list_head *item1; +struct list_head *item2; +struct i2c_client *client; +struct i2c_adapter *adap; + +int res =0 ;down (&core_lists); -for (i =0 ; i <I2C_DRIVER_MAX ; i++) -if (driver == drivers[i]) -break ; -if (I2C_DRIVER_MAX == i) { -printk (KERN_WARNING " i2c-core.o: unregister_driver: " -"[%s] not found\n" , - driver->name); - res = -ENODEV ; - goto out_unlock; - } - -driver_unregister (&driver->driver);/* Have a look at each adapter, if clients of this driver are still * attached. If so, detach them to be able to kill the driver * afterwards. */ DEB2 (printk (KERN_DEBUG "i2c-core.o: unregister_driver - looking for clients.\n" )); -/* removing clients does not depend on the notify flag, else * invalid operation might (will!) result, when using stale client * pointers. */ -for (k=0 ;k<I2C_ADAP_MAX ;k++) { -struct i2c_adapter *adap = adapters[k]; -if (adap ==NULL )/* skip empty entries. */ -continue ; +list_for_each (item1,&adapters) { + adap = list_entry(item1, struct i2c_adapter, list);DEB2 (dev_dbg (&adap->dev,"examining adapter\n" )); -if (driver->flags &I2C_DF_DUMMY ) { -/* DUMMY drivers do not register their clients, so we have to -* use a trick here: we call driver->attach_adapter to -* *detach* it! Of course, each dummy driver should know about -* this or hell will break loose... -*/ -if ((res = driver->attach_adapter (adap))) { +if (driver->detach_adapter) { +if ((res = driver->detach_adapter (adap))) {dev_warn (&adap->dev,"while unregistering " "dummy driver %s, adapter could " "not be detached properly; driver "
@@ -278,31 +233,31 @@ goto out_unlock; } }else { -for (j=0 ;j<I2C_CLIENT_MAX ;j++) { -struct i2c_client *client = adap->clients[j]; -if (client !=NULL && - client->driver == driver) { -DEB2 (printk (KERN_DEBUG "i2c-core.o: " -"detaching client %s:\n" , - client->dev.name)); -if ((res = driver->detach_client (client))) { -dev_err (&adap->dev,"while " -"unregistering driver " -"`%s', the client at " -"address %02x of " -"adapter could not " -"be detached; driver " -"not unloaded!" , - driver->name, - client->addr); - goto out_unlock; - } +list_for_each (item2,&adap->clients) { + client = list_entry(item2, struct i2c_client, list); +if (client->driver != driver) +continue ; +DEB2 (printk (KERN_DEBUG "i2c-core.o: " +"detaching client %s:\n" , + client->dev.name)); +if ((res = driver->detach_client (client))) { +dev_err (&adap->dev,"while " +"unregistering driver " +"`%s', the client at " +"address %02x of " +"adapter could not " +"be detached; driver " +"not unloaded!" , + driver->name, + client->addr); + goto out_unlock; } } } } - drivers[i] =NULL ; - + +driver_unregister (&driver->driver); +list_del (&driver->list);DEB (printk (KERN_DEBUG "i2c-core.o: driver unregistered: %s\n" ,driver->name)); out_unlock:
@@ -310,14 +265,16 @@return 0 ; } -static int __i2c_check_addr (struct i2c_adapter *adapter,int addr) +static int __i2c_check_addr (struct i2c_adapter *adapter,unsigned int addr) { -int i; +struct list_head *item; +struct i2c_client *client; -for (i =0 ; i <I2C_CLIENT_MAX ; i++) -if (adapter->clients[i] && (adapter->clients[i]->addr == addr)) +list_for_each (item,&adapter->clients) { + client = list_entry(item, struct i2c_client, list); +if (client->addr == addr)return -EBUSY ; - + }return 0 ; }
@@ -325,9 +282,9 @@ {int rval; -down (&adapter->list); +down (&adapter->clist_lock); rval =__i2c_check_addr (adapter, addr); -up (&adapter->list); +up (&adapter->clist_lock);return rval; }
@@ -335,28 +292,14 @@int i2c_attach_client (struct i2c_client *client) {struct i2c_adapter *adapter = client->adapter; -int i; - -down (&adapter->list); -if (__i2c_check_addr (client->adapter, client->addr)) - goto out_unlock_list; -for (i =0 ; i <I2C_CLIENT_MAX ; i++) { -if (!adapter->clients[i]) - goto free_slot; +down (&adapter->clist_lock); +if (__i2c_check_addr (client->adapter, client->addr)) { +up (&adapter->clist_lock); +return -EBUSY ; } - -printk (KERN_WARNING -" i2c-core.o: attach_client(%s) - enlarge I2C_CLIENT_MAX.\n" , - client->dev.name); - - out_unlock_list: -up (&adapter->list); -return -EBUSY ; - - free_slot: - adapter->clients[i] = client; -up (&adapter->list); +list_add_tail (&client->list,&adapter->clients); +up (&adapter->clist_lock);if (adapter->client_register) {if (adapter->client_register (client)) {
@@ -388,7 +331,7 @@int i2c_detach_client (struct i2c_client *client) {struct i2c_adapter *adapter = client->adapter; -int res =0 , i; +int res =0 ;if ((client->flags &I2C_CLIENT_ALLOW_USE ) && (client->usage_count >0 ))return -EBUSY ;
@@ -403,22 +346,11 @@ } } -down (&adapter->list); -for (i =0 ; i <I2C_CLIENT_MAX ; i++) { -if (client == adapter->clients[i]) { - adapter->clients[i] =NULL ; - goto out_unlock; - } - } - -printk (KERN_WARNING -" i2c-core.o: unregister_client [%s] not found\n" , - client->dev.name); - res = -ENODEV ; - - out_unlock: +down (&adapter->clist_lock); +list_del (&client->list);device_unregister (&client->dev); -up (&adapter->list); +up (&adapter->clist_lock); + out:return res; }
@@ -516,9 +448,9 @@if (adap->algo->master_xfer) {DEB2 (dev_dbg (&adap->dev,"master_xfer: with %d msgs.\n" , num)); -down (&adap->bus); +down (&adap->bus_lock); ret = adap->algo->master_xfer (adap,msgs,num); -up (&adap->bus); +up (&adap->bus_lock);return ret; }else {
@@ -542,9 +474,9 @@DEB2 (dev_dbg (&client->adapter->dev,"master_send: writing %d bytes.\n" , count)); -down (&adap->bus); +down (&adap->bus_lock); ret = adap->algo->master_xfer (adap,&msg,1 ); -up (&adap->bus); +up (&adap->bus_lock);/* if everything went ok (i.e. 1 msg transmitted), return #bytes * transmitted, else error code.
@@ -572,9 +504,9 @@DEB2 (dev_dbg (&client->adapter->dev,"master_recv: reading %d bytes.\n" , count)); -down (&adap->bus); +down (&adap->bus_lock); ret = adap->algo->master_xfer (adap,&msg,1 ); -up (&adap->bus); +up (&adap->bus_lock);DEB2 (printk (KERN_DEBUG "i2c-core.o: master_recv: return:%d (count:%d, addr:0x%02x)\n" , ret, count, client->addr));
@@ -743,11 +675,30 @@*/ int i2c_adapter_id (struct i2c_adapter *adap) { -int i; -for (i =0 ; i <I2C_ADAP_MAX ; i++) -if (adap == adapters[i]) -return i; -return -1 ; +return adap->nr; +} + +struct i2c_adapter *i2c_get_adapter (int id) +{ +struct list_head *item; +struct i2c_adapter *adapter; + +down (&core_lists); +list_for_each (item,&adapters) { + adapter = list_entry(item, struct i2c_adapter, list); +if (id == adapter->nr && +try_module_get (adapter->owner)) { +up (&core_lists); +return adapter; + } + } +up (&core_lists); +return NULL ; +} + +void i2c_put_adapter (struct i2c_adapter *adap) +{ +module_put (adap->owner); }/* The SMBus parts */
@@ -1189,10 +1140,10 @@ }if (adapter->algo->smbus_xfer) { -down (&adapter->bus); +down (&adapter->bus_lock); res = adapter->algo->smbus_xfer (adapter,addr,flags,read_write, command,size,data); -up (&adapter->bus); +up (&adapter->bus_lock); }else res =i2c_smbus_xfer_emulated (adapter,addr,flags,read_write, command,size,data);
@@ -1239,6 +1190,8 @@EXPORT_SYMBOL (i2c_control);EXPORT_SYMBOL (i2c_transfer);EXPORT_SYMBOL (i2c_adapter_id); +EXPORT_SYMBOL (i2c_get_adapter); +EXPORT_SYMBOL (i2c_put_adapter);EXPORT_SYMBOL (i2c_probe);EXPORT_SYMBOL (i2c_smbus_xfer);
drivers/i2c/i2c-dev.c +26 -36
115 lines not on this page · raw message
drivers/media/video/dpc7146.c +6 -7
@@ -96,7 +96,8 @@static int dpc_probe (struct saa7146_dev * dev) {struct dpc * dpc =0 ; -int i =0 ; +struct i2c_client *client; +struct list_head *item; dpc = (struct dpc *)kmalloc (sizeof (struct dpc ),GFP_KERNEL );if (NULL == dpc ) {
@@ -117,12 +118,10 @@ }/* loop through all i2c-devices on the bus and look who is there */ -for (i =0 ; i <I2C_CLIENT_MAX ; i++) { -if (NULL == dpc->i2c_adapter.clients[i] ) { -continue ; - } -if (I2C_SAA7111A == dpc->i2c_adapter.clients[i]->addr ) - dpc->saa7111a = dpc->i2c_adapter.clients[i]; +list_for_each (item,&dpc->i2c_adapter.clients) { + client = list_entry(item, struct i2c_client, list); +if (I2C_SAA7111A == client->addr ) + dpc->saa7111a = client; }/* check if all devices are present */
drivers/media/video/mxb.c +16 -17
@@ -208,7 +208,8 @@static int mxb_probe (struct saa7146_dev * dev) {struct mxb * mxb =0 ; -int i =0 ; +struct i2c_client *client; +struct list_head *item;request_module ("tuner" );request_module ("tea6420" );
@@ -235,22 +236,20 @@ }/* loop through all i2c-devices on the bus and look who is there */ -for (i =0 ; i <I2C_CLIENT_MAX ; i++) { -if (NULL == mxb->i2c_adapter.clients[i] ) { -continue ; - } -if (I2C_TEA6420_1 == mxb->i2c_adapter.clients[i]->addr ) - mxb->tea6420_1 = mxb->i2c_adapter.clients[i]; -if (I2C_TEA6420_2 == mxb->i2c_adapter.clients[i]->addr ) - mxb->tea6420_2 = mxb->i2c_adapter.clients[i]; -if (I2C_TEA6415C_2 == mxb->i2c_adapter.clients[i]->addr ) - mxb->tea6415c = mxb->i2c_adapter.clients[i]; -if (I2C_TDA9840 == mxb->i2c_adapter.clients[i]->addr ) - mxb->tda9840 = mxb->i2c_adapter.clients[i]; -if (I2C_SAA7111A == mxb->i2c_adapter.clients[i]->addr ) - mxb->saa7111a = mxb->i2c_adapter.clients[i]; -if (0x60 == mxb->i2c_adapter.clients[i]->addr ) - mxb->tuner = mxb->i2c_adapter.clients[i]; +list_for_each (item,&mxb->i2c_adapter.clients) { + client = list_entry(item, struct i2c_client, list); +if (I2C_TEA6420_1 == client->addr ) + mxb->tea6420_1 = client; +if (I2C_TEA6420_2 == client->addr ) + mxb->tea6420_2 = client; +if (I2C_TEA6415C_2 == client->addr ) + mxb->tea6415c = client; +if (I2C_TDA9840 == client->addr ) + mxb->tda9840 = client; +if (I2C_SAA7111A == client->addr ) + mxb->saa7111a = client; +if (0x60 == client->addr ) + mxb->tuner = client; }/* check if all devices are present */
drivers/media/video/tvmixer.c +10 -7
@@ -217,8 +217,9 @@ .owner = THIS_MODULE, .name = "tv card mixer driver", .id = I2C_DRIVERID_TVMIXER, - .flags = I2C_DF_DUMMY, + .flags = I2C_DF_NOTIFY, .attach_adapter = tvmixer_adapters, + .detach_adapter = tvmixer_adapters, .detach_client = tvmixer_clients, };
@@ -234,14 +235,15 @@static int tvmixer_adapters (struct i2c_adapter *adap) { -int i; +struct list_head *item; +struct i2c_client *client;if (debug)printk ("tvmixer: adapter %s\n" ,adap->dev.name); -for (i=0 ; i<I2C_CLIENT_MAX ; i++) { -if (!adap->clients[i]) -continue ; -tvmixer_clients (adap->clients[i]); + +list_for_each (item,&adap->clients) { + client = list_entry(item, struct i2c_client, list); +tvmixer_clients (client); }return 0 ; }
@@ -264,7 +266,8 @@ client->adapter->dev.name);return -1 ; } -printk ("tvmixer: debug: %s\n" ,client->dev.name); +if (debug) +printk ("tvmixer: debug: %s\n" ,client->dev.name);/* unregister ?? */ for (i =0 ; i <DEV_MAX ; i++) {
include/linux/i2c.h +16 -12
@@ -39,12 +39,6 @@/* --- General options ------------------------------------------------ */ -#define I2C_ALGO_MAX 4/* control memory consumption */ -#define I2C_ADAP_MAX 16 -#define I2C_DRIVER_MAX 16 -#define I2C_CLIENT_MAX 32 -#define I2C_DUMMY_MAX 4 -struct i2c_msg ;struct i2c_algorithm ;struct i2c_adapter ;
@@ -131,6 +125,7 @@* i2c_attach_client. */ int (*attach_adapter)(struct i2c_adapter *); +int (*detach_adapter)(struct i2c_adapter *);/* tells the driver that a client is about to be deleted & gives it * the chance to remove its private data. Also, if the client struct
@@ -145,6 +140,7 @@int (*command)(struct i2c_client *client,unsigned int cmd,void *arg);struct device_driver driver; +struct list_head list; };#define to_i2c_driver (d) container_of(d, struct i2c_driver, driver)
@@ -169,6 +165,7 @@int usage_count;/* How many accesses currently */ /* to the client */ struct device dev;/* the device structure */ +struct list_head list; };#define to_i2c_client (d) container_of(d, struct i2c_client, dev)
@@ -236,12 +233,10 @@int (*client_unregister)(struct i2c_client *);/* data fields that are valid for all devices */ -struct semaphore bus; -struct semaphore list; +struct semaphore bus_lock; +struct semaphore clist_lock;unsigned int flags;/* flags specifying div. data */ -struct i2c_client *clients[I2C_CLIENT_MAX ]; -int timeout;int retries;struct device dev;/* the adapter device */
@@ -250,6 +245,10 @@/* No need to set this when you initialize the adapter */ int inode;#endif /* def CONFIG_PROC_FS */ + +int nr; +struct list_head clients; +struct list_head list; };#define to_i2c_adapter (d) container_of(d, struct i2c_adapter, dev)
@@ -265,7 +264,11 @@/*flags for the driver struct: */ #define I2C_DF_NOTIFY 0x01/* notify on bus (de/a)ttaches */ -#define I2C_DF_DUMMY 0x02/* do not connect any clients */ +#if 0 +/* this flag is gone -- there is a (optional) driver->detach_adapter +* callback now which can be used instead */ +# define I2C_DF_DUMMY 0x02 +#endif /*flags for the client struct: */ #define I2C_CLIENT_ALLOW_USE 0x01/* Client allows access */
@@ -352,7 +355,8 @@* or -1 if the adapter was not registered. */ extern int i2c_adapter_id (struct i2c_adapter *adap); - +extern struct i2c_adapter *i2c_get_adapter (int id); +extern void i2c_put_adapter (struct i2c_adapter *adap);/* Return the functionality mask */
PATCH 1/1 i2c #2/3: add i2c_clients_command
Hi,
This is the second of three patches for i2c.
Changes:
* adds a i2c_clients_command() function to i2c-core which calls
the ->command() callback of all clients attached to a adapter.
* make bttv + saa7134 drivers use that function instead of mucking with the i2c_adapter struct themself.
Please apply,
Gerd
drivers/i2c/i2c-core.c +22 -0
@@ -411,6 +411,27 @@return 0 ; } +void i2c_clients_command (struct i2c_adapter *adap,unsigned int cmd,void *arg) +{ +struct list_head *item; +struct i2c_client *client; + +down (&adap->clist_lock); +list_for_each (item,&adap->clients) { + client = list_entry(item, struct i2c_client, list); +if (!try_module_get (client->driver->owner)) +continue ; +if (NULL != client->driver->command) { +up (&adap->clist_lock); + client->driver->command (client,cmd,arg); +down (&adap->clist_lock); + } +module_put (client->driver->owner); + } +up (&adap->clist_lock); +} + +/* match always succeeds, as we want the probe() to tell if we really accept this match */ static int i2c_device_match (struct device *dev,struct device_driver *drv) {
@@ -1183,6 +1204,7 @@EXPORT_SYMBOL (i2c_detach_client);EXPORT_SYMBOL (i2c_use_client);EXPORT_SYMBOL (i2c_release_client); +EXPORT_SYMBOL (i2c_clients_command);EXPORT_SYMBOL (i2c_check_addr);EXPORT_SYMBOL (i2c_master_send);
drivers/media/video/bttv-if.c +14 -49
100 lines not on this page · raw message
drivers/media/video/bttv.h +0 -1
@@ -243,7 +243,6 @@/* i2c */ -#define I2C_CLIENTS_MAX 16extern void bttv_bit_setscl (void *data,int state);extern void bttv_bit_setsda (void *data,int state);extern void bttv_call_i2c_clients (struct bttv *btv,unsigned int cmd,void *arg);
drivers/media/video/bttvp.h +2 -1
@@ -62,6 +62,8 @@#define RAW_LINES 640#define RAW_BPL 1024 +#define UNSET (-1U) +/* ---------------------------------------------------------- */ struct bttv_tvnorm
@@ -276,7 +278,6 @@struct i2c_algo_bit_data i2c_algo;struct i2c_client i2c_client;int i2c_state, i2c_rc; -struct i2c_client *i2c_clients[I2C_CLIENTS_MAX ];/* video4linux (1) */ struct video_device video_dev;
drivers/media/video/saa7134/saa7134-i2c.c +5 -18
@@ -334,19 +334,15 @@static struct i2c_adapter saa7134_adap_template = { .owner =THIS_MODULE , +I2C_DEVNAME ("saa7134" ), .id =I2C_ALGO_SAA7134 , .algo = &saa7134_algo, .client_register = attach_inform, - .dev = { - .name ="saa7134" , - }, };static struct i2c_client saa7134_client_template = { - .id =-1 , - .dev = { - .name ="saa7134 internal" , - }, +I2C_DEVNAME ("saa7134 internal" ), + .id =-1 , };/* ----------------------------------------------------------- */
@@ -399,22 +395,13 @@void saa7134_i2c_call_clients (struct saa7134_dev *dev,unsigned int cmd,void *arg) { -int i; - -for (i =0 ; i <I2C_CLIENT_MAX ; i++) { -if (NULL == dev->i2c_adap.clients[i]) -continue ; -if (NULL == dev->i2c_adap.clients[i]->driver->command) -continue ; - dev->i2c_adap.clients[i]->driver->command - (dev->i2c_adap.clients[i],cmd,arg); - } +i2c_clients_command (&dev->i2c_adap, cmd, arg); }int saa7134_i2c_register (struct saa7134_dev *dev) { dev->i2c_adap = saa7134_adap_template; -strncpy (dev->i2c_adap.dev.name, dev->name,DEVICE_NAME_SIZE ); +strcpy (dev->i2c_adap.dev.name,dev->name); dev->i2c_adap.algo_data = dev;i2c_add_adapter (&dev->i2c_adap);
include/linux/i2c.h +5 -0
@@ -334,6 +334,11 @@extern int i2c_use_client (struct i2c_client *);extern int i2c_release_client (struct i2c_client *); +/* call the i2c_client->command() of all attached clients with +* the given arguments */ +extern void i2c_clients_command (struct i2c_adapter *adap, +unsigned int cmd,void *arg); +/* returns -EBUSY if address has been taken, 0 if not. Note that the only other place at which this is called is within i2c_attach_client; so you can cheat by simply not registering. Not recommended, of course! */
PATCH 1/1 i2c #3/3: add class field to i2c_adapter
Hi,
This is the last of three patches for i2c. It introduces a new field to i2c_adapter which classifies the kind of hardware a i2c adapter belongs to (analog tv card / dvb card / smbus / gfx card ...). i2c chip drivers can use this infomation to decide whenever they want to look for hardware on that adapter or not. It doesn't make sense to probe for a tv tuner on a smbus for example ...
Gerd
drivers/i2c/busses/i2c-ali15x3.c +1 -0
@@ -475,6 +475,7 @@static struct i2c_adapter ali15x3_adapter = { .owner =THIS_MODULE , .id =I2C_ALGO_SMBUS |I2C_HW_SMBUS_ALI15X3 , + .class =I2C_ADAP_CLASS_SMBUS , .algo = &smbus_algorithm, .dev = { .name ="unset" ,
drivers/i2c/busses/i2c-amd756.c +1 -0
@@ -313,6 +313,7 @@static struct i2c_adapter amd756_adapter = { .owner =THIS_MODULE , .id =I2C_ALGO_SMBUS |I2C_HW_SMBUS_AMD756 , + .class =I2C_ADAP_CLASS_SMBUS , .algo = &smbus_algorithm, .dev = { .name ="unset" ,
drivers/i2c/busses/i2c-amd8111.c +1 -0
@@ -360,6 +360,7 @@snprintf (smbus->adapter.dev.name,DEVICE_NAME_SIZE ,"SMBus2 AMD8111 adapter at %04x" , smbus->base); smbus->adapter.id =I2C_ALGO_SMBUS |I2C_HW_SMBUS_AMD8111 ; + smbus->adapter.class =I2C_ADAP_CLASS_SMBUS ; smbus->adapter.algo = &smbus_algorithm; smbus->adapter.algo_data = smbus;
drivers/i2c/busses/i2c-i801.c +1 -0
@@ -547,6 +547,7 @@static struct i2c_adapter i801_adapter = { .owner =THIS_MODULE , .id =I2C_ALGO_SMBUS |I2C_HW_SMBUS_I801 , + .class =I2C_ADAP_CLASS_SMBUS , .algo = &smbus_algorithm, .dev = { .name ="unset" ,
drivers/i2c/busses/i2c-isa.c +1 -0
@@ -40,6 +40,7 @@static struct i2c_adapter isa_adapter = { .owner =THIS_MODULE , .id =I2C_ALGO_ISA |I2C_HW_ISA , + .class =I2C_ADAP_CLASS_SMBUS , .algo = &isa_algorithm, .dev = { .name ="ISA main adapter" ,
drivers/i2c/busses/i2c-piix4.c +1 -0
@@ -395,6 +395,7 @@static struct i2c_adapter piix4_adapter = { .owner =THIS_MODULE , .id =I2C_ALGO_SMBUS |I2C_HW_SMBUS_PIIX4 , + .class =I2C_ADAP_CLASS_SMBUS , .algo = &smbus_algorithm, .dev = { .name ="unset" ,
drivers/i2c/busses/i2c-viapro.c +1 -0
@@ -295,6 +295,7 @@static struct i2c_adapter vt596_adapter = { .owner =THIS_MODULE , .id =I2C_ALGO_SMBUS |I2C_HW_SMBUS_VIA2 , + .class =I2C_ADAP_CLASS_SMBUS , .algo = &smbus_algorithm, .dev = { .name ="unset" ,
drivers/i2c/chips/adm1021.c +2 -0
@@ -203,6 +203,8 @@static int adm1021_attach_adapter (struct i2c_adapter *adapter) { +if (!(adapter->class &I2C_ADAP_CLASS_SMBUS )) +return 0 ;return i2c_detect (adapter, &addr_data, adm1021_detect); }
drivers/i2c/chips/it87.c +2 -0
@@ -525,6 +525,8 @@* when a new adapter is inserted (and it87_driver is still present) */ static int it87_attach_adapter (struct i2c_adapter *adapter) { +if (!(adapter->class &I2C_ADAP_CLASS_SMBUS )) +return 0 ;return i2c_detect (adapter, &addr_data, it87_detect); }
drivers/i2c/chips/lm75.c +2 -0
@@ -121,6 +121,8 @@static int lm75_attach_adapter (struct i2c_adapter *adapter) { +if (!(adapter->class &I2C_ADAP_CLASS_SMBUS )) +return 0 ;return i2c_detect (adapter, &addr_data, lm75_detect); }
drivers/i2c/chips/via686a.c +2 -0
@@ -661,6 +661,8 @@/* This is called when the module is loaded */ static int via686a_attach_adapter (struct i2c_adapter *adapter) { +if (!(adapter->class &I2C_ADAP_CLASS_SMBUS )) +return 0 ;return i2c_detect (adapter, &addr_data, via686a_detect); }
drivers/i2c/chips/w83781d.c +2 -0
@@ -1026,6 +1026,8 @@static int w83781d_attach_adapter (struct i2c_adapter *adapter) { +if (!(adapter->class &I2C_ADAP_CLASS_SMBUS )) +return 0 ;return i2c_detect (adapter, &addr_data, w83781d_detect); }
drivers/media/video/bt832.c +3 -19
@@ -198,25 +198,9 @@static int bt832_probe (struct i2c_adapter *adap) { -int rc; - -printk ("bt832_probe\n" ); - -switch (adap->id) { -case I2C_ALGO_BIT |I2C_HW_B_BT848 : -case I2C_ALGO_BIT |I2C_HW_B_RIVA : -case I2C_ALGO_SAA7134 : -printk ("bt832: probing %s i2c adapter [id=0x%x]\n" , - adap->name,adap->id); - rc =i2c_probe (adap, &addr_data, bt832_attach); -break ; -default : -printk ("bt832: ignoring %s i2c adapter [id=0x%x]\n" , - adap->name,adap->id); - rc =0 ; -/* nothing */ - } -return rc; +if (adap->class &I2C_ADAP_CLASS_TV_ANALOG ) +return i2c_probe (adap, &addr_data, bt832_attach); +return 0 ; }static int bt832_detach (struct i2c_client *client)
drivers/media/video/bttv-if.c +1 -0
@@ -233,6 +233,7 @@ .owner = THIS_MODULE,I2C_DEVNAME ("bt848" ), .id = I2C_HW_B_BT848, + .class = I2C_ADAP_CLASS_TV_ANALOG, .client_register = attach_inform, };
drivers/media/video/msp3400.c +1 -1
@@ -1372,7 +1372,7 @@static int msp_probe (struct i2c_adapter *adap) { -if (adap->id == (I2C_ALGO_BIT |I2C_HW_B_BT848 )) +if (adap->class &I2C_ADAP_CLASS_TV_ANALOG )return i2c_probe (adap, &addr_data, msp_attach);return 0 ; }
drivers/media/video/saa5249.c +1 -5
@@ -224,12 +224,8 @@static int saa5249_probe (struct i2c_adapter *adap) { -/* Only attach these chips to the BT848 bus for now */ - -if (adap->id == (I2C_ALGO_BIT |I2C_HW_B_BT848 )) - { +if (adap->class &I2C_ADAP_CLASS_TV_ANALOG )return i2c_probe (adap, &addr_data, saa5249_attach); - }return 0 ; }
drivers/media/video/saa7134/saa7134-i2c.c +1 -0
@@ -336,6 +336,7 @@ .owner = THIS_MODULE,I2C_DEVNAME ("saa7134" ), .id = I2C_ALGO_SAA7134, + .class = I2C_ADAP_CLASS_TV_ANALOG, .algo = &saa7134_algo, .client_register = attach_inform, };
drivers/media/video/tda7432.c +1 -1
@@ -340,7 +340,7 @@static int tda7432_probe (struct i2c_adapter *adap) { -if (adap->id == (I2C_ALGO_BIT |I2C_HW_B_BT848 )) +if (adap->class &I2C_ADAP_CLASS_TV_ANALOG )return i2c_probe (adap, &addr_data, tda7432_attach);return 0 ; }
drivers/media/video/tda9875.c +1 -1
@@ -273,7 +273,7 @@static int tda9875_probe (struct i2c_adapter *adap) { -if (adap->id == (I2C_ALGO_BIT |I2C_HW_B_BT848 )) +if (adap->class &I2C_ADAP_CLASS_TV_ANALOG )return i2c_probe (adap, &addr_data, tda9875_attach);return 0 ; }
drivers/media/video/tda9887.c +3 -17
@@ -368,23 +368,9 @@static int tda9887_probe (struct i2c_adapter *adap) { -int rc; - -switch (adap->id) { -case I2C_ALGO_BIT |I2C_HW_B_BT848 : -case I2C_ALGO_BIT |I2C_HW_B_RIVA : -case I2C_ALGO_SAA7134 : -printk ("tda9887: probing %s i2c adapter [id=0x%x]\n" , - adap->dev.name,adap->id); - rc =i2c_probe (adap, &addr_data, tda9887_attach); -break ; -default : -printk ("tda9887: ignoring %s i2c adapter [id=0x%x]\n" , - adap->dev.name,adap->id); - rc =0 ; -/* nothing */ - } -return rc; +if (adap->class &I2C_ADAP_CLASS_TV_ANALOG ) +return i2c_probe (adap, &addr_data, tda9887_attach); +return 0 ; }static int tda9887_detach (struct i2c_client *client)
drivers/media/video/tuner.c +4 -18
@@ -817,29 +817,15 @@static int tuner_probe (struct i2c_adapter *adap) { -int rc; -if (0 != addr) { normal_i2c_range[0 ] = addr; normal_i2c_range[1 ] = addr; } this_adap =0 ; -switch (adap->id) { -case I2C_ALGO_BIT |I2C_HW_B_BT848 : -case I2C_ALGO_BIT |I2C_HW_B_RIVA : -case I2C_ALGO_SAA7134 : -case I2C_ALGO_SAA7146 : -printk ("tuner: probing %s i2c adapter [id=0x%x]\n" , - adap->dev.name,adap->id); - rc =i2c_probe (adap, &addr_data, tuner_attach); -break ; -default : -printk ("tuner: ignoring %s i2c adapter [id=0x%x]\n" , - adap->dev.name,adap->id); - rc =0 ; -/* nothing */ - } -return rc; + +if (adap->class &I2C_ADAP_CLASS_TV_ANALOG ) +return i2c_probe (adap, &addr_data, tuner_attach); +return 0 ; }static int tuner_detach (struct i2c_client *client)
drivers/media/video/tvaudio.c +2 -7
@@ -1408,14 +1408,9 @@static int chip_probe (struct i2c_adapter *adap) { -switch (adap->id) { -case I2C_ALGO_BIT |I2C_HW_B_BT848 : -case I2C_ALGO_BIT |I2C_HW_B_RIVA : +if (adap->class &I2C_ADAP_CLASS_TV_ANALOG )return i2c_probe (adap, &addr_data, chip_attach); -default : -/* ignore this i2c bus */ -return 0 ; - } +return 0 ; }static int chip_detach (struct i2c_client *client)
drivers/media/video/tvmixer.c +1 -6
@@ -254,12 +254,7 @@int i,minor;/* TV card ??? */ -switch (client->adapter->id) { -case I2C_ALGO_BIT |I2C_HW_B_BT848 : -case I2C_ALGO_BIT |I2C_HW_B_RIVA : -/* ok, have a look ... */ -break ; -default : +if (!(client->adapter->class &I2C_ADAP_CLASS_TV_ANALOG )) {/* ignore that one */ if (debug) printk("tvmixer: %s is not a tv card\n",
include/linux/i2c.h +7 -0
@@ -225,6 +225,7 @@struct module *owner;unsigned int id;/* == is algo->id | hwdep.struct->id, */ /* for registered values see below */ +unsigned int class;struct i2c_algorithm *algo;/* the algorithm to access the bus */ void *algo_data;
@@ -278,6 +279,12 @@#define I2C_CLIENT_TEN 0x10/* we have a ten bit chip address */ /* Must equal I2C_M_TEN below */ +/* i2c adapter classes (bitmask) */ +#define I2C_ADAP_CLASS_SMBUS (1<<0)/* lm_sensors, ... */ +#define I2C_ADAP_CLASS_TV_ANALOG (1<<1)/* bttv + friends */ +#define I2C_ADAP_CLASS_TV_DIGINAL (1<<2)/* dbv cards */ +#define I2C_ADAP_CLASS_DDC (1<<3)/* i2c-matroxfb ? */ +/* i2c_client_address_data is the struct for holding default client * addresses for a driver and for the parameters supplied on the * command line
Re: [patch] i2c #3/3: add class field to i2c_adapter
Quoted 4 lines · Gerd Knorr
This is the last of three patches for i2c. It introduces a new field to
i2c_adapterwhich classifies the kind of hardware a i2c adapter belongs to (analog tv card / dvb card / smbus / gfx card ...).
I've attached a patch that adds classes for analog and digital cameras (webcams, etc...). I plan to submit one such driver in the next few days.
The patch also fixes a typo ("DIGINAL").
Quoted 5 lines
i2c chip
drivers can use this infomation to decide whenever they want to look for hardware on that adapter or not. It doesn't make sense to probe for a tv tuner on a smbus for example ...
Actually it does in some cases. I know of two devices that have analog tuners on an smbus-like interface (OV511 USB TV and W9967CF USB TV). The tuner can be controlled using a pair of i2c_smbus_write_byte_data() calls. This works because, AFAIK, all four-byte tuners can differentiate between bytes 0-1 and 2-3 due to their bit patterns.
Would a patch that adds smbus algorithm support to tuner.c be acceptable? It will only add about twelve lines, and will still use i2c_master_send() when possible.
Signature · 2 lines
Mark McClelland [email protected]
Add I2C classes for analog and digital cameras, and fix a typo.
include/linux/i2c.h +6 -4
@@ -280,10 +280,12 @@/* Must equal I2C_M_TEN below */ /* i2c adapter classes (bitmask) */ -#define I2C_ADAP_CLASS_SMBUS (1<<0)/* lm_sensors, ... */ -#define I2C_ADAP_CLASS_TV_ANALOG (1<<1)/* bttv + friends */ -#define I2C_ADAP_CLASS_TV_DIGINAL (1<<2)/* dbv cards */ -#define I2C_ADAP_CLASS_DDC (1<<3)/* i2c-matroxfb ? */ +#define I2C_ADAP_CLASS_SMBUS (1<<0)/* lm_sensors, ... */ +#define I2C_ADAP_CLASS_TV_ANALOG (1<<1)/* bttv + friends */ +#define I2C_ADAP_CLASS_TV_DIGITAL (1<<2)/* dbv cards */ +#define I2C_ADAP_CLASS_DDC (1<<3)/* i2c-matroxfb ? */ +#define I2C_ADAP_CLASS_CAM_ANALOG (1<<4)/* camera with analog CCD */ +#define I2C_ADAP_CLASS_CAM_DIGITAL (1<<5)/* most webcams */ /* i2c_client_address_data is the struct for holding default client * addresses for a driver and for the parameters supplied on the
Greg KH
AppliedRe: [patch] i2c #3/3: add class field to i2c_adapter
Quoted 4 lines · Mark McClelland
I've attached a patch that adds classes for analog and digital cameras (webcams, etc...). I plan to submit one such driver in the next few days.
The patch also fixes a typo ("DIGINAL").
I've applied this, thanks.
greg k-h
Quoted 6 lines · Gerd Knorr
Hi,
This is the first of tree patches for i2c. Trying to get the i2c cleanups finshed before 2.6.x, so we (hopefully) don't have a ever-changing i2c subsystem in 2.7.x again (which is very annonying for driver maintainance).
Thanks for the patches, I've applied all three to my tree, and fixed up a small compile error if DEBUG is enabled. I'll send them all on to Linus in a bit, with some other i2c changes.
thanks,
greg k-h