diff options
author | Hans Verkuil <hverkuil@xs4all.nl> | 2008-11-23 10:19:45 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2008-12-30 06:38:37 -0500 |
commit | dd99120c7165c6873a423977d1eaa41b6e2d1ffc (patch) | |
tree | 3ee29916a484012dd4449de46c129cd5788b076a | |
parent | 2a1fcdf08230522bd5024f91da24aaa6e8d81f59 (diff) |
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>
-rw-r--r-- | drivers/media/video/v4l2-common.c | 113 | ||||
-rw-r--r-- | include/media/v4l2-common.h | 41 |
2 files changed, 154 insertions, 0 deletions
diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index fdc8871f631e..26f3254337da 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c | |||
@@ -58,6 +58,7 @@ | |||
58 | #include <asm/div64.h> | 58 | #include <asm/div64.h> |
59 | #define __OLD_VIDIOC_ /* To allow fixing old calls*/ | 59 | #define __OLD_VIDIOC_ /* To allow fixing old calls*/ |
60 | #include <media/v4l2-common.h> | 60 | #include <media/v4l2-common.h> |
61 | #include <media/v4l2-device.h> | ||
61 | #include <media/v4l2-chip-ident.h> | 62 | #include <media/v4l2-chip-ident.h> |
62 | 63 | ||
63 | #include <linux/videodev2.h> | 64 | #include <linux/videodev2.h> |
@@ -801,4 +802,116 @@ int v4l2_i2c_attach(struct i2c_adapter *adapter, int address, struct i2c_driver | |||
801 | return err != -ENOMEM ? 0 : err; | 802 | return err != -ENOMEM ? 0 : err; |
802 | } | 803 | } |
803 | EXPORT_SYMBOL(v4l2_i2c_attach); | 804 | EXPORT_SYMBOL(v4l2_i2c_attach); |
805 | |||
806 | void v4l2_i2c_subdev_init(struct v4l2_subdev *sd, struct i2c_client *client, | ||
807 | const struct v4l2_subdev_ops *ops) | ||
808 | { | ||
809 | v4l2_subdev_init(sd, ops); | ||
810 | /* the owner is the same as the i2c_client's driver owner */ | ||
811 | sd->owner = client->driver->driver.owner; | ||
812 | /* i2c_client and v4l2_subdev point to one another */ | ||
813 | v4l2_set_subdevdata(sd, client); | ||
814 | i2c_set_clientdata(client, sd); | ||
815 | /* initialize name */ | ||
816 | snprintf(sd->name, sizeof(sd->name), "%s %d-%04x", | ||
817 | client->driver->driver.name, i2c_adapter_id(client->adapter), | ||
818 | client->addr); | ||
819 | } | ||
820 | EXPORT_SYMBOL_GPL(v4l2_i2c_subdev_init); | ||
821 | |||
822 | |||
823 | |||
824 | /* Load an i2c sub-device. It assumes that i2c_get_adapdata(adapter) | ||
825 | returns the v4l2_device and that i2c_get_clientdata(client) | ||
826 | returns the v4l2_subdev. */ | ||
827 | struct v4l2_subdev *v4l2_i2c_new_subdev(struct i2c_adapter *adapter, | ||
828 | const char *module_name, const char *client_type, u8 addr) | ||
829 | { | ||
830 | struct v4l2_device *dev = i2c_get_adapdata(adapter); | ||
831 | struct v4l2_subdev *sd = NULL; | ||
832 | struct i2c_client *client; | ||
833 | struct i2c_board_info info; | ||
834 | |||
835 | BUG_ON(!dev); | ||
836 | #ifdef MODULE | ||
837 | if (module_name) | ||
838 | request_module(module_name); | ||
839 | #endif | ||
840 | /* Setup the i2c board info with the device type and | ||
841 | the device address. */ | ||
842 | memset(&info, 0, sizeof(info)); | ||
843 | strlcpy(info.type, client_type, sizeof(info.type)); | ||
844 | info.addr = addr; | ||
845 | |||
846 | /* Create the i2c client */ | ||
847 | client = i2c_new_device(adapter, &info); | ||
848 | /* Note: it is possible in the future that | ||
849 | c->driver is NULL if the driver is still being loaded. | ||
850 | We need better support from the kernel so that we | ||
851 | can easily wait for the load to finish. */ | ||
852 | if (client == NULL || client->driver == NULL) | ||
853 | return NULL; | ||
854 | |||
855 | /* Lock the module so we can safely get the v4l2_subdev pointer */ | ||
856 | if (!try_module_get(client->driver->driver.owner)) | ||
857 | return NULL; | ||
858 | sd = i2c_get_clientdata(client); | ||
859 | |||
860 | /* Register with the v4l2_device which increases the module's | ||
861 | use count as well. */ | ||
862 | if (v4l2_device_register_subdev(dev, sd)) | ||
863 | sd = NULL; | ||
864 | /* Decrease the module use count to match the first try_module_get. */ | ||
865 | module_put(client->driver->driver.owner); | ||
866 | return sd; | ||
867 | |||
868 | } | ||
869 | EXPORT_SYMBOL_GPL(v4l2_i2c_new_subdev); | ||
870 | |||
871 | /* Probe and load an i2c sub-device. It assumes that i2c_get_adapdata(adapter) | ||
872 | returns the v4l2_device and that i2c_get_clientdata(client) | ||
873 | returns the v4l2_subdev. */ | ||
874 | struct v4l2_subdev *v4l2_i2c_new_probed_subdev(struct i2c_adapter *adapter, | ||
875 | const char *module_name, const char *client_type, | ||
876 | const unsigned short *addrs) | ||
877 | { | ||
878 | struct v4l2_device *dev = i2c_get_adapdata(adapter); | ||
879 | struct v4l2_subdev *sd = NULL; | ||
880 | struct i2c_client *client = NULL; | ||
881 | struct i2c_board_info info; | ||
882 | |||
883 | BUG_ON(!dev); | ||
884 | #ifdef MODULE | ||
885 | if (module_name) | ||
886 | request_module(module_name); | ||
887 | #endif | ||
888 | /* Setup the i2c board info with the device type and | ||
889 | the device address. */ | ||
890 | memset(&info, 0, sizeof(info)); | ||
891 | strlcpy(info.type, client_type, sizeof(info.type)); | ||
892 | |||
893 | /* Probe and create the i2c client */ | ||
894 | client = i2c_new_probed_device(adapter, &info, addrs); | ||
895 | /* Note: it is possible in the future that | ||
896 | c->driver is NULL if the driver is still being loaded. | ||
897 | We need better support from the kernel so that we | ||
898 | can easily wait for the load to finish. */ | ||
899 | if (client == NULL || client->driver == NULL) | ||
900 | return NULL; | ||
901 | |||
902 | /* Lock the module so we can safely get the v4l2_subdev pointer */ | ||
903 | if (!try_module_get(client->driver->driver.owner)) | ||
904 | return NULL; | ||
905 | sd = i2c_get_clientdata(client); | ||
906 | |||
907 | /* Register with the v4l2_device which increases the module's | ||
908 | use count as well. */ | ||
909 | if (v4l2_device_register_subdev(dev, sd)) | ||
910 | sd = NULL; | ||
911 | /* Decrease the module use count to match the first try_module_get. */ | ||
912 | module_put(client->driver->driver.owner); | ||
913 | return sd; | ||
914 | } | ||
915 | EXPORT_SYMBOL_GPL(v4l2_i2c_new_probed_subdev); | ||
916 | |||
804 | #endif | 917 | #endif |
diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h index 2f8719abf5cb..f99c866d8c37 100644 --- a/include/media/v4l2-common.h +++ b/include/media/v4l2-common.h | |||
@@ -57,6 +57,29 @@ | |||
57 | 57 | ||
58 | /* ------------------------------------------------------------------------- */ | 58 | /* ------------------------------------------------------------------------- */ |
59 | 59 | ||
60 | /* These printk constructs can be used with v4l2_device and v4l2_subdev */ | ||
61 | #define v4l2_printk(level, dev, fmt, arg...) \ | ||
62 | printk(level "%s: " fmt, (dev)->name , ## arg) | ||
63 | |||
64 | #define v4l2_err(dev, fmt, arg...) \ | ||
65 | v4l2_printk(KERN_ERR, dev, fmt , ## arg) | ||
66 | |||
67 | #define v4l2_warn(dev, fmt, arg...) \ | ||
68 | v4l2_printk(KERN_WARNING, dev, fmt , ## arg) | ||
69 | |||
70 | #define v4l2_info(dev, fmt, arg...) \ | ||
71 | v4l2_printk(KERN_INFO, dev, fmt , ## arg) | ||
72 | |||
73 | /* These three macros assume that the debug level is set with a module | ||
74 | parameter called 'debug'. */ | ||
75 | #define v4l2_dbg(level, debug, dev, fmt, arg...) \ | ||
76 | do { \ | ||
77 | if (debug >= (level)) \ | ||
78 | v4l2_printk(KERN_DEBUG, dev, fmt , ## arg); \ | ||
79 | } while (0) | ||
80 | |||
81 | /* ------------------------------------------------------------------------- */ | ||
82 | |||
60 | /* Priority helper functions */ | 83 | /* Priority helper functions */ |
61 | 84 | ||
62 | struct v4l2_prio_state { | 85 | struct v4l2_prio_state { |
@@ -104,11 +127,29 @@ struct i2c_driver; | |||
104 | struct i2c_adapter; | 127 | struct i2c_adapter; |
105 | struct i2c_client; | 128 | struct i2c_client; |
106 | struct i2c_device_id; | 129 | struct i2c_device_id; |
130 | struct v4l2_device; | ||
131 | struct v4l2_subdev; | ||
132 | struct v4l2_subdev_ops; | ||
107 | 133 | ||
108 | int v4l2_i2c_attach(struct i2c_adapter *adapter, int address, struct i2c_driver *driver, | 134 | int v4l2_i2c_attach(struct i2c_adapter *adapter, int address, struct i2c_driver *driver, |
109 | const char *name, | 135 | const char *name, |
110 | int (*probe)(struct i2c_client *, const struct i2c_device_id *)); | 136 | int (*probe)(struct i2c_client *, const struct i2c_device_id *)); |
111 | 137 | ||
138 | /* Load an i2c module and return an initialized v4l2_subdev struct. | ||
139 | Only call request_module if module_name != NULL. | ||
140 | The client_type argument is the name of the chip that's on the adapter. */ | ||
141 | struct v4l2_subdev *v4l2_i2c_new_subdev(struct i2c_adapter *adapter, | ||
142 | const char *module_name, const char *client_type, u8 addr); | ||
143 | /* Probe and load an i2c module and return an initialized v4l2_subdev struct. | ||
144 | Only call request_module if module_name != NULL. | ||
145 | The client_type argument is the name of the chip that's on the adapter. */ | ||
146 | struct v4l2_subdev *v4l2_i2c_new_probed_subdev(struct i2c_adapter *adapter, | ||
147 | const char *module_name, const char *client_type, | ||
148 | const unsigned short *addrs); | ||
149 | /* Initialize an v4l2_subdev with data from an i2c_client struct */ | ||
150 | void v4l2_i2c_subdev_init(struct v4l2_subdev *sd, struct i2c_client *client, | ||
151 | const struct v4l2_subdev_ops *ops); | ||
152 | |||
112 | /* ------------------------------------------------------------------------- */ | 153 | /* ------------------------------------------------------------------------- */ |
113 | 154 | ||
114 | /* Internal ioctls */ | 155 | /* Internal ioctls */ |