OSDN Git Service

ASoC: pcm: update FE/BE trigger order based on the command
[sagit-ice-cold/kernel_xiaomi_msm8998.git] / sound / soc / soc-pcm.c
index dbdea19..81bedd9 100644 (file)
@@ -2026,42 +2026,81 @@ int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream,
 }
 EXPORT_SYMBOL_GPL(dpcm_be_dai_trigger);
 
+static int dpcm_dai_trigger_fe_be(struct snd_pcm_substream *substream,
+                                 int cmd, bool fe_first)
+{
+       struct snd_soc_pcm_runtime *fe = substream->private_data;
+       int ret;
+
+       /* call trigger on the frontend before the backend. */
+       if (fe_first) {
+               dev_dbg(fe->dev, "ASoC: pre trigger FE %s cmd %d\n",
+                       fe->dai_link->name, cmd);
+
+               ret = soc_pcm_trigger(substream, cmd);
+               if (ret < 0)
+                       return ret;
+
+               ret = dpcm_be_dai_trigger(fe, substream->stream, cmd);
+               return ret;
+       }
+
+       /* call trigger on the frontend after the backend. */
+       ret = dpcm_be_dai_trigger(fe, substream->stream, cmd);
+       if (ret < 0)
+               return ret;
+
+       dev_dbg(fe->dev, "ASoC: post trigger FE %s cmd %d\n",
+               fe->dai_link->name, cmd);
+
+       ret = soc_pcm_trigger(substream, cmd);
+
+       return ret;
+}
+
 static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd)
 {
        struct snd_soc_pcm_runtime *fe = substream->private_data;
-       int stream = substream->stream, ret;
+       int stream = substream->stream;
+       int ret = 0;
        enum snd_soc_dpcm_trigger trigger = fe->dai_link->trigger[stream];
 
        fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
 
        switch (trigger) {
        case SND_SOC_DPCM_TRIGGER_PRE:
-               /* call trigger on the frontend before the backend. */
-
-               dev_dbg(fe->dev, "ASoC: pre trigger FE %s cmd %d\n",
-                               fe->dai_link->name, cmd);
-
-               ret = soc_pcm_trigger(substream, cmd);
-               if (ret < 0) {
-                       dev_err(fe->dev,"ASoC: trigger FE failed %d\n", ret);
-                       goto out;
+               switch (cmd) {
+               case SNDRV_PCM_TRIGGER_START:
+               case SNDRV_PCM_TRIGGER_RESUME:
+               case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+                       ret = dpcm_dai_trigger_fe_be(substream, cmd, true);
+                       break;
+               case SNDRV_PCM_TRIGGER_STOP:
+               case SNDRV_PCM_TRIGGER_SUSPEND:
+               case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+                       ret = dpcm_dai_trigger_fe_be(substream, cmd, false);
+                       break;
+               default:
+                       ret = -EINVAL;
+                       break;
                }
-
-               ret = dpcm_be_dai_trigger(fe, substream->stream, cmd);
                break;
        case SND_SOC_DPCM_TRIGGER_POST:
-               /* call trigger on the frontend after the backend. */
-
-               ret = dpcm_be_dai_trigger(fe, substream->stream, cmd);
-               if (ret < 0) {
-                       dev_err(fe->dev,"ASoC: trigger FE failed %d\n", ret);
-                       goto out;
+               switch (cmd) {
+               case SNDRV_PCM_TRIGGER_START:
+               case SNDRV_PCM_TRIGGER_RESUME:
+               case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+                       ret = dpcm_dai_trigger_fe_be(substream, cmd, false);
+                       break;
+               case SNDRV_PCM_TRIGGER_STOP:
+               case SNDRV_PCM_TRIGGER_SUSPEND:
+               case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+                       ret = dpcm_dai_trigger_fe_be(substream, cmd, true);
+                       break;
+               default:
+                       ret = -EINVAL;
+                       break;
                }
-
-               dev_dbg(fe->dev, "ASoC: post trigger FE %s cmd %d\n",
-                               fe->dai_link->name, cmd);
-
-               ret = soc_pcm_trigger(substream, cmd);
                break;
        case SND_SOC_DPCM_TRIGGER_BESPOKE:
                /* bespoke trigger() - handles both FE and BEs */
@@ -2070,10 +2109,6 @@ static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd)
                                fe->dai_link->name, cmd);
 
                ret = soc_pcm_bespoke_trigger(substream, cmd);
-               if (ret < 0) {
-                       dev_err(fe->dev,"ASoC: trigger FE failed %d\n", ret);
-                       goto out;
-               }
                break;
        default:
                dev_err(fe->dev, "ASoC: invalid trigger cmd %d for %s\n", cmd,
@@ -2082,6 +2117,12 @@ static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd)
                goto out;
        }
 
+       if (ret < 0) {
+               dev_err(fe->dev, "ASoC: trigger FE cmd: %d failed: %d\n",
+                       cmd, ret);
+               goto out;
+       }
+
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
        case SNDRV_PCM_TRIGGER_RESUME: