summary refs log tree commit diff
path: root/sound/soc/soc-link.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/soc-link.c')
-rw-r--r--sound/soc/soc-link.c21
1 files changed, 20 insertions, 1 deletions
diff --git a/sound/soc/soc-link.c b/sound/soc/soc-link.c
index cec70b19863e..2a8881978930 100644
--- a/sound/soc/soc-link.c
+++ b/sound/soc/soc-link.c
@@ -30,6 +30,14 @@ static inline int _soc_link_ret(struct snd_soc_pcm_runtime *rtd,
 	return ret;
 }
 
+/*
+ * We might want to check substream by using list.
+ * In such case, we can update these macros.
+ */
+#define soc_link_mark_push(rtd, substream, tgt)		((rtd)->mark_##tgt = substream)
+#define soc_link_mark_pop(rtd, substream, tgt)		((rtd)->mark_##tgt = NULL)
+#define soc_link_mark_match(rtd, substream, tgt)	((rtd)->mark_##tgt == substream)
+
 int snd_soc_link_init(struct snd_soc_pcm_runtime *rtd)
 {
 	int ret = 0;
@@ -66,16 +74,27 @@ int snd_soc_link_startup(struct snd_pcm_substream *substream)
 	    rtd->dai_link->ops->startup)
 		ret = rtd->dai_link->ops->startup(substream);
 
+	/* mark substream if succeeded */
+	if (ret == 0)
+		soc_link_mark_push(rtd, substream, startup);
+
 	return soc_link_ret(rtd, ret);
 }
 
-void snd_soc_link_shutdown(struct snd_pcm_substream *substream)
+void snd_soc_link_shutdown(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, startup))
+		return;
+
 	if (rtd->dai_link->ops &&
 	    rtd->dai_link->ops->shutdown)
 		rtd->dai_link->ops->shutdown(substream);
+
+	/* remove marked substream */
+	soc_link_mark_pop(rtd, substream, startup);
 }
 
 int snd_soc_link_prepare(struct snd_pcm_substream *substream)