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(-)
@@ -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