V4L/DVB (9821): v4l2-common: add i2c helper functions
Add helper functions to load i2c sub-devices, integrating them into the v4l2-framework. Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
		
					parent
					
						
							
								2a1fcdf082
							
						
					
				
			
			
				commit
				
					
						dd99120c71
					
				
			
		
					 2 changed files with 154 additions and 0 deletions
				
			
		| 
						 | 
					@ -58,6 +58,7 @@
 | 
				
			||||||
#include <asm/div64.h>
 | 
					#include <asm/div64.h>
 | 
				
			||||||
#define __OLD_VIDIOC_ /* To allow fixing old calls*/
 | 
					#define __OLD_VIDIOC_ /* To allow fixing old calls*/
 | 
				
			||||||
#include <media/v4l2-common.h>
 | 
					#include <media/v4l2-common.h>
 | 
				
			||||||
 | 
					#include <media/v4l2-device.h>
 | 
				
			||||||
#include <media/v4l2-chip-ident.h>
 | 
					#include <media/v4l2-chip-ident.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <linux/videodev2.h>
 | 
					#include <linux/videodev2.h>
 | 
				
			||||||
| 
						 | 
					@ -801,4 +802,116 @@ int v4l2_i2c_attach(struct i2c_adapter *adapter, int address, struct i2c_driver
 | 
				
			||||||
	return err != -ENOMEM ? 0 : err;
 | 
						return err != -ENOMEM ? 0 : err;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
EXPORT_SYMBOL(v4l2_i2c_attach);
 | 
					EXPORT_SYMBOL(v4l2_i2c_attach);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void v4l2_i2c_subdev_init(struct v4l2_subdev *sd, struct i2c_client *client,
 | 
				
			||||||
 | 
							const struct v4l2_subdev_ops *ops)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						v4l2_subdev_init(sd, ops);
 | 
				
			||||||
 | 
						/* the owner is the same as the i2c_client's driver owner */
 | 
				
			||||||
 | 
						sd->owner = client->driver->driver.owner;
 | 
				
			||||||
 | 
						/* i2c_client and v4l2_subdev point to one another */
 | 
				
			||||||
 | 
						v4l2_set_subdevdata(sd, client);
 | 
				
			||||||
 | 
						i2c_set_clientdata(client, sd);
 | 
				
			||||||
 | 
						/* initialize name */
 | 
				
			||||||
 | 
						snprintf(sd->name, sizeof(sd->name), "%s %d-%04x",
 | 
				
			||||||
 | 
							client->driver->driver.name, i2c_adapter_id(client->adapter),
 | 
				
			||||||
 | 
							client->addr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(v4l2_i2c_subdev_init);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Load an i2c sub-device. It assumes that i2c_get_adapdata(adapter)
 | 
				
			||||||
 | 
					   returns the v4l2_device and that i2c_get_clientdata(client)
 | 
				
			||||||
 | 
					   returns the v4l2_subdev. */
 | 
				
			||||||
 | 
					struct v4l2_subdev *v4l2_i2c_new_subdev(struct i2c_adapter *adapter,
 | 
				
			||||||
 | 
							const char *module_name, const char *client_type, u8 addr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct v4l2_device *dev = i2c_get_adapdata(adapter);
 | 
				
			||||||
 | 
						struct v4l2_subdev *sd = NULL;
 | 
				
			||||||
 | 
						struct i2c_client *client;
 | 
				
			||||||
 | 
						struct i2c_board_info info;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						BUG_ON(!dev);
 | 
				
			||||||
 | 
					#ifdef MODULE
 | 
				
			||||||
 | 
						if (module_name)
 | 
				
			||||||
 | 
							request_module(module_name);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
						/* Setup the i2c board info with the device type and
 | 
				
			||||||
 | 
						   the device address. */
 | 
				
			||||||
 | 
						memset(&info, 0, sizeof(info));
 | 
				
			||||||
 | 
						strlcpy(info.type, client_type, sizeof(info.type));
 | 
				
			||||||
 | 
						info.addr = addr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Create the i2c client */
 | 
				
			||||||
 | 
						client = i2c_new_device(adapter, &info);
 | 
				
			||||||
 | 
						/* Note: it is possible in the future that
 | 
				
			||||||
 | 
						   c->driver is NULL if the driver is still being loaded.
 | 
				
			||||||
 | 
						   We need better support from the kernel so that we
 | 
				
			||||||
 | 
						   can easily wait for the load to finish. */
 | 
				
			||||||
 | 
						if (client == NULL || client->driver == NULL)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Lock the module so we can safely get the v4l2_subdev pointer */
 | 
				
			||||||
 | 
						if (!try_module_get(client->driver->driver.owner))
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						sd = i2c_get_clientdata(client);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Register with the v4l2_device which increases the module's
 | 
				
			||||||
 | 
						   use count as well. */
 | 
				
			||||||
 | 
						if (v4l2_device_register_subdev(dev, sd))
 | 
				
			||||||
 | 
							sd = NULL;
 | 
				
			||||||
 | 
						/* Decrease the module use count to match the first try_module_get. */
 | 
				
			||||||
 | 
						module_put(client->driver->driver.owner);
 | 
				
			||||||
 | 
						return sd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(v4l2_i2c_new_subdev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Probe and load an i2c sub-device. It assumes that i2c_get_adapdata(adapter)
 | 
				
			||||||
 | 
					   returns the v4l2_device and that i2c_get_clientdata(client)
 | 
				
			||||||
 | 
					   returns the v4l2_subdev. */
 | 
				
			||||||
 | 
					struct v4l2_subdev *v4l2_i2c_new_probed_subdev(struct i2c_adapter *adapter,
 | 
				
			||||||
 | 
						const char *module_name, const char *client_type,
 | 
				
			||||||
 | 
						const unsigned short *addrs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct v4l2_device *dev = i2c_get_adapdata(adapter);
 | 
				
			||||||
 | 
						struct v4l2_subdev *sd = NULL;
 | 
				
			||||||
 | 
						struct i2c_client *client = NULL;
 | 
				
			||||||
 | 
						struct i2c_board_info info;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						BUG_ON(!dev);
 | 
				
			||||||
 | 
					#ifdef MODULE
 | 
				
			||||||
 | 
						if (module_name)
 | 
				
			||||||
 | 
							request_module(module_name);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
						/* Setup the i2c board info with the device type and
 | 
				
			||||||
 | 
						   the device address. */
 | 
				
			||||||
 | 
						memset(&info, 0, sizeof(info));
 | 
				
			||||||
 | 
						strlcpy(info.type, client_type, sizeof(info.type));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Probe and create the i2c client */
 | 
				
			||||||
 | 
						client = i2c_new_probed_device(adapter, &info, addrs);
 | 
				
			||||||
 | 
						/* Note: it is possible in the future that
 | 
				
			||||||
 | 
						   c->driver is NULL if the driver is still being loaded.
 | 
				
			||||||
 | 
						   We need better support from the kernel so that we
 | 
				
			||||||
 | 
						   can easily wait for the load to finish. */
 | 
				
			||||||
 | 
						if (client == NULL || client->driver == NULL)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Lock the module so we can safely get the v4l2_subdev pointer */
 | 
				
			||||||
 | 
						if (!try_module_get(client->driver->driver.owner))
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						sd = i2c_get_clientdata(client);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Register with the v4l2_device which increases the module's
 | 
				
			||||||
 | 
						   use count as well. */
 | 
				
			||||||
 | 
						if (v4l2_device_register_subdev(dev, sd))
 | 
				
			||||||
 | 
							sd = NULL;
 | 
				
			||||||
 | 
						/* Decrease the module use count to match the first try_module_get. */
 | 
				
			||||||
 | 
						module_put(client->driver->driver.owner);
 | 
				
			||||||
 | 
						return sd;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(v4l2_i2c_new_probed_subdev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -57,6 +57,29 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* ------------------------------------------------------------------------- */
 | 
					/* ------------------------------------------------------------------------- */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* These printk constructs can be used with v4l2_device and v4l2_subdev */
 | 
				
			||||||
 | 
					#define v4l2_printk(level, dev, fmt, arg...) \
 | 
				
			||||||
 | 
						printk(level "%s: " fmt, (dev)->name , ## arg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define v4l2_err(dev, fmt, arg...) \
 | 
				
			||||||
 | 
						v4l2_printk(KERN_ERR, dev, fmt , ## arg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define v4l2_warn(dev, fmt, arg...) \
 | 
				
			||||||
 | 
						v4l2_printk(KERN_WARNING, dev, fmt , ## arg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define v4l2_info(dev, fmt, arg...) \
 | 
				
			||||||
 | 
						v4l2_printk(KERN_INFO, dev, fmt , ## arg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* These three macros assume that the debug level is set with a module
 | 
				
			||||||
 | 
					   parameter called 'debug'. */
 | 
				
			||||||
 | 
					#define v4l2_dbg(level, debug, dev, fmt, arg...)			\
 | 
				
			||||||
 | 
						do { 								\
 | 
				
			||||||
 | 
							if (debug >= (level))					\
 | 
				
			||||||
 | 
								v4l2_printk(KERN_DEBUG, dev, fmt , ## arg); 	\
 | 
				
			||||||
 | 
						} while (0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* ------------------------------------------------------------------------- */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Priority helper functions */
 | 
					/* Priority helper functions */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct v4l2_prio_state {
 | 
					struct v4l2_prio_state {
 | 
				
			||||||
| 
						 | 
					@ -104,11 +127,29 @@ struct i2c_driver;
 | 
				
			||||||
struct i2c_adapter;
 | 
					struct i2c_adapter;
 | 
				
			||||||
struct i2c_client;
 | 
					struct i2c_client;
 | 
				
			||||||
struct i2c_device_id;
 | 
					struct i2c_device_id;
 | 
				
			||||||
 | 
					struct v4l2_device;
 | 
				
			||||||
 | 
					struct v4l2_subdev;
 | 
				
			||||||
 | 
					struct v4l2_subdev_ops;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int v4l2_i2c_attach(struct i2c_adapter *adapter, int address, struct i2c_driver *driver,
 | 
					int v4l2_i2c_attach(struct i2c_adapter *adapter, int address, struct i2c_driver *driver,
 | 
				
			||||||
		const char *name,
 | 
							const char *name,
 | 
				
			||||||
		int (*probe)(struct i2c_client *, const struct i2c_device_id *));
 | 
							int (*probe)(struct i2c_client *, const struct i2c_device_id *));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Load an i2c module and return an initialized v4l2_subdev struct.
 | 
				
			||||||
 | 
					   Only call request_module if module_name != NULL.
 | 
				
			||||||
 | 
					   The client_type argument is the name of the chip that's on the adapter. */
 | 
				
			||||||
 | 
					struct v4l2_subdev *v4l2_i2c_new_subdev(struct i2c_adapter *adapter,
 | 
				
			||||||
 | 
							const char *module_name, const char *client_type, u8 addr);
 | 
				
			||||||
 | 
					/* Probe and load an i2c module and return an initialized v4l2_subdev struct.
 | 
				
			||||||
 | 
					   Only call request_module if module_name != NULL.
 | 
				
			||||||
 | 
					   The client_type argument is the name of the chip that's on the adapter. */
 | 
				
			||||||
 | 
					struct v4l2_subdev *v4l2_i2c_new_probed_subdev(struct i2c_adapter *adapter,
 | 
				
			||||||
 | 
							const char *module_name, const char *client_type,
 | 
				
			||||||
 | 
							const unsigned short *addrs);
 | 
				
			||||||
 | 
					/* Initialize an v4l2_subdev with data from an i2c_client struct */
 | 
				
			||||||
 | 
					void v4l2_i2c_subdev_init(struct v4l2_subdev *sd, struct i2c_client *client,
 | 
				
			||||||
 | 
							const struct v4l2_subdev_ops *ops);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* ------------------------------------------------------------------------- */
 | 
					/* ------------------------------------------------------------------------- */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Internal ioctls */
 | 
					/* Internal ioctls */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue