mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-03 17:40:04 +00:00
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: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Link: https://lore.kernel.org/r/87ft72bwn4.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
939a5cfb2a
commit
140a4532cd
1 changed files with 30 additions and 39 deletions
|
@ -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)
|
||||||
|
|
||||||
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)
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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);
|
mutex_unlock(&rtd->card->pcm_mutex);
|
||||||
return 0;
|
|
||||||
|
|
||||||
config_err:
|
if (ret < 0)
|
||||||
for_each_rtd_dais_rollback(rtd, i, dai)
|
soc_pcm_clean(substream, 1);
|
||||||
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);
|
|
||||||
pm_err:
|
|
||||||
snd_soc_pcm_component_pm_runtime_put(rtd, substream, 1);
|
|
||||||
|
|
||||||
for_each_rtd_components(rtd, i, component)
|
|
||||||
if (!snd_soc_component_active(component))
|
|
||||||
pinctrl_pm_select_sleep_state(component->dev);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue