diff options
author | Liam Girdwood <lrg@ti.com> | 2011-01-27 19:35:01 +0000 |
---|---|---|
committer | Colin Cross <ccross@android.com> | 2011-06-14 09:06:12 -0700 |
commit | 055cb29d144685566efff9c12d864dd3bfe91963 (patch) | |
tree | 05cd0b8b8c1ff5b04c4cb0a14de1d464b8616e6c /sound | |
parent | 70d9308c044b4ba3af896aa20105f3ac4f5f2f1a (diff) | |
download | kernel_samsung_tuna-055cb29d144685566efff9c12d864dd3bfe91963.zip kernel_samsung_tuna-055cb29d144685566efff9c12d864dd3bfe91963.tar.gz kernel_samsung_tuna-055cb29d144685566efff9c12d864dd3bfe91963.tar.bz2 |
ASoC: core - pcm mutex per rtd
In preparation for ASoC DSP support.
The new DSP core allows DSP DAIs to be dynamically re-routed at runtime
between the PCM device end (or Frontend - FE) and the physical DAI
(Backend - BE) using regular kcontrols (just like a hardware CODEC).
The DSP core therefore must be able to call PCM operations for both the
Frontend and Backend(s) DAIs at the same time.
Currently we have a global pcm_mutex that is used to serialise
the ASoC PCM operations. This patch removes the global mutex
and adds a mutex per RTD allowing the PCM operations to be reentrant and
allow control of more than one DAI at at time. e.g. a frontend DSP hw_params()
could configure multiple backend hw_params() with similar or different
hw parameters at the same time.
Also fix the naming of soc_pcm_close.
Signed-off-by: Liam Girdwood <lrg@ti.com>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/soc-core.c | 46 |
1 files changed, 23 insertions, 23 deletions
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 932711a..e629372 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -44,7 +44,6 @@ #define NAME_SIZE 32 -static DEFINE_MUTEX(pcm_mutex); static DECLARE_WAIT_QUEUE_HEAD(soc_pm_waitq); #ifdef CONFIG_DEBUG_FS @@ -526,7 +525,7 @@ static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream) * then initialized and any private data can be allocated. This also calls * startup for the cpu DAI, platform, machine and codec DAI. */ -static int soc_pcm_open(struct snd_pcm_substream *substream) +int soc_pcm_open(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_pcm_runtime *runtime = substream->runtime; @@ -537,7 +536,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) struct snd_soc_dai_driver *codec_dai_drv = codec_dai->driver; int ret = 0; - mutex_lock(&pcm_mutex); + mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); /* startup the audio subsystem */ if (cpu_dai->driver->ops->startup) { @@ -667,7 +666,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) cpu_dai->active++; codec_dai->active++; rtd->codec->active++; - mutex_unlock(&pcm_mutex); + mutex_unlock(&rtd->pcm_mutex); return 0; config_err: @@ -686,7 +685,7 @@ platform_err: if (cpu_dai->driver->ops->shutdown) cpu_dai->driver->ops->shutdown(substream, cpu_dai); out: - mutex_unlock(&pcm_mutex); + mutex_unlock(&rtd->pcm_mutex); return ret; } @@ -701,7 +700,7 @@ static void close_delayed_work(struct work_struct *work) container_of(work, struct snd_soc_pcm_runtime, delayed_work.work); struct snd_soc_dai *codec_dai = rtd->codec_dai; - mutex_lock(&pcm_mutex); + mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); pr_debug("pop wq checking: %s status: %s waiting: %s\n", codec_dai->driver->playback.stream_name, @@ -716,7 +715,7 @@ static void close_delayed_work(struct work_struct *work) SND_SOC_DAPM_STREAM_STOP); } - mutex_unlock(&pcm_mutex); + mutex_unlock(&rtd->pcm_mutex); } /* @@ -724,7 +723,7 @@ static void close_delayed_work(struct work_struct *work) * freed here. The cpu DAI, codec DAI, machine and platform are also * shutdown. */ -static int soc_codec_close(struct snd_pcm_substream *substream) +int soc_pcm_close(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_platform *platform = rtd->platform; @@ -732,7 +731,7 @@ static int soc_codec_close(struct snd_pcm_substream *substream) struct snd_soc_dai *codec_dai = rtd->codec_dai; struct snd_soc_codec *codec = rtd->codec; - mutex_lock(&pcm_mutex); + mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { cpu_dai->playback_active--; @@ -777,7 +776,7 @@ static int soc_codec_close(struct snd_pcm_substream *substream) SND_SOC_DAPM_STREAM_STOP); } - mutex_unlock(&pcm_mutex); + mutex_unlock(&rtd->pcm_mutex); return 0; } @@ -786,7 +785,7 @@ static int soc_codec_close(struct snd_pcm_substream *substream) * rate, etc. This function is non atomic and can be called multiple times, * it can refer to the runtime info. */ -static int soc_pcm_prepare(struct snd_pcm_substream *substream) +int soc_pcm_prepare(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_platform *platform = rtd->platform; @@ -794,7 +793,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) struct snd_soc_dai *codec_dai = rtd->codec_dai; int ret = 0; - mutex_lock(&pcm_mutex); + mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); if (rtd->dai_link->ops && rtd->dai_link->ops->prepare) { ret = rtd->dai_link->ops->prepare(substream); @@ -847,7 +846,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) snd_soc_dai_digital_mute(codec_dai, 0); out: - mutex_unlock(&pcm_mutex); + mutex_unlock(&rtd->pcm_mutex); return ret; } @@ -856,7 +855,7 @@ out: * function can also be called multiple times and can allocate buffers * (using snd_pcm_lib_* ). It's non-atomic. */ -static int soc_pcm_hw_params(struct snd_pcm_substream *substream, +int soc_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; @@ -865,7 +864,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *codec_dai = rtd->codec_dai; int ret = 0; - mutex_lock(&pcm_mutex); + mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); if (rtd->dai_link->ops && rtd->dai_link->ops->hw_params) { ret = rtd->dai_link->ops->hw_params(substream, params); @@ -905,7 +904,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, rtd->rate = params_rate(params); out: - mutex_unlock(&pcm_mutex); + mutex_unlock(&rtd->pcm_mutex); return ret; platform_err: @@ -920,14 +919,14 @@ codec_err: if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free) rtd->dai_link->ops->hw_free(substream); - mutex_unlock(&pcm_mutex); + mutex_unlock(&rtd->pcm_mutex); return ret; } /* * Frees resources allocated by hw_params, can be called multiple times */ -static int soc_pcm_hw_free(struct snd_pcm_substream *substream) +int soc_pcm_hw_free(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_platform *platform = rtd->platform; @@ -935,7 +934,7 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) struct snd_soc_dai *codec_dai = rtd->codec_dai; struct snd_soc_codec *codec = rtd->codec; - mutex_lock(&pcm_mutex); + mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); /* apply codec digital mute */ if (!codec->active) @@ -956,11 +955,11 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) if (cpu_dai->driver->ops->hw_free) cpu_dai->driver->ops->hw_free(substream, cpu_dai); - mutex_unlock(&pcm_mutex); + mutex_unlock(&rtd->pcm_mutex); return 0; } -static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) +int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_platform *platform = rtd->platform; @@ -993,7 +992,7 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) * If cpu_dai, codec_dai, platform driver has the delay callback, than * the runtime->delay will be updated accordingly. */ -static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream) +snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_platform *platform = rtd->platform; @@ -1023,7 +1022,7 @@ static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream) /* ASoC PCM operations */ static struct snd_pcm_ops soc_pcm_ops = { .open = soc_pcm_open, - .close = soc_codec_close, + .close = soc_pcm_close, .hw_params = soc_pcm_hw_params, .hw_free = soc_pcm_hw_free, .prepare = soc_pcm_prepare, @@ -1579,6 +1578,7 @@ static int soc_post_component_init(struct snd_soc_card *card, rtd->dev.parent = card->dev; rtd->dev.release = rtd_release; rtd->dev.init_name = name; + mutex_init(&rtd->pcm_mutex); ret = device_register(&rtd->dev); if (ret < 0) { dev_err(card->dev, |