diff options
-rw-r--r-- | drivers/media/video/v4l2-common.c | 1 | ||||
-rw-r--r-- | drivers/media/video/v4l2-device.c | 13 | ||||
-rw-r--r-- | include/media/v4l2-subdev.h | 5 |
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 | } |
89 | EXPORT_SYMBOL_GPL(v4l2_device_unregister); | 100 | EXPORT_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 | */ |
236 | struct v4l2_subdev { | 239 | struct 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; |