]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
media: v4l: fwnode: Add a convenience function for registering sensors
authorSakari Ailus <sakari.ailus@linux.intel.com>
Sun, 24 Sep 2017 22:47:44 +0000 (18:47 -0400)
committerMauro Carvalho Chehab <mchehab@s-opensource.com>
Tue, 31 Oct 2017 18:03:15 +0000 (14:03 -0400)
Add a convenience function for parsing firmware for information on related
devices using v4l2_async_notifier_parse_fwnode_sensor_common() registering
the notifier and finally the async sub-device itself.

This should be useful for sensor drivers that do not have device specific
requirements related to firmware information parsing or the async
framework.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Acked-by: Hans Verkuil <hans.verkuil@cisco.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Reviewed-by: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
drivers/media/v4l2-core/v4l2-async.c
drivers/media/v4l2-core/v4l2-fwnode.c
include/media/v4l2-async.h
include/media/v4l2-subdev.h

index 57bd54016064e390eebe5fea412ffc7b5876c961..49f7eccc76dbbc3b0ee6da68f9d8525428f7613f 100644 (file)
@@ -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(&notifier->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;
 
index 39387dc6cadd75cdaf3f77414ec818f162018fb2..3b9c6afb49a3478a5cf6525d5efb9b38863c5839 100644 (file)
@@ -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>");
index 8d8cfc3f31000ce676101af3f91d44e892d73b54..6152434cbe827196949d55f420d69da6999acbcb 100644 (file)
@@ -173,6 +173,28 @@ void v4l2_async_notifier_cleanup(struct v4l2_async_notifier *notifier);
  */
 int v4l2_async_register_subdev(struct v4l2_subdev *sd);
 
+/**
+ * v4l2_async_register_subdev_sensor_common - registers a sensor sub-device to
+ *                                           the asynchronous sub-device
+ *                                           framework and parse set up common
+ *                                           sensor related devices
+ *
+ * @sd: pointer to struct &v4l2_subdev
+ *
+ * This function is just like v4l2_async_register_subdev() with the exception
+ * that calling it will also parse firmware interfaces for remote references
+ * using v4l2_async_notifier_parse_fwnode_sensor_common() and registers the
+ * async sub-devices. The sub-device is similarly unregistered by calling
+ * v4l2_async_unregister_subdev().
+ *
+ * While registered, the subdev module is marked as in-use.
+ *
+ * An error is returned if the module is no longer loaded on any attempts
+ * to register it.
+ */
+int __must_check v4l2_async_register_subdev_sensor_common(
+       struct v4l2_subdev *sd);
+
 /**
  * v4l2_async_unregister_subdev - unregisters a sub-device to the asynchronous
  *     subdevice framework
index e83872078376a9874f68ae1362478e1a881b83ae..ec399c770301fc702ab3c2eb17f7ab563f9bb1fd 100644 (file)
@@ -793,6 +793,8 @@ struct v4l2_subdev_platform_data {
  *     list.
  * @asd: Pointer to respective &struct v4l2_async_subdev.
  * @notifier: Pointer to the managing notifier.
+ * @subdev_notifier: A sub-device notifier implicitly registered for the sub-
+ *                  device using v4l2_device_register_sensor_subdev().
  * @pdata: common part of subdevice platform data
  *
  * Each instance of a subdev driver should create this struct, either
@@ -823,6 +825,7 @@ struct v4l2_subdev {
        struct list_head async_list;
        struct v4l2_async_subdev *asd;
        struct v4l2_async_notifier *notifier;
+       struct v4l2_async_notifier *subdev_notifier;
        struct v4l2_subdev_platform_data *pdata;
 };