From feea1b5612da70bef7dc15a8af8797e56a93e129 Mon Sep 17 00:00:00 2001
From: Lars-Peter Clausen <lars@metafoo.de>
Date: Sun, 4 May 2014 13:06:15 +0200
Subject: [PATCH] ASoC: dapm: Handle multiple DAIs in snd_soc_dai_link_event()

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
 sound/soc/soc-dapm.c | 115 ++++++++++++++++++++++++---------------------------
 1 file changed, 54 insertions(+), 61 deletions(-)

diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index b34139a..2fa3f8a 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -3139,35 +3139,60 @@ int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm,
 }
 EXPORT_SYMBOL_GPL(snd_soc_dapm_new_controls);
 
+static void snd_soc_dai_event(struct snd_soc_dapm_widget *w, int event,
+	struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_dai *dai = w->priv;
+	int ret;
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		if (dai->driver->ops && dai->driver->ops->hw_params) {
+			ret = dai->driver->ops->hw_params(substream, params,
+				source);
+			if (ret != 0) {
+				dev_err(dai->dev,
+					"ASoC: hw_params() failed: %d\n", ret);
+				return ret;
+			}
+		}
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		ret = snd_soc_dai_digital_mute(dai, 0, stream);
+		if (ret != 0 && ret != -ENOTSUPP)
+			dev_warn(dai->dev, "ASoC: Failed to unmute: %d\n", ret);
+		ret = 0;
+		break;
+
+	case SND_SOC_DAPM_PRE_PMD:
+		ret = snd_soc_dai_digital_mute(dai, 1, stream);
+		if (ret != 0 && ret != -ENOTSUPP)
+			dev_warn(dai->dev, "ASoC: Failed to mute: %d\n", ret);
+		ret = 0;
+		break;
+
+	default:
+		WARN(1, "Unknown event %d\n", event);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+
 static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w,
 				  struct snd_kcontrol *kcontrol, int event)
 {
-	struct snd_soc_dapm_path *source_p, *sink_p;
-	struct snd_soc_dai *source, *sink;
 	const struct snd_soc_pcm_stream *config = w->params;
 	struct snd_pcm_substream substream;
 	struct snd_pcm_hw_params *params = NULL;
+	struct snd_soc_dapm_path *p;
 	u64 fmt;
 	int ret;
 
-	if (WARN_ON(!config) ||
-	    WARN_ON(list_empty(&w->sources) || list_empty(&w->sinks)))
+	if (WARN_ON(!config))
 		return -EINVAL;
 
-	/* We only support a single source and sink, pick the first */
-	source_p = list_first_entry(&w->sources, struct snd_soc_dapm_path,
-				    list_sink);
-	sink_p = list_first_entry(&w->sinks, struct snd_soc_dapm_path,
-				  list_source);
-
-	if (WARN_ON(!source_p || !sink_p) ||
-	    WARN_ON(!sink_p->source || !source_p->sink) ||
-	    WARN_ON(!source_p->source || !sink_p->sink))
-		return -EINVAL;
-
-	source = source_p->source->priv;
-	sink = sink_p->sink->priv;
-
 	/* Be a little careful as we don't want to overflow the mask array */
 	if (config->formats) {
 		fmt = ffs(config->formats) - 1;
@@ -3197,50 +3222,18 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w,
 
 	memset(&substream, 0, sizeof(substream));
 
-	switch (event) {
-	case SND_SOC_DAPM_PRE_PMU:
-		if (source->driver->ops && source->driver->ops->hw_params) {
-			substream.stream = SNDRV_PCM_STREAM_CAPTURE;
-			ret = source->driver->ops->hw_params(&substream,
-							     params, source);
-			if (ret != 0) {
-				dev_err(source->dev,
-					"ASoC: hw_params() failed: %d\n", ret);
-				goto out;
-			}
-		}
-
-		if (sink->driver->ops && sink->driver->ops->hw_params) {
-			substream.stream = SNDRV_PCM_STREAM_PLAYBACK;
-			ret = sink->driver->ops->hw_params(&substream, params,
-							   sink);
-			if (ret != 0) {
-				dev_err(sink->dev,
-					"ASoC: hw_params() failed: %d\n", ret);
-				goto out;
-			}
-		}
-		break;
-
-	case SND_SOC_DAPM_POST_PMU:
-		ret = snd_soc_dai_digital_mute(sink, 0,
-					       SNDRV_PCM_STREAM_PLAYBACK);
-		if (ret != 0 && ret != -ENOTSUPP)
-			dev_warn(sink->dev, "ASoC: Failed to unmute: %d\n", ret);
-		ret = 0;
-		break;
-
-	case SND_SOC_DAPM_PRE_PMD:
-		ret = snd_soc_dai_digital_mute(sink, 1,
-					       SNDRV_PCM_STREAM_PLAYBACK);
-		if (ret != 0 && ret != -ENOTSUPP)
-			dev_warn(sink->dev, "ASoC: Failed to mute: %d\n", ret);
-		ret = 0;
-		break;
+	substream.stream = SNDRV_PCM_STREAM_CAPTURE;
+	list_for_each_entry(p, &w->sources, list_sink) {
+		ret = snd_soc_dai_event(p->source, event, params, &substream);
+		if (ret)
+			goto out;
+	}
 
-	default:
-		WARN(1, "Unknown event %d\n", event);
-		return -EINVAL;
+	substream.stream = SNDRV_PCM_STREAM_PLAYBACK;
+	list_for_each_entry(p, &w->sinks, list_source) {
+		ret = snd_soc_dai_event(p->sink, event, params, &substream);
+		if (ret)
+			goto out;
 	}
 
 out:
-- 
1.8.0

