aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil@xs4all.nl>2008-11-23 10:19:45 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2008-12-30 06:38:37 -0500
commitdd99120c7165c6873a423977d1eaa41b6e2d1ffc (patch)
tree3ee29916a484012dd4449de46c129cd5788b076a /drivers
parent2a1fcdf08230522bd5024f91da24aaa6e8d81f59 (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.c113
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}
803EXPORT_SYMBOL(v4l2_i2c_attach); 804EXPORT_SYMBOL(v4l2_i2c_attach);
805
806void 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}
820EXPORT_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. */
827struct 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}
869EXPORT_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. */
874struct 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}
915EXPORT_SYMBOL_GPL(v4l2_i2c_new_probed_subdev);
916
804#endif 917#endif