summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sound/soc.h8
-rw-r--r--sound/soc/soc-core.c1
-rw-r--r--sound/soc/soc-pcm.c28
3 files changed, 23 insertions, 14 deletions
diff --git a/include/sound/soc.h b/include/sound/soc.h
index d5db87e82c6..4334ab25c5d 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -269,6 +269,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,
@@ -809,6 +814,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 32d7d2f8147..32bc50387f6 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -1032,6 +1032,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 9bebee82bc1..f4864b088d2 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;
}