ASoC: soc-pcm: Use different sequence for start/stop trigger
[linux-2.6-block.git] / sound / soc / soc-pcm.c
index e163dde5eab1d708a98b0767318811fa4f2491d8..e7a04c892817ba669726949260d7164d5b43fa23 100644 (file)
@@ -1047,7 +1047,7 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
        return 0;
 }
 
-static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+static int soc_pcm_trigger_start(struct snd_pcm_substream *substream, int cmd)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_component *component;
@@ -1056,8 +1056,8 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
        struct snd_soc_dai *codec_dai;
        int i, ret;
 
-       for_each_rtd_codec_dai(rtd, i, codec_dai) {
-               ret = snd_soc_dai_trigger(codec_dai, substream, cmd);
+       if (rtd->dai_link->ops->trigger) {
+               ret = rtd->dai_link->ops->trigger(substream, cmd);
                if (ret < 0)
                        return ret;
        }
@@ -1074,6 +1074,42 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
        if (ret < 0)
                return ret;
 
+       for_each_rtd_codec_dai(rtd, i, codec_dai) {
+               ret = snd_soc_dai_trigger(codec_dai, substream, cmd);
+               if (ret < 0)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static int soc_pcm_trigger_stop(struct snd_pcm_substream *substream, int cmd)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_component *component;
+       struct snd_soc_rtdcom_list *rtdcom;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+       struct snd_soc_dai *codec_dai;
+       int i, ret;
+
+       for_each_rtd_codec_dai(rtd, i, codec_dai) {
+               ret = snd_soc_dai_trigger(codec_dai, substream, cmd);
+               if (ret < 0)
+                       return ret;
+       }
+
+       ret = snd_soc_dai_trigger(cpu_dai, substream, cmd);
+       if (ret < 0)
+               return ret;
+
+       for_each_rtdcom(rtd, rtdcom) {
+               component = rtdcom->component;
+
+               ret = snd_soc_component_trigger(component, substream, cmd);
+               if (ret < 0)
+                       return ret;
+       }
+
        if (rtd->dai_link->ops->trigger) {
                ret = rtd->dai_link->ops->trigger(substream, cmd);
                if (ret < 0)
@@ -1083,6 +1119,28 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
        return 0;
 }
 
+static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+       int ret;
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+       case SNDRV_PCM_TRIGGER_RESUME:
+       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+               ret = soc_pcm_trigger_start(substream, cmd);
+               break;
+       case SNDRV_PCM_TRIGGER_STOP:
+       case SNDRV_PCM_TRIGGER_SUSPEND:
+       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+               ret = soc_pcm_trigger_stop(substream, cmd);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return ret;
+}
+
 static int soc_pcm_bespoke_trigger(struct snd_pcm_substream *substream,
                                   int cmd)
 {