@@ -381,8 +381,7 @@ int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card);
void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card);
int snd_soc_dapm_new_pcm(struct snd_soc_card *card,
const struct snd_soc_pcm_stream *params,
- struct snd_soc_dapm_widget *source,
- struct snd_soc_dapm_widget *sink);
+ struct snd_soc_pcm_runtime *rtd);
/* dapm path setup */
int snd_soc_dapm_new_widgets(struct snd_soc_card *card);
@@ -1483,37 +1483,8 @@ static int soc_link_dai_widgets(struct snd_soc_card *card,
struct snd_soc_dai_link *dai_link,
struct snd_soc_pcm_runtime *rtd)
{
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
- struct snd_soc_dai *codec_dai = rtd->codec_dai;
- struct snd_soc_dapm_widget *play_w, *capture_w;
- int ret;
-
/* link the DAI widgets */
- play_w = codec_dai->playback_widget;
- capture_w = cpu_dai->capture_widget;
- if (play_w && capture_w) {
- ret = snd_soc_dapm_new_pcm(card, dai_link->params,
- capture_w, play_w);
- if (ret != 0) {
- dev_err(card->dev, "ASoC: Can't link %s to %s: %d\n",
- play_w->name, capture_w->name, ret);
- return ret;
- }
- }
-
- play_w = cpu_dai->playback_widget;
- capture_w = codec_dai->capture_widget;
- if (play_w && capture_w) {
- ret = snd_soc_dapm_new_pcm(card, dai_link->params,
- capture_w, play_w);
- if (ret != 0) {
- dev_err(card->dev, "ASoC: Can't link %s to %s: %d\n",
- play_w->name, capture_w->name, ret);
- return ret;
- }
- }
-
- return 0;
+ return snd_soc_dapm_new_pcm(card, dai_link->params,rtd);
}
static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order)
@@ -22,7 +22,7 @@
* device reopen.
*
*/
-
+#define DEBUG
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
@@ -3248,22 +3248,12 @@ out:
return ret;
}
-int snd_soc_dapm_new_pcm(struct snd_soc_card *card,
+int snd_soc_dapm_new_link(struct snd_soc_card *card,
const struct snd_soc_pcm_stream *params,
- struct snd_soc_dapm_widget *source,
- struct snd_soc_dapm_widget *sink)
+ char *link_name)
{
- struct snd_soc_dapm_route routes[2];
struct snd_soc_dapm_widget template;
struct snd_soc_dapm_widget *w;
- size_t len;
- char *link_name;
-
- len = strlen(source->name) + strlen(sink->name) + 2;
- link_name = devm_kzalloc(card->dev, len, GFP_KERNEL);
- if (!link_name)
- return -ENOMEM;
- snprintf(link_name, len, "%s-%s", source->name, sink->name);
memset(&template, 0, sizeof(template));
template.reg = SND_SOC_NOPM;
@@ -3271,7 +3261,7 @@ int snd_soc_dapm_new_pcm(struct snd_soc_card *card,
template.name = link_name;
template.event = snd_soc_dai_link_event;
template.event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
- SND_SOC_DAPM_PRE_PMD;
+ SND_SOC_DAPM_PRE_PMD;
dev_dbg(card->dev, "ASoC: adding %s widget\n", link_name);
@@ -3284,15 +3274,115 @@ int snd_soc_dapm_new_pcm(struct snd_soc_card *card,
w->params = params;
- memset(&routes, 0, sizeof(routes));
+ return 0;
+}
+
+int snd_soc_dapm_new_pcm(struct snd_soc_card *card,
+ const struct snd_soc_pcm_stream *params,
+ struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_soc_dapm_route route;
+ struct snd_soc_dapm_widget *source, *sink;
+ size_t len;
+ char *link_name;
+ const char *codecs_link_name = "multiple";
+ unsigned int num_widgets = 0;
+ int i;
+
+ /* cpu_dai->capture_widget -> codec_dai->playback_widget */
+ for (i = 0; i < rtd->num_codecs; i++)
+ if (rtd->codec_dais[i]->playback_widget)
+ num_widgets++;
+
+ if (!rtd->cpu_dai->capture_widget || !num_widgets)
+ return 0;
+
+
+ source = rtd->cpu_dai->capture_widget;
+
+ if (num_widgets > 1) {
+ len = strlen(source->name) + strlen(codecs_link_name) + 2;
+ } else {
+ sink = rtd->codec_dais[0]->playback_widget;
+ len = strlen(source->name) + strlen(sink->name) + 2;
+ }
+
+ link_name = devm_kzalloc(card->dev, len, GFP_KERNEL);
+ if (!link_name)
+ return -ENOMEM;
+
+ if (num_widgets > 1)
+ snprintf(link_name, len, "%s-%s", source->name, codecs_link_name);
+ else
+ snprintf(link_name, len, "%s-%s", source->name, sink->name);
+
+ pr_info("%s(), link_name #1 %s", __func__,link_name);
+ snd_soc_dapm_new_link(card, params, link_name);
- routes[0].source = source->name;
- routes[0].sink = link_name;
- routes[1].source = link_name;
- routes[1].sink = sink->name;
- return snd_soc_dapm_add_routes(&card->dapm, routes,
- ARRAY_SIZE(routes));
+ memset(&route, 0, sizeof(route));
+ route.source = source->name;
+ route.sink = link_name;
+ snd_soc_dapm_add_route(&card->dapm, &route, false);
+
+ route.source = link_name;
+ for (i = 0; i < rtd->num_codecs; i++) {
+ if (!rtd->codec_dais[i]->playback_widget)
+ continue;
+
+ route.sink = rtd->codec_dais[i]->playback_widget->name;
+ snd_soc_dapm_add_route(&card->dapm, &route, false);
+ }
+
+
+ num_widgets = 0;
+
+ /* codec_dai->capture_widget -> cpu_dai->playback_widget */
+ for (i = 0; i < rtd->num_codecs; i++)
+ if (rtd->codec_dais[i]->capture_widget)
+ num_widgets++;
+
+ if (!rtd->cpu_dai->playback_widget || !num_widgets)
+ return 0;
+
+
+ sink = rtd->cpu_dai->playback_widget;
+
+ if (num_widgets > 1) {
+ len = strlen(sink->name) + strlen(codecs_link_name) + 2;
+ } else {
+ source = rtd->codec_dais[0]->playback_widget;
+ len = strlen(source->name) + strlen(sink->name) + 2;
+ }
+
+ link_name = devm_kzalloc(card->dev, len, GFP_KERNEL);
+ if (!link_name)
+ return -ENOMEM;
+
+ if (num_widgets > 1)
+ snprintf(link_name, len, "%s-%s", codecs_link_name, sink->name);
+ else
+ snprintf(link_name, len, "%s-%s", source->name, sink->name);
+
+ pr_info("%s(), link_name #2 %s", __func__,link_name);
+ snd_soc_dapm_new_link(card, params, link_name);
+
+
+ memset(&route, 0, sizeof(route));
+ route.sink = link_name;
+ for (i = 0; i < rtd->num_codecs; i++) {
+ if (!rtd->codec_dais[i]->capture_widget)
+ continue;
+
+ route.source = rtd->codec_dais[i]->capture_widget->name;
+ snd_soc_dapm_add_route(&card->dapm, &route, false);
+ }
+
+ route.source = link_name;
+ route.sink = sink->name;
+ snd_soc_dapm_add_route(&card->dapm, &route, false);
+
+ return 0;
}
int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm,