Commit aef69d54 authored by Sakari Ailus's avatar Sakari Ailus Committed by Mauro Carvalho Chehab

media: v4l: fwnode: Add a convenience function for registering sensors

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: default avatarSakari Ailus <sakari.ailus@linux.intel.com>
Acked-by: default avatarHans Verkuil <hans.verkuil@cisco.com>
Reviewed-by: default avatarNiklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Reviewed-by: default avatarSebastian Reichel <sebastian.reichel@collabora.co.uk>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@s-opensource.com>
parent 7a9ec808
...@@ -474,19 +474,25 @@ int v4l2_async_subdev_notifier_register(struct v4l2_subdev *sd, ...@@ -474,19 +474,25 @@ int v4l2_async_subdev_notifier_register(struct v4l2_subdev *sd,
} }
EXPORT_SYMBOL(v4l2_async_subdev_notifier_register); 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; return;
mutex_lock(&list_lock);
v4l2_async_notifier_unbind_all_subdevs(notifier); v4l2_async_notifier_unbind_all_subdevs(notifier);
notifier->sd = NULL; notifier->sd = NULL;
notifier->v4l2_dev = NULL; notifier->v4l2_dev = NULL;
list_del(&notifier->list); 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); mutex_unlock(&list_lock);
} }
...@@ -596,6 +602,11 @@ void v4l2_async_unregister_subdev(struct v4l2_subdev *sd) ...@@ -596,6 +602,11 @@ void v4l2_async_unregister_subdev(struct v4l2_subdev *sd)
{ {
mutex_lock(&list_lock); 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) { if (sd->asd) {
struct v4l2_async_notifier *notifier = sd->notifier; struct v4l2_async_notifier *notifier = sd->notifier;
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <media/v4l2-async.h> #include <media/v4l2-async.h>
#include <media/v4l2-fwnode.h> #include <media/v4l2-fwnode.h>
#include <media/v4l2-subdev.h>
enum v4l2_fwnode_bus_type { enum v4l2_fwnode_bus_type {
V4L2_FWNODE_BUS_TYPE_GUESS = 0, V4L2_FWNODE_BUS_TYPE_GUESS = 0,
...@@ -900,6 +901,46 @@ int v4l2_async_notifier_parse_fwnode_sensor_common( ...@@ -900,6 +901,46 @@ int v4l2_async_notifier_parse_fwnode_sensor_common(
} }
EXPORT_SYMBOL_GPL(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_LICENSE("GPL");
MODULE_AUTHOR("Sakari Ailus <sakari.ailus@linux.intel.com>"); MODULE_AUTHOR("Sakari Ailus <sakari.ailus@linux.intel.com>");
MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>"); MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
......
...@@ -173,6 +173,28 @@ void v4l2_async_notifier_cleanup(struct v4l2_async_notifier *notifier); ...@@ -173,6 +173,28 @@ void v4l2_async_notifier_cleanup(struct v4l2_async_notifier *notifier);
*/ */
int v4l2_async_register_subdev(struct v4l2_subdev *sd); 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 * v4l2_async_unregister_subdev - unregisters a sub-device to the asynchronous
* subdevice framework * subdevice framework
......
...@@ -793,6 +793,8 @@ struct v4l2_subdev_platform_data { ...@@ -793,6 +793,8 @@ struct v4l2_subdev_platform_data {
* list. * list.
* @asd: Pointer to respective &struct v4l2_async_subdev. * @asd: Pointer to respective &struct v4l2_async_subdev.
* @notifier: Pointer to the managing notifier. * @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 * @pdata: common part of subdevice platform data
* *
* Each instance of a subdev driver should create this struct, either * Each instance of a subdev driver should create this struct, either
...@@ -823,6 +825,7 @@ struct v4l2_subdev { ...@@ -823,6 +825,7 @@ struct v4l2_subdev {
struct list_head async_list; struct list_head async_list;
struct v4l2_async_subdev *asd; struct v4l2_async_subdev *asd;
struct v4l2_async_notifier *notifier; struct v4l2_async_notifier *notifier;
struct v4l2_async_notifier *subdev_notifier;
struct v4l2_subdev_platform_data *pdata; struct v4l2_subdev_platform_data *pdata;
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment