[alsa-devel] [RFC] ASoC: Allow mulitple usage of codec and cpu dai
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@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; }
On Thu, Feb 25, 2010 at 01:26:51PM +0900, Jassi Brar wrote:
/* startup the audio subsystem */
- if (cpu_dai->ops->startup) {
- if (cpu_dai->active == 0 && cpu_dai->ops->startup) {
I thought I'd been fairly clear last time that the drivers need to have an option to do stuff on startup(). As I said then a separate callback which is called only on the transitions into and out of active would be fine.
On Thu, Feb 25, 2010 at 7:03 PM, Mark Brown broonie@opensource.wolfsonmicro.com wrote:
On Thu, Feb 25, 2010 at 01:26:51PM +0900, Jassi Brar wrote:
/* startup the audio subsystem */
- if (cpu_dai->ops->startup) {
- if (cpu_dai->active == 0 && cpu_dai->ops->startup) {
I thought I'd been fairly clear last time that the drivers need to have an option to do stuff on startup(). As I said then a separate callback which is called only on the transitions into and out of active would be fine.
This is simply the patch, that you asked me to dig out from samsung-git and post to the list, adapted to for-2.6.35
I could drop startup,shutdown,mute-on/off as well, but no codec driver would work with that as such. If that's ok, i'll resend the patch.
On Thu, Feb 25, 2010 at 08:00:13PM +0900, jassi brar wrote:
On Thu, Feb 25, 2010 at 7:03 PM, Mark Brown
I thought I'd been fairly clear last time that the drivers need to have an option to do stuff on startup(). As I said then a separate callback which is called only on the transitions into and out of active would be fine.
This is simply the patch, that you asked me to dig out from samsung-git and post to the list, adapted to for-2.6.35
I asked you to pull out the bits that maintain active.
I could drop startup,shutdown,mute-on/off as well, but no codec driver would work with that as such. If that's ok, i'll resend the patch.
Honestly I didn't read the rest of the patch after I saw the change to remove the startup() callback. Clearly fiddling around with the active count isn't going to make every possible system work, and it may not be any use at all, but so long as it doesn't interfere with other users it's not really a problem.
As I said previously this should really be being done by showing the mixer as a device within ASoC rather than this way. Trying to pretend the mixer isn't there is going to cause problems, the confusion about when the stream is live being just one of them.
On Thu, Feb 25, 2010 at 10:06 PM, Mark Brown broonie@opensource.wolfsonmicro.com wrote:
On Thu, Feb 25, 2010 at 08:00:13PM +0900, jassi brar wrote:
On Thu, Feb 25, 2010 at 7:03 PM, Mark Brown
I thought I'd been fairly clear last time that the drivers need to have an option to do stuff on startup(). As I said then a separate callback which is called only on the transitions into and out of active would be fine.
This is simply the patch, that you asked me to dig out from samsung-git and post to the list, adapted to for-2.6.35
I asked you to pull out the bits that maintain active.
hmm... i misread ur reply. Just submitted refreshed patch for just that.
I could drop startup,shutdown,mute-on/off as well, but no codec driver would work with that as such. If that's ok, i'll resend the patch.
Honestly I didn't read the rest of the patch after I saw the change to remove the startup() callback. Clearly fiddling around with the active count isn't going to make every possible system work, and it may not be any use at all, but so long as it doesn't interfere with other users it's not really a problem.
Also, I think we should look into if we can do without snd_soc_codec.active when we have snd_soc_dai.playback/capture.active counters.
On Fri, Feb 26, 2010 at 09:32:27AM +0900, jassi brar wrote:
Also, I think we should look into if we can do without snd_soc_codec.active when we have snd_soc_dai.playback/capture.active counters.
Yes, the CODEC active counter has been pretty redundant for a long time since the mute is a DAI-specific operation and all the CODEC active counter is used for is muting on free. I believe it's a hangover from pre-DAPM days.
participants (3)
-
Jassi Brar
-
jassi brar
-
Mark Brown