diff mbox

[03/22,media] v4l: of: add v4l2_of_subdev_registered

Message ID 20161007160107.5074-4-p.zabel@pengutronix.de (mailing list archive)
State New, archived
Headers show

Commit Message

Philipp Zabel Oct. 7, 2016, 4 p.m. UTC
Provide a default registered callback for device tree probed subdevices
that use OF graph bindings to add still missing source subdevices to
the async notifier waiting list.
This is only necessary for subdevices that have input ports to which
other subdevices are connected that are not initially known to the
master/bridge device when it sets up the notifier.

Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
---
 drivers/media/v4l2-core/v4l2-of.c | 68 +++++++++++++++++++++++++++++++++++++++
 include/media/v4l2-of.h           | 12 +++++++
 2 files changed, 80 insertions(+)

Comments

Marek Vasut Oct. 7, 2016, 6:50 p.m. UTC | #1
On 10/07/2016 06:00 PM, Philipp Zabel wrote:
> Provide a default registered callback for device tree probed subdevices
> that use OF graph bindings to add still missing source subdevices to
> the async notifier waiting list.
> This is only necessary for subdevices that have input ports to which
> other subdevices are connected that are not initially known to the
> master/bridge device when it sets up the notifier.
> 
> Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>

[...]

> +int v4l2_of_subdev_registered(struct v4l2_subdev *sd)
> +{
> +	struct device_node *ep;
> +
> +	for_each_endpoint_of_node(sd->of_node, ep) {
> +		struct v4l2_of_link link;
> +		struct media_entity *entity;
> +		unsigned int pad;
> +		int ret;
> +
> +		ret = v4l2_of_parse_link(ep, &link);
> +		if (ret)
> +			continue;
> +
> +		/*
> +		 * Assume 1:1 correspondence between OF node and entity,
> +		 * and between OF port numbers and pad indices.
> +		 */
> +		entity = &sd->entity;

This here will not compile if CONFIG_MEDIA_CONTROLLER is not set,
because ->entity will be missing from struct v4l2_subdev {} .

> +		pad = link.local_port;
> +
> +		if (pad >= entity->num_pads)
> +			return -EINVAL;
> +
> +		/* Add source subdevs to async notifier */
> +		if (entity->pads[pad].flags & MEDIA_PAD_FL_SINK) {
> +			struct v4l2_async_subdev *asd;
> +
> +			asd = devm_kzalloc(sd->dev, sizeof(*asd), GFP_KERNEL);
> +			if (!asd) {
> +				v4l2_of_put_link(&link);
> +				return -ENOMEM;
> +			}
> +
> +			asd->match_type = V4L2_ASYNC_MATCH_OF;
> +			asd->match.of.node = link.remote_node;
> +
> +			__v4l2_async_notifier_add_subdev(sd->notifier, asd);
> +		}
> +
> +		v4l2_of_put_link(&link);
> +	}
> +
> +	return 0;
> +}
> diff --git a/include/media/v4l2-of.h b/include/media/v4l2-of.h
> index 4dc34b2..67d4f8b 100644
> --- a/include/media/v4l2-of.h
> +++ b/include/media/v4l2-of.h
> @@ -22,6 +22,8 @@
>  #include <media/v4l2-mediabus.h>
>  
>  struct device_node;
> +struct v4l2_device;
> +struct v4l2_subdev;
>  
>  /**
>   * struct v4l2_of_bus_mipi_csi2 - MIPI CSI-2 bus data structure
> @@ -95,6 +97,9 @@ void v4l2_of_free_endpoint(struct v4l2_of_endpoint *endpoint);
>  int v4l2_of_parse_link(const struct device_node *node,
>  		       struct v4l2_of_link *link);
>  void v4l2_of_put_link(struct v4l2_of_link *link);
> +int v4l2_of_subdev_registered(struct v4l2_subdev *sd);
> +struct v4l2_subdev *v4l2_find_subdev_by_node(struct v4l2_device *v4l2_dev,
> +					     struct device_node *node);
>  #else /* CONFIG_OF */
>  
>  static inline int v4l2_of_parse_endpoint(const struct device_node *node,
> @@ -123,6 +128,13 @@ static inline void v4l2_of_put_link(struct v4l2_of_link *link)
>  {
>  }
>  
> +#define v4l2_of_subdev_registered NULL
> +
> +struct v4l2_subdev *v4l2_find_subdev_by_node(struct v4l2_device *v4l2_dev,
> +					     struct device_node *node)
> +{
> +	return NULL;
> +}
>  #endif /* CONFIG_OF */
>  
>  #endif /* _V4L2_OF_H */
>
Sakari Ailus Oct. 7, 2016, 10:50 p.m. UTC | #2
Hi Philipp,

On Fri, Oct 07, 2016 at 06:00:48PM +0200, Philipp Zabel wrote:
> Provide a default registered callback for device tree probed subdevices
> that use OF graph bindings to add still missing source subdevices to
> the async notifier waiting list.
> This is only necessary for subdevices that have input ports to which
> other subdevices are connected that are not initially known to the
> master/bridge device when it sets up the notifier.
> 
> Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
> ---
>  drivers/media/v4l2-core/v4l2-of.c | 68 +++++++++++++++++++++++++++++++++++++++
>  include/media/v4l2-of.h           | 12 +++++++
>  2 files changed, 80 insertions(+)
> 
> diff --git a/drivers/media/v4l2-core/v4l2-of.c b/drivers/media/v4l2-core/v4l2-of.c
> index 93b3368..fbdd6b4 100644
> --- a/drivers/media/v4l2-core/v4l2-of.c
> +++ b/drivers/media/v4l2-core/v4l2-of.c
> @@ -19,6 +19,7 @@
>  #include <linux/types.h>
>  
>  #include <media/v4l2-of.h>
> +#include <media/v4l2-device.h>

Alphabetical order, please.

>  
>  static int v4l2_of_parse_csi_bus(const struct device_node *node,
>  				 struct v4l2_of_endpoint *endpoint)
> @@ -314,3 +315,70 @@ void v4l2_of_put_link(struct v4l2_of_link *link)
>  	of_node_put(link->remote_node);
>  }
>  EXPORT_SYMBOL(v4l2_of_put_link);
> +
> +struct v4l2_subdev *v4l2_find_subdev_by_node(struct v4l2_device *v4l2_dev,
> +					     struct device_node *node)
> +{
> +	struct v4l2_subdev *sd;
> +
> +	list_for_each_entry(sd, &v4l2_dev->subdevs, list) {
> +		if (sd->of_node == node)
> +			return sd;
> +	}

The braces aren't really needed. Up to you.

> +
> +	return NULL;
> +}
Philipp Zabel Oct. 14, 2016, 3:48 p.m. UTC | #3
Am Freitag, den 07.10.2016, 20:50 +0200 schrieb Marek Vasut:
> On 10/07/2016 06:00 PM, Philipp Zabel wrote:
> > Provide a default registered callback for device tree probed subdevices
> > that use OF graph bindings to add still missing source subdevices to
> > the async notifier waiting list.
> > This is only necessary for subdevices that have input ports to which
> > other subdevices are connected that are not initially known to the
> > master/bridge device when it sets up the notifier.
> > 
> > Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
> 
> [...]
> 
> > +int v4l2_of_subdev_registered(struct v4l2_subdev *sd)
> > +{
> > +	struct device_node *ep;
> > +
> > +	for_each_endpoint_of_node(sd->of_node, ep) {
> > +		struct v4l2_of_link link;
> > +		struct media_entity *entity;
> > +		unsigned int pad;
> > +		int ret;
> > +
> > +		ret = v4l2_of_parse_link(ep, &link);
> > +		if (ret)
> > +			continue;
> > +
> > +		/*
> > +		 * Assume 1:1 correspondence between OF node and entity,
> > +		 * and between OF port numbers and pad indices.
> > +		 */
> > +		entity = &sd->entity;
> 
> This here will not compile if CONFIG_MEDIA_CONTROLLER is not set,
> because ->entity will be missing from struct v4l2_subdev {} .

Thanks, I'll fix this.

regards
Philipp

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Philipp Zabel Oct. 14, 2016, 3:49 p.m. UTC | #4
Am Samstag, den 08.10.2016, 01:50 +0300 schrieb Sakari Ailus:
> Hi Philipp,
> 
> On Fri, Oct 07, 2016 at 06:00:48PM +0200, Philipp Zabel wrote:
> > Provide a default registered callback for device tree probed subdevices
> > that use OF graph bindings to add still missing source subdevices to
> > the async notifier waiting list.
> > This is only necessary for subdevices that have input ports to which
> > other subdevices are connected that are not initially known to the
> > master/bridge device when it sets up the notifier.
> > 
> > Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
> > ---
> >  drivers/media/v4l2-core/v4l2-of.c | 68 +++++++++++++++++++++++++++++++++++++++
> >  include/media/v4l2-of.h           | 12 +++++++
> >  2 files changed, 80 insertions(+)
> > 
> > diff --git a/drivers/media/v4l2-core/v4l2-of.c b/drivers/media/v4l2-core/v4l2-of.c
> > index 93b3368..fbdd6b4 100644
> > --- a/drivers/media/v4l2-core/v4l2-of.c
> > +++ b/drivers/media/v4l2-core/v4l2-of.c
> > @@ -19,6 +19,7 @@
> >  #include <linux/types.h>
> >  
> >  #include <media/v4l2-of.h>
> > +#include <media/v4l2-device.h>
> 
> Alphabetical order, please.

Will fix, thanks.

> >  static int v4l2_of_parse_csi_bus(const struct device_node *node,
> >  				 struct v4l2_of_endpoint *endpoint)
> > @@ -314,3 +315,70 @@ void v4l2_of_put_link(struct v4l2_of_link *link)
> >  	of_node_put(link->remote_node);
> >  }
> >  EXPORT_SYMBOL(v4l2_of_put_link);
> > +
> > +struct v4l2_subdev *v4l2_find_subdev_by_node(struct v4l2_device *v4l2_dev,
> > +					     struct device_node *node)
> > +{
> > +	struct v4l2_subdev *sd;
> > +
> > +	list_for_each_entry(sd, &v4l2_dev->subdevs, list) {
> > +		if (sd->of_node == node)
> > +			return sd;
> > +	}
> 
> The braces aren't really needed. Up to you.

I'll remove them in the next version.

regards
Philipp

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/media/v4l2-core/v4l2-of.c b/drivers/media/v4l2-core/v4l2-of.c
index 93b3368..fbdd6b4 100644
--- a/drivers/media/v4l2-core/v4l2-of.c
+++ b/drivers/media/v4l2-core/v4l2-of.c
@@ -19,6 +19,7 @@ 
 #include <linux/types.h>
 
 #include <media/v4l2-of.h>
+#include <media/v4l2-device.h>
 
 static int v4l2_of_parse_csi_bus(const struct device_node *node,
 				 struct v4l2_of_endpoint *endpoint)
@@ -314,3 +315,70 @@  void v4l2_of_put_link(struct v4l2_of_link *link)
 	of_node_put(link->remote_node);
 }
 EXPORT_SYMBOL(v4l2_of_put_link);
+
+struct v4l2_subdev *v4l2_find_subdev_by_node(struct v4l2_device *v4l2_dev,
+					     struct device_node *node)
+{
+	struct v4l2_subdev *sd;
+
+	list_for_each_entry(sd, &v4l2_dev->subdevs, list) {
+		if (sd->of_node == node)
+			return sd;
+	}
+
+	return NULL;
+}
+EXPORT_SYMBOL(v4l2_find_subdev_by_node);
+
+/**
+ * v4l2_of_subdev_registered() - default OF probed subdev registered callback
+ * @subdev: subdevice with initialized entities
+ *
+ * Parse all OF graph endpoints corrensponding to the subdev's entity input pads
+ * and add the remote subdevs to the async subdev notifier.
+ */
+int v4l2_of_subdev_registered(struct v4l2_subdev *sd)
+{
+	struct device_node *ep;
+
+	for_each_endpoint_of_node(sd->of_node, ep) {
+		struct v4l2_of_link link;
+		struct media_entity *entity;
+		unsigned int pad;
+		int ret;
+
+		ret = v4l2_of_parse_link(ep, &link);
+		if (ret)
+			continue;
+
+		/*
+		 * Assume 1:1 correspondence between OF node and entity,
+		 * and between OF port numbers and pad indices.
+		 */
+		entity = &sd->entity;
+		pad = link.local_port;
+
+		if (pad >= entity->num_pads)
+			return -EINVAL;
+
+		/* Add source subdevs to async notifier */
+		if (entity->pads[pad].flags & MEDIA_PAD_FL_SINK) {
+			struct v4l2_async_subdev *asd;
+
+			asd = devm_kzalloc(sd->dev, sizeof(*asd), GFP_KERNEL);
+			if (!asd) {
+				v4l2_of_put_link(&link);
+				return -ENOMEM;
+			}
+
+			asd->match_type = V4L2_ASYNC_MATCH_OF;
+			asd->match.of.node = link.remote_node;
+
+			__v4l2_async_notifier_add_subdev(sd->notifier, asd);
+		}
+
+		v4l2_of_put_link(&link);
+	}
+
+	return 0;
+}
diff --git a/include/media/v4l2-of.h b/include/media/v4l2-of.h
index 4dc34b2..67d4f8b 100644
--- a/include/media/v4l2-of.h
+++ b/include/media/v4l2-of.h
@@ -22,6 +22,8 @@ 
 #include <media/v4l2-mediabus.h>
 
 struct device_node;
+struct v4l2_device;
+struct v4l2_subdev;
 
 /**
  * struct v4l2_of_bus_mipi_csi2 - MIPI CSI-2 bus data structure
@@ -95,6 +97,9 @@  void v4l2_of_free_endpoint(struct v4l2_of_endpoint *endpoint);
 int v4l2_of_parse_link(const struct device_node *node,
 		       struct v4l2_of_link *link);
 void v4l2_of_put_link(struct v4l2_of_link *link);
+int v4l2_of_subdev_registered(struct v4l2_subdev *sd);
+struct v4l2_subdev *v4l2_find_subdev_by_node(struct v4l2_device *v4l2_dev,
+					     struct device_node *node);
 #else /* CONFIG_OF */
 
 static inline int v4l2_of_parse_endpoint(const struct device_node *node,
@@ -123,6 +128,13 @@  static inline void v4l2_of_put_link(struct v4l2_of_link *link)
 {
 }
 
+#define v4l2_of_subdev_registered NULL
+
+struct v4l2_subdev *v4l2_find_subdev_by_node(struct v4l2_device *v4l2_dev,
+					     struct device_node *node)
+{
+	return NULL;
+}
 #endif /* CONFIG_OF */
 
 #endif /* _V4L2_OF_H */