aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/soc-core.c
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2009-05-17 16:41:23 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2009-05-18 10:53:16 -0400
commit452c5eaa0d5162e02ffee742ea17540887bc2904 (patch)
tree7dbac625d69e3ff01445d7f1b1fa321aa35fcae5 /sound/soc/soc-core.c
parentaef908434cd24dd5529065bf5d781773fad21125 (diff)
ASoC: Integrate bias management with DAPM power management
Rather than managing the bias level of the system based on if there is an active audio stream manage it based on there being an active DAPM widget. This simplifies the code a little, moving the power handling into one place, and improves audio performance for bypass paths when no playbacks or captures are active. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/soc-core.c')
-rw-r--r--sound/soc/soc-core.c61
1 files changed, 10 insertions, 51 deletions
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index c0e706645ec4..4aa8e2d35061 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -299,7 +299,6 @@ static void close_delayed_work(struct work_struct *work)
299{ 299{
300 struct snd_soc_card *card = container_of(work, struct snd_soc_card, 300 struct snd_soc_card *card = container_of(work, struct snd_soc_card,
301 delayed_work.work); 301 delayed_work.work);
302 struct snd_soc_device *socdev = card->socdev;
303 struct snd_soc_codec *codec = card->codec; 302 struct snd_soc_codec *codec = card->codec;
304 struct snd_soc_dai *codec_dai; 303 struct snd_soc_dai *codec_dai;
305 int i; 304 int i;
@@ -315,27 +314,10 @@ static void close_delayed_work(struct work_struct *work)
315 314
316 /* are we waiting on this codec DAI stream */ 315 /* are we waiting on this codec DAI stream */
317 if (codec_dai->pop_wait == 1) { 316 if (codec_dai->pop_wait == 1) {
318
319 /* Reduce power if no longer active */
320 if (codec->active == 0) {
321 pr_debug("pop wq D1 %s %s\n", codec->name,
322 codec_dai->playback.stream_name);
323 snd_soc_dapm_set_bias_level(socdev,
324 SND_SOC_BIAS_PREPARE);
325 }
326
327 codec_dai->pop_wait = 0; 317 codec_dai->pop_wait = 0;
328 snd_soc_dapm_stream_event(codec, 318 snd_soc_dapm_stream_event(codec,
329 codec_dai->playback.stream_name, 319 codec_dai->playback.stream_name,
330 SND_SOC_DAPM_STREAM_STOP); 320 SND_SOC_DAPM_STREAM_STOP);
331
332 /* Fall into standby if no longer active */
333 if (codec->active == 0) {
334 pr_debug("pop wq D3 %s %s\n", codec->name,
335 codec_dai->playback.stream_name);
336 snd_soc_dapm_set_bias_level(socdev,
337 SND_SOC_BIAS_STANDBY);
338 }
339 } 321 }
340 } 322 }
341 mutex_unlock(&pcm_mutex); 323 mutex_unlock(&pcm_mutex);
@@ -399,10 +381,6 @@ static int soc_codec_close(struct snd_pcm_substream *substream)
399 snd_soc_dapm_stream_event(codec, 381 snd_soc_dapm_stream_event(codec,
400 codec_dai->capture.stream_name, 382 codec_dai->capture.stream_name,
401 SND_SOC_DAPM_STREAM_STOP); 383 SND_SOC_DAPM_STREAM_STOP);
402
403 if (codec->active == 0 && codec_dai->pop_wait == 0)
404 snd_soc_dapm_set_bias_level(socdev,
405 SND_SOC_BIAS_STANDBY);
406 } 384 }
407 385
408 mutex_unlock(&pcm_mutex); 386 mutex_unlock(&pcm_mutex);
@@ -467,36 +445,16 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
467 cancel_delayed_work(&card->delayed_work); 445 cancel_delayed_work(&card->delayed_work);
468 } 446 }
469 447
470 /* do we need to power up codec */ 448 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
471 if (codec->bias_level != SND_SOC_BIAS_ON) { 449 snd_soc_dapm_stream_event(codec,
472 snd_soc_dapm_set_bias_level(socdev, 450 codec_dai->playback.stream_name,
473 SND_SOC_BIAS_PREPARE); 451 SND_SOC_DAPM_STREAM_START);
474 452 else
475 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 453 snd_soc_dapm_stream_event(codec,
476 snd_soc_dapm_stream_event(codec, 454 codec_dai->capture.stream_name,
477 codec_dai->playback.stream_name, 455 SND_SOC_DAPM_STREAM_START);
478 SND_SOC_DAPM_STREAM_START);
479 else
480 snd_soc_dapm_stream_event(codec,
481 codec_dai->capture.stream_name,
482 SND_SOC_DAPM_STREAM_START);
483
484 snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_ON);
485 snd_soc_dai_digital_mute(codec_dai, 0);
486
487 } else {
488 /* codec already powered - power on widgets */
489 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
490 snd_soc_dapm_stream_event(codec,
491 codec_dai->playback.stream_name,
492 SND_SOC_DAPM_STREAM_START);
493 else
494 snd_soc_dapm_stream_event(codec,
495 codec_dai->capture.stream_name,
496 SND_SOC_DAPM_STREAM_START);
497 456
498 snd_soc_dai_digital_mute(codec_dai, 0); 457 snd_soc_dai_digital_mute(codec_dai, 0);
499 }
500 458
501out: 459out:
502 mutex_unlock(&pcm_mutex); 460 mutex_unlock(&pcm_mutex);
@@ -1372,6 +1330,7 @@ int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid)
1372 return ret; 1330 return ret;
1373 } 1331 }
1374 1332
1333 codec->socdev = socdev;
1375 codec->card->dev = socdev->dev; 1334 codec->card->dev = socdev->dev;
1376 codec->card->private_data = codec; 1335 codec->card->private_data = codec;
1377 strncpy(codec->card->driver, codec->name, sizeof(codec->card->driver)); 1336 strncpy(codec->card->driver, codec->name, sizeof(codec->card->driver));