diff options
-rw-r--r-- | include/sound/soc.h | 8 | ||||
-rw-r--r-- | sound/soc/soc-core.c | 1 | ||||
-rw-r--r-- | 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 d5db87e82c6..4334ab25c5d 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h | |||
@@ -269,6 +269,11 @@ enum snd_soc_compress_type { | |||
269 | SND_SOC_RBTREE_COMPRESSION | 269 | SND_SOC_RBTREE_COMPRESSION |
270 | }; | 270 | }; |
271 | 271 | ||
272 | enum snd_soc_pcm_subclass { | ||
273 | SND_SOC_PCM_CLASS_PCM = 0, | ||
274 | SND_SOC_PCM_CLASS_BE = 1, | ||
275 | }; | ||
276 | |||
272 | int snd_soc_codec_set_sysclk(struct snd_soc_codec *codec, int clk_id, | 277 | int snd_soc_codec_set_sysclk(struct snd_soc_codec *codec, int clk_id, |
273 | unsigned int freq, int dir); | 278 | unsigned int freq, int dir); |
274 | int snd_soc_codec_set_pll(struct snd_soc_codec *codec, int pll_id, int source, | 279 | 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 | struct device dev; | 814 | struct device dev; |
810 | struct snd_soc_card *card; | 815 | struct snd_soc_card *card; |
811 | struct snd_soc_dai_link *dai_link; | 816 | struct snd_soc_dai_link *dai_link; |
817 | struct mutex pcm_mutex; | ||
818 | enum snd_soc_pcm_subclass pcm_subclass; | ||
819 | struct snd_pcm_ops ops; | ||
812 | 820 | ||
813 | unsigned int complete:1; | 821 | unsigned int complete:1; |
814 | unsigned int dev_registered:1; | 822 | 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, | |||
1032 | rtd->dev.parent = card->dev; | 1032 | rtd->dev.parent = card->dev; |
1033 | rtd->dev.release = rtd_release; | 1033 | rtd->dev.release = rtd_release; |
1034 | rtd->dev.init_name = name; | 1034 | rtd->dev.init_name = name; |
1035 | mutex_init(&rtd->pcm_mutex); | ||
1035 | ret = device_register(&rtd->dev); | 1036 | ret = device_register(&rtd->dev); |
1036 | if (ret < 0) { | 1037 | if (ret < 0) { |
1037 | dev_err(card->dev, | 1038 | 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) | |||
81 | struct snd_soc_dai_driver *codec_dai_drv = codec_dai->driver; | 81 | struct snd_soc_dai_driver *codec_dai_drv = codec_dai->driver; |
82 | int ret = 0; | 82 | int ret = 0; |
83 | 83 | ||
84 | mutex_lock(&pcm_mutex); | 84 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); |
85 | 85 | ||
86 | /* startup the audio subsystem */ | 86 | /* startup the audio subsystem */ |
87 | if (cpu_dai->driver->ops->startup) { | 87 | if (cpu_dai->driver->ops->startup) { |
@@ -211,7 +211,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) | |||
211 | cpu_dai->active++; | 211 | cpu_dai->active++; |
212 | codec_dai->active++; | 212 | codec_dai->active++; |
213 | rtd->codec->active++; | 213 | rtd->codec->active++; |
214 | mutex_unlock(&pcm_mutex); | 214 | mutex_unlock(&rtd->pcm_mutex); |
215 | return 0; | 215 | return 0; |
216 | 216 | ||
217 | config_err: | 217 | config_err: |
@@ -230,7 +230,7 @@ platform_err: | |||
230 | if (cpu_dai->driver->ops->shutdown) | 230 | if (cpu_dai->driver->ops->shutdown) |
231 | cpu_dai->driver->ops->shutdown(substream, cpu_dai); | 231 | cpu_dai->driver->ops->shutdown(substream, cpu_dai); |
232 | out: | 232 | out: |
233 | mutex_unlock(&pcm_mutex); | 233 | mutex_unlock(&rtd->pcm_mutex); |
234 | return ret; | 234 | return ret; |
235 | } | 235 | } |
236 | 236 | ||
@@ -245,7 +245,7 @@ static void close_delayed_work(struct work_struct *work) | |||
245 | container_of(work, struct snd_soc_pcm_runtime, delayed_work.work); | 245 | container_of(work, struct snd_soc_pcm_runtime, delayed_work.work); |
246 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 246 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
247 | 247 | ||
248 | mutex_lock(&pcm_mutex); | 248 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); |
249 | 249 | ||
250 | pr_debug("pop wq checking: %s status: %s waiting: %s\n", | 250 | pr_debug("pop wq checking: %s status: %s waiting: %s\n", |
251 | codec_dai->driver->playback.stream_name, | 251 | codec_dai->driver->playback.stream_name, |
@@ -260,7 +260,7 @@ static void close_delayed_work(struct work_struct *work) | |||
260 | SND_SOC_DAPM_STREAM_STOP); | 260 | SND_SOC_DAPM_STREAM_STOP); |
261 | } | 261 | } |
262 | 262 | ||
263 | mutex_unlock(&pcm_mutex); | 263 | mutex_unlock(&rtd->pcm_mutex); |
264 | } | 264 | } |
265 | 265 | ||
266 | /* | 266 | /* |
@@ -276,7 +276,7 @@ static int soc_codec_close(struct snd_pcm_substream *substream) | |||
276 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 276 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
277 | struct snd_soc_codec *codec = rtd->codec; | 277 | struct snd_soc_codec *codec = rtd->codec; |
278 | 278 | ||
279 | mutex_lock(&pcm_mutex); | 279 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); |
280 | 280 | ||
281 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 281 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
282 | cpu_dai->playback_active--; | 282 | cpu_dai->playback_active--; |
@@ -321,7 +321,7 @@ static int soc_codec_close(struct snd_pcm_substream *substream) | |||
321 | SND_SOC_DAPM_STREAM_STOP); | 321 | SND_SOC_DAPM_STREAM_STOP); |
322 | } | 322 | } |
323 | 323 | ||
324 | mutex_unlock(&pcm_mutex); | 324 | mutex_unlock(&rtd->pcm_mutex); |
325 | return 0; | 325 | return 0; |
326 | } | 326 | } |
327 | 327 | ||
@@ -338,7 +338,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) | |||
338 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 338 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
339 | int ret = 0; | 339 | int ret = 0; |
340 | 340 | ||
341 | mutex_lock(&pcm_mutex); | 341 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); |
342 | 342 | ||
343 | if (rtd->dai_link->ops && rtd->dai_link->ops->prepare) { | 343 | if (rtd->dai_link->ops && rtd->dai_link->ops->prepare) { |
344 | ret = rtd->dai_link->ops->prepare(substream); | 344 | ret = rtd->dai_link->ops->prepare(substream); |
@@ -391,7 +391,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) | |||
391 | snd_soc_dai_digital_mute(codec_dai, 0); | 391 | snd_soc_dai_digital_mute(codec_dai, 0); |
392 | 392 | ||
393 | out: | 393 | out: |
394 | mutex_unlock(&pcm_mutex); | 394 | mutex_unlock(&rtd->pcm_mutex); |
395 | return ret; | 395 | return ret; |
396 | } | 396 | } |
397 | 397 | ||
@@ -409,7 +409,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, | |||
409 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 409 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
410 | int ret = 0; | 410 | int ret = 0; |
411 | 411 | ||
412 | mutex_lock(&pcm_mutex); | 412 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); |
413 | 413 | ||
414 | if (rtd->dai_link->ops && rtd->dai_link->ops->hw_params) { | 414 | if (rtd->dai_link->ops && rtd->dai_link->ops->hw_params) { |
415 | ret = rtd->dai_link->ops->hw_params(substream, params); | 415 | 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 | rtd->rate = params_rate(params); | 449 | rtd->rate = params_rate(params); |
450 | 450 | ||
451 | out: | 451 | out: |
452 | mutex_unlock(&pcm_mutex); | 452 | mutex_unlock(&rtd->pcm_mutex); |
453 | return ret; | 453 | return ret; |
454 | 454 | ||
455 | platform_err: | 455 | platform_err: |
@@ -464,7 +464,7 @@ codec_err: | |||
464 | if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free) | 464 | if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free) |
465 | rtd->dai_link->ops->hw_free(substream); | 465 | rtd->dai_link->ops->hw_free(substream); |
466 | 466 | ||
467 | mutex_unlock(&pcm_mutex); | 467 | mutex_unlock(&rtd->pcm_mutex); |
468 | return ret; | 468 | return ret; |
469 | } | 469 | } |
470 | 470 | ||
@@ -479,7 +479,7 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) | |||
479 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 479 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
480 | struct snd_soc_codec *codec = rtd->codec; | 480 | struct snd_soc_codec *codec = rtd->codec; |
481 | 481 | ||
482 | mutex_lock(&pcm_mutex); | 482 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); |
483 | 483 | ||
484 | /* apply codec digital mute */ | 484 | /* apply codec digital mute */ |
485 | if (!codec->active) | 485 | if (!codec->active) |
@@ -500,7 +500,7 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) | |||
500 | if (cpu_dai->driver->ops->hw_free) | 500 | if (cpu_dai->driver->ops->hw_free) |
501 | cpu_dai->driver->ops->hw_free(substream, cpu_dai); | 501 | cpu_dai->driver->ops->hw_free(substream, cpu_dai); |
502 | 502 | ||
503 | mutex_unlock(&pcm_mutex); | 503 | mutex_unlock(&rtd->pcm_mutex); |
504 | return 0; | 504 | return 0; |
505 | } | 505 | } |
506 | 506 | ||