aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sound/soc-link.h3
-rw-r--r--include/sound/soc.h3
-rw-r--r--sound/soc/soc-link.c21
-rw-r--r--sound/soc/soc-pcm.c4
4 files changed, 27 insertions, 4 deletions
diff --git a/include/sound/soc-link.h b/include/sound/soc-link.h
index 337ac5666757..dac6c0ce6ede 100644
--- a/include/sound/soc-link.h
+++ b/include/sound/soc-link.h
@@ -14,7 +14,8 @@ int snd_soc_link_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params);
int snd_soc_link_startup(struct snd_pcm_substream *substream);
-void snd_soc_link_shutdown(struct snd_pcm_substream *substream);
+void snd_soc_link_shutdown(struct snd_pcm_substream *substream,
+ int rollback);
int snd_soc_link_prepare(struct snd_pcm_substream *substream);
int snd_soc_link_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params);
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 09a7d8409ade..3b038c563ae1 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -1159,6 +1159,9 @@ struct snd_soc_pcm_runtime {
unsigned int num; /* 0-based and monotonic increasing */
struct list_head list; /* rtd list of the soc card */
+ /* function mark */
+ struct snd_pcm_substream *mark_startup;
+
/* bit field */
unsigned int pop_wait:1;
unsigned int fe_compr:1; /* for Dynamic PCM */
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)
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 00ed55e40819..45c19643d8e3 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -684,7 +684,7 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
for_each_rtd_dais(rtd, i, dai)
snd_soc_dai_shutdown(dai, substream, 0);
- snd_soc_link_shutdown(substream);
+ snd_soc_link_shutdown(substream, 0);
soc_pcm_components_close(substream);
@@ -815,7 +815,7 @@ config_err:
for_each_rtd_dais_rollback(rtd, i, dai)
snd_soc_dai_shutdown(dai, substream, 1);
- snd_soc_link_shutdown(substream);
+ snd_soc_link_shutdown(substream, 1);
rtd_startup_err:
soc_pcm_components_close(substream);
component_err: