aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/soc-dapm.c
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2010-05-07 15:24:05 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2010-05-10 05:36:36 -0400
commit9949788b793826f2d19e929ac0219ad0e0891e2d (patch)
treeed3fa0ff51350bf7da9735020a4d1849376bb56a /sound/soc/soc-dapm.c
parent50ae8384cde9a67714ff03010493c5052690624e (diff)
ASoC: Refactor DAPM suspend handling
Instead of using stream events to handle power down during suspend integrate the handling with the normal widget path checking by replacing all cases where we report a connected endpoint in a path with a function snd_soc_dapm_suspend_check() which looks at the ALSA power state for the card and reports false if we are in a D3 state. Since the core moves us into D3 prior to initating the suspend all power checks during suspend will cause the widgets to be powered down. In order to ensure that widgets are powered up on resume set the card to D2 at the start of resume handling (ALSA API calls require D0 so we are still protected against userspace access). Tested-by: Peter Ujfalusi <peter.ujfalusi@nokia.com> Acked-by: Liam Girdwood <lrg@slimlogic.co.uk> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/soc-dapm.c')
-rw-r--r--sound/soc/soc-dapm.c53
1 files changed, 30 insertions, 23 deletions
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index b30b0a255cd5..8c8b291320a8 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -430,6 +430,23 @@ static inline void dapm_clear_walk(struct snd_soc_codec *codec)
430 p->walked = 0; 430 p->walked = 0;
431} 431}
432 432
433/* We implement power down on suspend by checking the power state of
434 * the ALSA card - when we are suspending the ALSA state for the card
435 * is set to D3.
436 */
437static int snd_soc_dapm_suspend_check(struct snd_soc_dapm_widget *widget)
438{
439 struct snd_soc_codec *codec = widget->codec;
440
441 switch (snd_power_get_state(codec->card)) {
442 case SNDRV_CTL_POWER_D3hot:
443 case SNDRV_CTL_POWER_D3cold:
444 return 0;
445 default:
446 return 1;
447 }
448}
449
433/* 450/*
434 * Recursively check for a completed path to an active or physically connected 451 * Recursively check for a completed path to an active or physically connected
435 * output widget. Returns number of complete paths. 452 * output widget. Returns number of complete paths.
@@ -446,7 +463,7 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget)
446 case snd_soc_dapm_adc: 463 case snd_soc_dapm_adc:
447 case snd_soc_dapm_aif_out: 464 case snd_soc_dapm_aif_out:
448 if (widget->active) 465 if (widget->active)
449 return 1; 466 return snd_soc_dapm_suspend_check(widget);
450 default: 467 default:
451 break; 468 break;
452 } 469 }
@@ -454,12 +471,12 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget)
454 if (widget->connected) { 471 if (widget->connected) {
455 /* connected pin ? */ 472 /* connected pin ? */
456 if (widget->id == snd_soc_dapm_output && !widget->ext) 473 if (widget->id == snd_soc_dapm_output && !widget->ext)
457 return 1; 474 return snd_soc_dapm_suspend_check(widget);
458 475
459 /* connected jack or spk ? */ 476 /* connected jack or spk ? */
460 if (widget->id == snd_soc_dapm_hp || widget->id == snd_soc_dapm_spk || 477 if (widget->id == snd_soc_dapm_hp || widget->id == snd_soc_dapm_spk ||
461 (widget->id == snd_soc_dapm_line && !list_empty(&widget->sources))) 478 (widget->id == snd_soc_dapm_line && !list_empty(&widget->sources)))
462 return 1; 479 return snd_soc_dapm_suspend_check(widget);
463 } 480 }
464 481
465 list_for_each_entry(path, &widget->sinks, list_source) { 482 list_for_each_entry(path, &widget->sinks, list_source) {
@@ -492,7 +509,7 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget)
492 case snd_soc_dapm_dac: 509 case snd_soc_dapm_dac:
493 case snd_soc_dapm_aif_in: 510 case snd_soc_dapm_aif_in:
494 if (widget->active) 511 if (widget->active)
495 return 1; 512 return snd_soc_dapm_suspend_check(widget);
496 default: 513 default:
497 break; 514 break;
498 } 515 }
@@ -500,16 +517,16 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget)
500 if (widget->connected) { 517 if (widget->connected) {
501 /* connected pin ? */ 518 /* connected pin ? */
502 if (widget->id == snd_soc_dapm_input && !widget->ext) 519 if (widget->id == snd_soc_dapm_input && !widget->ext)
503 return 1; 520 return snd_soc_dapm_suspend_check(widget);
504 521
505 /* connected VMID/Bias for lower pops */ 522 /* connected VMID/Bias for lower pops */
506 if (widget->id == snd_soc_dapm_vmid) 523 if (widget->id == snd_soc_dapm_vmid)
507 return 1; 524 return snd_soc_dapm_suspend_check(widget);
508 525
509 /* connected jack ? */ 526 /* connected jack ? */
510 if (widget->id == snd_soc_dapm_mic || 527 if (widget->id == snd_soc_dapm_mic ||
511 (widget->id == snd_soc_dapm_line && !list_empty(&widget->sinks))) 528 (widget->id == snd_soc_dapm_line && !list_empty(&widget->sinks)))
512 return 1; 529 return snd_soc_dapm_suspend_check(widget);
513 } 530 }
514 531
515 list_for_each_entry(path, &widget->sources, list_sink) { 532 list_for_each_entry(path, &widget->sources, list_sink) {
@@ -897,22 +914,12 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
897 if (!w->power_check) 914 if (!w->power_check)
898 continue; 915 continue;
899 916
900 /* If we're suspending then pull down all the 917 if (!w->force)
901 * power. */ 918 power = w->power_check(w);
902 switch (event) { 919 else
903 case SND_SOC_DAPM_STREAM_SUSPEND: 920 power = 1;
904 power = 0; 921 if (power)
905 break; 922 sys_power = 1;
906
907 default:
908 if (!w->force)
909 power = w->power_check(w);
910 else
911 power = 1;
912 if (power)
913 sys_power = 1;
914 break;
915 }
916 923
917 if (w->power == power) 924 if (w->power == power)
918 continue; 925 continue;