aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/media/video/v4l2-common.c1
-rw-r--r--drivers/media/video/v4l2-device.c13
-rw-r--r--include/media/v4l2-subdev.h5
3 files changed, 18 insertions, 1 deletions
diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c
index e32de9e9b0f3..f96475626da7 100644
--- a/drivers/media/video/v4l2-common.c
+++ b/drivers/media/video/v4l2-common.c
@@ -746,6 +746,7 @@ void v4l2_i2c_subdev_init(struct v4l2_subdev *sd, struct i2c_client *client,
746 const struct v4l2_subdev_ops *ops) 746 const struct v4l2_subdev_ops *ops)
747{ 747{
748 v4l2_subdev_init(sd, ops); 748 v4l2_subdev_init(sd, ops);
749 sd->flags |= V4L2_SUBDEV_FL_IS_I2C;
749 /* the owner is the same as the i2c_client's driver owner */ 750 /* the owner is the same as the i2c_client's driver owner */
750 sd->owner = client->driver->driver.owner; 751 sd->owner = client->driver->driver.owner;
751 /* i2c_client and v4l2_subdev point to one another */ 752 /* i2c_client and v4l2_subdev point to one another */
diff --git a/drivers/media/video/v4l2-device.c b/drivers/media/video/v4l2-device.c
index ffb425f7c24c..e1520bc84f71 100644
--- a/drivers/media/video/v4l2-device.c
+++ b/drivers/media/video/v4l2-device.c
@@ -83,8 +83,19 @@ void v4l2_device_unregister(struct v4l2_device *v4l2_dev)
83 v4l2_device_disconnect(v4l2_dev); 83 v4l2_device_disconnect(v4l2_dev);
84 84
85 /* Unregister subdevs */ 85 /* Unregister subdevs */
86 list_for_each_entry_safe(sd, next, &v4l2_dev->subdevs, list) 86 list_for_each_entry_safe(sd, next, &v4l2_dev->subdevs, list) {
87 v4l2_device_unregister_subdev(sd); 87 v4l2_device_unregister_subdev(sd);
88 if (sd->flags & V4L2_SUBDEV_FL_IS_I2C) {
89 struct i2c_client *client = v4l2_get_subdevdata(sd);
90
91 /* We need to unregister the i2c client explicitly.
92 We cannot rely on i2c_del_adapter to always
93 unregister clients for us, since if the i2c bus
94 is a platform bus, then it is never deleted. */
95 if (client)
96 i2c_unregister_device(client);
97 }
98 }
88} 99}
89EXPORT_SYMBOL_GPL(v4l2_device_unregister); 100EXPORT_SYMBOL_GPL(v4l2_device_unregister);
90 101
diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
index 17856081c809..a503e1cee78b 100644
--- a/include/media/v4l2-subdev.h
+++ b/include/media/v4l2-subdev.h
@@ -230,12 +230,16 @@ struct v4l2_subdev_ops {
230 230
231#define V4L2_SUBDEV_NAME_SIZE 32 231#define V4L2_SUBDEV_NAME_SIZE 32
232 232
233/* Set this flag if this subdev is a i2c device. */
234#define V4L2_SUBDEV_FL_IS_I2C (1U << 0)
235
233/* Each instance of a subdev driver should create this struct, either 236/* Each instance of a subdev driver should create this struct, either
234 stand-alone or embedded in a larger struct. 237 stand-alone or embedded in a larger struct.
235 */ 238 */
236struct v4l2_subdev { 239struct v4l2_subdev {
237 struct list_head list; 240 struct list_head list;
238 struct module *owner; 241 struct module *owner;
242 u32 flags;
239 struct v4l2_device *v4l2_dev; 243 struct v4l2_device *v4l2_dev;
240 const struct v4l2_subdev_ops *ops; 244 const struct v4l2_subdev_ops *ops;
241 /* name must be unique */ 245 /* name must be unique */
@@ -264,6 +268,7 @@ static inline void v4l2_subdev_init(struct v4l2_subdev *sd,
264 BUG_ON(!ops || !ops->core); 268 BUG_ON(!ops || !ops->core);
265 sd->ops = ops; 269 sd->ops = ops;
266 sd->v4l2_dev = NULL; 270 sd->v4l2_dev = NULL;
271 sd->flags = 0;
267 sd->name[0] = '\0'; 272 sd->name[0] = '\0';
268 sd->grp_id = 0; 273 sd->grp_id = 0;
269 sd->priv = NULL; 274 sd->priv = NULL;