Merge tag 'kgdb-5.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/danielt...
[linux-2.6-microblaze.git] / sound / soc / soc-link.c
index 2a88819..619664c 100644 (file)
@@ -119,19 +119,29 @@ int snd_soc_link_hw_params(struct snd_pcm_substream *substream,
            rtd->dai_link->ops->hw_params)
                ret = rtd->dai_link->ops->hw_params(substream, params);
 
+       /* mark substream if succeeded */
+       if (ret == 0)
+               soc_link_mark_push(rtd, substream, hw_params);
+
        return soc_link_ret(rtd, ret);
 }
 
-void snd_soc_link_hw_free(struct snd_pcm_substream *substream)
+void snd_soc_link_hw_free(struct snd_pcm_substream *substream, int rollback)
 {
        struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
 
+       if (rollback && !soc_link_mark_match(rtd, substream, hw_params))
+               return;
+
        if (rtd->dai_link->ops &&
            rtd->dai_link->ops->hw_free)
                rtd->dai_link->ops->hw_free(substream);
+
+       /* remove marked substream */
+       soc_link_mark_pop(rtd, substream, hw_params);
 }
 
-int snd_soc_link_trigger(struct snd_pcm_substream *substream, int cmd)
+static int soc_link_trigger(struct snd_pcm_substream *substream, int cmd)
 {
        struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
        int ret = 0;
@@ -143,6 +153,34 @@ int snd_soc_link_trigger(struct snd_pcm_substream *substream, int cmd)
        return soc_link_ret(rtd, ret);
 }
 
+int snd_soc_link_trigger(struct snd_pcm_substream *substream, int cmd,
+                        int rollback)
+{
+       struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
+       int ret = 0;
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+       case SNDRV_PCM_TRIGGER_RESUME:
+       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+               ret = soc_link_trigger(substream, cmd);
+               if (ret < 0)
+                       break;
+               soc_link_mark_push(rtd, substream, trigger);
+               break;
+       case SNDRV_PCM_TRIGGER_STOP:
+       case SNDRV_PCM_TRIGGER_SUSPEND:
+       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+               if (rollback && !soc_link_mark_match(rtd, substream, trigger))
+                       break;
+
+               ret = soc_link_trigger(substream, cmd);
+               soc_link_mark_pop(rtd, substream, startup);
+       }
+
+       return ret;
+}
+
 int snd_soc_link_compr_startup(struct snd_compr_stream *cstream)
 {
        struct snd_soc_pcm_runtime *rtd = cstream->private_data;
@@ -152,17 +190,26 @@ int snd_soc_link_compr_startup(struct snd_compr_stream *cstream)
            rtd->dai_link->compr_ops->startup)
                ret = rtd->dai_link->compr_ops->startup(cstream);
 
+       if (ret == 0)
+               soc_link_mark_push(rtd, cstream, compr_startup);
+
        return soc_link_ret(rtd, ret);
 }
 EXPORT_SYMBOL_GPL(snd_soc_link_compr_startup);
 
-void snd_soc_link_compr_shutdown(struct snd_compr_stream *cstream)
+void snd_soc_link_compr_shutdown(struct snd_compr_stream *cstream,
+                                int rollback)
 {
        struct snd_soc_pcm_runtime *rtd = cstream->private_data;
 
+       if (rollback && !soc_link_mark_match(rtd, cstream, compr_startup))
+               return;
+
        if (rtd->dai_link->compr_ops &&
            rtd->dai_link->compr_ops->shutdown)
                rtd->dai_link->compr_ops->shutdown(cstream);
+
+       soc_link_mark_pop(rtd, cstream, compr_startup);
 }
 EXPORT_SYMBOL_GPL(snd_soc_link_compr_shutdown);