-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
V4L/DVB (6451): v4l2: add support for bus-based I2C drivers
Two new headers were added: one for I2C drivers that are only used by V4L2 drivers converted to the new bus-based I2C API, and one that can be used by both converted and unconverted drivers (at the expense of some additional overhead). To support the legacy I2C API a helper function was added to v4l2-common.c. These headers take care of all the 'boilerplate' code that all V4L2 I2C drivers have in common and will automatically support the bus-based I2C API introduced in kernel 2.6.22. Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
- Loading branch information
Hans Verkuil
authored and
Mauro Carvalho Chehab
committed
Jan 25, 2008
1 parent
5ef4730
commit 8ffbc65
Showing
4 changed files
with
235 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
/* | ||
* v4l2-i2c-drv-legacy.h - contains I2C handling code that's identical | ||
* for all V4L2 I2C drivers. Use this header if the | ||
* I2C driver is used by both legacy drivers and | ||
* drivers converted to the bus-based I2C API. | ||
* | ||
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> | ||
* | ||
* 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 | ||
* the Free Software Foundation; either version 2 of the License, or | ||
* (at your option) any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program; if not, write to the Free Software | ||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
*/ | ||
|
||
struct v4l2_i2c_driver_data { | ||
const char * const name; | ||
int driverid; | ||
int (*command)(struct i2c_client *client, unsigned int cmd, void *arg); | ||
int (*probe)(struct i2c_client *client); | ||
int (*remove)(struct i2c_client *client); | ||
int (*suspend)(struct i2c_client *client, pm_message_t state); | ||
int (*resume)(struct i2c_client *client); | ||
int legacy_class; | ||
}; | ||
|
||
static struct v4l2_i2c_driver_data v4l2_i2c_data; | ||
static struct i2c_client_address_data addr_data; | ||
static struct i2c_driver v4l2_i2c_driver_legacy; | ||
static char v4l2_i2c_drv_name_legacy[32]; | ||
|
||
static int v4l2_i2c_drv_attach_legacy(struct i2c_adapter *adapter, int address, int kind) | ||
{ | ||
return v4l2_i2c_attach(adapter, address, &v4l2_i2c_driver_legacy, | ||
v4l2_i2c_drv_name_legacy, v4l2_i2c_data.probe); | ||
} | ||
|
||
static int v4l2_i2c_drv_probe_legacy(struct i2c_adapter *adapter) | ||
{ | ||
if (adapter->class & v4l2_i2c_data.legacy_class) | ||
return i2c_probe(adapter, &addr_data, v4l2_i2c_drv_attach_legacy); | ||
return 0; | ||
} | ||
|
||
static int v4l2_i2c_drv_detach_legacy(struct i2c_client *client) | ||
{ | ||
int err = i2c_detach_client(client); | ||
|
||
if (err) | ||
return err; | ||
if (v4l2_i2c_data.remove) | ||
v4l2_i2c_data.remove(client); | ||
kfree(client); | ||
|
||
return 0; | ||
} | ||
|
||
static int v4l2_i2c_drv_suspend_helper(struct i2c_client *client, pm_message_t state) | ||
{ | ||
return v4l2_i2c_data.suspend ? v4l2_i2c_data.suspend(client, state) : 0; | ||
} | ||
|
||
static int v4l2_i2c_drv_resume_helper(struct i2c_client *client) | ||
{ | ||
return v4l2_i2c_data.resume ? v4l2_i2c_data.resume(client) : 0; | ||
} | ||
|
||
/* ----------------------------------------------------------------------- */ | ||
|
||
/* i2c implementation */ | ||
static struct i2c_driver v4l2_i2c_driver_legacy = { | ||
.driver = { | ||
.owner = THIS_MODULE, | ||
}, | ||
.attach_adapter = v4l2_i2c_drv_probe_legacy, | ||
.detach_client = v4l2_i2c_drv_detach_legacy, | ||
.suspend = v4l2_i2c_drv_suspend_helper, | ||
.resume = v4l2_i2c_drv_resume_helper, | ||
}; | ||
|
||
/* ----------------------------------------------------------------------- */ | ||
|
||
/* i2c implementation */ | ||
static struct i2c_driver v4l2_i2c_driver = { | ||
.suspend = v4l2_i2c_drv_suspend_helper, | ||
.resume = v4l2_i2c_drv_resume_helper, | ||
}; | ||
|
||
static int __init v4l2_i2c_drv_init(void) | ||
{ | ||
int err; | ||
|
||
strlcpy(v4l2_i2c_drv_name_legacy, v4l2_i2c_data.name, sizeof(v4l2_i2c_drv_name_legacy)); | ||
strlcat(v4l2_i2c_drv_name_legacy, "'", sizeof(v4l2_i2c_drv_name_legacy)); | ||
|
||
if (v4l2_i2c_data.legacy_class == 0) | ||
v4l2_i2c_data.legacy_class = I2C_CLASS_TV_ANALOG; | ||
|
||
v4l2_i2c_driver_legacy.driver.name = v4l2_i2c_drv_name_legacy; | ||
v4l2_i2c_driver_legacy.id = v4l2_i2c_data.driverid; | ||
v4l2_i2c_driver_legacy.command = v4l2_i2c_data.command; | ||
err = i2c_add_driver(&v4l2_i2c_driver_legacy); | ||
|
||
if (err) | ||
return err; | ||
v4l2_i2c_driver.driver.name = v4l2_i2c_data.name; | ||
v4l2_i2c_driver.id = v4l2_i2c_data.driverid; | ||
v4l2_i2c_driver.command = v4l2_i2c_data.command; | ||
v4l2_i2c_driver.probe = v4l2_i2c_data.probe; | ||
v4l2_i2c_driver.remove = v4l2_i2c_data.remove; | ||
err = i2c_add_driver(&v4l2_i2c_driver); | ||
if (err) | ||
i2c_del_driver(&v4l2_i2c_driver_legacy); | ||
return err; | ||
} | ||
|
||
static void __exit v4l2_i2c_drv_cleanup(void) | ||
{ | ||
i2c_del_driver(&v4l2_i2c_driver_legacy); | ||
i2c_del_driver(&v4l2_i2c_driver); | ||
} | ||
|
||
module_init(v4l2_i2c_drv_init); | ||
module_exit(v4l2_i2c_drv_cleanup); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
/* | ||
* v4l2-i2c-drv.h - contains I2C handling code that's identical for | ||
* all V4L2 I2C drivers. Use this header if the | ||
* I2C driver is only used by drivers converted | ||
* to the bus-based I2C API. | ||
* | ||
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> | ||
* | ||
* 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 | ||
* the Free Software Foundation; either version 2 of the License, or | ||
* (at your option) any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program; if not, write to the Free Software | ||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
*/ | ||
|
||
struct v4l2_i2c_driver_data { | ||
const char * const name; | ||
int driverid; | ||
int (*command)(struct i2c_client *client, unsigned int cmd, void *arg); | ||
int (*probe)(struct i2c_client *client); | ||
int (*remove)(struct i2c_client *client); | ||
int (*suspend)(struct i2c_client *client, pm_message_t state); | ||
int (*resume)(struct i2c_client *client); | ||
int legacy_class; | ||
}; | ||
|
||
static struct v4l2_i2c_driver_data v4l2_i2c_data; | ||
static struct i2c_client_address_data addr_data; | ||
static struct i2c_driver v4l2_i2c_driver; | ||
|
||
|
||
/* Bus-based I2C implementation for kernels >= 2.6.22 */ | ||
|
||
static int __init v4l2_i2c_drv_init(void) | ||
{ | ||
v4l2_i2c_driver.driver.name = v4l2_i2c_data.name; | ||
v4l2_i2c_driver.id = v4l2_i2c_data.driverid; | ||
v4l2_i2c_driver.command = v4l2_i2c_data.command; | ||
v4l2_i2c_driver.probe = v4l2_i2c_data.probe; | ||
v4l2_i2c_driver.remove = v4l2_i2c_data.remove; | ||
v4l2_i2c_driver.suspend = v4l2_i2c_data.suspend; | ||
v4l2_i2c_driver.resume = v4l2_i2c_data.resume; | ||
return i2c_add_driver(&v4l2_i2c_driver); | ||
} | ||
|
||
|
||
static void __exit v4l2_i2c_drv_cleanup(void) | ||
{ | ||
i2c_del_driver(&v4l2_i2c_driver); | ||
} | ||
|
||
module_init(v4l2_i2c_drv_init); | ||
module_exit(v4l2_i2c_drv_cleanup); |