aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/sound/simple_card_utils.h5
-rw-r--r--include/sound/soc-dai.h3
-rw-r--r--include/sound/soc.h6
-rw-r--r--sound/soc/generic/audio-graph-card.c2
-rw-r--r--sound/soc/generic/audio-graph-card2.c2
-rw-r--r--sound/soc/generic/simple-card-utils.c23
-rw-r--r--sound/soc/generic/simple-card.c20
-rw-r--r--sound/soc/soc-core.c133
8 files changed, 166 insertions, 28 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/include/sound/soc-dai.h b/include/sound/soc-dai.h
index e3906ecda740..a33d803fe548 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.
@@ -397,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..fa2337a3cf4c 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 {
@@ -1335,6 +1336,11 @@ 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 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,
bool legacy_dai_naming);
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 3019626b0592..5b18a4af022f 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);
@@ -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;
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)
@@ -71,6 +73,19 @@ static int asoc_simple_parse_dai(struct device_node *node,
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
*
* Here, dlc->dai_name is pointer to CPU/Codec DAI name.
@@ -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;
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 94e856d67a46..a5b96c17633a 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,8 +266,52 @@ 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,
+ struct snd_soc_dai *dai)
+{
+ 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;
+
+ /* 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)
@@ -749,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)
@@ -758,6 +831,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)
@@ -810,18 +892,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;
}
@@ -2943,6 +3018,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,
@@ -3316,9 +3399,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
@@ -3386,6 +3467,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) {