From 09f75f098105d65c37915e41a6ed3a75ec3ecfc7 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 10 Jul 2023 10:19:53 +0900 Subject: ASoC: soc-dai.c: add DAI get/match functions Current ASoC is specifying and checking DAI name. But where it came from and how to check was ambiguous. This patch adds snd_soc_dai_name_get() / snd_soc_dlc_dai_is_match() and makes it clear. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87h6qco952.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 2 ++ sound/soc/soc-core.c | 62 +++++++++++++++++++++++++++++++++++++------------ 2 files changed, 49 insertions(+), 15 deletions(-) diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index e3906ecda740..a4538040e88d 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -271,6 +271,8 @@ int snd_soc_dai_compr_get_metadata(struct snd_soc_dai *dai, struct snd_compr_stream *cstream, struct snd_compr_metadata *metadata); +const char *snd_soc_dai_name_get(struct snd_soc_dai *dai); + struct snd_soc_dai_ops { /* * DAI clocking configuration, all optional. diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 94e856d67a46..ee309d3fe89c 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -253,6 +253,47 @@ static inline int snd_soc_dlc_dai_is_empty(struct snd_soc_dai_link_component *dl return !dlc->dai_name; } +static int snd_soc_is_matching_dai(const struct snd_soc_dai_link_component *dlc, + struct snd_soc_dai *dai) +{ + if (!dlc) + return 0; + + if (!dlc->dai_name) + return 1; + + /* see snd_soc_dai_name_get() */ + + if (strcmp(dlc->dai_name, dai->name) == 0) + return 1; + + if (dai->driver->name && + strcmp(dai->driver->name, dlc->dai_name) == 0) + return 1; + + if (dai->component->name && + strcmp(dlc->dai_name, dai->component->name) == 0) + return 1; + + return 0; +} + +const char *snd_soc_dai_name_get(struct snd_soc_dai *dai) +{ + /* see snd_soc_is_matching_dai() */ + if (dai->name) + return dai->name; + + if (dai->driver->name) + return dai->driver->name; + + if (dai->component->name) + return dai->component->name; + + return NULL; +} +EXPORT_SYMBOL_GPL(snd_soc_dai_name_get); + static int snd_soc_rtd_add_component(struct snd_soc_pcm_runtime *rtd, struct snd_soc_component *component) { @@ -810,18 +851,11 @@ struct snd_soc_dai *snd_soc_find_dai( lockdep_assert_held(&client_mutex); /* Find CPU DAI from registered DAIs */ - for_each_component(component) { - if (!snd_soc_is_matching_component(dlc, component)) - continue; - for_each_component_dais(component, dai) { - if (dlc->dai_name && strcmp(dai->name, dlc->dai_name) - && (!dai->driver->name - || strcmp(dai->driver->name, dlc->dai_name))) - continue; - - return dai; - } - } + for_each_component(component) + if (snd_soc_is_matching_component(dlc, component)) + for_each_component_dais(component, dai) + if (snd_soc_is_matching_dai(dlc, dai)) + return dai; return NULL; } @@ -3316,9 +3350,7 @@ int snd_soc_get_dlc(const struct of_phandle_args *args, struct snd_soc_dai_link_ id--; } - dlc->dai_name = dai->driver->name; - if (!dlc->dai_name) - dlc->dai_name = pos->name; + dlc->dai_name = snd_soc_dai_name_get(dai); } else if (ret) { /* * if another error than ENOTSUPP is returned go on and -- cgit From 45655ec69cb954d7fa594054bec33d6d5b99f8d5 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 10 Jul 2023 10:20:00 +0900 Subject: ASoC: soc-core.c: enable multi Component Current ASoC Card is using dlc (snd_soc_dai_link_component) to find target DAI / Component to be used. Current dlc has below 3 items to identify DAI / Component (a) name for Component (b) of_node for Component (c) dai_name for DAI (a) or (b) is used to identify target Component, and (c) is used to identify DAI. One of the biggest issue on it today is dlc needs "name matching" for "dai_name" (c). It was not a big deal when we were using platform_device, because we could specify nessesary "dai_name" via its platform_data. But we need to find DAI name pointer from whole registered datas and/or each related driver somehow in case of DT, because we can't specify it. Therefore, Card driver parses DT and assumes the DAI, and find its name pointer. How to assume is based on each Component and/or Card. Next biggest issue is Component node (a)/(b). Basically, Component is registered when CPU/Codec driver was probed() (X). Here, 1 Component is possible to have some DAIs. int xxx_probe(struct platform_device *pdev) { ... (X) ret = devm_snd_soc_register_component(pdev->dev, &component_driver, &dai_driver, dai_driver_num); ... } The image of each data will be like below. One note here is "driver" is included for later explanation. +-driver------+ |+-component-+| || dai0|| || dai1|| || ...|| |+-----------+| +-------------+ The point here is 1 driver has 1 Component, because basically driver calles snd_soc_register_component() (= X) once. Here is the very basic CPU/Codec connection image. HW image SW image +-- Board ------------+ +-card--------------------------+ |+-----+ +------+| |+-driver------+ +-driver------+| || CPU | <--> |CodecA|| ||+-component-+| |+-component-+|| |+-----+ +------+| ||| dai|<=>|dai ||| +---------------------+ ||+-----------+| |+-----------+|| |+-------------+ +-------------+| +-------------------------------+ It will be very complex if it has multi DAIs. Here is intuitive easy to understandable HW / SW example. HW image SW image +-- Board ---------------+ +-card--------------------------+ |+--------+ +------+| |+-driver------+ +-driver------+| || CPU ch0| <--> |CodecA|| ||+-component-+| |+-component-+|| || | +------+| ||| ch0 dai|<=>|dai ||| || | +------+| ||| || |+-----------+|| || ch1| <--> |CodecB|| ||| || +-------------+| |+--------+ +------+| ||| || +-driver------+| +------------------------+ ||| || |+-component-+|| ||| ch1 dai|<=>|dai ||| ||+-----------+| |+-----------+|| |+-------------+ +-------------+| +-------------------------------+ It will be handled as multi interface as "one Card". card0,0: CPU-ch0 - CodecA card0,1: CPU-ch1 - CodecB ^ But, here is the HW image example which will be more complex +-- Basic Board ---------+ |+--------+ +------+| || CPU ch0| <--> |CodecA|| || ch1| <-+ +------+| |+--------+ | | +-------------|----------+ +-- expansion board -----+ | | +------+| | +->|CodecB|| | +------+| +------------------------+ We intuitively think we want to handle these as "2 Sound Cards". card0,0: CPU-ch0 - CodecA card1,0: CPU-ch1 - CodecB ^ But below image which we can register today doesn't allow it, because the same Component will be connected to both Card0/1, but it will be rejected by (Z). +-driver------+ |+-component-+| +-card0-------------------------+ ||| || +-driver------+| ||| || |+-component-+|| ||| ch0 dai|<=>|dai ||| ||| || |+-----------+|| ||| || +-------------+| +-------------------------------+ || || +-card1-------------------------+ ||| || +-driver------+| ||| || |+-component-+|| ||| ch1 dai|<=>|dai ||| ||| || |+-----------+|| ||| || +-------------+| +-------------------------------+ |+-----------+| +-------------+ static int soc_probe_component() { ... if (component->card) { (Z) if (component->card != card) { dev_err(component->dev, ...); return -ENODEV; } return 0; } ... } So, how about to call snd_soc_register_component() (= X) multiple times on probe() to avoid buplicated component->card limitation, to be like below ? +-driver------+ +-card0-------------------------+ || | +-driver------+| ||+-component-+| |+-component-+|| ||| ch0 dai|<=>|dai ||| ||+-----------+| |+-----------+|| || | +-------------+| +-------------------------------+ | | +-card1-------------------------+ || | +-driver------+| ||+-component-+| |+-component-+|| ||| ch1 dai|<=>|dai ||| ||+-----------+| |+-----------+|| || | +-------------+| +-------------------------------+ +-------------+ Yes, looks good. But unfortunately it doesn't help us for now. Let's see soc_component_to_node() and snd_soc_is_matching_component() static struct device_node *soc_component_to_node(struct snd_soc_component *component) { ... (A) of_node = component->dev->of_node; ... } static int snd_soc_is_matching_component(...) { ... (B) if (dlc->of_node && component_of_node != dlc->of_node) ... } dlc checkes "of_node" to identify target component (B), but this "of_node" came from component->dev (A) which is added by snd_soc_register_component() (X) on probe(). This means we can have different "component->card", but have same "component->dev" in this case. Even though we calls snd_soc_register_component() (= X) multiple times, all Components have same driver's dev, thus it is impossible to identified the Component. And if it was impossible to identify Component, it is impossible to identify DAI on current implementation. So, how to handle above complex HW image today is 2 patterns. One is handles it as "1 big sound card". The SW image is like below. SW image +-card--------------------------+ |+-driver------+ +-driver------+| ||+-component-+| |+-component-+|| ||| ch0 dai|<=>|dai ||| ||| || |+-----------+|| ||| || +-------------+| ||| || +-driver------+| ||| || |+-component-+|| ||| ch1 dai|<->|dai ||| ||+-----------+| |+-----------+|| |+-------------+ +-------------+| +-------------------------------+ But the problem is not intuitive. We want to handle it as "2 Cards". 2nd pattern is like below. SW image +-card0-------------------------+ |+-driver------+ +-driver------+| ||+-component-+| |+-component-+|| ||| ch0 dai|<=>|dai ||| ||+-----------+| |+-----------+|| |+-------------+ +-------------+| +-------------------------------+ +-card1-------------------------+ |+-driver------+ +-driver------+| ||+-component-+| |+-component-+|| ||| ch1 dai|<=>|dai ||| ||+-----------+| |+-----------+|| |+-------------+ +-------------+| +-------------------------------+ It handles as "2 Cards", but CPU part needs to be probed as 2 drivers. It is also not intuitive. To solve this issue, we need to have multi Component support. In current implementation, we need to identify Component first to identify DAI, and it is using name matching to identify DAI. But how about to be enable to directly identify DAI by unique way instead of name matching ? In such case, we can directly identify DAI, then it can identify Component from DAI. For example Simple-Card / Audio-Graph-Card case, it is specifying DAI via its node. Simple-Card sound-dai = <&cpu-sound>; Audio-Graph-Card dais = <&cpu-sound>; If each CPU/Codec driver keeps this property when probing, we can identify DAI directly from Card. Being able to identify DAI directly means being able to identify its Component as well even though Component has same dev (= B). This patch adds new "dai_node" for it. To keeping compatibility, it checks "dai_node" first if it has, otherwise, use existing method (name matching). Link: https://lore.kernel.org/r/87fskz5yrr.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87fs5wo94v.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 1 + include/sound/soc.h | 1 + sound/soc/soc-core.c | 32 ++++++++++++++++++++++++++++++-- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index a4538040e88d..a33d803fe548 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -399,6 +399,7 @@ struct snd_soc_dai_driver { unsigned int id; unsigned int base; struct snd_soc_dobj dobj; + struct of_phandle_args *dai_args; /* DAI driver callbacks */ int (*probe)(struct snd_soc_dai *dai); diff --git a/include/sound/soc.h b/include/sound/soc.h index b27f84580c5b..dda731795bd4 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -651,6 +651,7 @@ struct snd_soc_dai_link_component { const char *name; struct device_node *of_node; const char *dai_name; + struct of_phandle_args *dai_args; }; struct snd_soc_dai_link_codec_ch_map { diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index ee309d3fe89c..8487a4c12753 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -238,9 +238,25 @@ static inline void snd_soc_debugfs_exit(void) { } #endif +static int snd_soc_is_match_dai_args(struct of_phandle_args *args1, + struct of_phandle_args *args2) +{ + if (!args1 || !args2) + return 0; + + if (args1->np != args2->np) + return 0; + + for (int i = 0; i < args1->args_count; i++) + if (args1->args[i] != args2->args[i]) + return 0; + + return 1; +} + static inline int snd_soc_dlc_component_is_empty(struct snd_soc_dai_link_component *dlc) { - return !(dlc->name || dlc->of_node); + return !(dlc->dai_args || dlc->name || dlc->of_node); } static inline int snd_soc_dlc_component_is_invalid(struct snd_soc_dai_link_component *dlc) @@ -250,7 +266,7 @@ static inline int snd_soc_dlc_component_is_invalid(struct snd_soc_dai_link_compo static inline int snd_soc_dlc_dai_is_empty(struct snd_soc_dai_link_component *dlc) { - return !dlc->dai_name; + return !(dlc->dai_args || dlc->dai_name); } static int snd_soc_is_matching_dai(const struct snd_soc_dai_link_component *dlc, @@ -259,6 +275,9 @@ static int snd_soc_is_matching_dai(const struct snd_soc_dai_link_component *dlc, if (!dlc) return 0; + if (dlc->dai_args) + return snd_soc_is_match_dai_args(dai->driver->dai_args, dlc->dai_args); + if (!dlc->dai_name) return 1; @@ -799,6 +818,15 @@ static int snd_soc_is_matching_component( if (!dlc) return 0; + if (dlc->dai_args) { + struct snd_soc_dai *dai; + + for_each_component_dais(component, dai) + if (snd_soc_is_matching_dai(dlc, dai)) + return 1; + return 0; + } + component_of_node = soc_component_to_node(component); if (dlc->of_node && component_of_node != dlc->of_node) -- cgit From 442ae56cf5c007faaf7440d4aa018c62e5761157 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 10 Jul 2023 10:20:06 +0900 Subject: ASoC: soc-core.c: add snd_soc_get_dai_via_args() To enable multi Component, Card driver need to get DAI via dai_args to identify it. This patch adds snd_soc_get_dai_via_args() for it. This is helper function for multi Component support. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87edlgo94p.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc.h | 1 + sound/soc/soc-core.c | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/include/sound/soc.h b/include/sound/soc.h index dda731795bd4..1b3c58fe14c4 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1336,6 +1336,7 @@ int snd_soc_add_pcm_runtimes(struct snd_soc_card *card, void snd_soc_remove_pcm_runtime(struct snd_soc_card *card, struct snd_soc_pcm_runtime *rtd); +struct snd_soc_dai *snd_soc_get_dai_via_args(struct of_phandle_args *dai_args); struct snd_soc_dai *snd_soc_register_dai(struct snd_soc_component *component, struct snd_soc_dai_driver *dai_drv, bool legacy_dai_naming); diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 8487a4c12753..22a065f4c908 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -3446,6 +3446,24 @@ int snd_soc_of_get_dai_name(struct device_node *of_node, } EXPORT_SYMBOL_GPL(snd_soc_of_get_dai_name); +struct snd_soc_dai *snd_soc_get_dai_via_args(struct of_phandle_args *dai_args) +{ + struct snd_soc_dai *dai; + struct snd_soc_component *component; + + mutex_lock(&client_mutex); + for_each_component(component) { + for_each_component_dais(component, dai) + if (snd_soc_is_match_dai_args(dai->driver->dai_args, dai_args)) + goto found; + } + dai = NULL; +found: + mutex_unlock(&client_mutex); + return dai; +} +EXPORT_SYMBOL_GPL(snd_soc_get_dai_via_args); + static void __snd_soc_of_put_component(struct snd_soc_dai_link_component *component) { if (component->of_node) { -- cgit From 988bad5ee4d7138d26081f3661779b63725605d8 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 10 Jul 2023 10:20:11 +0900 Subject: ASoC: soc-core.c: add snd_soc_dlc_use_cpu_as_platform() Current snd_soc_is_matching_component() checks "of_node" or "dai_args". Thus coping "of_node" only is not enough to use CPU as Platform. This patch adds snd_soc_dlc_use_cpu_as_platform() and help it. This is helper function for multi Component support. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87cz10o94k.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc.h | 2 ++ sound/soc/generic/simple-card-utils.c | 2 +- sound/soc/soc-core.c | 8 ++++++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index 1b3c58fe14c4..94fca10f01ad 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1336,6 +1336,8 @@ int snd_soc_add_pcm_runtimes(struct snd_soc_card *card, void snd_soc_remove_pcm_runtime(struct snd_soc_card *card, struct snd_soc_pcm_runtime *rtd); +void snd_soc_dlc_use_cpu_as_platform(struct snd_soc_dai_link_component *platforms, + struct snd_soc_dai_link_component *cpus); struct snd_soc_dai *snd_soc_get_dai_via_args(struct of_phandle_args *dai_args); struct snd_soc_dai *snd_soc_register_dai(struct snd_soc_component *component, struct snd_soc_dai_driver *dai_drv, diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index 3019626b0592..c142571992a1 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -649,7 +649,7 @@ void asoc_simple_canonicalize_platform(struct snd_soc_dai_link_component *platfo * simple-card.c :: simple_count_noml() */ if (!platforms->of_node) - platforms->of_node = cpus->of_node; + snd_soc_dlc_use_cpu_as_platform(platforms, cpus); } EXPORT_SYMBOL_GPL(asoc_simple_canonicalize_platform); diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 22a065f4c908..9fd7e633d374 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -3005,6 +3005,14 @@ int snd_soc_of_parse_tdm_slot(struct device_node *np, } EXPORT_SYMBOL_GPL(snd_soc_of_parse_tdm_slot); +void snd_soc_dlc_use_cpu_as_platform(struct snd_soc_dai_link_component *platforms, + struct snd_soc_dai_link_component *cpus) +{ + platforms->of_node = cpus->of_node; + platforms->dai_args = cpus->dai_args; +} +EXPORT_SYMBOL_GPL(snd_soc_dlc_use_cpu_as_platform); + void snd_soc_of_parse_node_prefix(struct device_node *np, struct snd_soc_codec_conf *codec_conf, struct device_node *of_node, -- cgit From bbde4a30c6b18dd034dcce41612907dc64817175 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 10 Jul 2023 10:20:17 +0900 Subject: ASoC: soc-core.c: add snd_soc_copy_dai_args() To use multi Component support, we need to check dai_args whether Card could get DAI from args (CPU/Codec needs set dai_args on DAI driver). If it could, we need to allocate dai_args for dlc. This patch adds snd_soc_copy_dai_args() for it. This is helper function for multi Component support. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87bkgko94e.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc.h | 2 ++ sound/soc/soc-core.c | 13 +++++++++++++ 2 files changed, 15 insertions(+) diff --git a/include/sound/soc.h b/include/sound/soc.h index 94fca10f01ad..fa2337a3cf4c 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1338,6 +1338,8 @@ void snd_soc_remove_pcm_runtime(struct snd_soc_card *card, void snd_soc_dlc_use_cpu_as_platform(struct snd_soc_dai_link_component *platforms, struct snd_soc_dai_link_component *cpus); +struct of_phandle_args *snd_soc_copy_dai_args(struct device *dev, + struct of_phandle_args *args); struct snd_soc_dai *snd_soc_get_dai_via_args(struct of_phandle_args *dai_args); struct snd_soc_dai *snd_soc_register_dai(struct snd_soc_component *component, struct snd_soc_dai_driver *dai_drv, diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 9fd7e633d374..a5b96c17633a 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -809,6 +809,19 @@ static struct device_node return of_node; } +struct of_phandle_args *snd_soc_copy_dai_args(struct device *dev, struct of_phandle_args *args) +{ + struct of_phandle_args *ret = devm_kzalloc(dev, sizeof(*ret), GFP_KERNEL); + + if (!ret) + return NULL; + + *ret = *args; + + return ret; +} +EXPORT_SYMBOL_GPL(snd_soc_copy_dai_args); + static int snd_soc_is_matching_component( const struct snd_soc_dai_link_component *dlc, struct snd_soc_component *component) -- cgit From 90de551c1bf0c78ca5cd10c5ff424dee4d44cb1c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 10 Jul 2023 10:20:22 +0900 Subject: ASoC: simple-card-utils.c: enable multi Component support If CPU/Codec driver keeps its DAI node, we can directly identify actual DAI by using snd_soc_get_dai_via_args(). This means we can use multi Component. This patch enables multi Component support on Audio Graph Card/Card2. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87a5w4o949.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/simple_card_utils.h | 5 ++--- sound/soc/generic/audio-graph-card.c | 2 +- sound/soc/generic/audio-graph-card2.c | 2 +- sound/soc/generic/simple-card-utils.c | 21 ++++++++++++++++++--- 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h index b450d5873227..d1a95bc33c56 100644 --- a/include/sound/simple_card_utils.h +++ b/include/sound/simple_card_utils.h @@ -192,9 +192,8 @@ int asoc_simple_remove(struct platform_device *pdev); int asoc_graph_card_probe(struct snd_soc_card *card); int asoc_graph_is_ports0(struct device_node *port); -int asoc_graph_parse_dai(struct device_node *ep, - struct snd_soc_dai_link_component *dlc, - int *is_single_link); +int asoc_graph_parse_dai(struct device *dev, struct device_node *ep, + struct snd_soc_dai_link_component *dlc, int *is_single_link); #ifdef DEBUG static inline void asoc_simple_debug_dai(struct asoc_simple_priv *priv, diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index c6e0f9132193..0b8258b6bd8e 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c @@ -126,7 +126,7 @@ static int graph_parse_node(struct asoc_simple_priv *priv, graph_parse_mclk_fs(top, ep, dai_props); - ret = asoc_graph_parse_dai(ep, dlc, cpu); + ret = asoc_graph_parse_dai(dev, ep, dlc, cpu); if (ret < 0) return ret; diff --git a/sound/soc/generic/audio-graph-card2.c b/sound/soc/generic/audio-graph-card2.c index 542c4a114940..98732468a992 100644 --- a/sound/soc/generic/audio-graph-card2.c +++ b/sound/soc/generic/audio-graph-card2.c @@ -407,7 +407,7 @@ static int __graph_parse_node(struct asoc_simple_priv *priv, graph_parse_mclk_fs(ep, dai_props); - ret = asoc_graph_parse_dai(ep, dlc, &is_single_links); + ret = asoc_graph_parse_dai(dev, ep, dlc, &is_single_links); if (ret < 0) return ret; diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index c142571992a1..5b18a4af022f 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -1066,12 +1066,12 @@ static int graph_get_dai_id(struct device_node *ep) return id; } -int asoc_graph_parse_dai(struct device_node *ep, - struct snd_soc_dai_link_component *dlc, - int *is_single_link) +int asoc_graph_parse_dai(struct device *dev, struct device_node *ep, + struct snd_soc_dai_link_component *dlc, int *is_single_link) { struct device_node *node; struct of_phandle_args args = {}; + struct snd_soc_dai *dai; int ret; if (!ep) @@ -1079,6 +1079,20 @@ int asoc_graph_parse_dai(struct device_node *ep, node = of_graph_get_port_parent(ep); + /* + * Try to find from DAI node + */ + args.np = ep; + dai = snd_soc_get_dai_via_args(&args); + if (dai) { + dlc->dai_name = snd_soc_dai_name_get(dai); + dlc->dai_args = snd_soc_copy_dai_args(dev, &args); + if (!dlc->dai_args) + return -ENOMEM; + + goto parse_dai_end; + } + /* Get dai->name */ args.np = node; args.args[0] = graph_get_dai_id(ep); @@ -1109,6 +1123,7 @@ int asoc_graph_parse_dai(struct device_node *ep, return ret; } +parse_dai_end: if (is_single_link) *is_single_link = of_graph_get_endpoint_count(node) == 1; -- cgit From 970dc991b2aaf22cdd497bf66c8fbb13c28c7de4 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 10 Jul 2023 10:20:28 +0900 Subject: ASoC: simple-card.c: enable multi Component support If CPU/Codec driver keeps its DAI node, we can directly identify actual DAI by using snd_soc_get_dai_via_args(). This means we can use multi Component. This patch enables multi Component support for Simple Card Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/878rboo943.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/generic/simple-card.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index a78babf44f38..190f11366e84 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -52,11 +52,13 @@ static int asoc_simple_parse_platform(struct device_node *node, return 0; } -static int asoc_simple_parse_dai(struct device_node *node, +static int asoc_simple_parse_dai(struct device *dev, + struct device_node *node, struct snd_soc_dai_link_component *dlc, int *is_single_link) { struct of_phandle_args args; + struct snd_soc_dai *dai; int ret; if (!node) @@ -70,6 +72,19 @@ static int asoc_simple_parse_dai(struct device_node *node, if (ret) return ret; + /* + * Try to find from DAI args + */ + dai = snd_soc_get_dai_via_args(&args); + if (dai) { + dlc->dai_name = snd_soc_dai_name_get(dai); + dlc->dai_args = snd_soc_copy_dai_args(dev, &args); + if (!dlc->dai_args) + return -ENOMEM; + + goto parse_dai_end; + } + /* * FIXME * @@ -93,6 +108,7 @@ static int asoc_simple_parse_dai(struct device_node *node, if (ret < 0) return ret; +parse_dai_end: if (is_single_link) *is_single_link = !args.args_count; @@ -156,7 +172,7 @@ static int simple_parse_node(struct asoc_simple_priv *priv, simple_parse_mclk_fs(top, np, dai_props, prefix); - ret = asoc_simple_parse_dai(np, dlc, cpu); + ret = asoc_simple_parse_dai(dev, np, dlc, cpu); if (ret) return ret; -- cgit