summaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/soc-component.c35
-rw-r--r--sound/soc/soc-pcm.c28
2 files changed, 40 insertions, 23 deletions
diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c
index 5504b92946e3..147b46e29ff4 100644
--- a/sound/soc/soc-component.c
+++ b/sound/soc/soc-component.c
@@ -33,6 +33,14 @@ static inline int _soc_component_ret(struct snd_soc_component *component,
return ret;
}
+/*
+ * We might want to check substream by using list.
+ * In such case, we can update these macros.
+ */
+#define soc_component_mark_push(component, substream, tgt) ((component)->mark_##tgt = substream)
+#define soc_component_mark_pop(component, substream, tgt) ((component)->mark_##tgt = NULL)
+#define soc_component_mark_match(component, substream, tgt) ((component)->mark_##tgt == substream)
+
void snd_soc_component_set_aux(struct snd_soc_component *component,
struct snd_soc_aux_dev *aux)
{
@@ -238,6 +246,7 @@ int snd_soc_component_set_jack(struct snd_soc_component *component,
EXPORT_SYMBOL_GPL(snd_soc_component_set_jack);
int snd_soc_component_module_get(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream,
int upon_open)
{
int ret = 0;
@@ -246,14 +255,25 @@ int snd_soc_component_module_get(struct snd_soc_component *component,
!try_module_get(component->dev->driver->owner))
ret = -ENODEV;
+ /* mark substream if succeeded */
+ if (ret == 0)
+ soc_component_mark_push(component, substream, module);
+
return soc_component_ret(component, ret);
}
void snd_soc_component_module_put(struct snd_soc_component *component,
- int upon_open)
+ struct snd_pcm_substream *substream,
+ int upon_open, int rollback)
{
+ if (rollback && !soc_component_mark_match(component, substream, module))
+ return;
+
if (component->driver->module_get_upon_open == !!upon_open)
module_put(component->dev->driver->owner);
+
+ /* remove marked substream */
+ soc_component_mark_pop(component, substream, module);
}
int snd_soc_component_open(struct snd_soc_component *component,
@@ -264,17 +284,28 @@ int snd_soc_component_open(struct snd_soc_component *component,
if (component->driver->open)
ret = component->driver->open(component, substream);
+ /* mark substream if succeeded */
+ if (ret == 0)
+ soc_component_mark_push(component, substream, open);
+
return soc_component_ret(component, ret);
}
int snd_soc_component_close(struct snd_soc_component *component,
- struct snd_pcm_substream *substream)
+ struct snd_pcm_substream *substream,
+ int rollback)
{
int ret = 0;
+ if (rollback && !soc_component_mark_match(component, substream, open))
+ return 0;
+
if (component->driver->close)
ret = component->driver->close(component, substream);
+ /* remove marked substream */
+ soc_component_mark_pop(component, substream, open);
+
return soc_component_ret(component, ret);
}
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 45c19643d8e3..d9f9c0a243df 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -609,14 +609,11 @@ static void soc_pcm_init_runtime_hw(struct snd_pcm_substream *substream)
static int soc_pcm_components_open(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
- struct snd_soc_component *last = NULL;
struct snd_soc_component *component;
int i, ret = 0;
for_each_rtd_components(rtd, i, component) {
- last = component;
-
- ret = snd_soc_component_module_get_when_open(component);
+ ret = snd_soc_component_module_get_when_open(component, substream);
if (ret < 0) {
dev_err(component->dev,
"ASoC: can't get module %s\n",
@@ -626,7 +623,6 @@ static int soc_pcm_components_open(struct snd_pcm_substream *substream)
ret = snd_soc_component_open(component, substream);
if (ret < 0) {
- snd_soc_component_module_put_when_close(component);
dev_err(component->dev,
"ASoC: can't open component %s: %d\n",
component->name, ret);
@@ -634,32 +630,22 @@ static int soc_pcm_components_open(struct snd_pcm_substream *substream)
}
}
- if (ret < 0) {
- /* rollback on error */
- for_each_rtd_components(rtd, i, component) {
- if (component == last)
- break;
-
- snd_soc_component_close(component, substream);
- snd_soc_component_module_put_when_close(component);
- }
- }
-
return ret;
}
-static int soc_pcm_components_close(struct snd_pcm_substream *substream)
+static int soc_pcm_components_close(struct snd_pcm_substream *substream,
+ int rollback)
{
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_soc_component *component;
int i, r, ret = 0;
for_each_rtd_components(rtd, i, component) {
- r = snd_soc_component_close(component, substream);
+ r = snd_soc_component_close(component, substream, rollback);
if (r < 0)
ret = r; /* use last ret */
- snd_soc_component_module_put_when_close(component);
+ snd_soc_component_module_put_when_close(component, substream, rollback);
}
return ret;
@@ -686,7 +672,7 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
snd_soc_link_shutdown(substream, 0);
- soc_pcm_components_close(substream);
+ soc_pcm_components_close(substream, 0);
snd_soc_dapm_stream_stop(rtd, substream->stream);
@@ -817,7 +803,7 @@ config_err:
snd_soc_link_shutdown(substream, 1);
rtd_startup_err:
- soc_pcm_components_close(substream);
+ soc_pcm_components_close(substream, 1);
component_err:
mutex_unlock(&rtd->card->pcm_mutex);