diff options
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/v4l2-core/v4l2-async.c | 19 | ||||
-rw-r--r-- | drivers/media/v4l2-core/v4l2-fwnode.c | 41 |
2 files changed, 56 insertions, 4 deletions
diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c index 57bd54016064..49f7eccc76db 100644 --- a/drivers/media/v4l2-core/v4l2-async.c +++ b/drivers/media/v4l2-core/v4l2-async.c @@ -474,19 +474,25 @@ int v4l2_async_subdev_notifier_register(struct v4l2_subdev *sd, } EXPORT_SYMBOL(v4l2_async_subdev_notifier_register); -void v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier) +static void __v4l2_async_notifier_unregister( + struct v4l2_async_notifier *notifier) { - if (!notifier->v4l2_dev && !notifier->sd) + if (!notifier || (!notifier->v4l2_dev && !notifier->sd)) return; - mutex_lock(&list_lock); - v4l2_async_notifier_unbind_all_subdevs(notifier); notifier->sd = NULL; notifier->v4l2_dev = NULL; list_del(¬ifier->list); +} + +void v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier) +{ + mutex_lock(&list_lock); + + __v4l2_async_notifier_unregister(notifier); mutex_unlock(&list_lock); } @@ -596,6 +602,11 @@ void v4l2_async_unregister_subdev(struct v4l2_subdev *sd) { mutex_lock(&list_lock); + __v4l2_async_notifier_unregister(sd->subdev_notifier); + v4l2_async_notifier_cleanup(sd->subdev_notifier); + kfree(sd->subdev_notifier); + sd->subdev_notifier = NULL; + if (sd->asd) { struct v4l2_async_notifier *notifier = sd->notifier; diff --git a/drivers/media/v4l2-core/v4l2-fwnode.c b/drivers/media/v4l2-core/v4l2-fwnode.c index 39387dc6cadd..3b9c6afb49a3 100644 --- a/drivers/media/v4l2-core/v4l2-fwnode.c +++ b/drivers/media/v4l2-core/v4l2-fwnode.c @@ -29,6 +29,7 @@ #include <media/v4l2-async.h> #include <media/v4l2-fwnode.h> +#include <media/v4l2-subdev.h> enum v4l2_fwnode_bus_type { V4L2_FWNODE_BUS_TYPE_GUESS = 0, @@ -900,6 +901,46 @@ int v4l2_async_notifier_parse_fwnode_sensor_common( } EXPORT_SYMBOL_GPL(v4l2_async_notifier_parse_fwnode_sensor_common); +int v4l2_async_register_subdev_sensor_common(struct v4l2_subdev *sd) +{ + struct v4l2_async_notifier *notifier; + int ret; + + if (WARN_ON(!sd->dev)) + return -ENODEV; + + notifier = kzalloc(sizeof(*notifier), GFP_KERNEL); + if (!notifier) + return -ENOMEM; + + ret = v4l2_async_notifier_parse_fwnode_sensor_common(sd->dev, + notifier); + if (ret < 0) + goto out_cleanup; + + ret = v4l2_async_subdev_notifier_register(sd, notifier); + if (ret < 0) + goto out_cleanup; + + ret = v4l2_async_register_subdev(sd); + if (ret < 0) + goto out_unregister; + + sd->subdev_notifier = notifier; + + return 0; + +out_unregister: + v4l2_async_notifier_unregister(notifier); + +out_cleanup: + v4l2_async_notifier_cleanup(notifier); + kfree(notifier); + + return ret; +} +EXPORT_SYMBOL_GPL(v4l2_async_register_subdev_sensor_common); + MODULE_LICENSE("GPL"); MODULE_AUTHOR("Sakari Ailus <sakari.ailus@linux.intel.com>"); MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>"); |