Commit 140a4532 authored by Kuninori Morimoto's avatar Kuninori Morimoto Committed by Mark Brown

ASoC: soc-pcm: add soc_pcm_clean() and call it from soc_pcm_open/close()

soc_pcm_open() does rollback when failed (A),
but, it is almost same as soc_pcm_close().

	static int soc_pcm_open(xxx)
	{
		...
		if (ret < 0)
			goto xxx_err;
		...
		return 0;

 ^	config_err:
 |		...
 |	rtd_startup_err:
(A)		...
 |	component_err:
 |		...
 v		return ret;
	}

The difference is
soc_pcm_close() is for all dai/component/substream,
rollback        is for succeeded part only.

This kind of duplicated code can be a hotbed of bugs,
thus, we want to share soc_pcm_close() and rollback.

Now, soc_pcm_open/close() are handling
	1) snd_soc_dai_startup/shutdown()
	2) snd_soc_link_startup/shutdown()
	3) snd_soc_component_module_get/put()
	4) snd_soc_component_open/close()
	5) pm_runtime_put/get()

Now, 1) to 5) are handled.
This patch adds new soc_pcm_clean() and call it from
soc_pcm_open() as rollback, and from soc_pcm_close() as
normal close handler.

One note here is that it don't need to call snd_soc_runtime_deactivate()
when rollback case, because it will be called without
snd_soc_runtime_activate().
It also don't need to call snd_soc_dapm_stream_stop() when rollback case.
Signed-off-by: default avatarKuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Link: https://lore.kernel.org/r/87ft72bwn4.wl-kuninori.morimoto.gx@renesas.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent 939a5cfb
...@@ -651,12 +651,7 @@ static int soc_pcm_components_close(struct snd_pcm_substream *substream, ...@@ -651,12 +651,7 @@ static int soc_pcm_components_close(struct snd_pcm_substream *substream,
return ret; return ret;
} }
/* static int soc_pcm_clean(struct snd_pcm_substream *substream, int rollback)
* Called by ALSA when a PCM substream is closed. Private data can be
* freed here. The cpu DAI, codec DAI, machine and components are also
* shutdown.
*/
static int soc_pcm_close(struct snd_pcm_substream *substream)
{ {
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_soc_component *component; struct snd_soc_component *component;
...@@ -665,20 +660,22 @@ static int soc_pcm_close(struct snd_pcm_substream *substream) ...@@ -665,20 +660,22 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
snd_soc_runtime_deactivate(rtd, substream->stream); if (!rollback)
snd_soc_runtime_deactivate(rtd, substream->stream);
for_each_rtd_dais(rtd, i, dai) for_each_rtd_dais(rtd, i, dai)
snd_soc_dai_shutdown(dai, substream, 0); snd_soc_dai_shutdown(dai, substream, rollback);
snd_soc_link_shutdown(substream, 0); snd_soc_link_shutdown(substream, rollback);
soc_pcm_components_close(substream, 0); soc_pcm_components_close(substream, rollback);
snd_soc_dapm_stream_stop(rtd, substream->stream); if (!rollback)
snd_soc_dapm_stream_stop(rtd, substream->stream);
mutex_unlock(&rtd->card->pcm_mutex); mutex_unlock(&rtd->card->pcm_mutex);
snd_soc_pcm_component_pm_runtime_put(rtd, substream, 0); snd_soc_pcm_component_pm_runtime_put(rtd, substream, rollback);
for_each_rtd_components(rtd, i, component) for_each_rtd_components(rtd, i, component)
if (!snd_soc_component_active(component)) if (!snd_soc_component_active(component))
...@@ -687,6 +684,16 @@ static int soc_pcm_close(struct snd_pcm_substream *substream) ...@@ -687,6 +684,16 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
return 0; return 0;
} }
/*
* Called by ALSA when a PCM substream is closed. Private data can be
* freed here. The cpu DAI, codec DAI, machine and components are also
* shutdown.
*/
static int soc_pcm_close(struct snd_pcm_substream *substream)
{
return soc_pcm_clean(substream, 0);
}
/* /*
* Called by ALSA when a PCM substream is opened, the runtime->hw record is * Called by ALSA when a PCM substream is opened, the runtime->hw record is
* then initialized and any private data can be allocated. This also calls * then initialized and any private data can be allocated. This also calls
...@@ -707,17 +714,17 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) ...@@ -707,17 +714,17 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
ret = snd_soc_pcm_component_pm_runtime_get(rtd, substream); ret = snd_soc_pcm_component_pm_runtime_get(rtd, substream);
if (ret < 0) if (ret < 0)
goto pm_err; goto err;
mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
ret = soc_pcm_components_open(substream); ret = soc_pcm_components_open(substream);
if (ret < 0) if (ret < 0)
goto component_err; goto err;
ret = snd_soc_link_startup(substream); ret = snd_soc_link_startup(substream);
if (ret < 0) if (ret < 0)
goto rtd_startup_err; goto err;
/* startup the audio subsystem */ /* startup the audio subsystem */
for_each_rtd_dais(rtd, i, dai) { for_each_rtd_dais(rtd, i, dai) {
...@@ -726,7 +733,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) ...@@ -726,7 +733,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
dev_err(dai->dev, dev_err(dai->dev,
"ASoC: can't open DAI %s: %d\n", "ASoC: can't open DAI %s: %d\n",
dai->name, ret); dai->name, ret);
goto config_err; goto err;
} }
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
...@@ -755,18 +762,18 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) ...@@ -755,18 +762,18 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
if (!runtime->hw.rates) { if (!runtime->hw.rates) {
printk(KERN_ERR "ASoC: %s <-> %s No matching rates\n", printk(KERN_ERR "ASoC: %s <-> %s No matching rates\n",
codec_dai_name, cpu_dai_name); codec_dai_name, cpu_dai_name);
goto config_err; goto err;
} }
if (!runtime->hw.formats) { if (!runtime->hw.formats) {
printk(KERN_ERR "ASoC: %s <-> %s No matching formats\n", printk(KERN_ERR "ASoC: %s <-> %s No matching formats\n",
codec_dai_name, cpu_dai_name); codec_dai_name, cpu_dai_name);
goto config_err; goto err;
} }
if (!runtime->hw.channels_min || !runtime->hw.channels_max || if (!runtime->hw.channels_min || !runtime->hw.channels_max ||
runtime->hw.channels_min > runtime->hw.channels_max) { runtime->hw.channels_min > runtime->hw.channels_max) {
printk(KERN_ERR "ASoC: %s <-> %s No matching channels\n", printk(KERN_ERR "ASoC: %s <-> %s No matching channels\n",
codec_dai_name, cpu_dai_name); codec_dai_name, cpu_dai_name);
goto config_err; goto err;
} }
soc_pcm_apply_msb(substream); soc_pcm_apply_msb(substream);
...@@ -776,7 +783,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) ...@@ -776,7 +783,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
if (snd_soc_dai_active(dai)) { if (snd_soc_dai_active(dai)) {
ret = soc_pcm_apply_symmetry(substream, dai); ret = soc_pcm_apply_symmetry(substream, dai);
if (ret != 0) if (ret != 0)
goto config_err; goto err;
} }
} }
...@@ -787,29 +794,13 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) ...@@ -787,29 +794,13 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
runtime->hw.channels_max); runtime->hw.channels_max);
pr_debug("ASoC: min rate %d max rate %d\n", runtime->hw.rate_min, pr_debug("ASoC: min rate %d max rate %d\n", runtime->hw.rate_min,
runtime->hw.rate_max); runtime->hw.rate_max);
dynamic: dynamic:
snd_soc_runtime_activate(rtd, substream->stream); snd_soc_runtime_activate(rtd, substream->stream);
err:
mutex_unlock(&rtd->card->pcm_mutex);
return 0;
config_err:
for_each_rtd_dais_rollback(rtd, i, dai)
snd_soc_dai_shutdown(dai, substream, 1);
snd_soc_link_shutdown(substream, 1);
rtd_startup_err:
soc_pcm_components_close(substream, 1);
component_err:
mutex_unlock(&rtd->card->pcm_mutex); mutex_unlock(&rtd->card->pcm_mutex);
pm_err:
snd_soc_pcm_component_pm_runtime_put(rtd, substream, 1);
for_each_rtd_components(rtd, i, component) if (ret < 0)
if (!snd_soc_component_active(component)) soc_pcm_clean(substream, 1);
pinctrl_pm_select_sleep_state(component->dev);
return ret; return ret;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment