| From 7c74178e9fd0dbf8b3e823a1fea0a0f4ab907afe Mon Sep 17 00:00:00 2001 |
| From: Liam Girdwood <lrg@ti.com> |
| Date: Thu, 9 Jun 2011 17:04:39 +0100 |
| Subject: ASoC: core - PCM mutex per rtd |
| |
| In preparation for the new ASoC Dynamic PCM support (AKA DSP support). |
| |
| The new ASoC Dynamic PCM core allows 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 routes |
| audio in the analog domain). The Dynamic PCM 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 PCM hw_params() |
| could configure multiple backend DAI hw_params() with similar or different |
| hw parameters at the same time. |
| |
| Signed-off-by: Liam Girdwood <lrg@ti.com> |
| Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> |
| (cherry picked from commit b8c0dab9bf3373010e857a8d3f1b594c60a348dd) |
| |
| Signed-off-by: Simon Horman <horms@verge.net.au> |
| --- |
| include/sound/soc.h | 8 ++++++++ |
| sound/soc/soc-core.c | 1 + |
| sound/soc/soc-pcm.c | 28 ++++++++++++++-------------- |
| 3 files changed, 23 insertions(+), 14 deletions(-) |
| |
| diff --git a/include/sound/soc.h b/include/sound/soc.h |
| index 447232c..9e6d13e 100644 |
| --- a/include/sound/soc.h |
| +++ b/include/sound/soc.h |
| @@ -268,6 +268,11 @@ enum snd_soc_compress_type { |
| SND_SOC_RBTREE_COMPRESSION |
| }; |
| |
| +enum snd_soc_pcm_subclass { |
| + SND_SOC_PCM_CLASS_PCM = 0, |
| + SND_SOC_PCM_CLASS_BE = 1, |
| +}; |
| + |
| int snd_soc_codec_set_sysclk(struct snd_soc_codec *codec, int clk_id, |
| unsigned int freq, int dir); |
| int snd_soc_codec_set_pll(struct snd_soc_codec *codec, int pll_id, int source, |
| @@ -806,6 +811,9 @@ struct snd_soc_pcm_runtime { |
| struct device dev; |
| struct snd_soc_card *card; |
| struct snd_soc_dai_link *dai_link; |
| + struct mutex pcm_mutex; |
| + enum snd_soc_pcm_subclass pcm_subclass; |
| + struct snd_pcm_ops ops; |
| |
| unsigned int complete:1; |
| unsigned int dev_registered:1; |
| diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c |
| index f5ec7d8..71cf27f 100644 |
| --- a/sound/soc/soc-core.c |
| +++ b/sound/soc/soc-core.c |
| @@ -1034,6 +1034,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, |
| diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c |
| index 9bebee8..f4864b0 100644 |
| --- a/sound/soc/soc-pcm.c |
| +++ b/sound/soc/soc-pcm.c |
| @@ -81,7 +81,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) { |
| @@ -211,7 +211,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: |
| @@ -230,7 +230,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; |
| } |
| |
| @@ -245,7 +245,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, |
| @@ -260,7 +260,7 @@ static void close_delayed_work(struct work_struct *work) |
| SND_SOC_DAPM_STREAM_STOP); |
| } |
| |
| - mutex_unlock(&pcm_mutex); |
| + mutex_unlock(&rtd->pcm_mutex); |
| } |
| |
| /* |
| @@ -276,7 +276,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--; |
| @@ -321,7 +321,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; |
| } |
| |
| @@ -338,7 +338,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); |
| @@ -391,7 +391,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; |
| } |
| |
| @@ -409,7 +409,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); |
| @@ -449,7 +449,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: |
| @@ -464,7 +464,7 @@ 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; |
| } |
| |
| @@ -479,7 +479,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) |
| @@ -500,7 +500,7 @@ 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; |
| } |
| |
| -- |
| 1.7.10.2.565.gbd578b5 |
| |