[alsa-devel] [RFC] ASoC: Allow mulitple usage of codec and cpu dai
Jassi Brar
jassi.brar at samsung.com
Thu Feb 25 05:26:51 CET 2010
We can have a snd_soc_dai i.e, cpu_dai and codec_dai, shared among two or more
dai_links by avoiding shutting-down/powering-up if the dai is already in
an appropriate state.
For that, we change semantics of the snd_soc_dai.active flag from indicator
to reference counter.
This patch only attempts to block duplicate startup/shutdown and the mute
callbacks, presuming currently no dai driver anticipates 'dai reuse'.
Signed-off-by: Jassi Brar <jassi.brar at samsung.com>
---
include/sound/soc.h | 2 +-
sound/soc/soc-core.c | 47 ++++++++++++++++++++++++++++-------------------
2 files changed, 29 insertions(+), 20 deletions(-)
The codec->active can also be deducted by codec_dai->capture/playback.active
So, we can get rid of snd_soc_codec.active field as well to reduce number of
variables we have to manage in future while making delicate changes in ASoC.
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 27a2ad9..f792c18 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -375,7 +375,7 @@ struct snd_soc_pcm_stream {
unsigned int rate_max; /* max rate */
unsigned int channels_min; /* min channels */
unsigned int channels_max; /* max channels */
- unsigned int active:1; /* stream is in use */
+ unsigned int active; /* num of active users of the stream */
};
/* SoC audio ops */
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 2b66719..459f1f5 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -352,7 +352,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
mutex_lock(&pcm_mutex);
/* startup the audio subsystem */
- if (cpu_dai->ops->startup) {
+ if (cpu_dai->active == 0 && cpu_dai->ops->startup) {
ret = cpu_dai->ops->startup(substream, cpu_dai);
if (ret < 0) {
printk(KERN_ERR "asoc: can't open interface %s\n",
@@ -369,7 +369,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
}
}
- if (codec_dai->ops->startup) {
+ if (codec_dai->active == 0 && codec_dai->ops->startup) {
ret = codec_dai->ops->startup(substream, codec_dai);
if (ret < 0) {
printk(KERN_ERR "asoc: can't open codec %s\n",
@@ -454,11 +454,15 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
pr_debug("asoc: min rate %d max rate %d\n", runtime->hw.rate_min,
runtime->hw.rate_max);
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- cpu_dai->playback.active = codec_dai->playback.active = 1;
- else
- cpu_dai->capture.active = codec_dai->capture.active = 1;
- cpu_dai->active = codec_dai->active = 1;
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ cpu_dai->playback.active++;
+ codec_dai->playback.active++;
+ } else {
+ cpu_dai->capture.active++;
+ codec_dai->capture.active++;
+ }
+ cpu_dai->active++;
+ codec_dai->active++;
card->codec->active++;
mutex_unlock(&pcm_mutex);
return 0;
@@ -534,27 +538,28 @@ static int soc_codec_close(struct snd_pcm_substream *substream)
mutex_lock(&pcm_mutex);
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- cpu_dai->playback.active = codec_dai->playback.active = 0;
- else
- cpu_dai->capture.active = codec_dai->capture.active = 0;
-
- if (codec_dai->playback.active == 0 &&
- codec_dai->capture.active == 0) {
- cpu_dai->active = codec_dai->active = 0;
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ cpu_dai->playback.active--;
+ codec_dai->playback.active--;
+ } else {
+ cpu_dai->capture.active--;
+ codec_dai->capture.active--;
}
+
+ cpu_dai->active--;
+ codec_dai->active--;
codec->active--;
/* Muting the DAC suppresses artifacts caused during digital
* shutdown, for example from stopping clocks.
*/
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ if (codec_dai->active == 0 && substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
snd_soc_dai_digital_mute(codec_dai, 1);
- if (cpu_dai->ops->shutdown)
+ if (cpu_dai->active == 0 && cpu_dai->ops->shutdown)
cpu_dai->ops->shutdown(substream, cpu_dai);
- if (codec_dai->ops->shutdown)
+ if (codec_dai->active == 0 && codec_dai->ops->shutdown)
codec_dai->ops->shutdown(substream, codec_dai);
if (machine->ops && machine->ops->shutdown)
@@ -563,6 +568,10 @@ static int soc_codec_close(struct snd_pcm_substream *substream)
if (platform->pcm_ops->close)
platform->pcm_ops->close(substream);
+ /* Skip DAPM if codec is still active via some other dai_link */
+ if (codec_dai->active)
+ goto exit;
+
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
/* start delayed pop wq here for playback streams */
codec_dai->pop_wait = 1;
@@ -574,7 +583,7 @@ static int soc_codec_close(struct snd_pcm_substream *substream)
codec_dai->capture.stream_name,
SND_SOC_DAPM_STREAM_STOP);
}
-
+exit:
mutex_unlock(&pcm_mutex);
return 0;
}
--
1.6.2.5
More information about the Alsa-devel
mailing list