* [PATCH RFC 0/3] ASoC: audio-graph-card2: support explicitly disabled links
@ 2025-05-15 15:31 Laurentiu Mihalcea
2025-05-15 15:31 ` [PATCH RFC 1/3] ASoC: re-introduce disable_route_checks flag for OF routes Laurentiu Mihalcea
` (2 more replies)
0 siblings, 3 replies; 14+ messages in thread
From: Laurentiu Mihalcea @ 2025-05-15 15:31 UTC (permalink / raw)
To: Mark Brown, Kuninori Morimoto, Jaroslav Kysela, Takashi Iwai,
Liam Girdwood
Cc: linux-kernel, linux-sound
From: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
Some boards (referred to as "base" boards here) support attaching daughter
boards (referred to as "plugin" boards here) to them to extend their audio
capabilities (i.e. the daughter boards may contain additional codecs that
can be attached to the DAIs exposed by the base boards). This can be seen
in the following diagram:
+========+ +========+
| | D0 <-----> C0 | |
| BASE | | PLUGIN |
| | D1 <-----> C1 | |
+========+ +========+
where D0 and D1 are the DAIs of BASE board connected to PLUGIN's C0 and C1
codecs.
Currently, if any of the devices that make up a DAI link have their
DT nodes disabled using the 'status = "disabled"' property, the creation
of the sound card using "audio-graph-card2" driver will fail.
To allow for some extra flexibility with respect to the devicetrees,
this series allows the existence of explicitly disabled links. An
explicitly disabled link is a link whose CODEC/DAI DT node has been
disabled using the 'status = "disabled"' property. The sound card creation
will no longer fail if such a link is encountered.
The main usage of this feature is to support links that can be removed.
For instance, links D0-C0 and D1-C1 cannot be created unless PLUGIN is
connected. As such, we can disable the DT nodes of C0 and C1 in the
BASE's DTS and then enable them using PLUGIN's DT overlay.
Additionally, since links might be disabled, the route creation may fail.
So, if there's at least one link that was explicitly disabled then we need
to allow the route creation to fail (by re-introducing an OF variant of
the previously removed "disabled_of_route_checks"). This also allows
making the DT overlays for the plugins more scalable as we remove the
dependency of the "routing" property on the base board.
In addition to the aforementioned feature, this series also includes a set
of DTSIs that I've used for testing. I've included them in case anyone
would like to try out this new feature. If they don't bring any value then
we can just drop them.
An example of how this feature can be used is shown below. We assume that
C0 has widget C00. We also assume that BASE has an additional connection:
D2-C2, where C2 is a codec present on the BASE board. C2 has widgets C20
and C21.
[snippet from base.dts]
card {
compatible = "audio-graph-card2";
links = <&l0>, <&l1>, <&l2>;
routing = "Headphones", "C20",
"Headphones", "C21",
"Line", "C01";
};
d0: cpu@0 {
l0: port { l0_ep: endpoint { remote-endpoint = <&c0_ep>; } };
};
d1: cpu@1 {
l1: port { l1_ep: endpoint { remote-endpoint = <&c1_ep>; } };
};
d2: cpu@2 {
l2: port { l2_ep: endpoint { remote-endpoint = <&c2_ep>; } };
};
c0: codec@0 {
status = "disabled";
port { c0_ep: endpoint { remote-endpoint = <&l0_ep>; } };
};
c1: codec@1 {
status = "disabled";
port { c1_ep: endpoint { remote-endpoint = <&l1_ep>; } };
};
c2: codec@2 {
port { c2_ep: endpoint { remote-endpoint = <&l2_ep>; } };
};
[snippet from plugin.dtso]
&c0 {
status = "okay";
};
&c1 {
status = "okay";
};
Since codecs c0 and c1 do not exist unless PLUGIN is connected, they are
disabled in BASE's DTS. If PLUGIN's DTBO is not applied then only link l2
will be created. Otherwise, all links will be created. PLUGIN's DTBO can
be applied to the DTB of any BASE board it's compatible with under the
condition that the DT node labels for said codecs are kept the same.
Laurentiu Mihalcea (3):
ASoC: re-introduce disable_route_checks flag for OF routes
ASoC: audio-graph-card2: support explicitly disabled links
ASoC: generic: add more sample DTSIs for audio-graph-card2
include/sound/simple_card_utils.h | 3 +-
include/sound/soc.h | 1 +
.../generic/audio-graph-card2-sample1.dtsi | 278 ++++++
.../generic/audio-graph-card2-sample2.dtsi | 878 ++++++++++++++++++
.../generic/audio-graph-card2-sample3.dtsi | 486 ++++++++++
sound/soc/generic/audio-graph-card2.c | 231 +++++
sound/soc/soc-core.c | 12 +-
7 files changed, 1886 insertions(+), 3 deletions(-)
create mode 100644 sound/soc/generic/audio-graph-card2-sample1.dtsi
create mode 100644 sound/soc/generic/audio-graph-card2-sample2.dtsi
create mode 100644 sound/soc/generic/audio-graph-card2-sample3.dtsi
--
2.34.1
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH RFC 1/3] ASoC: re-introduce disable_route_checks flag for OF routes
2025-05-15 15:31 [PATCH RFC 0/3] ASoC: audio-graph-card2: support explicitly disabled links Laurentiu Mihalcea
@ 2025-05-15 15:31 ` Laurentiu Mihalcea
2025-05-16 1:22 ` Kuninori Morimoto
2025-05-15 15:31 ` [PATCH RFC 2/3] ASoC: audio-graph-card2: support explicitly disabled links Laurentiu Mihalcea
2025-05-15 15:31 ` [PATCH RFC 3/3] ASoC: generic: add more sample DTSIs for audio-graph-card2 Laurentiu Mihalcea
2 siblings, 1 reply; 14+ messages in thread
From: Laurentiu Mihalcea @ 2025-05-15 15:31 UTC (permalink / raw)
To: Mark Brown, Kuninori Morimoto, Jaroslav Kysela, Takashi Iwai,
Liam Girdwood
Cc: linux-kernel, linux-sound
From: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
The "disable_route_checks" flag was previously removed via commit
dd2395162c07 ("ASoC: remove disable_route_checks") as it wasn't being
used anywhere.
Re-introduce an OF-specific variant of the flag: "disable_of_route_checks"
as this will be used by audio-graph-card2.
Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
---
include/sound/soc.h | 1 +
sound/soc/soc-core.c | 12 ++++++++++--
2 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 1fffef311c41..e76da038557d 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -1077,6 +1077,7 @@ struct snd_soc_card {
unsigned int instantiated:1;
unsigned int topology_shortname_created:1;
unsigned int fully_routed:1;
+ unsigned int disable_of_route_checks:1;
unsigned int probed:1;
unsigned int component_chaining:1;
struct device *devres_dev;
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 67bebc339148..b14a52d6f550 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -2245,8 +2245,16 @@ static int snd_soc_bind_card(struct snd_soc_card *card)
ret = snd_soc_dapm_add_routes(&card->dapm, card->of_dapm_routes,
card->num_of_dapm_routes);
- if (ret < 0)
- goto probe_end;
+ if (ret < 0) {
+ if (card->disable_of_route_checks) {
+ ret = 0;
+ dev_info(card->dev,
+ "%s: disable_of_route_checks set, ignoring errors on add_routes\n",
+ __func__);
+ } else {
+ goto probe_end;
+ }
+ }
/* try to set some sane longname if DMI is available */
snd_soc_set_dmi_name(card);
--
2.34.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH RFC 2/3] ASoC: audio-graph-card2: support explicitly disabled links
2025-05-15 15:31 [PATCH RFC 0/3] ASoC: audio-graph-card2: support explicitly disabled links Laurentiu Mihalcea
2025-05-15 15:31 ` [PATCH RFC 1/3] ASoC: re-introduce disable_route_checks flag for OF routes Laurentiu Mihalcea
@ 2025-05-15 15:31 ` Laurentiu Mihalcea
2025-05-16 1:36 ` Kuninori Morimoto
2025-05-15 15:31 ` [PATCH RFC 3/3] ASoC: generic: add more sample DTSIs for audio-graph-card2 Laurentiu Mihalcea
2 siblings, 1 reply; 14+ messages in thread
From: Laurentiu Mihalcea @ 2025-05-15 15:31 UTC (permalink / raw)
To: Mark Brown, Kuninori Morimoto, Jaroslav Kysela, Takashi Iwai,
Liam Girdwood
Cc: linux-kernel, linux-sound
From: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
An explicitly disabled link is a DAI link in which one of its device
endpoints (e.g: codec or CPU) has been disabled in the DTS via the
"status" property. Formally speaking:
OF_LINK_IS_DISABLED(lnk) = OF_NODE_IS_DISABLED(dev0) ||
OF_NODE_IS_DISABLED(dev1);
where dev0 and dev1 are the two devices (CPU/codec) that make up the
link.
If at least one link was explicitly disabled that means DAPM routes
passed through the OF property "routing" can fail as some widgets might
not exist. Consider the following example:
CODEC A has widgets A0, A1.
CODEC B has widgets B0, B1.
my-card {
compatible = "audio-graph-card2":
label = "my-label";
links = <&cpu0_port>, <&cpu1_port>;
routing = "A0", "A1",
"B0", "B1";
};
CODEC A's DT node was disabled.
CODEC B's DT node is enabled.
CPU0's DT node is enabled.
CPU1's DT node is enabled.
If CODEC A's DT node is disabled via the 'status = "disabled"' property
that means the A0 -> A1 route cannot be created. This doesn't affect the
B0 -> B1 route though as CODEC B was never disabled in the DT.
This is why, if any explicitly disabled link is discovered, the
"disable_of_route_checks" flag is turned on.
If all links were explicitly disabled the sound card creation will fail.
Otherwise, if there's at least one link which wasn't explicitly disabled
then the sound card creation will succeed.
Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
---
include/sound/simple_card_utils.h | 3 +-
sound/soc/generic/audio-graph-card2.c | 231 ++++++++++++++++++++++++++
2 files changed, 233 insertions(+), 1 deletion(-)
diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h
index 69a9c9c4d0e9..3fde0314dbb2 100644
--- a/include/sound/simple_card_utils.h
+++ b/include/sound/simple_card_utils.h
@@ -132,9 +132,10 @@ struct simple_util_priv {
#define SNDRV_MAX_LINKS 512
struct link_info {
- int link; /* number of link */
+ int link; /* number of available links */
int cpu; /* turn for CPU / Codec */
struct prop_nums num[SNDRV_MAX_LINKS];
+ bool disabled_link; /* true if there's at least one explicitly disabled link */
};
int simple_util_parse_daifmt(struct device *dev,
diff --git a/sound/soc/generic/audio-graph-card2.c b/sound/soc/generic/audio-graph-card2.c
index 5dcc78c551a2..92774361a688 100644
--- a/sound/soc/generic/audio-graph-card2.c
+++ b/sound/soc/generic/audio-graph-card2.c
@@ -1269,6 +1269,226 @@ static int graph_count(struct simple_util_priv *priv,
return graph_ret(priv, ret);
}
+static bool single_port_device_is_disabled(struct device_node *port)
+{
+ struct device_node *port_device __free(device_node) = NULL;
+ struct device_node *ports __free(device_node) = port_to_ports(port);
+
+ if (!ports)
+ port_device = of_get_parent(port);
+ else
+ port_device = of_get_parent(ports);
+
+ return !of_device_is_available(port_device);
+}
+
+static bool multi_nm_port_device_is_disabled(struct device_node *port)
+{
+ struct device_node *ep, *prev = NULL;
+ struct device_node *remote_ep __free(device_node) = NULL;
+ struct device_node *remote_port __free(device_node) = NULL;
+ struct device_node *remote_device __free(device_node) = NULL;
+
+ while (1) {
+ ep = of_graph_get_next_port_endpoint(port, prev);
+ if (!ep)
+ break;
+
+ /* first endpoint is special because it points to the remote device */
+ if (!prev) {
+ remote_device = of_graph_get_remote_port(ep);
+
+ if (single_port_device_is_disabled(remote_device))
+ return true;
+
+ prev = ep;
+
+ continue;
+ }
+
+ /* first get the remote port associated with the current endpoint */
+ remote_port = of_graph_get_remote_port(ep);
+ if (!remote_port)
+ break;
+
+ /* ... then get the first endpoint in remote port */
+ remote_ep = of_graph_get_next_port_endpoint(remote_port, NULL);
+ if (!remote_ep)
+ break;
+
+ /* ... and finally get the remote device node */
+ remote_device = of_graph_get_remote_port(remote_ep);
+ if (!remote_device)
+ break;
+
+ if (single_port_device_is_disabled(remote_device))
+ return true;
+
+ prev = ep;
+ }
+
+ return false;
+}
+
+static int graph_get_port_endpoint_count(struct device_node *port)
+{
+ int num = 0;
+
+ for_each_of_graph_port_endpoint(port, it)
+ num++;
+
+ return num;
+}
+
+static bool multi_port_device_is_disabled(struct device_node *lnk)
+{
+ int i, ep_count;
+ struct device_node *port __free(device_node) = NULL;
+ struct device_node *port_ep __free(device_node) = NULL;
+ struct device_node *remote_port __free(device_node) = NULL;
+ struct device_node *ports __free(device_node) = port_to_ports(lnk);
+
+ if (!ports)
+ return false;
+
+ for (i = 0;; i++) {
+ port = of_graph_get_port_by_id(ports, i + 1);
+ if (!port)
+ break;
+
+ /* N CPUs to M CODECs will have the endpoint count > 1 */
+ ep_count = graph_get_port_endpoint_count(port);
+ if (!ep_count)
+ break;
+
+ if (ep_count > 1) {
+ if (multi_nm_port_device_is_disabled(port))
+ return true;
+
+ continue;
+ }
+
+ port_ep = of_graph_get_next_port_endpoint(port, NULL);
+ if (!port_ep)
+ break;
+
+ remote_port = of_graph_get_remote_port(port_ep);
+ if (!remote_port)
+ break;
+
+ /*
+ * if one port device is disabled then the whole link will
+ * be disabled, thus we can stop at the first disabled device.
+ */
+ if (single_port_device_is_disabled(remote_port))
+ return true;
+ }
+
+ return false;
+}
+
+static bool normal_port_device_is_disabled(struct device_node *port)
+{
+ if (graph_lnk_is_multi(port))
+ return multi_port_device_is_disabled(port);
+ else
+ return single_port_device_is_disabled(port);
+}
+
+static bool _dpcm_c2c_link_is_disabled(struct snd_soc_card *card,
+ struct device_node *lnk)
+{
+ struct device_node *ep __free(device_node) = NULL;
+ struct device_node *remote_port __free(device_node) = NULL;
+
+ ep = of_graph_get_next_port_endpoint(lnk, NULL);
+ if (!ep) {
+ dev_err(card->dev, "port has no endpoint\n");
+ return false;
+ }
+
+ remote_port = of_graph_get_remote_port(ep);
+ if (!remote_port) {
+ dev_err(card->dev, "failed to fetch remote port\n");
+ return false;
+ }
+
+ if (__graph_get_type(remote_port) == GRAPH_MULTI)
+ return multi_port_device_is_disabled(remote_port);
+ else
+ return single_port_device_is_disabled(remote_port);
+}
+
+static bool c2c_link_is_disabled(struct snd_soc_card *card,
+ struct device_node *lnk)
+{
+ struct device_node *ports __free(device_node) = NULL;
+
+ ports = port_to_ports(lnk);
+
+ if (!ports) {
+ dev_err(card->dev, "C2C port should be child of 'ports'\n");
+ return false;
+ }
+
+ for_each_of_graph_port(ports, it) {
+ if (_dpcm_c2c_link_is_disabled(card, it))
+ return true;
+ };
+
+ return false;
+}
+
+static bool normal_link_is_disabled(struct snd_soc_card *card,
+ struct device_node *lnk)
+{
+ struct device_node *cpu_port;
+ struct device_node *cpu_ep __free(device_node) = NULL;
+ struct device_node *codec_port __free(device_node) = NULL;
+
+ cpu_port = lnk;
+
+ cpu_ep = of_graph_get_next_port_endpoint(cpu_port, NULL);
+ if (!cpu_ep) {
+ dev_err(card->dev, "CPU port has no endpoint\n");
+ return false;
+ }
+
+ codec_port = of_graph_get_remote_port(cpu_ep);
+ if (!codec_port) {
+ dev_err(card->dev, "unable to find remote codec port\n");
+ return false;
+ }
+
+ return normal_port_device_is_disabled(codec_port) ||
+ normal_port_device_is_disabled(cpu_port);
+}
+
+static bool graph_link_is_disabled(struct simple_util_priv *priv,
+ enum graph_type gtype,
+ struct device_node *lnk,
+ struct link_info *li)
+{
+ bool link_disabled = false;
+ struct snd_soc_card *card = simple_priv_to_card(priv);
+
+ switch (gtype) {
+ case GRAPH_NORMAL:
+ link_disabled = normal_link_is_disabled(card, lnk);
+ break;
+ case GRAPH_DPCM:
+ link_disabled = _dpcm_c2c_link_is_disabled(card, lnk);
+ break;
+ case GRAPH_C2C:
+ link_disabled = c2c_link_is_disabled(card, lnk);
+ break;
+ default:
+ break;
+ }
+
+ return link_disabled;
+}
+
static int graph_for_each_link(struct simple_util_priv *priv,
struct graph2_custom_hooks *hooks,
struct link_info *li,
@@ -1291,6 +1511,12 @@ static int graph_for_each_link(struct simple_util_priv *priv,
gtype = graph_get_type(priv, lnk);
+ if (graph_link_is_disabled(priv, gtype, lnk, li)) {
+ if (!li->disabled_link)
+ li->disabled_link = true;
+ continue;
+ }
+
ret = func(priv, hooks, gtype, lnk, li);
if (ret < 0)
break;
@@ -1325,6 +1551,11 @@ int audio_graph2_parse_of(struct simple_util_priv *priv, struct device *dev,
if (ret < 0)
goto err;
+ if (li->disabled_link) {
+ dev_info(dev, "detected disabled link(s) - route creation may fail\n");
+ card->disable_of_route_checks = 1;
+ }
+
ret = simple_util_init_priv(priv, li);
if (ret < 0)
goto err;
--
2.34.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH RFC 3/3] ASoC: generic: add more sample DTSIs for audio-graph-card2
2025-05-15 15:31 [PATCH RFC 0/3] ASoC: audio-graph-card2: support explicitly disabled links Laurentiu Mihalcea
2025-05-15 15:31 ` [PATCH RFC 1/3] ASoC: re-introduce disable_route_checks flag for OF routes Laurentiu Mihalcea
2025-05-15 15:31 ` [PATCH RFC 2/3] ASoC: audio-graph-card2: support explicitly disabled links Laurentiu Mihalcea
@ 2025-05-15 15:31 ` Laurentiu Mihalcea
2025-05-16 1:59 ` Kuninori Morimoto
2 siblings, 1 reply; 14+ messages in thread
From: Laurentiu Mihalcea @ 2025-05-15 15:31 UTC (permalink / raw)
To: Mark Brown, Kuninori Morimoto, Jaroslav Kysela, Takashi Iwai,
Liam Girdwood
Cc: linux-kernel, linux-sound
From: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
Add some more audio-graph-card2 sample DTSIs meant to aid in testing
the driver's capability to parse explicitly disabled links. To conclude
that the feature works correctly, all audio-graph-card2 samples need to
work as expected. This includes the custom ones:
1) audio-graph-card2-custom-sample1.dtsi
2) audio-graph-card2-custom-sample2.dtsi
Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
---
.../generic/audio-graph-card2-sample1.dtsi | 278 ++++++
.../generic/audio-graph-card2-sample2.dtsi | 878 ++++++++++++++++++
.../generic/audio-graph-card2-sample3.dtsi | 486 ++++++++++
3 files changed, 1642 insertions(+)
create mode 100644 sound/soc/generic/audio-graph-card2-sample1.dtsi
create mode 100644 sound/soc/generic/audio-graph-card2-sample2.dtsi
create mode 100644 sound/soc/generic/audio-graph-card2-sample3.dtsi
diff --git a/sound/soc/generic/audio-graph-card2-sample1.dtsi b/sound/soc/generic/audio-graph-card2-sample1.dtsi
new file mode 100644
index 000000000000..ce0098a160a6
--- /dev/null
+++ b/sound/soc/generic/audio-graph-card2-sample1.dtsi
@@ -0,0 +1,278 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2025 NXP
+ *
+ * audio-graph-card2 simple link test scenarios
+ *
+ * IMPORTANT:
+ *
+ * 1) DO NOT use this alongside the other test scenarios as the
+ * node names are not unique across test DTSIs.
+ */
+
+/ {
+ /*
+ * Testcase 00
+ *
+ * DESCRIPTION: test simple CPU-CODEC with no routing specified. Each
+ * endpoint device has only one available port.
+ *
+ * TOPOLOGY:
+ *
+ * CPU0 <---@----> CODEC0
+ * CPU1 <---@----> CODEC1
+ * CPU2 <---@----> CODEC2
+ *
+ * CPU0 => ENABLED
+ * CPU1 => DISABLED
+ * CPU2 => ENABLED
+ * CODEC0 => ENABLED
+ * CODEC1 => ENABLED
+ * CODEC2 => DISABLED
+ *
+ * RESULT:
+ * - sound card creation should succeed with 2 explicitly disabled links.
+ */
+ test-case-00 {
+ compatible = "audio-graph-card2";
+ label = "test-case-00";
+ links = <&simple_cpu0_port>,
+ <&simple_cpu1_port>,
+ <&simple_cpu2_port>;
+ };
+
+ test-cpu0 {
+ compatible = "test-cpu";
+
+ simple_cpu0_port: port {
+ biclock-master;
+ frame-master;
+
+ test_cpu_0_ep: endpoint {
+ remote-endpoint = <&test_codec_0_ep>;
+ };
+ };
+ };
+
+ test-cpu1 {
+ compatible = "test-cpu";
+ status = "disabled";
+
+ simple_cpu1_port: port {
+ biclock-master;
+ frame-master;
+
+ test_cpu_1_ep: endpoint {
+ remote-endpoint = <&test_codec_1_ep>;
+ };
+ };
+ };
+
+ test-cpu2 {
+ compatible = "test-cpu";
+
+ simple_cpu2_port: port {
+ bitclock-master;
+ frame-master;
+
+ test_cpu_2_ep: endpoint {
+ remote-endpoint = <&test_codec_2_ep>;
+ };
+ };
+ };
+
+ test-codec0 {
+ compatible = "test-codec";
+
+ port {
+ test_codec_0_ep: endpoint {
+ remote-endpoint = <&test_cpu_0_ep>;
+ };
+ };
+ };
+
+ test-codec1 {
+ compatible = "test-codec";
+
+ port {
+ test_codec_1_ep: endpoint {
+ remote-endpoint = <&test_cpu_1_ep>;
+ };
+ };
+ };
+
+ test-codec2 {
+ compatible = "test-codec";
+ status = "disabled";
+
+ port {
+ test_codec_2_ep: endpoint {
+ remote-endpoint = <&test_cpu_2_ep>;
+ };
+ };
+ };
+
+ /*
+ * Testcase 01
+ *
+ * DESCRIPTION: test simple CPU-CODEC with no routing specified. Each
+ * endpoint device has one or more available ports.
+ *
+ * TOPOLOGY:
+ *
+ * CPU3/P0 <---@----> CODEC3
+ * CPU3/P1 <---@----> CODEC4
+ * CPU4 <---@----> CODEC5/P0
+ * CPU3/P2 <---@----> CODEC5/P1
+ *
+ * CPU3 => ENABLED
+ * CPU4 => DISABLED
+ * CODEC3 => ENABLED
+ * CODEC4 => DISABLED
+ *
+ * RESULT:
+ * - sound card creation should succeed with 2 explicitly disabled links
+ */
+ test-case-01 {
+ compatible = "audio-graph-card2";
+ label = "test-case-01";
+ links = <&test_cpu3_port0>,
+ <&test_cpu3_port1>,
+ <&test_cpu4_port>,
+ <&test_cpu3_port2>;
+ };
+
+ test-cpu3 {
+ compatible = "test-cpu";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ test_cpu3_port0: port@0 {
+ reg = <0>;
+
+ test_cpu3_p0_ep: endpoint {
+ remote-endpoint = <&test_codec3_ep>;
+ };
+ };
+
+ test_cpu3_port1: port@1 {
+ reg = <1>;
+
+ test_cpu3_p1_ep: endpoint {
+ remote-endpoint = <&test_codec4_ep>;
+ };
+ };
+
+ test_cpu3_port2: port@2 {
+ reg = <2>;
+
+ test_cpu3_p2_ep: endpoint {
+ remote-endpoint = <&test_codec5_p1_ep>;
+ };
+ };
+ };
+ };
+
+ test-cpu4 {
+ compatible = "test-cpu";
+ status = "disabled";
+
+ test_cpu4_port: port {
+ test_cpu4_ep: endpoint {
+ remote-endpoint = <&test_codec5_p0_ep>;
+ };
+ };
+ };
+
+ test-codec3 {
+ compatible = "test-codec";
+
+ port {
+ test_codec3_ep: endpoint {
+ remote-endpoint = <&test_cpu3_p0_ep>;
+ };
+ };
+ };
+
+ test-codec4 {
+ compatible = "test-codec";
+ status = "disabled";
+
+ port {
+ test_codec4_ep: endpoint {
+ remote-endpoint = <&test_cpu3_p1_ep>;
+ };
+ };
+ };
+
+ test-codec5 {
+ compatible = "test-codec";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ test_codec5_port0: port@0 {
+ reg = <0>;
+
+ test_codec5_p0_ep: endpoint {
+ remote-endpoint = <&test_cpu4_ep>;
+ };
+ };
+
+ test_codec5_port1: port@1 {
+ reg = <1>;
+
+ test_codec5_p1_ep: endpoint {
+ remote-endpoint = <&test_cpu3_p2_ep>;
+ };
+ };
+ };
+ };
+
+ /*
+ * Testcase 02
+ *
+ * DESCRIPTION: test simple CPU-CODEC with no routing specified. The
+ * CPU-CODEC link is disabled.
+ *
+ * TOPOLOGY:
+ *
+ * CPU5 <---@-----> CODEC6
+ *
+ * CPU5 => DISABLED
+ * CODEC6 => ENABLED
+ *
+ * RESULT:
+ * - sound card creation should fail since all of its links are
+ * explicitly disabled.
+ */
+ test-case-02 {
+ compatible = "audio-graph-card2";
+ label = "test-case-02";
+ links = <&test_cpu5_port>;
+ };
+
+ test-cpu5 {
+ compatible = "test-cpu";
+ status = "disabled";
+
+ test_cpu5_port: port {
+ test_cpu5_port_ep: endpoint {
+ remote-endpoint = <&test_codec6_port_ep>;
+ };
+ };
+ };
+
+ test-codec6 {
+ compatible = "test-codec";
+
+ port {
+ test_codec6_port_ep: endpoint {
+ remote-endpoint = <&test_cpu5_port_ep>;
+ };
+ };
+ };
+};
diff --git a/sound/soc/generic/audio-graph-card2-sample2.dtsi b/sound/soc/generic/audio-graph-card2-sample2.dtsi
new file mode 100644
index 000000000000..0bcbf2a46b79
--- /dev/null
+++ b/sound/soc/generic/audio-graph-card2-sample2.dtsi
@@ -0,0 +1,878 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2025 NXP
+ *
+ * audio-graph-card2 multi link test scenarios
+ *
+ * IMPORTANT:
+ *
+ * 1) DO NOT use this alongside the other test scenarios as the
+ * node names are not unique across test DTSIs.
+ *
+ * 2) The test topologies used here are adapted from
+ * "audio-graph-card2-custom-sample1.dtsi".
+ */
+
+/ {
+ /*
+ * Testcase 00
+ *
+ * DESCRIPTION: test disabled semi-multi link
+ *
+ * TOPOLOGY:
+ *
+ * +-+
+ * TEST_CPU0/P0 <-@--------> | |-> TEST_CODEC0/P0
+ * | |-> TEST_CODEC0/P1
+ * +-+
+ *
+ * TEST_CODEC0 => DISABLED
+ * TEST_CPU0 => ENABLED
+ *
+ *
+ * RESULT:
+ * - sound card creation should fail as all of its links are
+ * explicitly disabled.
+ */
+ test-case-00 {
+ compatible = "audio-graph-card2";
+ label = "test-case-00";
+ links = <&cpu0_port0>;
+
+ multi {
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ /* SM link port */
+ port@0 {
+ reg = <0>;
+
+ smcodec0_port0_ep: endpoint {
+ remote-endpoint = <&cpu0_port0_ep>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ smcodec0_port1_ep: endpoint {
+ remote-endpoint = <&codec0_port0_ep>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+
+ smcodec0_port2_ep: endpoint {
+ remote-endpoint = <&codec0_port1_ep>;
+ };
+ };
+ };
+ };
+ };
+
+ test-cpu0 {
+ compatible = "test-cpu";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu0_port0: port@0 {
+ reg = <0>;
+
+ cpu0_port0_ep: endpoint {
+ remote-endpoint = <&smcodec0_port0_ep>;
+ };
+ };
+ };
+ };
+
+ test-codec0 {
+ compatible = "test-codec";
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ codec0_port0_ep: endpoint {
+ remote-endpoint = <&smcodec0_port1_ep>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ codec0_port1_ep: endpoint {
+ remote-endpoint = <&smcodec0_port2_ep>;
+ };
+ };
+ };
+ };
+
+ /*
+ * Testcase 01
+ *
+ * DESCRIPTION: test semi-multi link with explicitly disabled CPU.
+ *
+ * TOPOLOGY:
+ *
+ * +-+
+ * TEST_CPU1 <-@--------> | |-> TEST_CODEC1/P0
+ * | |-> TEST_CODEC1/P1
+ * +-+
+ *
+ * TEST_CPU2 <---@----> TEST_CODEC2 (ACTIVE)
+ *
+ *
+ * TEST_CPU1 => DISABLED
+ * TEST_CPU2 => ENABLED
+ * TEST_CODEC1 => ENABLED
+ * TEST_CODEC2 => ENABLED
+ *
+ * RESULT:
+ * - sound card creation should succeed with 1 explicitly disabled link.
+ */
+ test-case-01 {
+ compatible = "audio-graph-card2";
+ label = "test-case-01";
+ links = <&cpu1_port>, <&cpu2_port>;
+
+ multi {
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ /* SM link port */
+ port@0 {
+ reg = <0>;
+
+ smcodec1_port0_ep: endpoint {
+ remote-endpoint = <&cpu1_port_ep>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ smcodec1_port1_ep: endpoint {
+ remote-endpoint = <&codec1_port0_ep>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+
+ smcodec1_port2_ep: endpoint {
+ remote-endpoint = <&codec1_port1_ep>;
+ };
+ };
+ };
+ };
+ };
+
+ test-cpu1 {
+ compatible = "test-cpu";
+ status = "disabled";
+
+ cpu1_port: port {
+ cpu1_port_ep: endpoint {
+ remote-endpoint = <&smcodec1_port0_ep>;
+ };
+ };
+ };
+
+ test-cpu2 {
+ compatible = "test-cpu";
+
+ cpu2_port: port {
+ cpu2_port_ep: endpoint {
+ remote-endpoint = <&codec2_port_ep>;
+ };
+ };
+ };
+
+ test-codec1 {
+ compatible = "test-codec";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ codec1_port0_ep: endpoint {
+ remote-endpoint = <&smcodec1_port1_ep>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ codec1_port1_ep: endpoint {
+ remote-endpoint = <&smcodec1_port2_ep>;
+ };
+ };
+ };
+ };
+
+ test-codec2 {
+ compatible = "test-codec";
+
+ port {
+ codec2_port_ep: endpoint {
+ remote-endpoint = <&cpu2_port_ep>;
+ };
+ };
+ };
+
+ /*
+ * Testcase 02
+ *
+ * DESCRIPTION: test semi-multi link with one explicitly disabled codec.
+ *
+ * TOPOLOGY:
+ *
+ * +-+
+ * TEST_CPU3 <-@--------> | |-> TEST_CODEC3 (ACTIVE)
+ * (ACTIVE) | |-> TEST_CODEC4 (DISABLED)
+ * +-+
+ *
+ * TEST_CPU4 <---@----> TEST_CODEC5 (ACTIVE)
+ * (ACTIVE)
+ *
+ *
+ * TEST_CPU3 => ENABLED
+ * TEST_CPU4 => ENABLED
+ * TEST_CODEC3 => ENABLED
+ * TEST_CODEC4 => DISABLED
+ * TEST_CODEC5 => ENABLED
+ *
+ * RESULT:
+ * - sound card creation should succeed with 1 explicitly disabled link.
+ */
+ test-case-02 {
+ compatible = "audio-graph-card2";
+ label = "test-case-02";
+ links = <&cpu3_port>, <&cpu4_port>;
+
+ multi {
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ /* SM link port */
+ port@0 {
+ reg = <0>;
+
+ smcodec2_port0_ep: endpoint {
+ remote-endpoint = <&cpu3_port_ep>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ smcodec2_port1_ep: endpoint {
+ remote-endpoint = <&codec3_port_ep>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+
+ smcodec2_port2_ep: endpoint {
+ remote-endpoint = <&codec4_port_ep>;
+ };
+ };
+ };
+ };
+ };
+
+ test-cpu3 {
+ compatible = "test-cpu";
+
+ cpu3_port: port {
+ cpu3_port_ep: endpoint {
+ remote-endpoint = <&smcodec2_port0_ep>;
+ };
+ };
+ };
+
+ test-cpu4 {
+ compatible = "test-cpu";
+
+ cpu4_port: port {
+ cpu4_port_ep: endpoint {
+ remote-endpoint = <&codec5_port_ep>;
+ };
+ };
+ };
+
+ test-codec3 {
+ compatible = "test-codec";
+
+ port {
+ codec3_port_ep: endpoint {
+ remote-endpoint = <&smcodec2_port1_ep>;
+ };
+ };
+ };
+
+ test-codec4 {
+ compatible = "test-codec";
+ status = "disabled";
+
+ port {
+ codec4_port_ep: endpoint {
+ remote-endpoint = <&smcodec2_port2_ep>;
+ };
+ };
+ };
+
+ test-codec5 {
+ compatible = "test-codec";
+
+ port {
+ codec5_port_ep: endpoint {
+ remote-endpoint = <&cpu4_port_ep>;
+ };
+ };
+ };
+
+ /*
+ * Testcase 03
+ *
+ * DESCRIPTION: test disabled multi link.
+ *
+ * TOPOLOGY:
+ * +---+ +---+
+ * TEST_CPU5/P0 <- | | <---@----> | | -> TEST_CODEC6/P0
+ * TEST_CPU5/P1 <- | | | | -> TEST_CODEC6/P1
+ * +---+ +---+
+ *
+ *
+ * TEST_CPU5 => DISABLED
+ * TEST_CODEC6 => ENABLED
+ *
+ * RESULT:
+ * - sound card creation should fail since all of its links are
+ * explicitly disabled.
+ */
+ test-case-03 {
+ compatible = "audio-graph-card2";
+ label = "test-case-03";
+ links = <&multi0_cpu_port0>;
+
+ multi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ports@0 {
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ multi0_cpu_port0: port@0 {
+ reg = <0>;
+
+ multi0_cpu_port0_ep: endpoint {
+ remote-endpoint = <&multi0_codec_port0_ep>;
+ };
+ };
+
+ multi0_cpu_port1: port@1 {
+ reg = <1>;
+
+ multi0_cpu_port1_ep: endpoint {
+ remote-endpoint = <&cpu6_port0_ep>;
+ };
+ };
+
+ multi0_cpu_port2: port@2 {
+ reg = <2>;
+
+ multi0_cpu_port2_ep: endpoint {
+ remote-endpoint = <&cpu6_port1_ep>;
+ };
+ };
+ };
+
+ ports@1 {
+ reg = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ multi0_codec_port0: port@0 {
+ reg = <0>;
+
+ multi0_codec_port0_ep: endpoint {
+ remote-endpoint = <&multi0_cpu_port0_ep>;
+ };
+ };
+
+ multi0_codec_port1: port@1 {
+ reg = <1>;
+
+ multi0_codec_port1_ep: endpoint {
+ remote-endpoint = <&codec6_port0_ep>;
+ };
+ };
+
+ multi0_codec_port2: port@2 {
+ reg = <2>;
+
+ multi0_codec_port2_ep: endpoint {
+ remote-endpoint = <&codec6_port1_ep>;
+ };
+ };
+ };
+ };
+ };
+
+ test-cpu5 {
+ compatible = "test-cpu";
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu6_port0: port@0 {
+ reg = <0>;
+
+ cpu6_port0_ep: endpoint {
+ remote-endpoint = <&multi0_cpu_port1_ep>;
+ };
+ };
+
+ cpu6_port1: port@1 {
+ reg = <1>;
+
+ cpu6_port1_ep: endpoint {
+ remote-endpoint = <&multi0_cpu_port2_ep>;
+ };
+ };
+ };
+ };
+
+ test-codec6 {
+ compatible = "test-codec";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ codec6_port0: port@0 {
+ reg = <0>;
+
+ codec6_port0_ep: endpoint {
+ remote-endpoint = <&multi0_codec_port1_ep>;
+ };
+ };
+
+ codec6_port1: port@1 {
+ reg = <1>;
+
+ codec6_port1_ep: endpoint {
+ remote-endpoint = <&multi0_codec_port2_ep>;
+ };
+ };
+ };
+ };
+
+ /*
+ * Testcase 04
+ *
+ * DESCRIPTION: test multi link with disabled CPU.
+ *
+ * TOPOLOGY:
+ * +---+ +---+
+ * TEST_CPU7/P0 <- | | <---@----> | | -> TEST_CODEC8/P0
+ * TEST_CPU7/P1 <- | | | | -> TEST_CODEC8/P1
+ * +---+ +---+
+ *
+ * TEST_CPU6 <---@-----> TEST_CODEC7
+ *
+ *
+ * TEST_CPU6 => ENABLED
+ * TEST_CPU7 => DISABLED
+ * TEST_CODEC7 => ENABLED
+ * TEST_CODEC8 => ENABLED
+ *
+ * RESULT:
+ * - sound card creation should succeed with 1 explicitly disabled link.
+ */
+ test-case-04 {
+ compatible = "audio-graph-card2";
+ label = "test-case-04";
+ links = <&cpu6_port>, <&multi1_cpu_port0>;
+
+ multi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ports@0 {
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ multi1_cpu_port0: port@0 {
+ reg = <0>;
+
+ multi1_cpu_port0_ep: endpoint {
+ remote-endpoint = <&multi1_codec_port0_ep>;
+ };
+ };
+
+ multi1_cpu_port1: port@1 {
+ reg = <1>;
+
+ multi1_cpu_port1_ep: endpoint {
+ remote-endpoint = <&cpu7_port0_ep>;
+ };
+ };
+
+ multi1_cpu_port2: port@2 {
+ reg = <2>;
+
+ multi1_cpu_port2_ep: endpoint {
+ remote-endpoint = <&cpu7_port1_ep>;
+ };
+ };
+ };
+
+ ports@1 {
+ reg = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ multi1_codec_port0: port@0 {
+ reg = <0>;
+
+ multi1_codec_port0_ep: endpoint {
+ remote-endpoint = <&multi1_cpu_port0_ep>;
+ };
+ };
+
+ multi1_codec_port1: port@1 {
+ reg = <1>;
+
+ multi1_codec_port1_ep: endpoint {
+ remote-endpoint = <&codec8_port0_ep>;
+ };
+ };
+
+ multi1_codec_port2: port@2 {
+ reg = <2>;
+
+ multi1_codec_port2_ep: endpoint {
+ remote-endpoint = <&codec8_port1_ep>;
+ };
+ };
+ };
+ };
+ };
+
+ test-cpu6 {
+ compatible = "test-cpu";
+
+ cpu6_port: port {
+ cpu6_port_ep: endpoint {
+ remote-endpoint = <&codec7_port_ep>;
+ };
+ };
+ };
+
+ test-cpu7 {
+ compatible = "test-cpu";
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu7_port0: port@0 {
+ reg = <0>;
+
+ cpu7_port0_ep: endpoint {
+ remote-endpoint = <&multi1_cpu_port1_ep>;
+ };
+ };
+
+ cpu7_port1: port@1 {
+ reg = <1>;
+
+ cpu7_port1_ep: endpoint {
+ remote-endpoint = <&multi1_cpu_port2_ep>;
+ };
+ };
+ };
+ };
+
+ test-codec7 {
+ compatible = "test-codec";
+
+ port {
+ codec7_port_ep: endpoint {
+ remote-endpoint = <&cpu6_port_ep>;
+ };
+ };
+ };
+
+ test-codec8 {
+ compatible = "test-codec";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ codec8_port0: port@0 {
+ reg = <0>;
+
+ codec8_port0_ep: endpoint {
+ remote-endpoint = <&multi1_codec_port1_ep>;
+ };
+ };
+
+ codec8_port1: port@1 {
+ reg = <1>;
+
+ codec8_port1_ep: endpoint {
+ remote-endpoint = <&multi1_codec_port2_ep>;
+ };
+ };
+ };
+ };
+
+ /*
+ * Testcase 05
+ *
+ * DESCRIPTION: test N:M (CPUS:CODECS), N < M multi link with disabled codec.
+ *
+ * TOPOLOGY:
+ *
+ * +---+ +---+
+ * | | <---@----> | |
+ * | | | |
+ * TEST_CPU8/P0 <- | | <--------> | | -> TEST_CODEC9/P0
+ * TEST_CPU8/P1 <- | | <---+----> | | -> TEST_CODEC9/P1
+ * | | \----> | | -> TEST_CODEC9/P2
+ * +---+ +---+
+ *
+ *
+ * TEST_CPU9 <---@----> TEST_CODEC10
+ *
+ * TEST_CPU8 => ENABLED
+ * TEST_CODEC9 => DISABLED
+ * TEST_CPU9 => ENABLED
+ * TEST_CODEC10 => ENABLED
+ *
+ * RESULT:
+ * - sound card creation should succeed with 1 disabled link.
+ */
+ test-case-05 {
+ compatible = "audio-graph-card2";
+ label = "test-case-05";
+ links = <&multi2_cpu_port0>, <&cpu9_port>;
+
+ multi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ports@0 {
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ multi2_cpu_port0: port@0 {
+ reg = <0>;
+
+ multi2_cpu_port0_ep: endpoint {
+ remote-endpoint = <&multi2_codec_port0_ep>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ multi2_cpu_port1_ep0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&cpu8_port0_ep>;
+ };
+
+ multi2_cpu_port1_ep1: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&multi2_codec_port1_ep1>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ multi2_cpu_port2_ep0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&cpu8_port1_ep>;
+ };
+
+ multi2_cpu_port2_ep1: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&multi2_codec_port2_ep1>;
+ };
+
+ multi2_cpu_port2_ep2: endpoint@2 {
+ reg = <2>;
+ remote-endpoint = <&multi2_codec_port3_ep1>;
+ };
+ };
+ };
+
+ ports@1 {
+ reg = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ multi2_codec_port0_ep: endpoint {
+ remote-endpoint = <&multi2_cpu_port0_ep>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ multi2_codec_port1_ep0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&codec9_port0_ep>;
+ };
+
+ multi2_codec_port1_ep1: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&multi2_cpu_port1_ep1>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ multi2_codec_port2_ep0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&codec9_port1_ep>;
+ };
+
+ multi2_codec_port2_ep1: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&multi2_cpu_port2_ep1>;
+ };
+ };
+
+ port@3 {
+ reg = <3>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ multi2_codec_port3_ep0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&codec9_port2_ep>;
+ };
+
+ multi2_codec_port3_ep1: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&multi2_cpu_port2_ep2>;
+ };
+ };
+ };
+ };
+ };
+
+ test-cpu8 {
+ compatible = "test-cpu";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ cpu8_port0_ep: endpoint {
+ remote-endpoint = <&multi2_cpu_port1_ep0>;
+ };
+ };
+
+ port@1 {
+ cpu8_port1_ep: endpoint {
+ remote-endpoint = <&multi2_cpu_port2_ep0>;
+ };
+ };
+ };
+ };
+
+ test-cpu9 {
+ compatible = "test-cpu";
+
+ cpu9_port: port {
+ cpu9_port_ep: endpoint {
+ remote-endpoint = <&codec10_port_ep>;
+ };
+ };
+ };
+
+ test-codec9 {
+ compatible = "test-codec";
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ codec9_port0_ep: endpoint {
+ remote-endpoint = <&multi2_codec_port1_ep0>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ codec9_port1_ep: endpoint {
+ remote-endpoint = <&multi2_codec_port2_ep0>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+
+ codec9_port2_ep: endpoint {
+ remote-endpoint = <&multi2_codec_port3_ep0>;
+ };
+ };
+ };
+ };
+
+ test-codec10 {
+ compatible = "test-codec";
+
+ port {
+ codec10_port_ep: endpoint {
+ remote-endpoint = <&cpu9_port_ep>;
+ };
+ };
+ };
+};
diff --git a/sound/soc/generic/audio-graph-card2-sample3.dtsi b/sound/soc/generic/audio-graph-card2-sample3.dtsi
new file mode 100644
index 000000000000..b96da5b5d6d3
--- /dev/null
+++ b/sound/soc/generic/audio-graph-card2-sample3.dtsi
@@ -0,0 +1,486 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2025 NXP
+ *
+ * audio-graph-card2 DPCM/C2C link test scenarios
+ *
+ * IMPORTANT:
+ *
+ * 1) DO NOT use this alongside the other test scenarios as the
+ * node names are not unique across test DTSIs.
+ *
+ * 2) The test topologies used here are adapted from
+ * "audio-graph-card2-custom-sample2.dtsi"
+ */
+
+/ {
+ /*
+ * Testcase 00:
+ *
+ * DESCRIPTION: test DPCM links with CODEC disabled.
+ *
+ * TOPOLOGY:
+ *
+ * ****
+ * TEST_CPU0/P0 <---@----* * ----@---> TEST_CODEC0
+ * TEST_CPU0/P1 <---@----* *
+ * ****
+ *
+ * TEST_CPU0 => ENABLED
+ * TEST_CODEC0 => DISABLED
+ *
+ * RESULT:
+ * - sound card creation should succeed with only the FEs being
+ * created. Attempting to play a song on any of the FEs should
+ * result in an error since there's no BE attached.
+ */
+ test-case-00 {
+ compatible = "audio-graph-card2";
+ label = "test-case-00";
+ links = <&fe0_port0>, <&fe0_port1>, <&be0_port0>;
+ routing = "TC DAI0 Playback", "DAI0 Playback",
+ "TC DAI0 Playback", "DAI1 Playback",
+ "DAI0 Capture", "TC DAI0 Capture",
+ "DAI1 Capture", "TC DAI0 Capture";
+
+ dpcm {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ /* FEs */
+ ports@0 {
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ fe0_port0: port@0 {
+ reg = <0>;
+
+ fe0_port0_ep: endpoint {
+ remote-endpoint = <&cpu0_port0_ep>;
+ };
+ };
+
+ fe0_port1: port@1 {
+ reg = <1>;
+
+ fe0_port1_ep: endpoint {
+ remote-endpoint = <&cpu0_port1_ep>;
+ };
+ };
+ };
+
+ /* BEs */
+ ports@1 {
+ reg = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ be0_port0: port@0 {
+ reg = <0>;
+
+ be0_port0_ep: endpoint {
+ remote-endpoint = <&codec0_port_ep>;
+ };
+ };
+ };
+ };
+ };
+
+ test-cpu0 {
+ compatible = "test-cpu";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ cpu0_port0_ep: endpoint {
+ remote-endpoint = <&fe0_port0_ep>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ cpu0_port1_ep: endpoint {
+ remote-endpoint = <&fe0_port1_ep>;
+ };
+ };
+ };
+ };
+
+ test-codec0 {
+ compatible = "test-codec";
+ status = "disabled";
+
+ port {
+ prefix = "TC";
+
+ codec0_port_ep: endpoint {
+ remote-endpoint = <&be0_port0_ep>;
+ };
+ };
+ };
+
+ /*
+ * Testcase 01:
+ *
+ * DESCRIPTION: test DPCM links with CPU disabled.
+ *
+ * TOPOLOGY:
+ *
+ * ****
+ * TEST_CPU1/P0 <---@----* * ----@---> TEST_CODEC1
+ * TEST_CPU1/P1 <---@----* *
+ * ****
+ *
+ * TEST_CPU0 => DISABLED
+ * TEST_CODEC0 => ENABLED
+ *
+ * RESULT:
+ * - sound card creation should succeed with only the BE
+ * being created.
+ */
+ test-case-01 {
+ compatible = "audio-graph-card2";
+ label = "test-case-01";
+ links = <&fe1_port0>, <&fe1_port1>, <&be1_port0>;
+ routing = "TC DAI0 Playback", "DAI0 Playback",
+ "TC DAI0 Playback", "DAI1 Playback",
+ "DAI0 Capture", "TC DAI0 Capture",
+ "DAI1 Capture", "TC DAI0 Capture";
+
+ dpcm {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ /* FEs */
+ ports@0 {
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ fe1_port0: port@0 {
+ reg = <0>;
+
+ fe1_port0_ep: endpoint {
+ remote-endpoint = <&cpu1_port0_ep>;
+ };
+ };
+
+ fe1_port1: port@1 {
+ reg = <1>;
+
+ fe1_port1_ep: endpoint {
+ remote-endpoint = <&cpu1_port1_ep>;
+ };
+ };
+ };
+
+ /* BEs */
+ ports@1 {
+ reg = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ be1_port0: port@0 {
+ reg = <0>;
+
+ be1_port0_ep: endpoint {
+ remote-endpoint = <&codec1_port_ep>;
+ };
+ };
+ };
+ };
+ };
+
+ test-cpu1 {
+ compatible = "test-cpu";
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ cpu1_port0_ep: endpoint {
+ remote-endpoint = <&fe1_port0_ep>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ cpu1_port1_ep: endpoint {
+ remote-endpoint = <&fe1_port1_ep>;
+ };
+ };
+ };
+ };
+
+ test-codec1 {
+ compatible = "test-codec";
+
+ port {
+ prefix = "TC";
+
+ codec1_port_ep: endpoint {
+ remote-endpoint = <&be1_port0_ep>;
+ };
+ };
+ };
+
+ /*
+ * Testcase 02
+ *
+ * DESCRIPTION: test DPCM links with multi BE with CODEC disabled.
+ *
+ * TOPOLOGY:
+ *
+ * **** +---+
+ * TEST_CPU2/P0 <---@----* * ----@---> | | -> TEST_CODEC2/P0
+ * TEST_CPU2/P1 <---@----* * | | -> TEST_CODEC2/P1
+ * **** +---+
+ *
+ * TEST_CPU2 => ENABLED
+ * TEST_CODEC2 => DISABLED
+ *
+ * RESULT:
+ * - sound card creation should succeed with only the FEs being
+ * created.
+ */
+ test-case-02 {
+ compatible = "audio-graph-card2";
+ label = "test-case-02";
+ links = <&fe2_port0>, <&fe2_port1>, <&multi0_be_port0>;
+
+ dpcm {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ /* FEs */
+ ports@0 {
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ fe2_port0: port@0 {
+ reg = <0>;
+
+ fe2_port0_ep: endpoint {
+ remote-endpoint = <&cpu2_port0_ep>;
+ };
+ };
+
+ fe2_port1: port@1 {
+ reg = <1>;
+
+ fe2_port1_ep: endpoint {
+ remote-endpoint = <&cpu2_port1_ep>;
+ };
+ };
+ };
+
+ /* BEs */
+ ports@1 {
+ reg = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ multi0_be_port0: port@0 {
+ reg = <0>;
+
+ multi0_be_port0_ep: endpoint {
+ remote-endpoint = <&multi0_codec_port0_ep>;
+ };
+ };
+ };
+ };
+
+ multi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ports@0 {
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ multi0_codec_port0_ep: endpoint {
+ remote-endpoint = <&multi0_be_port0_ep>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ multi0_codec_port1_ep: endpoint {
+ remote-endpoint = <&codec2_port0_ep>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+
+ multi0_codec_port2_ep: endpoint {
+ remote-endpoint = <&codec2_port1_ep>;
+ };
+ };
+ };
+ };
+ };
+
+ test-cpu2 {
+ compatible = "test-cpu";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ cpu2_port0_ep: endpoint {
+ remote-endpoint = <&fe2_port0_ep>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ cpu2_port1_ep: endpoint {
+ remote-endpoint = <&fe2_port1_ep>;
+ };
+ };
+ };
+ };
+
+ test-codec2 {
+ compatible = "test-codec";
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ codec2_port0_ep: endpoint {
+ remote-endpoint = <&multi0_codec_port1_ep>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ codec2_port1_ep: endpoint {
+ remote-endpoint = <&multi0_codec_port2_ep>;
+ };
+ };
+ };
+ };
+
+ /*
+ * Testcase 03
+ *
+ * DESCRIPTION: test C2C links with codec disabled
+ *
+ * TOPOLOGY:
+ *
+ * +---@----> TEST_CODEC3/P0
+ * |
+ * +--------> TEST_CODEC3/P1
+ *
+ * TEST_CPU3 <---@----> TEST_CODEC4
+ *
+ * TEST_CPU3 => ENABLED
+ * TEST_CODEC3 => DISABLED
+ * TEST_CODEC4 => ENABLED
+ *
+ * RESULT:
+ * - sound card creation should succeed with 1 disabled link.
+ */
+ test-case-03 {
+ compatible = "audio-graph-card2";
+ label = "test-case-03";
+ links = <&c2c0_port0>, <&cpu3_port>;
+
+ codec2codec {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ports@0 {
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ c2c0_port0: port@0 {
+ reg = <0>;
+
+ c2c0_port0_ep: endpoint {
+ remote-endpoint = <&codec3_port0_ep>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ c2c0_port1_ep: endpoint {
+ remote-endpoint = <&codec3_port1_ep>;
+ };
+ };
+ };
+ };
+ };
+
+ test-cpu3 {
+ compatible = "test-cpu";
+
+ cpu3_port: port {
+ cpu3_port_ep: endpoint {
+ remote-endpoint = <&codec4_port_ep>;
+ };
+ };
+ };
+
+ test-codec3 {
+ compatible = "test-codec";
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ codec3_port0_ep: endpoint {
+ remote-endpoint = <&c2c0_port0_ep>;
+ };
+ };
+
+ port@1 {
+ codec3_port1_ep: endpoint {
+ remote-endpoint = <&c2c0_port1_ep>;
+ };
+ };
+ };
+ };
+
+ test-codec4 {
+ compatible = "test-codec";
+
+ port {
+ codec4_port_ep: endpoint {
+ remote-endpoint = <&cpu3_port_ep>;
+ };
+ };
+ };
+};
--
2.34.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH RFC 1/3] ASoC: re-introduce disable_route_checks flag for OF routes
2025-05-15 15:31 ` [PATCH RFC 1/3] ASoC: re-introduce disable_route_checks flag for OF routes Laurentiu Mihalcea
@ 2025-05-16 1:22 ` Kuninori Morimoto
2025-05-16 10:13 ` Mihalcea Laurentiu
0 siblings, 1 reply; 14+ messages in thread
From: Kuninori Morimoto @ 2025-05-16 1:22 UTC (permalink / raw)
To: Laurentiu Mihalcea
Cc: Mark Brown, Jaroslav Kysela, Takashi Iwai, Liam Girdwood,
linux-kernel, linux-sound
Hi Laurentiu
Thank you for the patch
> The "disable_route_checks" flag was previously removed via commit
> dd2395162c07 ("ASoC: remove disable_route_checks") as it wasn't being
> used anywhere.
>
> Re-introduce an OF-specific variant of the flag: "disable_of_route_checks"
> as this will be used by audio-graph-card2.
>
> Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
> ---
> include/sound/soc.h | 1 +
> sound/soc/soc-core.c | 12 ++++++++++--
> 2 files changed, 11 insertions(+), 2 deletions(-)
>
> diff --git a/include/sound/soc.h b/include/sound/soc.h
> index 1fffef311c41..e76da038557d 100644
> --- a/include/sound/soc.h
> +++ b/include/sound/soc.h
> @@ -1077,6 +1077,7 @@ struct snd_soc_card {
> unsigned int instantiated:1;
> unsigned int topology_shortname_created:1;
> unsigned int fully_routed:1;
> + unsigned int disable_of_route_checks:1;
> unsigned int probed:1;
> unsigned int component_chaining:1;
> struct device *devres_dev;
> diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
> index 67bebc339148..b14a52d6f550 100644
> --- a/sound/soc/soc-core.c
> +++ b/sound/soc/soc-core.c
> @@ -2245,8 +2245,16 @@ static int snd_soc_bind_card(struct snd_soc_card *card)
>
> ret = snd_soc_dapm_add_routes(&card->dapm, card->of_dapm_routes,
> card->num_of_dapm_routes);
> - if (ret < 0)
> - goto probe_end;
> + if (ret < 0) {
> + if (card->disable_of_route_checks) {
> + ret = 0;
> + dev_info(card->dev,
> + "%s: disable_of_route_checks set, ignoring errors on add_routes\n",
> + __func__);
> + } else {
> + goto probe_end;
> + }
> + }
commit dd2395162c07 removed flag from 3 parts (core x2 / topology), but
this patch get back only one of them.
I think this flag check should be implemented in snd_soc_dapm_add_route()
itself instead of each caller, but what do you think ?
And maybe we want to use more easy-to-understand naming, like
"ignore route check", etc ?
Thank you for your help !!
Best regards
---
Kuninori Morimoto
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH RFC 2/3] ASoC: audio-graph-card2: support explicitly disabled links
2025-05-15 15:31 ` [PATCH RFC 2/3] ASoC: audio-graph-card2: support explicitly disabled links Laurentiu Mihalcea
@ 2025-05-16 1:36 ` Kuninori Morimoto
2025-05-16 12:50 ` Mihalcea Laurentiu
0 siblings, 1 reply; 14+ messages in thread
From: Kuninori Morimoto @ 2025-05-16 1:36 UTC (permalink / raw)
To: Laurentiu Mihalcea
Cc: Mark Brown, Jaroslav Kysela, Takashi Iwai, Liam Girdwood,
linux-kernel, linux-sound
Hi Laurentiu
Thank you for the patch
> An explicitly disabled link is a DAI link in which one of its device
> endpoints (e.g: codec or CPU) has been disabled in the DTS via the
> "status" property. Formally speaking:
>
> OF_LINK_IS_DISABLED(lnk) = OF_NODE_IS_DISABLED(dev0) ||
> OF_NODE_IS_DISABLED(dev1);
>
> where dev0 and dev1 are the two devices (CPU/codec) that make up the
> link.
>
> If at least one link was explicitly disabled that means DAPM routes
> passed through the OF property "routing" can fail as some widgets might
> not exist. Consider the following example:
>
> CODEC A has widgets A0, A1.
> CODEC B has widgets B0, B1.
>
> my-card {
> compatible = "audio-graph-card2":
> label = "my-label";
> links = <&cpu0_port>, <&cpu1_port>;
> routing = "A0", "A1",
> "B0", "B1";
> };
>
> CODEC A's DT node was disabled.
> CODEC B's DT node is enabled.
> CPU0's DT node is enabled.
> CPU1's DT node is enabled.
>
> If CODEC A's DT node is disabled via the 'status = "disabled"' property
> that means the A0 -> A1 route cannot be created. This doesn't affect the
> B0 -> B1 route though as CODEC B was never disabled in the DT.
>
> This is why, if any explicitly disabled link is discovered, the
> "disable_of_route_checks" flag is turned on.
>
> If all links were explicitly disabled the sound card creation will fail.
> Otherwise, if there's at least one link which wasn't explicitly disabled
> then the sound card creation will succeed.
>
> Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
> ---
I think I could understand your situation, but the solution (= this patch) is
too much complicated for me. Indeed it might detect disabled device, but some
board might want to detect it as error, unlike your case.
You want to add "disable_of_route_checks" flag to the card, right ?
How about to add new property, like "force detect xxx", or
"DAI might not be detected", etc, etc, etc...
If we can have such property, it will be more simple code.
if (it_has_flag("force_detect_xxx")) {
dev_info(dev, "xxx");
card->disable_of_route_checks = 1;
}
Thank you for your help !!
Best regards
---
Kuninori Morimoto
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH RFC 3/3] ASoC: generic: add more sample DTSIs for audio-graph-card2
2025-05-15 15:31 ` [PATCH RFC 3/3] ASoC: generic: add more sample DTSIs for audio-graph-card2 Laurentiu Mihalcea
@ 2025-05-16 1:59 ` Kuninori Morimoto
0 siblings, 0 replies; 14+ messages in thread
From: Kuninori Morimoto @ 2025-05-16 1:59 UTC (permalink / raw)
To: Laurentiu Mihalcea; +Cc: Mark Brown, linux-kernel, linux-sound
Hi Laurentiu
Thank you for caring sample dtsi
> Add some more audio-graph-card2 sample DTSIs meant to aid in testing
> the driver's capability to parse explicitly disabled links. To conclude
> that the feature works correctly, all audio-graph-card2 samples need to
> work as expected. This includes the custom ones:
>
> 1) audio-graph-card2-custom-sample1.dtsi
> 2) audio-graph-card2-custom-sample2.dtsi
>
> Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
> ---
> .../generic/audio-graph-card2-sample1.dtsi | 278 ++++++
> .../generic/audio-graph-card2-sample2.dtsi | 878 ++++++++++++++++++
> .../generic/audio-graph-card2-sample3.dtsi | 486 ++++++++++
This is not a "audio graph card2 sample", but a "disable_of_route_checks"
sample, I think.
I wonder can we re-use existing sample dtsi, like below ??
/*
* Sample of disable_of_route_checks
*/
#include "..../audio-graph-card2-custom-sample1.dtsi"
&audio-graph-card2-custom-sample-1 {
force_detect_xxx;
};
&test_codec_1 {
status = "disabled";
};
Indeed current existing sample is using single Codec or CPU which have
many DAIs. So can't enable/disable each detail DAIs, like your patch did.
If it was not good for you, may be we can separate ?
test_codec_1 {
...
- port@X { ... };
- port@Y { ... };
}
test_codec_2 {
...
+ port@X { ... };
+ port@Y { ... };
}
&test_codec_2 {
status = "disabled";
};
Thank you for your help !!
Best regards
---
Kuninori Morimoto
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH RFC 1/3] ASoC: re-introduce disable_route_checks flag for OF routes
2025-05-16 1:22 ` Kuninori Morimoto
@ 2025-05-16 10:13 ` Mihalcea Laurentiu
0 siblings, 0 replies; 14+ messages in thread
From: Mihalcea Laurentiu @ 2025-05-16 10:13 UTC (permalink / raw)
To: Kuninori Morimoto
Cc: Mark Brown, Jaroslav Kysela, Takashi Iwai, Liam Girdwood,
linux-kernel, linux-sound
On 16.05.2025 04:22, Kuninori Morimoto wrote:
> Hi Laurentiu
>
> Thank you for the patch
>
>> The "disable_route_checks" flag was previously removed via commit
>> dd2395162c07 ("ASoC: remove disable_route_checks") as it wasn't being
>> used anywhere.
>>
>> Re-introduce an OF-specific variant of the flag: "disable_of_route_checks"
>> as this will be used by audio-graph-card2.
>>
>> Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
>> ---
>> include/sound/soc.h | 1 +
>> sound/soc/soc-core.c | 12 ++++++++++--
>> 2 files changed, 11 insertions(+), 2 deletions(-)
>>
>> diff --git a/include/sound/soc.h b/include/sound/soc.h
>> index 1fffef311c41..e76da038557d 100644
>> --- a/include/sound/soc.h
>> +++ b/include/sound/soc.h
>> @@ -1077,6 +1077,7 @@ struct snd_soc_card {
>> unsigned int instantiated:1;
>> unsigned int topology_shortname_created:1;
>> unsigned int fully_routed:1;
>> + unsigned int disable_of_route_checks:1;
>> unsigned int probed:1;
>> unsigned int component_chaining:1;
>> struct device *devres_dev;
>> diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
>> index 67bebc339148..b14a52d6f550 100644
>> --- a/sound/soc/soc-core.c
>> +++ b/sound/soc/soc-core.c
>> @@ -2245,8 +2245,16 @@ static int snd_soc_bind_card(struct snd_soc_card *card)
>>
>> ret = snd_soc_dapm_add_routes(&card->dapm, card->of_dapm_routes,
>> card->num_of_dapm_routes);
>> - if (ret < 0)
>> - goto probe_end;
>> + if (ret < 0) {
>> + if (card->disable_of_route_checks) {
>> + ret = 0;
>> + dev_info(card->dev,
>> + "%s: disable_of_route_checks set, ignoring errors on add_routes\n",
>> + __func__);
>> + } else {
>> + goto probe_end;
>> + }
>> + }
> commit dd2395162c07 removed flag from 3 parts (core x2 / topology), but
> this patch get back only one of them.
hm, so the rationale for introducing this OF-specific flag was because
audio-graph-card2 is the only user for this feature and this user only
needs to disable route checks for OF-based routes. On second thought
though I think it might be better to have this feature for all routes in case
someone might need it for non-OF routes as well? (if we go with the current
approach and it turns out someone needs it for non-OF routes you're going
to need more changes to support that)
>
> I think this flag check should be implemented in snd_soc_dapm_add_route()
> itself instead of each caller, but what do you think ?
good idea, I'll give it a try
>
> And maybe we want to use more easy-to-understand naming, like
> "ignore route check", etc ?
sure
>
> Thank you for your help !!
>
> Best regards
> ---
> Kuninori Morimoto
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH RFC 2/3] ASoC: audio-graph-card2: support explicitly disabled links
2025-05-16 1:36 ` Kuninori Morimoto
@ 2025-05-16 12:50 ` Mihalcea Laurentiu
2025-05-19 1:15 ` Kuninori Morimoto
0 siblings, 1 reply; 14+ messages in thread
From: Mihalcea Laurentiu @ 2025-05-16 12:50 UTC (permalink / raw)
To: Kuninori Morimoto
Cc: Mark Brown, Jaroslav Kysela, Takashi Iwai, Liam Girdwood,
linux-kernel, linux-sound
On 16.05.2025 04:36, Kuninori Morimoto wrote:
> Hi Laurentiu
>
> Thank you for the patch
>
>> An explicitly disabled link is a DAI link in which one of its device
>> endpoints (e.g: codec or CPU) has been disabled in the DTS via the
>> "status" property. Formally speaking:
>>
>> OF_LINK_IS_DISABLED(lnk) = OF_NODE_IS_DISABLED(dev0) ||
>> OF_NODE_IS_DISABLED(dev1);
>>
>> where dev0 and dev1 are the two devices (CPU/codec) that make up the
>> link.
>>
>> If at least one link was explicitly disabled that means DAPM routes
>> passed through the OF property "routing" can fail as some widgets might
>> not exist. Consider the following example:
>>
>> CODEC A has widgets A0, A1.
>> CODEC B has widgets B0, B1.
>>
>> my-card {
>> compatible = "audio-graph-card2":
>> label = "my-label";
>> links = <&cpu0_port>, <&cpu1_port>;
>> routing = "A0", "A1",
>> "B0", "B1";
>> };
>>
>> CODEC A's DT node was disabled.
>> CODEC B's DT node is enabled.
>> CPU0's DT node is enabled.
>> CPU1's DT node is enabled.
>>
>> If CODEC A's DT node is disabled via the 'status = "disabled"' property
>> that means the A0 -> A1 route cannot be created. This doesn't affect the
>> B0 -> B1 route though as CODEC B was never disabled in the DT.
>>
>> This is why, if any explicitly disabled link is discovered, the
>> "disable_of_route_checks" flag is turned on.
>>
>> If all links were explicitly disabled the sound card creation will fail.
>> Otherwise, if there's at least one link which wasn't explicitly disabled
>> then the sound card creation will succeed.
>>
>> Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
>> ---
> I think I could understand your situation, but the solution (= this patch) is
> too much complicated for me. Indeed it might detect disabled device, but some
> board might want to detect it as error, unlike your case.
that is true. One problem with this solution is the fact that you can't
really distinguish between links that were intentionally disabled (see example
from RFC's cover letter) and links that were accidentally disabled (e.g. user
forgot to set 'status = "okay"' for one of the link's devices)
>
> You want to add "disable_of_route_checks" flag to the card, right ?
> How about to add new property, like "force detect xxx", or
> "DAI might not be detected", etc, etc, etc...
>
> If we can have such property, it will be more simple code.
>
> if (it_has_flag("force_detect_xxx")) {
> dev_info(dev, "xxx");
> card->disable_of_route_checks = 1;
> }
well, I think the solution is made up of 2 parts:
1) the part that allows link devices to be disabled
2) the part that allows routes to fails
what you're suggesting is dropping the first part and going with just the second one.
The problem I see with this (let's assume we have the BASE-PLUGIN example presented
in the RFC's cover letter) is that:
1) You'll have to specify the links inside of PLUGIN's DT overlay (instead of BASE's DTS)
2) You'll have to do the link connection part inside PLUGIN's DT overlay.
So, our example DTS and DT overlay would look like this:
[snippet from base.dts]
my_card: card {
compatible = "audio-graph-card2";
links = <&l2>; /* here, we're only allowed to specify links that exist */
routing = "Headphones", "C20",
"Headphones", "C21",
"Line", "C01";
};
d0: cpu@0 {
l0: port { l0_ep: endpoint { /* connected when plugin.dtbo is applied */ } };
};
d1: cpu@1 {
l1: port { l1_ep: endpoint { /* connected when plugin.dtbo is applied */ } };
};
d2: cpu@2 {
l2: port { l2_ep: endpoint { remote-endpoint = <&c2_ep>; } };
};
c2: codec@2 {
port { c2_ep: endpoint { remote-endpoint = <&l2_ep>; } };
};
[snippet from plugin.dtso]
&my_card {
/* here we're forced to also specify l2 even if this is already done
* in base.dts. This is because DT overlays don't support appending to
* properties.
*/
remote-endpoint = <&l0>, <&l1>, <&l2>;
};
&l0_ep {
remote-endpoint = <&c1_ep>;
};
&l1_ep {
remote-endpoint = <&c2_ep>;
};
c0: codec@0 {
port { c0_ep: endpoint { remote-endpoint = <&l0_ep>; } };
};
c1: codec@1 {
port { c1_ep: endpoint { remote-endpoint = <&l1_ep>; } };
};
Assume that we also have BASE1 that is compatible with PLUGIN but
C0 and C1 are connected to BASE1's D0 and D5. Since there's no D1-C1
connection that means you'll have to create another DT overlay. Thus,
the scalability of plugin.dtso decreases.
Now, for our particular case, we have BASE0 and BASE1 with the following
DAIs and CODECS (these are physically present on the base boards):
BASE0 has DAIs D0, D1 and CODEC C0
BASE1 has DAIs D0, D1 and CODEC C1
Both of these boards are compatible with plugin PLUGIN that has codec C2.
The possible DAI links are:
For BASE0:
D0 <----> C0
D1 <----> C2 (only possible with PLUGIN connected)
For BASE1:
D0 <----> C1
D1 <----> C2 (only possible with PLUGIN connected)
Since the D1 <---> C2 connection is valid for both BASE0-PLUGIN and
BASE1-PLUGIN combinations I think we can make do without the support
for explicitly disabled links. But I don't think this is ideal because:
1) If we ever need to support board BASE3 that is compatible with PLUGIN
and uses Dn != D1 to connect with PLUGIN's C2 codec then we're going to
either modify our devicetrees (to make plugin.dtso applicable to BASE3
as well) or add another DT overlay (not really desirable because we already
have a lot of devicetrees). (note: more of an _if_ situation. Don't think we
can actually use this as an argument. I just wanted to have this out in the
open)
2) People might get confused when looking at the "links" and "routing"
properties. Now, "links" will only contain links that actually exist, while
"routing" can contain widgets from codecs that don't exist on the base board.
(note: perhaps not a deal breaker? again, just wanted to have this out in the
open)
Either way, I believe your concern is valid. This new feature adds a lot of
extra code and validating it is a pain. Still, even if we go with just the
extra DT property as you suggested I believe this is a step forward so I think
we can go with that for now and see how well this scales.
BTW, thanks a lot for taking the time to review this huge series!!
> Thank you for your help !!
>
> Best regards
> ---
> Kuninori Morimoto
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH RFC 2/3] ASoC: audio-graph-card2: support explicitly disabled links
2025-05-16 12:50 ` Mihalcea Laurentiu
@ 2025-05-19 1:15 ` Kuninori Morimoto
2025-05-19 9:30 ` Mihalcea Laurentiu
0 siblings, 1 reply; 14+ messages in thread
From: Kuninori Morimoto @ 2025-05-19 1:15 UTC (permalink / raw)
To: Mihalcea Laurentiu
Cc: Mark Brown, Jaroslav Kysela, Takashi Iwai, Liam Girdwood,
linux-kernel, linux-sound
Hi Mihalcea
Thank you for clarify details.
> [snippet from base.dts]
>
> my_card: card {
> compatible = "audio-graph-card2";
> links = <&l2>; /* here, we're only allowed to specify links that exist */
> routing = "Headphones", "C20",
> "Headphones", "C21",
> "Line", "C01";
> };
(snip)
> &my_card {
> /* here we're forced to also specify l2 even if this is already done
> * in base.dts. This is because DT overlays don't support appending to
> * properties.
> */
> remote-endpoint = <&l0>, <&l1>, <&l2>;
> };
This is very nit pickking, but I need to confirm.
You want to indicate here is this ?
&my_card {
- remote-endpoint = <&l0>, <&l1>, <&l2>;
+ links = <&l0>, <&l1>, <&l2>;
};
> &l0_ep {
> remote-endpoint = <&c1_ep>;
> };
>
> &l1_ep {
> remote-endpoint = <&c2_ep>;
> };
>
> c0: codec@0 {
> port { c0_ep: endpoint { remote-endpoint = <&l0_ep>; } };
> };
>
> c1: codec@1 {
> port { c1_ep: endpoint { remote-endpoint = <&l1_ep>; } };
> };
This is also nit pickking, but I think above is wrong.
I guess you want to indicate is...
&l0_ep {
- remote-endpoint = <&c1_ep>;
+ remote-endpoint = <&c0_ep>;
};
&l1_ep {
- remote-endpoint = <&c2_ep>;
+ remote-endpoint = <&c1_ep>;
};
Your are indicating very confusable naming, so I want to understand
correctly as much as possible.
> >> CODEC A has widgets A0, A1.
> >> CODEC B has widgets B0, B1.
> >>
> >> my-card {
> >> compatible = "audio-graph-card2":
> >> label = "my-label";
> >> links = <&cpu0_port>, <&cpu1_port>;
> >> routing = "A0", "A1",
> >> "B0", "B1";
> >> };
> >>
> >> CODEC A's DT node was disabled.
> >> CODEC B's DT node is enabled.
> >> CPU0's DT node is enabled.
> >> CPU1's DT node is enabled.
(snip)
> Assume that we also have BASE1 that is compatible with PLUGIN but
> C0 and C1 are connected to BASE1's D0 and D5. Since there's no D1-C1
> connection that means you'll have to create another DT overlay. Thus,
> the scalability of plugin.dtso decreases.
>
> Now, for our particular case, we have BASE0 and BASE1 with the following
> DAIs and CODECS (these are physically present on the base boards):
>
> BASE0 has DAIs D0, D1 and CODEC C0
> BASE1 has DAIs D0, D1 and CODEC C1
>
> Both of these boards are compatible with plugin PLUGIN that has codec C2.
> The possible DAI links are:
>
> For BASE0:
>
> D0 <----> C0
> D1 <----> C2 (only possible with PLUGIN connected)
>
> For BASE1:
>
> D0 <----> C1
> D1 <----> C2 (only possible with PLUGIN connected)
>
> Since the D1 <---> C2 connection is valid for both BASE0-PLUGIN and
> BASE1-PLUGIN combinations I think we can make do without the support
> for explicitly disabled links. But I don't think this is ideal because:
Let's avoid BASE3 case here to avoid _if_ story.
You are now indicating too many complex/cofusable situations with wrong
setting samples (D0/D1/D2..., C0/C1/C2. BASEx has no D1-C1..., etc, etc...)
I noticed that why you need to add disabled Codec routing on BASE DT ?
It is the reason why you can't detect BASE only sound card, right ?
---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ----
[snippet from base.dts]
my_card: card {
compatible = "audio-graph-card2";
links = <&l2>; /* here, we're only allowed to specify links that exist */
routing = "Headphones", "C20",
"Headphones", "C21",
=> "Line", "C01";
};
---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ----
If my understanding was correct, your system can be indicated like below
(It is not same as your D0/D1/D2 sample, but I think same things, and
not confusable sample)
BASE PLUGIN
+-----------------+
| CPU0 <-> Codec0 | +--------+
| CPU1 | <-> | Codec1 |
| CPU2 | <-> | Codec2 |
+-----------------+ +--------+
How it works by below ?
BASE
/*
* detect CPU0-Codec0 connection only
* Codec1/2 are disabled, but not related to BASE
*/
my_card: card {
links = <&cpu0>;
routing = "Headphone0", "Codec0"; /* for CPU0-Codec0 */
};
PLUGIN
/* detect all
* CPU0-Codec0 connection
* CPU1-Codec1 connection
* CPU2-Codec2 connection, and its routings */
&my_card {
links = <&cpu0>, <&cpu1>, <&cpu2>;
routing = "Headphone0", "Codec0", /* for CPU0-Codec0 */
"Headphone1", "Codec1", /* for CPU1-Codec1 */
"Headphone2", "Codec2"; /* for CPU2-Codec2 */
};
And/Or your situation is similar as mine (I should have noticed
about this sooner).
d70be079c3cf34bd91e1c8f7b4bc760356c9150c
("arm64: dts: renesas: ulcb/kf: Use multi Component sound")
547b02f74e4ac1e7d295a6266d5bc93a647cd4ac
("ASoC: rsnd: enable multi Component support for Audio Graph Card/Card2")
45655ec69cb954d7fa594054bec33d6d5b99f8d5
("ASoC: soc-core.c: enable multi Component")
My board is handling above sample as 2 cards, by using "multi Component"
BASE PLUGIN
+-----------------+ ^
| CPU0 <-> Codec0 | | Card1
| | v
| | +--------+ ^
| CPU1 | <-> | Codec1 | | Card2
| CPU2 | <-> | Codec2 | |
+-----------------+ +--------+ v
Thank you for your help !!
Best regards
---
Kuninori Morimoto
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH RFC 2/3] ASoC: audio-graph-card2: support explicitly disabled links
2025-05-19 1:15 ` Kuninori Morimoto
@ 2025-05-19 9:30 ` Mihalcea Laurentiu
2025-05-20 0:38 ` Kuninori Morimoto
0 siblings, 1 reply; 14+ messages in thread
From: Mihalcea Laurentiu @ 2025-05-19 9:30 UTC (permalink / raw)
To: Kuninori Morimoto
Cc: Mark Brown, Jaroslav Kysela, Takashi Iwai, Liam Girdwood,
linux-kernel, linux-sound
On 19.05.2025 04:15, Kuninori Morimoto wrote:
> Hi Mihalcea
>
> Thank you for clarify details.
>
>> [snippet from base.dts]
>>
>> my_card: card {
>> compatible = "audio-graph-card2";
>> links = <&l2>; /* here, we're only allowed to specify links that exist */
>> routing = "Headphones", "C20",
>> "Headphones", "C21",
>> "Line", "C01";
>> };
> (snip)
>> &my_card {
>> /* here we're forced to also specify l2 even if this is already done
>> * in base.dts. This is because DT overlays don't support appending to
>> * properties.
>> */
>> remote-endpoint = <&l0>, <&l1>, <&l2>;
>> };
> This is very nit pickking, but I need to confirm.
> You want to indicate here is this ?
>
> &my_card {
> - remote-endpoint = <&l0>, <&l1>, <&l2>;
> + links = <&l0>, <&l1>, <&l2>;
> };
yes, I'm very sorry for the mistakes....
>
>> &l0_ep {
>> remote-endpoint = <&c1_ep>;
>> };
>>
>> &l1_ep {
>> remote-endpoint = <&c2_ep>;
>> };
>>
>> c0: codec@0 {
>> port { c0_ep: endpoint { remote-endpoint = <&l0_ep>; } };
>> };
>>
>> c1: codec@1 {
>> port { c1_ep: endpoint { remote-endpoint = <&l1_ep>; } };
>> };
> This is also nit pickking, but I think above is wrong.
> I guess you want to indicate is...
>
> &l0_ep {
> - remote-endpoint = <&c1_ep>;
> + remote-endpoint = <&c0_ep>;
> };
>
> &l1_ep {
> - remote-endpoint = <&c2_ep>;
> + remote-endpoint = <&c1_ep>;
> };
>
>
> Your are indicating very confusable naming, so I want to understand
> correctly as much as possible.
yep, you're right. Again, very sorry.
>
>>>> CODEC A has widgets A0, A1.
>>>> CODEC B has widgets B0, B1.
>>>>
>>>> my-card {
>>>> compatible = "audio-graph-card2":
>>>> label = "my-label";
>>>> links = <&cpu0_port>, <&cpu1_port>;
>>>> routing = "A0", "A1",
>>>> "B0", "B1";
>>>> };
>>>>
>>>> CODEC A's DT node was disabled.
>>>> CODEC B's DT node is enabled.
>>>> CPU0's DT node is enabled.
>>>> CPU1's DT node is enabled.
> (snip)
>> Assume that we also have BASE1 that is compatible with PLUGIN but
>> C0 and C1 are connected to BASE1's D0 and D5. Since there's no D1-C1
>> connection that means you'll have to create another DT overlay. Thus,
>> the scalability of plugin.dtso decreases.
>>
>> Now, for our particular case, we have BASE0 and BASE1 with the following
>> DAIs and CODECS (these are physically present on the base boards):
>>
>> BASE0 has DAIs D0, D1 and CODEC C0
>> BASE1 has DAIs D0, D1 and CODEC C1
>>
>> Both of these boards are compatible with plugin PLUGIN that has codec C2.
>> The possible DAI links are:
>>
>> For BASE0:
>>
>> D0 <----> C0
>> D1 <----> C2 (only possible with PLUGIN connected)
>>
>> For BASE1:
>>
>> D0 <----> C1
>> D1 <----> C2 (only possible with PLUGIN connected)
>>
>> Since the D1 <---> C2 connection is valid for both BASE0-PLUGIN and
>> BASE1-PLUGIN combinations I think we can make do without the support
>> for explicitly disabled links. But I don't think this is ideal because:
> Let's avoid BASE3 case here to avoid _if_ story.
> You are now indicating too many complex/cofusable situations with wrong
> setting samples (D0/D1/D2..., C0/C1/C2. BASEx has no D1-C1..., etc, etc...)
>
> I noticed that why you need to add disabled Codec routing on BASE DT ?
> It is the reason why you can't detect BASE only sound card, right ?
exactly!!!
>
> ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ----
> [snippet from base.dts]
>
> my_card: card {
> compatible = "audio-graph-card2";
> links = <&l2>; /* here, we're only allowed to specify links that exist */
> routing = "Headphones", "C20",
> "Headphones", "C21",
> => "Line", "C01";
> };
>
> ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ----
>
> If my understanding was correct, your system can be indicated like below
> (It is not same as your D0/D1/D2 sample, but I think same things, and
> not confusable sample)
>
> BASE PLUGIN
> +-----------------+
> | CPU0 <-> Codec0 | +--------+
> | CPU1 | <-> | Codec1 |
> | CPU2 | <-> | Codec2 |
> +-----------------+ +--------+
pretty much. The only difference would be that PLUGIN has only 1 codec
in our case. I think it'll be much easier to just stick to your naming conventions...
>
> How it works by below ?
>
> BASE
> /*
> * detect CPU0-Codec0 connection only
> * Codec1/2 are disabled, but not related to BASE
> */
> my_card: card {
> links = <&cpu0>;
> routing = "Headphone0", "Codec0"; /* for CPU0-Codec0 */
> };
>
> PLUGIN
> /* detect all
> * CPU0-Codec0 connection
> * CPU1-Codec1 connection
> * CPU2-Codec2 connection, and its routings */
> &my_card {
> links = <&cpu0>, <&cpu1>, <&cpu2>;
> routing = "Headphone0", "Codec0", /* for CPU0-Codec0 */
> "Headphone1", "Codec1", /* for CPU1-Codec1 */
> "Headphone2", "Codec2"; /* for CPU2-Codec2 */
> };
so, the problem with this is the fact that (assuming you've used a DT overlay
for the PLUGIN) you won't be able to use the DT overlay on other boards because
you've also added the "Headphone0", "Codec0" route which is specific to BASE's
Codec0. We have multiple boards so our system would look like this:
BASE0 PLUGIN
+-----------------+
| CPU0 <-> Codec0 | +--------+
| CPU1 | <-> | Codec1 |
+-----------------+ +--------+
BASE1 PLUGIN
+-----------------+
| CPU0 <-> Codec3 | +--------+
| CPU1 | <-> | Codec1 |
+-----------------+ +--------+
The plugin is the same. The only difference between BASE1 and BASE0 is the fact that CPU0
is connected to Codec0 on BASE0, while, on BASE1, CPU0 is connected to a different codec: Codec3.
>
>
> And/Or your situation is similar as mine (I should have noticed
> about this sooner).
>
> d70be079c3cf34bd91e1c8f7b4bc760356c9150c
> ("arm64: dts: renesas: ulcb/kf: Use multi Component sound")
>
> 547b02f74e4ac1e7d295a6266d5bc93a647cd4ac
> ("ASoC: rsnd: enable multi Component support for Audio Graph Card/Card2")
>
> 45655ec69cb954d7fa594054bec33d6d5b99f8d5
> ("ASoC: soc-core.c: enable multi Component")
>
> My board is handling above sample as 2 cards, by using "multi Component"
>
> BASE PLUGIN
> +-----------------+ ^
> | CPU0 <-> Codec0 | | Card1
> | | v
> | | +--------+ ^
> | CPU1 | <-> | Codec1 | | Card2
> | CPU2 | <-> | Codec2 | |
> +-----------------+ +--------+ v
one important thing to note here is the fact that we can only
have 1 sound card because all DAIs (CPU0, CPU1, CPU2) belong
to the same component.
>
>
> Thank you for your help !!
>
> Best regards
> ---
> Kuninori Morimoto
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH RFC 2/3] ASoC: audio-graph-card2: support explicitly disabled links
2025-05-19 9:30 ` Mihalcea Laurentiu
@ 2025-05-20 0:38 ` Kuninori Morimoto
2025-05-21 12:15 ` Mihalcea Laurentiu
0 siblings, 1 reply; 14+ messages in thread
From: Kuninori Morimoto @ 2025-05-20 0:38 UTC (permalink / raw)
To: Mihalcea Laurentiu
Cc: Mark Brown, Jaroslav Kysela, Takashi Iwai, Liam Girdwood,
linux-kernel, linux-sound
Hi Laurentiu
> so, the problem with this is the fact that (assuming you've used a DT overlay
> for the PLUGIN) you won't be able to use the DT overlay on other boards because
> you've also added the "Headphone0", "Codec0" route which is specific to BASE's
> Codec0. We have multiple boards so our system would look like this:
>
> BASE0 PLUGIN
> +-----------------+
> | CPU0 <-> Codec0 | +--------+
> | CPU1 | <-> | Codec1 |
> +-----------------+ +--------+
>
>
> BASE1 PLUGIN
> +-----------------+
> | CPU0 <-> Codec3 | +--------+
> | CPU1 | <-> | Codec1 |
> +-----------------+ +--------+
>
>
> The plugin is the same. The only difference between BASE1 and BASE0 is the fact that CPU0
> is connected to Codec0 on BASE0, while, on BASE1, CPU0 is connected to a different codec: Codec3.
Ah, OK, that it the reason why you added the route on BASE side...
Hmm... I think my previous suggested idea (new flag) is reasonable, but you
mentioned that you want to check whether it was "disabled" or not.
So, how about to add "plugin-route" and "plugin-links" instead ?
BASE
my_card: card {
links = <&cpu0>;
routing = "Headphone0", "Codec0"; /* for CPU0-Codec0 */
};
PLUGIN
&my_card {
plugin-links = <&cpu1>, <&cpu2>
plugin-routing = "Headphone1", "Codec1", /* for CPU1-Codec1 */
^^^^^^ "Headphone2", "Codec2"; /* for CPU2-Codec2 */
};
Audio Card2 parses "links" + "plugin-links", and
"routing" + "plugin-routing". It is more intuitive ?
> > BASE PLUGIN
> > +-----------------+ ^
> > | CPU0 <-> Codec0 | | Card1
> > | | v
> > | | +--------+ ^
> > | CPU1 | <-> | Codec1 | | Card2
> > | CPU2 | <-> | Codec2 | |
> > +-----------------+ +--------+ v
>
> one important thing to note here is the fact that we can only
> have 1 sound card because all DAIs (CPU0, CPU1, CPU2) belong
> to the same component.
Indeed it depens on the CPU side driver style.
I have updated my driver to allow to be multi components by checking DT.
I'm not sure which one (= use plugin-xxx flag or use multi Cards) is
more intuitive, but supporting both is not bad idea ?
Thank you for your help !!
Best regards
---
Kuninori Morimoto
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH RFC 2/3] ASoC: audio-graph-card2: support explicitly disabled links
2025-05-20 0:38 ` Kuninori Morimoto
@ 2025-05-21 12:15 ` Mihalcea Laurentiu
2025-05-22 1:19 ` Kuninori Morimoto
0 siblings, 1 reply; 14+ messages in thread
From: Mihalcea Laurentiu @ 2025-05-21 12:15 UTC (permalink / raw)
To: Kuninori Morimoto
Cc: Mark Brown, Jaroslav Kysela, Takashi Iwai, Liam Girdwood,
linux-kernel, linux-sound
On 20.05.2025 03:38, Kuninori Morimoto wrote:
> Hi Laurentiu
>
>> so, the problem with this is the fact that (assuming you've used a DT overlay
>> for the PLUGIN) you won't be able to use the DT overlay on other boards because
>> you've also added the "Headphone0", "Codec0" route which is specific to BASE's
>> Codec0. We have multiple boards so our system would look like this:
>>
>> BASE0 PLUGIN
>> +-----------------+
>> | CPU0 <-> Codec0 | +--------+
>> | CPU1 | <-> | Codec1 |
>> +-----------------+ +--------+
>>
>>
>> BASE1 PLUGIN
>> +-----------------+
>> | CPU0 <-> Codec3 | +--------+
>> | CPU1 | <-> | Codec1 |
>> +-----------------+ +--------+
>>
>>
>> The plugin is the same. The only difference between BASE1 and BASE0 is the fact that CPU0
>> is connected to Codec0 on BASE0, while, on BASE1, CPU0 is connected to a different codec: Codec3.
> Ah, OK, that it the reason why you added the route on BASE side...
exactly!
>
> Hmm... I think my previous suggested idea (new flag) is reasonable, but you
> mentioned that you want to check whether it was "disabled" or not.
> So, how about to add "plugin-route" and "plugin-links" instead ?
>
> BASE
> my_card: card {
> links = <&cpu0>;
> routing = "Headphone0", "Codec0"; /* for CPU0-Codec0 */
> };
>
> PLUGIN
> &my_card {
> plugin-links = <&cpu1>, <&cpu2>
> plugin-routing = "Headphone1", "Codec1", /* for CPU1-Codec1 */
> ^^^^^^ "Headphone2", "Codec2"; /* for CPU2-Codec2 */
> };
>
> Audio Card2 parses "links" + "plugin-links", and
> "routing" + "plugin-routing". It is more intuitive ?
hm, I believe this _should_ work. I also think that we can just drop the whole
"ignore_route_check" flag idea since you can just use "plugin-routing" in
your DT overlay to specify the CODEC-specific routes (instead of having
them in your BASE DTS). This way, you'll avoid having routes that might
not exist in your BASE DTS.
if we go for this though I think we need to clarify the usage of the
"plugin-links" and "plugin-routing" properties. For me, these properties
only make sense if you use them in a DT overlay to add additional links/routes
introduced by the PLUGIN board. This is basically a workaround the fact
that DT overlays don't support appending to the properties of the BASE
DTS.
also, I believe we can drop the whole "explicitly disabled links" idea
since IMO, links passed via the "plugin-links" property _must_ exist.
anyhow, I will have test out this new idea on our particular scenario and see
how well it works. Thank you very much for this discussion! It was really, really
helpful!
>
>>> BASE PLUGIN
>>> +-----------------+ ^
>>> | CPU0 <-> Codec0 | | Card1
>>> | | v
>>> | | +--------+ ^
>>> | CPU1 | <-> | Codec1 | | Card2
>>> | CPU2 | <-> | Codec2 | |
>>> +-----------------+ +--------+ v
>> one important thing to note here is the fact that we can only
>> have 1 sound card because all DAIs (CPU0, CPU1, CPU2) belong
>> to the same component.
> Indeed it depens on the CPU side driver style.
> I have updated my driver to allow to be multi components by checking DT.
>
> I'm not sure which one (= use plugin-xxx flag or use multi Cards) is
> more intuitive, but supporting both is not bad idea ?
>
> Thank you for your help !!
>
> Best regards
> ---
> Kuninori Morimoto
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH RFC 2/3] ASoC: audio-graph-card2: support explicitly disabled links
2025-05-21 12:15 ` Mihalcea Laurentiu
@ 2025-05-22 1:19 ` Kuninori Morimoto
0 siblings, 0 replies; 14+ messages in thread
From: Kuninori Morimoto @ 2025-05-22 1:19 UTC (permalink / raw)
To: Mihalcea Laurentiu
Cc: Mark Brown, Jaroslav Kysela, Takashi Iwai, Liam Girdwood,
linux-kernel, linux-sound
Hi Mihalcea
Thank you for rhw the reply
> >> BASE0 PLUGIN
> >> +-----------------+
> >> | CPU0 <-> Codec0 | +--------+
> >> | CPU1 | <-> | Codec1 |
> >> +-----------------+ +--------+
> >>
> >>
> >> BASE1 PLUGIN
> >> +-----------------+
> >> | CPU0 <-> Codec3 | +--------+
> >> | CPU1 | <-> | Codec1 |
> >> +-----------------+ +--------+
(snip)
> > BASE
> > my_card: card {
> > links = <&cpu0>;
> > routing = "Headphone0", "Codec0"; /* for CPU0-Codec0 */
> > };
> >
> > PLUGIN
> > &my_card {
> > plugin-links = <&cpu1>, <&cpu2>
> > plugin-routing = "Headphone1", "Codec1", /* for CPU1-Codec1 */
> > ^^^^^^ "Headphone2", "Codec2"; /* for CPU2-Codec2 */
> > };
(snip)
> hm, I believe this _should_ work.
I hope so.
> I also think that we can just drop the whole
> "ignore_route_check" flag idea
(snip)
> also, I believe we can drop the whole "explicitly disabled links" idea
> since IMO, links passed via the "plugin-links" property _must_ exist.
Yes, agree. It is no longer needed on new plugin-xxx idea.
> if we go for this though I think we need to clarify the usage of the
> "plugin-links" and "plugin-routing" properties.
Yes. I think you need to confirm or persuade to DT maintainer that whether
it can be accepted idea or not.
> Thank you very much for this discussion! It was really, really
> helpful!
Same here. I'm very happy could do that
Thank you for your help !!
Best regards
---
Kuninori Morimoto
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2025-05-22 1:19 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-05-15 15:31 [PATCH RFC 0/3] ASoC: audio-graph-card2: support explicitly disabled links Laurentiu Mihalcea
2025-05-15 15:31 ` [PATCH RFC 1/3] ASoC: re-introduce disable_route_checks flag for OF routes Laurentiu Mihalcea
2025-05-16 1:22 ` Kuninori Morimoto
2025-05-16 10:13 ` Mihalcea Laurentiu
2025-05-15 15:31 ` [PATCH RFC 2/3] ASoC: audio-graph-card2: support explicitly disabled links Laurentiu Mihalcea
2025-05-16 1:36 ` Kuninori Morimoto
2025-05-16 12:50 ` Mihalcea Laurentiu
2025-05-19 1:15 ` Kuninori Morimoto
2025-05-19 9:30 ` Mihalcea Laurentiu
2025-05-20 0:38 ` Kuninori Morimoto
2025-05-21 12:15 ` Mihalcea Laurentiu
2025-05-22 1:19 ` Kuninori Morimoto
2025-05-15 15:31 ` [PATCH RFC 3/3] ASoC: generic: add more sample DTSIs for audio-graph-card2 Laurentiu Mihalcea
2025-05-16 1:59 ` Kuninori Morimoto
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).