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 /drivers | |
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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/media/video/v4l2-common.c | 113 |
1 files changed, 113 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 |