diff --git a/include/sound/soc.h b/include/sound/soc.h index d5db87e82c6d..4334ab25c5d5 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 32d7d2f8147c..32bc50387f61 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 9bebee82bc15..f4864b088d2c 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; }