Commit 37d7f421 authored by Gerd Knorr's avatar Gerd Knorr Committed by Greg Kroah-Hartman

[PATCH] i2c #2/3: add i2c_clients_command

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.
parent 22f0b1c0
...@@ -411,6 +411,27 @@ int i2c_release_client(struct i2c_client *client) ...@@ -411,6 +411,27 @@ int i2c_release_client(struct i2c_client *client)
return 0; 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 */ /* 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) static int i2c_device_match(struct device *dev, struct device_driver *drv)
{ {
...@@ -1183,6 +1204,7 @@ EXPORT_SYMBOL(i2c_attach_client); ...@@ -1183,6 +1204,7 @@ EXPORT_SYMBOL(i2c_attach_client);
EXPORT_SYMBOL(i2c_detach_client); EXPORT_SYMBOL(i2c_detach_client);
EXPORT_SYMBOL(i2c_use_client); EXPORT_SYMBOL(i2c_use_client);
EXPORT_SYMBOL(i2c_release_client); EXPORT_SYMBOL(i2c_release_client);
EXPORT_SYMBOL(i2c_clients_command);
EXPORT_SYMBOL(i2c_check_addr); EXPORT_SYMBOL(i2c_check_addr);
EXPORT_SYMBOL(i2c_master_send); EXPORT_SYMBOL(i2c_master_send);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de)
& Marcus Metzler (mocm@thp.uni-koeln.de) & Marcus Metzler (mocm@thp.uni-koeln.de)
(c) 1999,2000 Gerd Knorr <kraxel@goldbach.in-berlin.de> (c) 1999-2003 Gerd Knorr <kraxel@bytesex.org>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
...@@ -195,51 +195,21 @@ static int bttv_bit_getsda(void *data) ...@@ -195,51 +195,21 @@ static int bttv_bit_getsda(void *data)
static int attach_inform(struct i2c_client *client) static int attach_inform(struct i2c_client *client)
{ {
struct bttv *btv = i2c_get_adapdata(client->adapter); struct bttv *btv = i2c_get_adapdata(client->adapter);
int i;
for (i = 0; i < I2C_CLIENTS_MAX; i++) { if (btv->tuner_type != UNSET)
if (btv->i2c_clients[i] == NULL) {
btv->i2c_clients[i] = client;
break;
}
}
if (btv->tuner_type != -1)
bttv_call_i2c_clients(btv,TUNER_SET_TYPE,&btv->tuner_type); bttv_call_i2c_clients(btv,TUNER_SET_TYPE,&btv->tuner_type);
if (bttv_verbose)
printk("bttv%d: i2c attach [client=%s,%s]\n",btv->nr,
client->dev.name, (i < I2C_CLIENTS_MAX) ? "ok" : "failed");
return 0;
}
static int detach_inform(struct i2c_client *client)
{
struct bttv *btv = i2c_get_adapdata(client->adapter);
int i;
for (i = 0; i < I2C_CLIENTS_MAX; i++) { if (bttv_debug)
if (btv->i2c_clients[i] == client) { printk("bttv%d: i2c attach [client=%s]\n",
btv->i2c_clients[i] = NULL; btv->nr, i2c_clientname(client));
break;
}
}
if (bttv_verbose)
printk("bttv%d: i2c detach [client=%s,%s]\n",btv->nr,
client->dev.name, (i < I2C_CLIENTS_MAX) ? "ok" : "failed");
return 0; return 0;
} }
void bttv_call_i2c_clients(struct bttv *btv, unsigned int cmd, void *arg) void bttv_call_i2c_clients(struct bttv *btv, unsigned int cmd, void *arg)
{ {
int i; if (0 != btv->i2c_rc)
return;
for (i = 0; i < I2C_CLIENTS_MAX; i++) { i2c_clients_command(&btv->i2c_adap, cmd, arg);
if (NULL == btv->i2c_clients[i])
continue;
if (NULL == btv->i2c_clients[i]->driver->command)
continue;
btv->i2c_clients[i]->driver->command(
btv->i2c_clients[i],cmd,arg);
}
} }
void bttv_i2c_call(unsigned int card, unsigned int cmd, void *arg) void bttv_i2c_call(unsigned int card, unsigned int cmd, void *arg)
...@@ -260,20 +230,15 @@ static struct i2c_algo_bit_data bttv_i2c_algo_template = { ...@@ -260,20 +230,15 @@ static struct i2c_algo_bit_data bttv_i2c_algo_template = {
}; };
static struct i2c_adapter bttv_i2c_adap_template = { static struct i2c_adapter bttv_i2c_adap_template = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
I2C_DEVNAME("bt848"),
.id = I2C_HW_B_BT848, .id = I2C_HW_B_BT848,
.client_register = attach_inform, .client_register = attach_inform,
.client_unregister = detach_inform,
.dev = {
.name = "bt848",
},
}; };
static struct i2c_client bttv_i2c_client_template = { static struct i2c_client bttv_i2c_client_template = {
.id = -1, I2C_DEVNAME("bttv internal"),
.dev = { .id = -1,
.name = "bttv internal",
},
}; };
...@@ -347,8 +312,8 @@ int __devinit init_bttv_i2c(struct bttv *btv) ...@@ -347,8 +312,8 @@ int __devinit init_bttv_i2c(struct bttv *btv)
memcpy(&btv->i2c_client, &bttv_i2c_client_template, memcpy(&btv->i2c_client, &bttv_i2c_client_template,
sizeof(struct i2c_client)); sizeof(struct i2c_client));
sprintf(btv->i2c_adap.dev.name+strlen(btv->i2c_adap.dev.name), sprintf(btv->i2c_adap.dev.name, "bt848 #%d", btv->nr);
" #%d", btv->nr);
btv->i2c_algo.data = btv; btv->i2c_algo.data = btv;
i2c_set_adapdata(&btv->i2c_adap, btv); i2c_set_adapdata(&btv->i2c_adap, btv);
btv->i2c_adap.algo_data = &btv->i2c_algo; btv->i2c_adap.algo_data = &btv->i2c_algo;
......
...@@ -243,7 +243,6 @@ extern void bttv_i2c_call(unsigned int card, unsigned int cmd, void *arg); ...@@ -243,7 +243,6 @@ extern void bttv_i2c_call(unsigned int card, unsigned int cmd, void *arg);
/* i2c */ /* i2c */
#define I2C_CLIENTS_MAX 16
extern void bttv_bit_setscl(void *data, int state); extern void bttv_bit_setscl(void *data, int state);
extern void bttv_bit_setsda(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); extern void bttv_call_i2c_clients(struct bttv *btv, unsigned int cmd, void *arg);
......
...@@ -62,6 +62,8 @@ ...@@ -62,6 +62,8 @@
#define RAW_LINES 640 #define RAW_LINES 640
#define RAW_BPL 1024 #define RAW_BPL 1024
#define UNSET (-1U)
/* ---------------------------------------------------------- */ /* ---------------------------------------------------------- */
struct bttv_tvnorm struct bttv_tvnorm
...@@ -276,7 +278,6 @@ struct bttv { ...@@ -276,7 +278,6 @@ struct bttv {
struct i2c_algo_bit_data i2c_algo; struct i2c_algo_bit_data i2c_algo;
struct i2c_client i2c_client; struct i2c_client i2c_client;
int i2c_state, i2c_rc; int i2c_state, i2c_rc;
struct i2c_client *i2c_clients[I2C_CLIENTS_MAX];
/* video4linux (1) */ /* video4linux (1) */
struct video_device video_dev; struct video_device video_dev;
......
...@@ -334,19 +334,15 @@ static struct i2c_algorithm saa7134_algo = { ...@@ -334,19 +334,15 @@ static struct i2c_algorithm saa7134_algo = {
static struct i2c_adapter saa7134_adap_template = { static struct i2c_adapter saa7134_adap_template = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
I2C_DEVNAME("saa7134"),
.id = I2C_ALGO_SAA7134, .id = I2C_ALGO_SAA7134,
.algo = &saa7134_algo, .algo = &saa7134_algo,
.client_register = attach_inform, .client_register = attach_inform,
.dev = {
.name = "saa7134",
},
}; };
static struct i2c_client saa7134_client_template = { static struct i2c_client saa7134_client_template = {
.id = -1, I2C_DEVNAME("saa7134 internal"),
.dev = { .id = -1,
.name = "saa7134 internal",
},
}; };
/* ----------------------------------------------------------- */ /* ----------------------------------------------------------- */
...@@ -399,22 +395,13 @@ saa7134_i2c_scan(struct saa7134_dev *dev) ...@@ -399,22 +395,13 @@ saa7134_i2c_scan(struct saa7134_dev *dev)
void saa7134_i2c_call_clients(struct saa7134_dev *dev, void saa7134_i2c_call_clients(struct saa7134_dev *dev,
unsigned int cmd, void *arg) unsigned int cmd, void *arg)
{ {
int i; i2c_clients_command(&dev->i2c_adap, cmd, arg);
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);
}
} }
int saa7134_i2c_register(struct saa7134_dev *dev) int saa7134_i2c_register(struct saa7134_dev *dev)
{ {
dev->i2c_adap = saa7134_adap_template; 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; dev->i2c_adap.algo_data = dev;
i2c_add_adapter(&dev->i2c_adap); i2c_add_adapter(&dev->i2c_adap);
......
...@@ -334,6 +334,11 @@ extern struct i2c_client *i2c_get_client(int driver_id, int adapter_id, ...@@ -334,6 +334,11 @@ extern struct i2c_client *i2c_get_client(int driver_id, int adapter_id,
extern int i2c_use_client(struct i2c_client *); extern int i2c_use_client(struct i2c_client *);
extern int i2c_release_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 /* 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 other place at which this is called is within i2c_attach_client; so
you can cheat by simply not registering. Not recommended, of course! */ you can cheat by simply not registering. Not recommended, of course! */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment