提交 b8c0dab9 编写于 作者: L Liam Girdwood 提交者: Mark Brown

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: NLiam Girdwood <lrg@ti.com>
Signed-off-by: NMark Brown <broonie@opensource.wolfsonmicro.com>
上级 2c36c2ce
...@@ -269,6 +269,11 @@ enum snd_soc_compress_type { ...@@ -269,6 +269,11 @@ enum snd_soc_compress_type {
SND_SOC_RBTREE_COMPRESSION 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, int snd_soc_codec_set_sysclk(struct snd_soc_codec *codec, int clk_id,
unsigned int freq, int dir); unsigned int freq, int dir);
int snd_soc_codec_set_pll(struct snd_soc_codec *codec, int pll_id, int source, int snd_soc_codec_set_pll(struct snd_soc_codec *codec, int pll_id, int source,
...@@ -809,6 +814,9 @@ struct snd_soc_pcm_runtime { ...@@ -809,6 +814,9 @@ struct snd_soc_pcm_runtime {
struct device dev; struct device dev;
struct snd_soc_card *card; struct snd_soc_card *card;
struct snd_soc_dai_link *dai_link; 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 complete:1;
unsigned int dev_registered:1; unsigned int dev_registered:1;
......
...@@ -1032,6 +1032,7 @@ static int soc_post_component_init(struct snd_soc_card *card, ...@@ -1032,6 +1032,7 @@ static int soc_post_component_init(struct snd_soc_card *card,
rtd->dev.parent = card->dev; rtd->dev.parent = card->dev;
rtd->dev.release = rtd_release; rtd->dev.release = rtd_release;
rtd->dev.init_name = name; rtd->dev.init_name = name;
mutex_init(&rtd->pcm_mutex);
ret = device_register(&rtd->dev); ret = device_register(&rtd->dev);
if (ret < 0) { if (ret < 0) {
dev_err(card->dev, dev_err(card->dev,
......
...@@ -81,7 +81,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) ...@@ -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; struct snd_soc_dai_driver *codec_dai_drv = codec_dai->driver;
int ret = 0; int ret = 0;
mutex_lock(&pcm_mutex); mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
/* startup the audio subsystem */ /* startup the audio subsystem */
if (cpu_dai->driver->ops->startup) { if (cpu_dai->driver->ops->startup) {
...@@ -211,7 +211,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) ...@@ -211,7 +211,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
cpu_dai->active++; cpu_dai->active++;
codec_dai->active++; codec_dai->active++;
rtd->codec->active++; rtd->codec->active++;
mutex_unlock(&pcm_mutex); mutex_unlock(&rtd->pcm_mutex);
return 0; return 0;
config_err: config_err:
...@@ -230,7 +230,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) ...@@ -230,7 +230,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
if (cpu_dai->driver->ops->shutdown) if (cpu_dai->driver->ops->shutdown)
cpu_dai->driver->ops->shutdown(substream, cpu_dai); cpu_dai->driver->ops->shutdown(substream, cpu_dai);
out: out:
mutex_unlock(&pcm_mutex); mutex_unlock(&rtd->pcm_mutex);
return ret; return ret;
} }
...@@ -245,7 +245,7 @@ static void close_delayed_work(struct work_struct *work) ...@@ -245,7 +245,7 @@ static void close_delayed_work(struct work_struct *work)
container_of(work, struct snd_soc_pcm_runtime, delayed_work.work); container_of(work, struct snd_soc_pcm_runtime, delayed_work.work);
struct snd_soc_dai *codec_dai = rtd->codec_dai; 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", pr_debug("pop wq checking: %s status: %s waiting: %s\n",
codec_dai->driver->playback.stream_name, codec_dai->driver->playback.stream_name,
...@@ -260,7 +260,7 @@ static void close_delayed_work(struct work_struct *work) ...@@ -260,7 +260,7 @@ static void close_delayed_work(struct work_struct *work)
SND_SOC_DAPM_STREAM_STOP); 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) ...@@ -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_dai *codec_dai = rtd->codec_dai;
struct snd_soc_codec *codec = rtd->codec; 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) { if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
cpu_dai->playback_active--; cpu_dai->playback_active--;
...@@ -321,7 +321,7 @@ static int soc_codec_close(struct snd_pcm_substream *substream) ...@@ -321,7 +321,7 @@ static int soc_codec_close(struct snd_pcm_substream *substream)
SND_SOC_DAPM_STREAM_STOP); SND_SOC_DAPM_STREAM_STOP);
} }
mutex_unlock(&pcm_mutex); mutex_unlock(&rtd->pcm_mutex);
return 0; return 0;
} }
...@@ -338,7 +338,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) ...@@ -338,7 +338,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
struct snd_soc_dai *codec_dai = rtd->codec_dai; struct snd_soc_dai *codec_dai = rtd->codec_dai;
int ret = 0; 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) { if (rtd->dai_link->ops && rtd->dai_link->ops->prepare) {
ret = rtd->dai_link->ops->prepare(substream); ret = rtd->dai_link->ops->prepare(substream);
...@@ -391,7 +391,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) ...@@ -391,7 +391,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
snd_soc_dai_digital_mute(codec_dai, 0); snd_soc_dai_digital_mute(codec_dai, 0);
out: out:
mutex_unlock(&pcm_mutex); mutex_unlock(&rtd->pcm_mutex);
return ret; return ret;
} }
...@@ -409,7 +409,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, ...@@ -409,7 +409,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *codec_dai = rtd->codec_dai; struct snd_soc_dai *codec_dai = rtd->codec_dai;
int ret = 0; 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) { if (rtd->dai_link->ops && rtd->dai_link->ops->hw_params) {
ret = rtd->dai_link->ops->hw_params(substream, 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, ...@@ -449,7 +449,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
rtd->rate = params_rate(params); rtd->rate = params_rate(params);
out: out:
mutex_unlock(&pcm_mutex); mutex_unlock(&rtd->pcm_mutex);
return ret; return ret;
platform_err: platform_err:
...@@ -464,7 +464,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, ...@@ -464,7 +464,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free) if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free)
rtd->dai_link->ops->hw_free(substream); rtd->dai_link->ops->hw_free(substream);
mutex_unlock(&pcm_mutex); mutex_unlock(&rtd->pcm_mutex);
return ret; return ret;
} }
...@@ -479,7 +479,7 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) ...@@ -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_dai *codec_dai = rtd->codec_dai;
struct snd_soc_codec *codec = rtd->codec; struct snd_soc_codec *codec = rtd->codec;
mutex_lock(&pcm_mutex); mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
/* apply codec digital mute */ /* apply codec digital mute */
if (!codec->active) if (!codec->active)
...@@ -500,7 +500,7 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) ...@@ -500,7 +500,7 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
if (cpu_dai->driver->ops->hw_free) if (cpu_dai->driver->ops->hw_free)
cpu_dai->driver->ops->hw_free(substream, cpu_dai); cpu_dai->driver->ops->hw_free(substream, cpu_dai);
mutex_unlock(&pcm_mutex); mutex_unlock(&rtd->pcm_mutex);
return 0; return 0;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册