aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil@xs4all.nl>2009-06-09 16:12:33 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-06-23 02:15:47 -0400
commitf0222c7d860f09a61bec5e500539f28db0184b38 (patch)
treeabcd69a4421985d205ede4df0365c7616d192453 /drivers/media
parent90135c96869fa0ef3182282b2a661b57fcdb7230 (diff)
V4L/DVB (12125): v4l2: add new s_config subdev ops and v4l2_i2c_new_subdev_cfg/board calls
Add a new s_config core ops call: this is called with the irq and platform data to be used to initialize the subdev. Added new v4l2_i2c_new_subdev_cfg and v4l2_i2c_new_subdev_board calls that allows you to pass these new arguments. The existing v4l2_i2c_new_subdev functions were modified to also call s_config. In the future the existing v4l2_i2c_new_subdev functions will be replaced by a single v4l2_i2c_new_subdev function similar to v4l2_i2c_new_subdev_cfg but without the irq and platform_data arguments. Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/video/v4l2-common.c105
1 files changed, 105 insertions, 0 deletions
diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c
index f96475626da7..e7b443c116f0 100644
--- a/drivers/media/video/v4l2-common.c
+++ b/drivers/media/video/v4l2-common.c
@@ -802,6 +802,17 @@ struct v4l2_subdev *v4l2_i2c_new_subdev(struct v4l2_device *v4l2_dev,
802 /* Decrease the module use count to match the first try_module_get. */ 802 /* Decrease the module use count to match the first try_module_get. */
803 module_put(client->driver->driver.owner); 803 module_put(client->driver->driver.owner);
804 804
805 if (sd) {
806 /* We return errors from v4l2_subdev_call only if we have the
807 callback as the .s_config is not mandatory */
808 int err = v4l2_subdev_call(sd, core, s_config, 0, NULL);
809
810 if (err && err != -ENOIOCTLCMD) {
811 v4l2_device_unregister_subdev(sd);
812 sd = NULL;
813 }
814 }
815
805error: 816error:
806 /* If we have a client but no subdev, then something went wrong and 817 /* If we have a client but no subdev, then something went wrong and
807 we must unregister the client. */ 818 we must unregister the client. */
@@ -852,6 +863,17 @@ struct v4l2_subdev *v4l2_i2c_new_probed_subdev(struct v4l2_device *v4l2_dev,
852 /* Decrease the module use count to match the first try_module_get. */ 863 /* Decrease the module use count to match the first try_module_get. */
853 module_put(client->driver->driver.owner); 864 module_put(client->driver->driver.owner);
854 865
866 if (sd) {
867 /* We return errors from v4l2_subdev_call only if we have the
868 callback as the .s_config is not mandatory */
869 int err = v4l2_subdev_call(sd, core, s_config, 0, NULL);
870
871 if (err && err != -ENOIOCTLCMD) {
872 v4l2_device_unregister_subdev(sd);
873 sd = NULL;
874 }
875 }
876
855error: 877error:
856 /* If we have a client but no subdev, then something went wrong and 878 /* If we have a client but no subdev, then something went wrong and
857 we must unregister the client. */ 879 we must unregister the client. */
@@ -872,6 +894,89 @@ struct v4l2_subdev *v4l2_i2c_new_probed_subdev_addr(struct v4l2_device *v4l2_dev
872} 894}
873EXPORT_SYMBOL_GPL(v4l2_i2c_new_probed_subdev_addr); 895EXPORT_SYMBOL_GPL(v4l2_i2c_new_probed_subdev_addr);
874 896
897/* Load an i2c sub-device. */
898struct v4l2_subdev *v4l2_i2c_new_subdev_board(struct v4l2_device *v4l2_dev,
899 struct i2c_adapter *adapter, const char *module_name,
900 struct i2c_board_info *info, const unsigned short *probe_addrs)
901{
902 struct v4l2_subdev *sd = NULL;
903 struct i2c_client *client;
904
905 BUG_ON(!v4l2_dev);
906
907 if (module_name)
908 request_module(module_name);
909
910 /* Create the i2c client */
911 if (info->addr == 0 && probe_addrs)
912 client = i2c_new_probed_device(adapter, info, probe_addrs);
913 else
914 client = i2c_new_device(adapter, info);
915
916 /* Note: by loading the module first we are certain that c->driver
917 will be set if the driver was found. If the module was not loaded
918 first, then the i2c core tries to delay-load the module for us,
919 and then c->driver is still NULL until the module is finally
920 loaded. This delay-load mechanism doesn't work if other drivers
921 want to use the i2c device, so explicitly loading the module
922 is the best alternative. */
923 if (client == NULL || client->driver == NULL)
924 goto error;
925
926 /* Lock the module so we can safely get the v4l2_subdev pointer */
927 if (!try_module_get(client->driver->driver.owner))
928 goto error;
929 sd = i2c_get_clientdata(client);
930
931 /* Register with the v4l2_device which increases the module's
932 use count as well. */
933 if (v4l2_device_register_subdev(v4l2_dev, sd))
934 sd = NULL;
935 /* Decrease the module use count to match the first try_module_get. */
936 module_put(client->driver->driver.owner);
937
938 if (sd) {
939 /* We return errors from v4l2_subdev_call only if we have the
940 callback as the .s_config is not mandatory */
941 int err = v4l2_subdev_call(sd, core, s_config,
942 info->irq, info->platform_data);
943
944 if (err && err != -ENOIOCTLCMD) {
945 v4l2_device_unregister_subdev(sd);
946 sd = NULL;
947 }
948 }
949
950error:
951 /* If we have a client but no subdev, then something went wrong and
952 we must unregister the client. */
953 if (client && sd == NULL)
954 i2c_unregister_device(client);
955 return sd;
956}
957EXPORT_SYMBOL_GPL(v4l2_i2c_new_subdev_board);
958
959struct v4l2_subdev *v4l2_i2c_new_subdev_cfg(struct v4l2_device *v4l2_dev,
960 struct i2c_adapter *adapter,
961 const char *module_name, const char *client_type,
962 int irq, void *platform_data,
963 u8 addr, const unsigned short *probe_addrs)
964{
965 struct i2c_board_info info;
966
967 /* Setup the i2c board info with the device type and
968 the device address. */
969 memset(&info, 0, sizeof(info));
970 strlcpy(info.type, client_type, sizeof(info.type));
971 info.addr = addr;
972 info.irq = irq;
973 info.platform_data = platform_data;
974
975 return v4l2_i2c_new_subdev_board(v4l2_dev, adapter, module_name,
976 &info, probe_addrs);
977}
978EXPORT_SYMBOL_GPL(v4l2_i2c_new_subdev_cfg);
979
875/* Return i2c client address of v4l2_subdev. */ 980/* Return i2c client address of v4l2_subdev. */
876unsigned short v4l2_i2c_subdev_addr(struct v4l2_subdev *sd) 981unsigned short v4l2_i2c_subdev_addr(struct v4l2_subdev *sd)
877{ 982{