[media] v4l: of: Add v4l2_of_parse_link() function
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Fri, 17 May 2013 10:31:04 +0000 (07:31 -0300)
committerMauro Carvalho Chehab <mchehab@osg.samsung.com>
Fri, 3 Apr 2015 03:50:46 +0000 (00:50 -0300)
The function fills a link data structure with the device node and port
number at both the local and remote ends of a link defined by one of its
endpoint nodes.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Hans Verkuil <hans.verkuil@cisco.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Acked-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
drivers/media/v4l2-core/v4l2-of.c
include/media/v4l2-of.h

index 58e401f4893a9f3f5a119b4f25cd194b5da60b25..83143d39dea760d1120f6bf7d2fa309a147a2189 100644 (file)
@@ -165,3 +165,64 @@ int v4l2_of_parse_endpoint(const struct device_node *node,
        return 0;
 }
 EXPORT_SYMBOL(v4l2_of_parse_endpoint);
+
+/**
+ * v4l2_of_parse_link() - parse a link between two endpoints
+ * @node: pointer to the endpoint at the local end of the link
+ * @link: pointer to the V4L2 OF link data structure
+ *
+ * Fill the link structure with the local and remote nodes and port numbers.
+ * The local_node and remote_node fields are set to point to the local and
+ * remote port's parent nodes respectively (the port parent node being the
+ * parent node of the port node if that node isn't a 'ports' node, or the
+ * grand-parent node of the port node otherwise).
+ *
+ * A reference is taken to both the local and remote nodes, the caller must use
+ * v4l2_of_put_link() to drop the references when done with the link.
+ *
+ * Return: 0 on success, or -ENOLINK if the remote endpoint can't be found.
+ */
+int v4l2_of_parse_link(const struct device_node *node,
+                      struct v4l2_of_link *link)
+{
+       struct device_node *np;
+
+       memset(link, 0, sizeof(*link));
+
+       np = of_get_parent(node);
+       of_property_read_u32(np, "reg", &link->local_port);
+       np = of_get_next_parent(np);
+       if (of_node_cmp(np->name, "ports") == 0)
+               np = of_get_next_parent(np);
+       link->local_node = np;
+
+       np = of_parse_phandle(node, "remote-endpoint", 0);
+       if (!np) {
+               of_node_put(link->local_node);
+               return -ENOLINK;
+       }
+
+       np = of_get_parent(np);
+       of_property_read_u32(np, "reg", &link->remote_port);
+       np = of_get_next_parent(np);
+       if (of_node_cmp(np->name, "ports") == 0)
+               np = of_get_next_parent(np);
+       link->remote_node = np;
+
+       return 0;
+}
+EXPORT_SYMBOL(v4l2_of_parse_link);
+
+/**
+ * v4l2_of_put_link() - drop references to nodes in a link
+ * @link: pointer to the V4L2 OF link data structure
+ *
+ * Drop references to the local and remote nodes in the link. This function must
+ * be called on every link parsed with v4l2_of_parse_link().
+ */
+void v4l2_of_put_link(struct v4l2_of_link *link)
+{
+       of_node_put(link->local_node);
+       of_node_put(link->remote_node);
+}
+EXPORT_SYMBOL(v4l2_of_put_link);
index 2de42c584eb28015aaa48c43ef7c5106f69c185b..f831c9c225b60baeb78c3f0964662ea46b8e2857 100644 (file)
@@ -69,9 +69,26 @@ struct v4l2_of_endpoint {
        struct list_head head;
 };
 
+/**
+ * struct v4l2_of_link - a link between two endpoints
+ * @local_node: pointer to device_node of this endpoint
+ * @local_port: identifier of the port this endpoint belongs to
+ * @remote_node: pointer to device_node of the remote endpoint
+ * @remote_port: identifier of the port the remote endpoint belongs to
+ */
+struct v4l2_of_link {
+       struct device_node *local_node;
+       unsigned int local_port;
+       struct device_node *remote_node;
+       unsigned int remote_port;
+};
+
 #ifdef CONFIG_OF
 int v4l2_of_parse_endpoint(const struct device_node *node,
                           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);
 #else /* CONFIG_OF */
 
 static inline int v4l2_of_parse_endpoint(const struct device_node *node,
@@ -80,6 +97,16 @@ static inline int v4l2_of_parse_endpoint(const struct device_node *node,
        return -ENOSYS;
 }
 
+static inline int v4l2_of_parse_link(const struct device_node *node,
+                                    struct v4l2_of_link *link)
+{
+       return -ENOSYS;
+}
+
+static inline void v4l2_of_put_link(struct v4l2_of_link *link)
+{
+}
+
 #endif /* CONFIG_OF */
 
 #endif /* _V4L2_OF_H */