summaryrefslogtreecommitdiffstats
path: root/sound/soc/generic
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/generic')
-rw-r--r--sound/soc/generic/audio-graph-card.c143
-rw-r--r--sound/soc/generic/audio-graph-card2-custom-sample.dtsi7
-rw-r--r--sound/soc/generic/audio-graph-card2.c14
-rw-r--r--sound/soc/generic/simple-card-utils.c23
-rw-r--r--sound/soc/generic/simple-card.c66
5 files changed, 171 insertions, 82 deletions
diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c
index c6e0f9132193..844a2ef15948 100644
--- a/sound/soc/generic/audio-graph-card.c
+++ b/sound/soc/generic/audio-graph-card.c
@@ -60,7 +60,7 @@ static bool soc_component_is_pcm(struct snd_soc_dai_link_component *dlc)
struct snd_soc_dai *dai = snd_soc_find_dai_with_mutex(dlc);
if (dai && (dai->component->driver->pcm_construct ||
- dai->driver->pcm_new))
+ (dai->driver->ops && dai->driver->ops->pcm_new)))
return true;
return false;
@@ -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;
@@ -425,77 +425,6 @@ static int graph_for_each_link(struct asoc_simple_priv *priv,
return ret;
}
-static int graph_get_dais_count(struct asoc_simple_priv *priv,
- struct link_info *li);
-
-int audio_graph_parse_of(struct asoc_simple_priv *priv, struct device *dev)
-{
- struct snd_soc_card *card = simple_priv_to_card(priv);
- struct link_info *li;
- int ret;
-
- li = devm_kzalloc(dev, sizeof(*li), GFP_KERNEL);
- if (!li)
- return -ENOMEM;
-
- card->owner = THIS_MODULE;
- card->dev = dev;
-
- ret = graph_get_dais_count(priv, li);
- if (ret < 0)
- return ret;
-
- if (!li->link)
- return -EINVAL;
-
- ret = asoc_simple_init_priv(priv, li);
- if (ret < 0)
- return ret;
-
- priv->pa_gpio = devm_gpiod_get_optional(dev, "pa", GPIOD_OUT_LOW);
- if (IS_ERR(priv->pa_gpio)) {
- ret = PTR_ERR(priv->pa_gpio);
- dev_err(dev, "failed to get amplifier gpio: %d\n", ret);
- return ret;
- }
-
- ret = asoc_simple_parse_widgets(card, NULL);
- if (ret < 0)
- return ret;
-
- ret = asoc_simple_parse_routing(card, NULL);
- if (ret < 0)
- return ret;
-
- memset(li, 0, sizeof(*li));
- ret = graph_for_each_link(priv, li,
- graph_dai_link_of,
- graph_dai_link_of_dpcm);
- if (ret < 0)
- goto err;
-
- ret = asoc_simple_parse_card_name(card, NULL);
- if (ret < 0)
- goto err;
-
- snd_soc_card_set_drvdata(card, priv);
-
- asoc_simple_debug_info(priv);
-
- ret = devm_snd_soc_register_card(dev, card);
- if (ret < 0)
- goto err;
-
- devm_kfree(dev, li);
- return 0;
-
-err:
- asoc_simple_clean_reference(card);
-
- return dev_err_probe(dev, ret, "parse error\n");
-}
-EXPORT_SYMBOL_GPL(audio_graph_parse_of);
-
static int graph_count_noml(struct asoc_simple_priv *priv,
struct device_node *cpu_ep,
struct device_node *codec_ep,
@@ -612,6 +541,74 @@ static int graph_get_dais_count(struct asoc_simple_priv *priv,
graph_count_dpcm);
}
+int audio_graph_parse_of(struct asoc_simple_priv *priv, struct device *dev)
+{
+ struct snd_soc_card *card = simple_priv_to_card(priv);
+ struct link_info *li;
+ int ret;
+
+ li = devm_kzalloc(dev, sizeof(*li), GFP_KERNEL);
+ if (!li)
+ return -ENOMEM;
+
+ card->owner = THIS_MODULE;
+ card->dev = dev;
+
+ ret = graph_get_dais_count(priv, li);
+ if (ret < 0)
+ return ret;
+
+ if (!li->link)
+ return -EINVAL;
+
+ ret = asoc_simple_init_priv(priv, li);
+ if (ret < 0)
+ return ret;
+
+ priv->pa_gpio = devm_gpiod_get_optional(dev, "pa", GPIOD_OUT_LOW);
+ if (IS_ERR(priv->pa_gpio)) {
+ ret = PTR_ERR(priv->pa_gpio);
+ dev_err(dev, "failed to get amplifier gpio: %d\n", ret);
+ return ret;
+ }
+
+ ret = asoc_simple_parse_widgets(card, NULL);
+ if (ret < 0)
+ return ret;
+
+ ret = asoc_simple_parse_routing(card, NULL);
+ if (ret < 0)
+ return ret;
+
+ memset(li, 0, sizeof(*li));
+ ret = graph_for_each_link(priv, li,
+ graph_dai_link_of,
+ graph_dai_link_of_dpcm);
+ if (ret < 0)
+ goto err;
+
+ ret = asoc_simple_parse_card_name(card, NULL);
+ if (ret < 0)
+ goto err;
+
+ snd_soc_card_set_drvdata(card, priv);
+
+ asoc_simple_debug_info(priv);
+
+ ret = devm_snd_soc_register_card(dev, card);
+ if (ret < 0)
+ goto err;
+
+ devm_kfree(dev, li);
+ return 0;
+
+err:
+ asoc_simple_clean_reference(card);
+
+ return dev_err_probe(dev, ret, "parse error\n");
+}
+EXPORT_SYMBOL_GPL(audio_graph_parse_of);
+
static int graph_probe(struct platform_device *pdev)
{
struct asoc_simple_priv *priv;
diff --git a/sound/soc/generic/audio-graph-card2-custom-sample.dtsi b/sound/soc/generic/audio-graph-card2-custom-sample.dtsi
index 2ac0de3c21da..8acaa2ddb335 100644
--- a/sound/soc/generic/audio-graph-card2-custom-sample.dtsi
+++ b/sound/soc/generic/audio-graph-card2-custom-sample.dtsi
@@ -34,6 +34,13 @@
* ...
* };
*
+ *
+ * Below sample doesn't use "format" property,
+ * because test-component driver (test-cpu/test-codec) is supporting
+ * snd_soc_dai_ops :: .auto_selectable_formats.
+ * see
+ * snd_soc_runtime_get_dai_fmt()
+ * linux/sound/soc/generic/test-component.c :: test_dai_formats
*/
/ {
/*
diff --git a/sound/soc/generic/audio-graph-card2.c b/sound/soc/generic/audio-graph-card2.c
index 542c4a114940..b1c675c6b6db 100644
--- a/sound/soc/generic/audio-graph-card2.c
+++ b/sound/soc/generic/audio-graph-card2.c
@@ -47,6 +47,18 @@
see
graph_parse_daifmt().
+ "format" property is no longer needed on DT if both CPU/Codec drivers are
+ supporting snd_soc_dai_ops :: .auto_selectable_formats.
+ see
+ snd_soc_runtime_get_dai_fmt()
+
+ sample driver
+ linux/sound/soc/sh/rcar/core.c
+ linux/sound/soc/codecs/ak4613.c
+ linux/sound/soc/codecs/pcm3168a.c
+ linux/sound/soc/soc-utils.c
+ linux/sound/soc/generic/test-component.c
+
************************************
Normal Audio-Graph
************************************
@@ -407,7 +419,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 0745bf6a09aa..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;
@@ -346,6 +362,7 @@ static int __simple_for_each_link(struct asoc_simple_priv *priv,
struct device *dev = simple_priv_to_dev(priv);
struct device_node *top = dev->of_node;
struct device_node *node;
+ struct device_node *add_devs;
uintptr_t dpcm_selectable = (uintptr_t)of_device_get_match_data(dev);
bool is_top = 0;
int ret = 0;
@@ -357,6 +374,8 @@ static int __simple_for_each_link(struct asoc_simple_priv *priv,
is_top = 1;
}
+ add_devs = of_get_child_by_name(top, PREFIX "additional-devs");
+
/* loop for all dai-link */
do {
struct asoc_simple_data adata;
@@ -365,6 +384,12 @@ static int __simple_for_each_link(struct asoc_simple_priv *priv,
struct device_node *np;
int num = of_get_child_count(node);
+ /* Skip additional-devs node */
+ if (node == add_devs) {
+ node = of_get_next_child(top, node);
+ continue;
+ }
+
/* get codec */
codec = of_get_child_by_name(node, is_top ?
PREFIX "codec" : "codec");
@@ -378,12 +403,15 @@ static int __simple_for_each_link(struct asoc_simple_priv *priv,
/* get convert-xxx property */
memset(&adata, 0, sizeof(adata));
- for_each_child_of_node(node, np)
+ for_each_child_of_node(node, np) {
+ if (np == add_devs)
+ continue;
simple_parse_convert(dev, np, &adata);
+ }
/* loop for all CPU/Codec node */
for_each_child_of_node(node, np) {
- if (plat == np)
+ if (plat == np || add_devs == np)
continue;
/*
* It is DPCM
@@ -426,6 +454,7 @@ static int __simple_for_each_link(struct asoc_simple_priv *priv,
} while (!is_top && node);
error:
+ of_node_put(add_devs);
of_node_put(node);
return ret;
}
@@ -463,6 +492,31 @@ static int simple_for_each_link(struct asoc_simple_priv *priv,
return ret;
}
+static void simple_depopulate_aux(void *data)
+{
+ struct asoc_simple_priv *priv = data;
+
+ of_platform_depopulate(simple_priv_to_dev(priv));
+}
+
+static int simple_populate_aux(struct asoc_simple_priv *priv)
+{
+ struct device *dev = simple_priv_to_dev(priv);
+ struct device_node *node;
+ int ret;
+
+ node = of_get_child_by_name(dev->of_node, PREFIX "additional-devs");
+ if (!node)
+ return 0;
+
+ ret = of_platform_populate(node, NULL, NULL, dev);
+ of_node_put(node);
+ if (ret)
+ return ret;
+
+ return devm_add_action_or_reset(dev, simple_depopulate_aux, priv);
+}
+
static int simple_parse_of(struct asoc_simple_priv *priv, struct link_info *li)
{
struct snd_soc_card *card = simple_priv_to_card(priv);
@@ -492,6 +546,10 @@ static int simple_parse_of(struct asoc_simple_priv *priv, struct link_info *li)
if (ret < 0)
return ret;
+ ret = simple_populate_aux(priv);
+ if (ret < 0)
+ return ret;
+
ret = snd_soc_of_parse_aux_devs(card, PREFIX "aux-devs");
return ret;