summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/sound/soc-link.h3
-rw-r--r--include/sound/soc.h1
-rw-r--r--sound/soc/soc-link.c12
-rw-r--r--sound/soc/soc-pcm.c4
4 files changed, 16 insertions, 4 deletions
diff --git a/include/sound/soc-link.h b/include/sound/soc-link.h
index dac6c0ce6ede..eff34fc7d3d3 100644
--- a/include/sound/soc-link.h
+++ b/include/sound/soc-link.h
@@ -19,7 +19,8 @@ void snd_soc_link_shutdown(struct snd_pcm_substream *substream,
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);
-void snd_soc_link_hw_free(struct snd_pcm_substream *substream);
+void snd_soc_link_hw_free(struct snd_pcm_substream *substream,
+ int rollback);
int snd_soc_link_trigger(struct snd_pcm_substream *substream, int cmd);
int snd_soc_link_compr_startup(struct snd_compr_stream *cstream);
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 7541c71c9eb8..fa6ce936f899 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -1161,6 +1161,7 @@ struct snd_soc_pcm_runtime {
/* function mark */
struct snd_pcm_substream *mark_startup;
+ struct snd_pcm_substream *mark_hw_params;
/* bit field */
unsigned int pop_wait:1;
diff --git a/sound/soc/soc-link.c b/sound/soc/soc-link.c
index 2a8881978930..409ae4940da3 100644
--- a/sound/soc/soc-link.c
+++ b/sound/soc/soc-link.c
@@ -119,16 +119,26 @@ 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)
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 697c9cb4a127..8c69288f1bf5 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -886,7 +886,7 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
}
/* free any machine hw params */
- snd_soc_link_hw_free(substream);
+ snd_soc_link_hw_free(substream, 0);
/* free any component resources */
snd_soc_pcm_component_hw_free(substream, NULL);
@@ -1028,7 +1028,7 @@ codec_err:
codec_dai->rate = 0;
}
- snd_soc_link_hw_free(substream);
+ snd_soc_link_hw_free(substream, 1);
mutex_unlock(&rtd->card->pcm_mutex);
return ret;