aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLiam Girdwood <lrg@ti.com>2011-06-09 12:04:39 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2011-06-09 14:29:29 -0400
commitb8c0dab9bf3373010e857a8d3f1b594c60a348dd (patch)
tree9ea917827ed56fc655c3528431dfb234e8231660
parent2c36c2ce00987a416bf75681742617a0f85335eb (diff)
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>
-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 {
269 SND_SOC_RBTREE_COMPRESSION 269 SND_SOC_RBTREE_COMPRESSION
270}; 270};
271 271
272enum snd_soc_pcm_subclass {
273 SND_SOC_PCM_CLASS_PCM = 0,
274 SND_SOC_PCM_CLASS_BE = 1,
275};
276
272int snd_soc_codec_set_sysclk(struct snd_soc_codec *codec, int clk_id, 277int 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);
274int snd_soc_codec_set_pll(struct snd_soc_codec *codec, int pll_id, int source, 279int 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
217config_err: 217config_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);
232out: 232out:
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
393out: 393out:
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
451out: 451out:
452 mutex_unlock(&pcm_mutex); 452 mutex_unlock(&rtd->pcm_mutex);
453 return ret; 453 return ret;
454 454
455platform_err: 455platform_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