diff options
author | Mauro Carvalho Chehab <mchehab@s-opensource.com> | 2018-03-02 18:21:16 +0300 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@s-opensource.com> | 2018-03-06 13:00:31 +0300 |
commit | 8f569c0b4e6b6bd5db1d09551b2df87d912f124e (patch) | |
tree | f8311565f09f55db349bf9937e46cb9f6ff56c68 /drivers/media/dvb-core | |
parent | f410b4093fdd4d8f4644d3d486afe3040eceef7b (diff) | |
download | linux-8f569c0b4e6b6bd5db1d09551b2df87d912f124e.tar.xz |
media: dvb-core: add helper functions for I2C binding
The dvb_attach()/dvb_detach() methods are ugly hacks designed
to keep using the I2C low-level API. The proper way is to
do I2C bus bindings instead.
Several modules were already converted to use it. Yet,
it is painful to use it, as lots of code need to be
duplicated.
Make it easier by providing two new helper functions:
- dvb_module_probe()
- dvb_module_release()
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
Diffstat (limited to 'drivers/media/dvb-core')
-rw-r--r-- | drivers/media/dvb-core/dvbdev.c | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c index 60e9c2ba26be..a840133feacb 100644 --- a/drivers/media/dvb-core/dvbdev.c +++ b/drivers/media/dvb-core/dvbdev.c @@ -24,6 +24,7 @@ #include <linux/string.h> #include <linux/module.h> #include <linux/kernel.h> +#include <linux/i2c.h> #include <linux/init.h> #include <linux/slab.h> #include <linux/device.h> @@ -941,6 +942,53 @@ out: return err; } +#ifdef CONFIG_I2C +struct i2c_client *dvb_module_probe(const char *module_name, + const char *name, + struct i2c_adapter *adap, + unsigned char addr, + void *platform_data) +{ + struct i2c_client *client; + struct i2c_board_info *board_info; + + board_info = kzalloc(sizeof(*board_info), GFP_KERNEL); + + if (name) + strlcpy(board_info->type, name, I2C_NAME_SIZE); + else + strlcpy(board_info->type, module_name, I2C_NAME_SIZE); + + board_info->addr = addr; + board_info->platform_data = platform_data; + request_module(module_name); + client = i2c_new_device(adap, board_info); + if (client == NULL || client->dev.driver == NULL) { + kfree(board_info); + return NULL; + } + + if (!try_module_get(client->dev.driver->owner)) { + i2c_unregister_device(client); + client = NULL; + } + + kfree(board_info); + return client; +} +EXPORT_SYMBOL_GPL(dvb_module_probe); + +void dvb_module_release(struct i2c_client *client) +{ + if (!client) + return; + + module_put(client->dev.driver->owner); + i2c_unregister_device(client); +} +EXPORT_SYMBOL_GPL(dvb_module_release); +#endif + static int dvb_uevent(struct device *dev, struct kobj_uevent_env *env) { struct dvb_device *dvbdev = dev_get_drvdata(dev); |