aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--drivers/media/video/v4l2-common.c105
-rw-r--r--include/media/v4l2-common.h16
-rw-r--r--include/media/v4l2-subdev.h7
3 files changed, 127 insertions, 1 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{
diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h
index c48c24e4d0fa..95f4364322eb 100644
--- a/include/media/v4l2-common.h
+++ b/include/media/v4l2-common.h
@@ -153,6 +153,22 @@ struct v4l2_subdev *v4l2_i2c_new_probed_subdev(struct v4l2_device *v4l2_dev,
153struct v4l2_subdev *v4l2_i2c_new_probed_subdev_addr(struct v4l2_device *v4l2_dev, 153struct v4l2_subdev *v4l2_i2c_new_probed_subdev_addr(struct v4l2_device *v4l2_dev,
154 struct i2c_adapter *adapter, 154 struct i2c_adapter *adapter,
155 const char *module_name, const char *client_type, u8 addr); 155 const char *module_name, const char *client_type, u8 addr);
156
157/* Load an i2c module and return an initialized v4l2_subdev struct.
158 Only call request_module if module_name != NULL.
159 The client_type argument is the name of the chip that's on the adapter. */
160struct v4l2_subdev *v4l2_i2c_new_subdev_cfg(struct v4l2_device *v4l2_dev,
161 struct i2c_adapter *adapter,
162 const char *module_name, const char *client_type,
163 int irq, void *platform_data,
164 u8 addr, const unsigned short *probe_addrs);
165
166struct i2c_board_info;
167
168struct v4l2_subdev *v4l2_i2c_new_subdev_board(struct v4l2_device *v4l2_dev,
169 struct i2c_adapter *adapter, const char *module_name,
170 struct i2c_board_info *info, const unsigned short *probe_addrs);
171
156/* Initialize an v4l2_subdev with data from an i2c_client struct */ 172/* Initialize an v4l2_subdev with data from an i2c_client struct */
157void v4l2_i2c_subdev_init(struct v4l2_subdev *sd, struct i2c_client *client, 173void v4l2_i2c_subdev_init(struct v4l2_subdev *sd, struct i2c_client *client,
158 const struct v4l2_subdev_ops *ops); 174 const struct v4l2_subdev_ops *ops);
diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
index a503e1cee78b..5dcb36785529 100644
--- a/include/media/v4l2-subdev.h
+++ b/include/media/v4l2-subdev.h
@@ -79,7 +79,11 @@ struct v4l2_decode_vbi_line {
79 not yet implemented) since ops provide proper type-checking. 79 not yet implemented) since ops provide proper type-checking.
80 */ 80 */
81 81
82/* init: initialize the sensor registors to some sort of reasonable default 82/* s_config: if set, then it is always called by the v4l2_i2c_new_subdev*
83 functions after the v4l2_subdev was registered. It is used to pass
84 platform data to the subdev which can be used during initialization.
85
86 init: initialize the sensor registors to some sort of reasonable default
83 values. Do not use for new drivers and should be removed in existing 87 values. Do not use for new drivers and should be removed in existing
84 drivers. 88 drivers.
85 89
@@ -96,6 +100,7 @@ struct v4l2_decode_vbi_line {
96struct v4l2_subdev_core_ops { 100struct v4l2_subdev_core_ops {
97 int (*g_chip_ident)(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip); 101 int (*g_chip_ident)(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip);
98 int (*log_status)(struct v4l2_subdev *sd); 102 int (*log_status)(struct v4l2_subdev *sd);
103 int (*s_config)(struct v4l2_subdev *sd, int irq, void *platform_data);
99 int (*init)(struct v4l2_subdev *sd, u32 val); 104 int (*init)(struct v4l2_subdev *sd, u32 val);
100 int (*load_fw)(struct v4l2_subdev *sd); 105 int (*load_fw)(struct v4l2_subdev *sd);
101 int (*reset)(struct v4l2_subdev *sd, u32 val); 106 int (*reset)(struct v4l2_subdev *sd, u32 val);