diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2010-05-07 15:24:05 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2010-05-10 05:36:36 -0400 |
commit | 9949788b793826f2d19e929ac0219ad0e0891e2d (patch) | |
tree | ed3fa0ff51350bf7da9735020a4d1849376bb56a | |
parent | 50ae8384cde9a67714ff03010493c5052690624e (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>
-rw-r--r-- | sound/soc/soc-core.c | 3 | ||||
-rw-r--r-- | sound/soc/soc-dapm.c | 53 |
2 files changed, 33 insertions, 23 deletions
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 4079223203eb..95739767ec45 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -963,6 +963,9 @@ static void soc_resume_deferred(struct work_struct *work) | |||
963 | 963 | ||
964 | dev_dbg(socdev->dev, "starting resume work\n"); | 964 | dev_dbg(socdev->dev, "starting resume work\n"); |
965 | 965 | ||
966 | /* Bring us up into D2 so that DAPM starts enabling things */ | ||
967 | snd_power_change_state(codec->card, SNDRV_CTL_POWER_D2); | ||
968 | |||
966 | if (card->resume_pre) | 969 | if (card->resume_pre) |
967 | card->resume_pre(pdev); | 970 | card->resume_pre(pdev); |
968 | 971 | ||
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 | */ | ||
437 | static 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; |