diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c index 96cc733f35ef..ff32f95d94f0 100644 --- a/drivers/media/v4l2-core/v4l2-async.c +++ b/drivers/media/v4l2-core/v4l2-async.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -46,6 +47,16 @@ static bool match_of(struct v4l2_subdev *sd, struct v4l2_async_subdev *asd) of_node_full_name(asd->match.of.node)); } +static bool match_fwnode(struct v4l2_subdev *sd, struct v4l2_async_subdev *asd) +{ + if (!is_of_node(sd->fwnode) || !is_of_node(asd->match.fwnode.fwnode)) + return sd->fwnode == asd->match.fwnode.fwnode; + + return !of_node_cmp(of_node_full_name(to_of_node(sd->fwnode)), + of_node_full_name( + to_of_node(asd->match.fwnode.fwnode))); +} + static bool match_custom(struct v4l2_subdev *sd, struct v4l2_async_subdev *asd) { if (!asd->match.custom.match) @@ -80,6 +91,9 @@ static struct v4l2_async_subdev *v4l2_async_belongs(struct v4l2_async_notifier * case V4L2_ASYNC_MATCH_OF: match = match_of; break; + case V4L2_ASYNC_MATCH_FWNODE: + match = match_fwnode; + break; default: /* Cannot happen, unless someone breaks us */ WARN_ON(true); @@ -158,6 +172,7 @@ int v4l2_async_notifier_register(struct v4l2_device *v4l2_dev, case V4L2_ASYNC_MATCH_DEVNAME: case V4L2_ASYNC_MATCH_I2C: case V4L2_ASYNC_MATCH_OF: + case V4L2_ASYNC_MATCH_FWNODE: break; default: dev_err(notifier->v4l2_dev ? notifier->v4l2_dev->dev : NULL, diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h index 1d6d7da4c45d..7c8642c9a5b9 100644 --- a/include/media/v4l2-async.h +++ b/include/media/v4l2-async.h @@ -23,11 +23,26 @@ struct v4l2_async_notifier; /* A random max subdevice number, used to allocate an array on stack */ #define V4L2_MAX_SUBDEVS 128U +/** + * enum v4l2_async_match_type - type of asynchronous subdevice logic to be used + * in order to identify a match + * + * @V4L2_ASYNC_MATCH_CUSTOM: Match will use the logic provided by &struct + * v4l2_async_subdev.match ops + * @V4L2_ASYNC_MATCH_DEVNAME: Match will use the device name + * @V4L2_ASYNC_MATCH_I2C: Match will check for I2C adapter ID and address + * @V4L2_ASYNC_MATCH_OF: Match will use OF node + * @V4L2_ASYNC_MATCH_FWNODE: Match will use firmware node + * + * This enum is used by the asyncrhronous sub-device logic to define the + * algorithm that will be used to match an asynchronous device. + */ enum v4l2_async_match_type { V4L2_ASYNC_MATCH_CUSTOM, V4L2_ASYNC_MATCH_DEVNAME, V4L2_ASYNC_MATCH_I2C, V4L2_ASYNC_MATCH_OF, + V4L2_ASYNC_MATCH_FWNODE, }; /** @@ -44,6 +59,9 @@ struct v4l2_async_subdev { struct { const struct device_node *node; } of; + struct { + struct fwnode_handle *fwnode; + } fwnode; struct { const char *name; } device_name; diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index b273cf9ac047..9b003a694a8f 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -726,6 +726,7 @@ struct v4l2_subdev { struct device *dev; /* The device_node of the subdev, usually the same as dev->of_node. */ struct device_node *of_node; + struct fwnode_handle *fwnode; /* Links this subdev to a global subdev_list or @notifier->done list. */ struct list_head async_list; /* Pointer to respective struct v4l2_async_subdev. */