[alsa-devel] [PATCH 0/7] of_graph: prepare for ALSA graph support
Hi Rob, Mark Cc Guennadi, Laurent
Now OF graph is mainly used by V4L2 SoC, and ALSA SoC is using different style for SoC <-> Codec binding. But, for example, HDMI case, V4L2 <-> ALSA need to collaborate, and then ALSA SoC needs to adjust to OF graph.
OTOH, V4L2's "OF graph" position is same as ALSA SoC "sound card" position. And ALSA SoC side want to keep existing supported feature on new OF graph style. I'm posting this on ALSA SoC ML now.
Now, current of_graph is indicating port/endpoint, but there is no way to understand that it is for video port ? or sound port ? or other device port ? For example, HDMI has video port, and sound port. Because of this reason, ALSA SoC side can't handle OF graph correctly. Thus, this patch-set tries to add new "type" on OF graph.
And this patch-set includes small feature which are useful for ALSA SoC side OF graph support.
Kuninori Morimoto (7): Documentation: of: add type property of_graph: add of_graph_get_remote_endpoint() of_graph: add of_graph_port/endpoint_type_is() of_graph: add of_graph_get_endpoint_count() of_graph: add of_graph_get_port_parent() of_graph: add of_graph_get_top_port() of_graph: add for_each_of_port() / for_each_of_endpoint_in_port()
Documentation/devicetree/bindings/graph.txt | 26 ++++ drivers/of/base.c | 196 ++++++++++++++++++++++++++-- include/linux/of_graph.h | 67 ++++++++++ 3 files changed, 279 insertions(+), 10 deletions(-)
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
OF graph is used mainly from V4L2, but ALSA needs to use it too. Then, ALSA needs to know each port/endpoint type, otherwise it can't detect ALSA port/endpoint correctly. This patch enables to use type property on OF graph.
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- Documentation/devicetree/bindings/graph.txt | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+)
diff --git a/Documentation/devicetree/bindings/graph.txt b/Documentation/devicetree/bindings/graph.txt index fcb1c6a..b5b9040 100644 --- a/Documentation/devicetree/bindings/graph.txt +++ b/Documentation/devicetree/bindings/graph.txt @@ -110,6 +110,32 @@ device-2 { }; };
+port / endpoint type +-------------------- + +Each ports / port / endpoint can have its type if needed. +child node can take over parent node type. below example indicates +device0 type is "typeA" && "typeB", +device1 type is "typeA" && "typeB" && "typeC". + +device { + ports { + type = "typeA"; + + port@0 { + type = "typeB"; + + device0: endpoint@0 { + }; + + device1: endpoint@1 { + type = "typeC"; + }; + }; + ... + }; +}; +
Required properties -------------------
On Thu, Jun 23, 2016 at 9:32 PM, Kuninori Morimoto kuninori.morimoto.gx@renesas.com wrote:
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
OF graph is used mainly from V4L2, but ALSA needs to use it too. Then, ALSA needs to know each port/endpoint type, otherwise it can't detect ALSA port/endpoint correctly.
Bindings should be defined in terms of hardware, not Linux subsystems.
This patch enables to use type property on OF graph.
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
Documentation/devicetree/bindings/graph.txt | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+)
diff --git a/Documentation/devicetree/bindings/graph.txt b/Documentation/devicetree/bindings/graph.txt index fcb1c6a..b5b9040 100644 --- a/Documentation/devicetree/bindings/graph.txt +++ b/Documentation/devicetree/bindings/graph.txt @@ -110,6 +110,32 @@ device-2 { }; };
+port / endpoint type +--------------------
+Each ports / port / endpoint can have its type if needed.
I think type should only apply to a port. ports is only a grouping for multiple ports. endpoints are just the connection. A port is a single data flow, so 2 endpoints on a port reflect 2 possible connections for that data flow.
+child node can take over parent node type. below example indicates +device0 type is "typeA" && "typeB", +device1 type is "typeA" && "typeB" && "typeC".
This does not make sense to me. A concrete example perhaps using HDMI audio would be helpful.
+device {
ports {
type = "typeA";
port@0 {
type = "typeB";
device0: endpoint@0 {
};
device1: endpoint@1 {
type = "typeC";
};
};
...
};
+};
Required properties
-- 1.9.1
Hi Rob
Thank you for your review
+Each ports / port / endpoint can have its type if needed.
I think type should only apply to a port. ports is only a grouping for multiple ports. endpoints are just the connection. A port is a single data flow, so 2 endpoints on a port reflect 2 possible connections for that data flow.
+child node can take over parent node type. below example indicates +device0 type is "typeA" && "typeB", +device1 type is "typeA" && "typeB" && "typeC".
This does not make sense to me. A concrete example perhaps using HDMI audio would be helpful.
"type" on "port" only is OK. I will fix that.
Multi type feature (= take over from parent) and type on "endpoint" is not urgent at this point, so I will drop these in v2. I just thought that it will be necessary in the future.
Hi Rob, Laurent
+Each ports / port / endpoint can have its type if needed.
I think type should only apply to a port. ports is only a grouping for multiple ports. endpoints are just the connection. A port is a single data flow, so 2 endpoints on a port reflect 2 possible connections for that data flow.
+child node can take over parent node type. below example indicates +device0 type is "typeA" && "typeB", +device1 type is "typeA" && "typeB" && "typeC".
This does not make sense to me. A concrete example perhaps using HDMI audio would be helpful.
"type" on "port" only is OK. I will fix that.
Multi type feature (= take over from parent) and type on "endpoint" is not urgent at this point, so I will drop these in v2. I just thought that it will be necessary in the future.
In HDMI case, which one is better DT ?
port@0 { type = "video"; endpoint { remote-endpoint = <&xxx>; }; }; port@1 { type = "sound"; endpoint { remote-endpoint = <&xxx>; }; };
or
port { endpoint { type = "video"; remote-endpoint = <&xxx>; }; endpoint { type = "sound"; remote-endpoint = <&xxx>; }; };
If 2nd one is better, type on endpoint is needed.
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
It should use same method to get same result. To getting remote-endpoint node, let's use of_graph_get_remote_endpoint()
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- drivers/of/base.c | 18 ++++++++++++++++-- include/linux/of_graph.h | 8 ++++++++ 2 files changed, 24 insertions(+), 2 deletions(-)
diff --git a/drivers/of/base.c b/drivers/of/base.c index ebf84e3..347118e 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -2327,6 +2327,20 @@ struct device_node *of_graph_get_endpoint_by_regs( EXPORT_SYMBOL(of_graph_get_endpoint_by_regs);
/** + * of_graph_get_remote_endpoint() - get remote endpoint node + * @node: pointer to a local endpoint device_node + * + * Return: Remote endpoint node associated with remote endpoint node linked + * to @node. Use of_node_put() on it when done. + */ +struct device_node *of_graph_get_remote_endpoint(const struct device_node *node) +{ + /* Get remote endpoint node. */ + return of_parse_phandle(node, "remote-endpoint", 0); +} +EXPORT_SYMBOL(of_graph_get_remote_endpoint); + +/** * of_graph_get_remote_port_parent() - get remote port's parent node * @node: pointer to a local endpoint device_node * @@ -2340,7 +2354,7 @@ struct device_node *of_graph_get_remote_port_parent( unsigned int depth;
/* Get remote endpoint node. */ - np = of_parse_phandle(node, "remote-endpoint", 0); + np = of_graph_get_remote_endpoint(node);
/* Walk 3 levels up only if there is 'ports' node. */ for (depth = 3; depth && np; depth--) { @@ -2364,7 +2378,7 @@ struct device_node *of_graph_get_remote_port(const struct device_node *node) struct device_node *np;
/* Get remote endpoint node. */ - np = of_parse_phandle(node, "remote-endpoint", 0); + np = of_graph_get_remote_endpoint(node); if (!np) return NULL; return of_get_next_parent(np); diff --git a/include/linux/of_graph.h b/include/linux/of_graph.h index bb3a5a2..d9d6d9c 100644 --- a/include/linux/of_graph.h +++ b/include/linux/of_graph.h @@ -48,6 +48,8 @@ struct device_node *of_graph_get_next_endpoint(const struct device_node *parent, struct device_node *previous); struct device_node *of_graph_get_endpoint_by_regs( const struct device_node *parent, int port_reg, int reg); +struct device_node *of_graph_get_remote_endpoint( + const struct device_node *node); struct device_node *of_graph_get_remote_port_parent( const struct device_node *node); struct device_node *of_graph_get_remote_port(const struct device_node *node); @@ -78,6 +80,12 @@ static inline struct device_node *of_graph_get_endpoint_by_regs( return NULL; }
+static inline struct device_node *of_graph_get_remote_endpoint( + const struct device_node *node) +{ + return NULL; +} + static inline struct device_node *of_graph_get_remote_port_parent( const struct device_node *node) {
The patch
of_graph: add of_graph_get_remote_endpoint()
has been applied to the asoc tree at
git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
From 4c9c3d595f1bad021cc126d20879df4016801736 Mon Sep 17 00:00:00 2001
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com Date: Thu, 20 Apr 2017 01:31:42 +0000 Subject: [PATCH] of_graph: add of_graph_get_remote_endpoint()
It should use same method to get same result. To getting remote-endpoint node, let's use of_graph_get_remote_endpoint()
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com Acked-by: Rob Herring robh@kernel.org Signed-off-by: Mark Brown broonie@kernel.org --- drivers/of/base.c | 18 ++++++++++++++++-- include/linux/of_graph.h | 8 ++++++++ 2 files changed, 24 insertions(+), 2 deletions(-)
diff --git a/drivers/of/base.c b/drivers/of/base.c index 5db6aa1688e9..b169508a9b56 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -2487,6 +2487,20 @@ struct device_node *of_graph_get_endpoint_by_regs( EXPORT_SYMBOL(of_graph_get_endpoint_by_regs);
/** + * of_graph_get_remote_endpoint() - get remote endpoint node + * @node: pointer to a local endpoint device_node + * + * Return: Remote endpoint node associated with remote endpoint node linked + * to @node. Use of_node_put() on it when done. + */ +struct device_node *of_graph_get_remote_endpoint(const struct device_node *node) +{ + /* Get remote endpoint node. */ + return of_parse_phandle(node, "remote-endpoint", 0); +} +EXPORT_SYMBOL(of_graph_get_remote_endpoint); + +/** * of_graph_get_remote_port_parent() - get remote port's parent node * @node: pointer to a local endpoint device_node * @@ -2500,7 +2514,7 @@ struct device_node *of_graph_get_remote_port_parent( unsigned int depth;
/* Get remote endpoint node. */ - np = of_parse_phandle(node, "remote-endpoint", 0); + np = of_graph_get_remote_endpoint(node);
/* Walk 3 levels up only if there is 'ports' node. */ for (depth = 3; depth && np; depth--) { @@ -2524,7 +2538,7 @@ struct device_node *of_graph_get_remote_port(const struct device_node *node) struct device_node *np;
/* Get remote endpoint node. */ - np = of_parse_phandle(node, "remote-endpoint", 0); + np = of_graph_get_remote_endpoint(node); if (!np) return NULL; return of_get_next_parent(np); diff --git a/include/linux/of_graph.h b/include/linux/of_graph.h index abdb02eaef06..0c9473a169dd 100644 --- a/include/linux/of_graph.h +++ b/include/linux/of_graph.h @@ -48,6 +48,8 @@ struct device_node *of_graph_get_next_endpoint(const struct device_node *parent, struct device_node *previous); struct device_node *of_graph_get_endpoint_by_regs( const struct device_node *parent, int port_reg, int reg); +struct device_node *of_graph_get_remote_endpoint( + const struct device_node *node); struct device_node *of_graph_get_remote_port_parent( const struct device_node *node); struct device_node *of_graph_get_remote_port(const struct device_node *node); @@ -80,6 +82,12 @@ static inline struct device_node *of_graph_get_endpoint_by_regs( return NULL; }
+static inline struct device_node *of_graph_get_remote_endpoint( + const struct device_node *node) +{ + return NULL; +} + static inline struct device_node *of_graph_get_remote_port_parent( const struct device_node *node) {
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
OF graph endpoint is now used for V4L2 video, but ALSA will use it too. Then for example HDMI case, it needs to indicate endpoint type. Otherwise, ALSA can't handle sound endpoint correctly. This patch adds of_graph_port/endpoint_type_is() for it, and adds of_graph_port/endpoint_type_is_sound macro
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- drivers/of/base.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ include/linux/of_graph.h | 15 +++++++++++++++ 2 files changed, 61 insertions(+)
diff --git a/drivers/of/base.c b/drivers/of/base.c index 347118e..a0fc63c 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -2384,3 +2384,49 @@ struct device_node *of_graph_get_remote_port(const struct device_node *node) return of_get_next_parent(np); } EXPORT_SYMBOL(of_graph_get_remote_port); + +static bool of_graph_node_type_is(struct device_node *np, char *type) +{ + const char *prop = NULL; + + of_property_read_string(np, "type", &prop); + + if (prop && + strcmp(prop, type) == 0) + return true; + + return false; +} + +bool of_graph_port_type_is(struct device_node *port, char *type) +{ + struct device_node *ports; + bool ret; + + /* try port side */ + ret = of_graph_node_type_is(port, type); + if (ret) + return ret; + + /* try ports side */ + ports = of_get_next_parent(port); + if (ports && of_node_cmp(ports->name, "ports") == 0) + return of_graph_node_type_is(ports, type); + + return false; +} +EXPORT_SYMBOL(of_graph_port_type_is); + +bool of_graph_endpoint_type_is(struct device_node *ep, char *type) +{ + bool ret; + + /* try endpoint side */ + ret = of_graph_node_type_is(ep, type); + if (ret) + return ret; + + /* try port side */ + return of_graph_port_type_is(of_get_parent(ep), type); +} +EXPORT_SYMBOL(of_graph_endpoint_type_is); diff --git a/include/linux/of_graph.h b/include/linux/of_graph.h index d9d6d9c..1750d5c 100644 --- a/include/linux/of_graph.h +++ b/include/linux/of_graph.h @@ -40,9 +40,14 @@ struct of_endpoint { for (child = of_graph_get_next_endpoint(parent, NULL); child != NULL; \ child = of_graph_get_next_endpoint(parent, child))
+#define of_graph_port_type_is_sound(n) of_graph_port_type_is(n, "sound") +#define of_graph_endpoint_type_is_sound(n) of_graph_endpoint_type_is(n, "sound") + #ifdef CONFIG_OF int of_graph_parse_endpoint(const struct device_node *node, struct of_endpoint *endpoint); +bool of_graph_port_type_is(struct device_node *port, char *type); +bool of_graph_endpoint_type_is(struct device_node *ep, char *type); struct device_node *of_graph_get_port_by_id(struct device_node *node, u32 id); struct device_node *of_graph_get_next_endpoint(const struct device_node *parent, struct device_node *previous); @@ -61,6 +66,16 @@ static inline int of_graph_parse_endpoint(const struct device_node *node, return -ENOSYS; }
+static bool of_graph_port_type_is(struct device_node *port, char *type) +{ + return false; +} + +static bool of_graph_endpoint_type_is(struct device_node *ep, char *type) +{ + return false; +} + static inline struct device_node *of_graph_get_port_by_id( struct device_node *node, u32 id) {
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
OF graph want to count its endpoint number, same as of_get_child_count(). This patch adds of_graph_get_endpoint_count() which can check specific type. It will count all endpoint if type was NULL.
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- drivers/of/base.c | 16 ++++++++++++++++ include/linux/of_graph.h | 8 ++++++++ 2 files changed, 24 insertions(+)
diff --git a/drivers/of/base.c b/drivers/of/base.c index a0fc63c..a39d470 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -2430,3 +2430,19 @@ bool of_graph_endpoint_type_is(struct device_node *ep, char *type) return of_graph_port_type_is(of_get_parent(ep), type); } EXPORT_SYMBOL(of_graph_endpoint_type_is); + +int of_graph_get_endpoint_count(const struct device_node *np, char *type) +{ + struct device_node *child; + int num = 0; + + for_each_endpoint_of_node(np, child) { + if (!type) + num++; + else + num += of_graph_endpoint_type_is(child, type); + } + + return num; +} +EXPORT_SYMBOL(of_graph_get_endpoint_count); diff --git a/include/linux/of_graph.h b/include/linux/of_graph.h index 1750d5c..86baae5 100644 --- a/include/linux/of_graph.h +++ b/include/linux/of_graph.h @@ -42,12 +42,14 @@ struct of_endpoint {
#define of_graph_port_type_is_sound(n) of_graph_port_type_is(n, "sound") #define of_graph_endpoint_type_is_sound(n) of_graph_endpoint_type_is(n, "sound") +#define of_graph_get_sound_endpoint_count(n) of_graph_get_endpoint_count(n, "sound")
#ifdef CONFIG_OF int of_graph_parse_endpoint(const struct device_node *node, struct of_endpoint *endpoint); bool of_graph_port_type_is(struct device_node *port, char *type); bool of_graph_endpoint_type_is(struct device_node *ep, char *type); +int of_graph_get_endpoint_count(const struct device_node *np, char *type); struct device_node *of_graph_get_port_by_id(struct device_node *node, u32 id); struct device_node *of_graph_get_next_endpoint(const struct device_node *parent, struct device_node *previous); @@ -76,6 +78,12 @@ static bool of_graph_endpoint_type_is(struct device_node *ep, char *type) return false; }
+static inline int of_graph_get_endpoint_count(const struct device_node *np, + char *type) +{ + return 0; +} + static inline struct device_node *of_graph_get_port_by_id( struct device_node *node, u32 id) {
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
Linux kernel already has of_graph_get_remote_port_parent(), but, sometimes we want to get own port parent. This patch adds of_graph_get_port_parent()
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- drivers/of/base.c | 30 ++++++++++++++++++++++-------- include/linux/of_graph.h | 7 +++++++ 2 files changed, 29 insertions(+), 8 deletions(-)
diff --git a/drivers/of/base.c b/drivers/of/base.c index a39d470..283cfbb 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -2341,6 +2341,27 @@ struct device_node *of_graph_get_remote_endpoint(const struct device_node *node) EXPORT_SYMBOL(of_graph_get_remote_endpoint);
/** + * of_graph_get_port_parent() - get port's parent node + * @node: pointer to a local endpoint device_node + * + * Return: device node associated with endpoint node linked + * to @node. Use of_node_put() on it when done. + */ +struct device_node *of_graph_get_port_parent(struct device_node *node) +{ + unsigned int depth; + + /* Walk 3 levels up only if there is 'ports' node. */ + for (depth = 3; depth && node; depth--) { + node = of_get_next_parent(node); + if (depth == 2 && of_node_cmp(node->name, "ports")) + break; + } + return node; +} +EXPORT_SYMBOL(of_graph_get_port_parent); + +/** * of_graph_get_remote_port_parent() - get remote port's parent node * @node: pointer to a local endpoint device_node * @@ -2351,18 +2372,11 @@ struct device_node *of_graph_get_remote_port_parent( const struct device_node *node) { struct device_node *np; - unsigned int depth;
/* Get remote endpoint node. */ np = of_graph_get_remote_endpoint(node);
- /* Walk 3 levels up only if there is 'ports' node. */ - for (depth = 3; depth && np; depth--) { - np = of_get_next_parent(np); - if (depth == 2 && of_node_cmp(np->name, "ports")) - break; - } - return np; + return of_graph_get_port_parent(np); } EXPORT_SYMBOL(of_graph_get_remote_port_parent);
diff --git a/include/linux/of_graph.h b/include/linux/of_graph.h index 86baae5..d9868c2 100644 --- a/include/linux/of_graph.h +++ b/include/linux/of_graph.h @@ -57,6 +57,7 @@ struct device_node *of_graph_get_endpoint_by_regs( const struct device_node *parent, int port_reg, int reg); struct device_node *of_graph_get_remote_endpoint( const struct device_node *node); +struct device_node *of_graph_get_port_parent(struct device_node *node); struct device_node *of_graph_get_remote_port_parent( const struct device_node *node); struct device_node *of_graph_get_remote_port(const struct device_node *node); @@ -109,6 +110,12 @@ static inline struct device_node *of_graph_get_remote_endpoint( return NULL; }
+static inline struct device_node *of_graph_get_port_parent( + struct device_node *node) +{ + return NULL; +} + static inline struct device_node *of_graph_get_remote_port_parent( const struct device_node *node) {
The patch
of_graph: add of_graph_get_port_parent()
has been applied to the asoc tree at
git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
From 0ef472a973ebbfc20f2f12769e77a8cfd3612778 Mon Sep 17 00:00:00 2001
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com Date: Thu, 20 Apr 2017 01:32:17 +0000 Subject: [PATCH] of_graph: add of_graph_get_port_parent()
Linux kernel already has of_graph_get_remote_port_parent(), but, sometimes we want to get own port parent. This patch adds of_graph_get_port_parent()
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com Acked-by: Rob Herring robh@kernel.org Signed-off-by: Mark Brown broonie@kernel.org --- drivers/of/base.c | 30 ++++++++++++++++++++++-------- include/linux/of_graph.h | 7 +++++++ 2 files changed, 29 insertions(+), 8 deletions(-)
diff --git a/drivers/of/base.c b/drivers/of/base.c index b169508a9b56..4c305599a664 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -2501,6 +2501,27 @@ struct device_node *of_graph_get_remote_endpoint(const struct device_node *node) EXPORT_SYMBOL(of_graph_get_remote_endpoint);
/** + * of_graph_get_port_parent() - get port's parent node + * @node: pointer to a local endpoint device_node + * + * Return: device node associated with endpoint node linked + * to @node. Use of_node_put() on it when done. + */ +struct device_node *of_graph_get_port_parent(struct device_node *node) +{ + unsigned int depth; + + /* Walk 3 levels up only if there is 'ports' node. */ + for (depth = 3; depth && node; depth--) { + node = of_get_next_parent(node); + if (depth == 2 && of_node_cmp(node->name, "ports")) + break; + } + return node; +} +EXPORT_SYMBOL(of_graph_get_port_parent); + +/** * of_graph_get_remote_port_parent() - get remote port's parent node * @node: pointer to a local endpoint device_node * @@ -2511,18 +2532,11 @@ struct device_node *of_graph_get_remote_port_parent( const struct device_node *node) { struct device_node *np; - unsigned int depth;
/* Get remote endpoint node. */ np = of_graph_get_remote_endpoint(node);
- /* Walk 3 levels up only if there is 'ports' node. */ - for (depth = 3; depth && np; depth--) { - np = of_get_next_parent(np); - if (depth == 2 && of_node_cmp(np->name, "ports")) - break; - } - return np; + return of_graph_get_port_parent(np); } EXPORT_SYMBOL(of_graph_get_remote_port_parent);
diff --git a/include/linux/of_graph.h b/include/linux/of_graph.h index 0c9473a169dd..9db632d16cbc 100644 --- a/include/linux/of_graph.h +++ b/include/linux/of_graph.h @@ -50,6 +50,7 @@ struct device_node *of_graph_get_endpoint_by_regs( const struct device_node *parent, int port_reg, int reg); struct device_node *of_graph_get_remote_endpoint( const struct device_node *node); +struct device_node *of_graph_get_port_parent(struct device_node *node); struct device_node *of_graph_get_remote_port_parent( const struct device_node *node); struct device_node *of_graph_get_remote_port(const struct device_node *node); @@ -88,6 +89,12 @@ static inline struct device_node *of_graph_get_remote_endpoint( return NULL; }
+static inline struct device_node *of_graph_get_port_parent( + struct device_node *node) +{ + return NULL; +} + static inline struct device_node *of_graph_get_remote_port_parent( const struct device_node *node) {
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
driver want to get top level of port[s] node. This patch adds of_graph_get_top_port() for this purpose
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- drivers/of/base.c | 24 ++++++++++++++++++++++++ include/linux/of_graph.h | 1 + 2 files changed, 25 insertions(+)
diff --git a/drivers/of/base.c b/drivers/of/base.c index 283cfbb..e220a16 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -2225,6 +2225,30 @@ struct device_node *of_graph_get_port_by_id(struct device_node *parent, u32 id) EXPORT_SYMBOL(of_graph_get_port_by_id);
/** + * of_graph_get_top_port() - get the top port node + * @dev: pointer to the device + * + * Return: A 'port' node pointer with refcount incremented. The caller + * has to use of_node_put() on it when done. + */ +struct device_node *of_graph_get_top_port(struct device *dev) +{ + struct device_node *np = dev->of_node; + struct device_node *node; + + node = of_get_child_by_name(np, "ports"); + if (node) + return node; + + node = of_get_child_by_name(np, "port"); + if (node) + return node; + + return NULL; +} +EXPORT_SYMBOL(of_graph_get_top_port); + +/** * of_graph_get_next_endpoint() - get next endpoint node * @parent: pointer to the parent device node * @prev: previous endpoint node, or NULL to get first diff --git a/include/linux/of_graph.h b/include/linux/of_graph.h index d9868c2..b87a89f 100644 --- a/include/linux/of_graph.h +++ b/include/linux/of_graph.h @@ -51,6 +51,7 @@ bool of_graph_port_type_is(struct device_node *port, char *type); bool of_graph_endpoint_type_is(struct device_node *ep, char *type); int of_graph_get_endpoint_count(const struct device_node *np, char *type); struct device_node *of_graph_get_port_by_id(struct device_node *node, u32 id); +struct device_node *of_graph_get_top_port(struct device *dev); struct device_node *of_graph_get_next_endpoint(const struct device_node *parent, struct device_node *previous); struct device_node *of_graph_get_endpoint_by_regs(
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
OF graph is used mainly from V4L2, but ALSA needs to use it. It already has for_each_endpoint_of_node() which is for-loop for each endpoint. But, ALSA needs for-loop for each port[s], and for-loop for each endpoint of inside port[s]. This patch adds for_each_of_port() and for_each_of_endpoint_in_port() for this purpose.
And it also adds for_each_of_endpoint() which is similar to for_each_endpoint_of_node(). The difference is it can catch port handle during for-loop.
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- drivers/of/base.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/of_graph.h | 28 ++++++++++++++++++++++ 2 files changed, 90 insertions(+)
diff --git a/drivers/of/base.c b/drivers/of/base.c index e220a16..392a7bb 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -2249,6 +2249,68 @@ struct device_node *of_graph_get_top_port(struct device *dev) EXPORT_SYMBOL(of_graph_get_top_port);
/** + * of_graph_get_next_port() - get next port node + * @parent: pointer to the parent device node + * @prev: previous endpoint node, or NULL to get first + * + * Return: An 'endpoint' node pointer with refcount incremented. Refcount + * of the passed @prev node is decremented. + */ +struct device_node *of_graph_get_next_port(const struct device_node *parent, + struct device_node *prev) +{ + struct device_node *port; + struct device_node *node; + + if (!parent) + return NULL; + + node = of_get_child_by_name(parent, "ports"); + if (node) + parent = node; + + /* + * Start by locating the port node. If no previous endpoint is specified + * search for the first port node, otherwise get the previous endpoint + * parent port node. + */ + if (!prev) { + port = of_get_child_by_name(parent, "port"); + if (!port) + pr_err("%s(): no port node found in %s\n", + __func__, parent->full_name); + } else { + do { + port = of_get_next_child(parent, prev); + if (!port) + break; + } while (of_node_cmp(port->name, "port")); + } + + of_node_put(node); + + return port; +} +EXPORT_SYMBOL(of_graph_get_next_port); + +/** + * of_graph_get_next_endpoint_in_port() - get next endpoint node in port + * @parent: pointer to the parent device node + * @prev: previous endpoint node, or NULL to get first + * + * Return: An 'endpoint' node pointer with refcount incremented. Refcount + * of the passed @prev node is decremented. + */ +struct device_node *of_graph_get_next_endpoint_in_port(const struct device_node *port, + struct device_node *prev) +{ + if (!port) + return NULL; + + return of_get_next_child(port, prev); +} + +/** * of_graph_get_next_endpoint() - get next endpoint node * @parent: pointer to the parent device node * @prev: previous endpoint node, or NULL to get first diff --git a/include/linux/of_graph.h b/include/linux/of_graph.h index b87a89f..d140ae3 100644 --- a/include/linux/of_graph.h +++ b/include/linux/of_graph.h @@ -29,6 +29,16 @@ struct of_endpoint { const struct device_node *local_node; };
+#define for_each_of_port(parent, port) \ + for (port = of_graph_get_next_port(parent, NULL); port != NULL; \ + port = of_graph_get_next_port(parent, port)) +#define for_each_of_endpoint_in_port(port, ep) \ + for (ep = of_graph_get_next_endpoint_in_port(port, NULL); ep != NULL; \ + ep = of_graph_get_next_endpoint_in_port(port, ep)) +#define for_each_of_endpoint(parent, port, ep) \ + for_each_of_port(parent, port) \ + for_each_of_endpoint_in_port(port, ep) + /** * for_each_endpoint_of_node - iterate over every endpoint in a device node * @parent: parent device node containing ports and endpoints @@ -52,6 +62,10 @@ bool of_graph_endpoint_type_is(struct device_node *ep, char *type); int of_graph_get_endpoint_count(const struct device_node *np, char *type); struct device_node *of_graph_get_port_by_id(struct device_node *node, u32 id); struct device_node *of_graph_get_top_port(struct device *dev); +struct device_node *of_graph_get_next_port(const struct device_node *parent, + struct device_node *prev); +struct device_node *of_graph_get_next_endpoint_in_port(const struct device_node *port, + struct device_node *prev); struct device_node *of_graph_get_next_endpoint(const struct device_node *parent, struct device_node *previous); struct device_node *of_graph_get_endpoint_by_regs( @@ -92,6 +106,20 @@ static inline struct device_node *of_graph_get_port_by_id( return NULL; }
+static inline struct device_node *of_graph_get_next_port( + const struct device_node *parent, + struct device_node *prev) +{ + return NULL; +} + +static inline struct device_node *of_graph_get_next_endpoint_in_port( + const struct device_node *port, + struct device_node *prev) +{ + return NULL; +} + static inline struct device_node *of_graph_get_next_endpoint( const struct device_node *parent, struct device_node *previous)
participants (3)
-
Kuninori Morimoto
-
Mark Brown
-
Rob Herring