diff options
author | Lars-Peter Clausen <lars@metafoo.de> | 2014-09-04 13:44:06 -0400 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2014-09-04 15:10:25 -0400 |
commit | 86dbf2ac6fcb2d2932d4610f2dfe0954aa0633f7 (patch) | |
tree | eca1064e4c727feb98ab402f81f3f8b83e3f0bd1 | |
parent | 1c325f771a88579f227fe017e4ee77d852cf5435 (diff) |
ASoC: Add support for automatically going to BIAS_OFF on suspend
There is a substantial amount of drivers that in go to SND_SOC_BIAS_OFF on
suspend and go back to SND_SOC_BIAS_SUSPEND on resume (Often this is even
the only thing done in the suspend and resume handlers). This patch
introduces a new suspend_bias_off flag, which when set by a driver will let
the ASoC core automatically put the device's DAPM context at the
SND_SOC_BIAS_OFF level during suspend. Once the device is resumed the DAPM
context will go back to SND_SOC_BIAS_STANDBY (if the context is idle,
otherwise to SND_SOC_BIAS_ON).
This will allow us to remove a fair bit of duplicated code from the drivers.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r-- | include/sound/soc-dapm.h | 3 | ||||
-rw-r--r-- | include/sound/soc.h | 1 | ||||
-rw-r--r-- | sound/soc/soc-core.c | 1 | ||||
-rw-r--r-- | sound/soc/soc-dapm.c | 20 |
4 files changed, 22 insertions, 3 deletions
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index aac04ff84eea..f955d65c5656 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h | |||
@@ -587,7 +587,8 @@ struct snd_soc_dapm_context { | |||
587 | enum snd_soc_bias_level suspend_bias_level; | 587 | enum snd_soc_bias_level suspend_bias_level; |
588 | struct delayed_work delayed_work; | 588 | struct delayed_work delayed_work; |
589 | unsigned int idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */ | 589 | unsigned int idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */ |
590 | 590 | /* Go to BIAS_OFF in suspend if the DAPM context is idle */ | |
591 | unsigned int suspend_bias_off:1; | ||
591 | void (*seq_notifier)(struct snd_soc_dapm_context *, | 592 | void (*seq_notifier)(struct snd_soc_dapm_context *, |
592 | enum snd_soc_dapm_type, int); | 593 | enum snd_soc_dapm_type, int); |
593 | 594 | ||
diff --git a/include/sound/soc.h b/include/sound/soc.h index ce09302bfd6d..ac99fc083eec 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h | |||
@@ -848,6 +848,7 @@ struct snd_soc_codec_driver { | |||
848 | int (*set_bias_level)(struct snd_soc_codec *, | 848 | int (*set_bias_level)(struct snd_soc_codec *, |
849 | enum snd_soc_bias_level level); | 849 | enum snd_soc_bias_level level); |
850 | bool idle_bias_off; | 850 | bool idle_bias_off; |
851 | bool suspend_bias_off; | ||
851 | 852 | ||
852 | void (*seq_notifier)(struct snd_soc_dapm_context *, | 853 | void (*seq_notifier)(struct snd_soc_dapm_context *, |
853 | enum snd_soc_dapm_type, int); | 854 | enum snd_soc_dapm_type, int); |
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 068785fa1a06..2bdf9a4ac2b4 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -4402,6 +4402,7 @@ int snd_soc_register_codec(struct device *dev, | |||
4402 | codec->component.ignore_pmdown_time = codec_drv->ignore_pmdown_time; | 4402 | codec->component.ignore_pmdown_time = codec_drv->ignore_pmdown_time; |
4403 | codec->dapm.codec = codec; | 4403 | codec->dapm.codec = codec; |
4404 | codec->dapm.idle_bias_off = codec_drv->idle_bias_off; | 4404 | codec->dapm.idle_bias_off = codec_drv->idle_bias_off; |
4405 | codec->dapm.suspend_bias_off = codec_drv->suspend_bias_off; | ||
4405 | if (codec_drv->seq_notifier) | 4406 | if (codec_drv->seq_notifier) |
4406 | codec->dapm.seq_notifier = codec_drv->seq_notifier; | 4407 | codec->dapm.seq_notifier = codec_drv->seq_notifier; |
4407 | if (codec_drv->set_bias_level) | 4408 | if (codec_drv->set_bias_level) |
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 8348352dc2c6..a2025a6b6a29 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c | |||
@@ -1683,6 +1683,22 @@ static void dapm_power_one_widget(struct snd_soc_dapm_widget *w, | |||
1683 | } | 1683 | } |
1684 | } | 1684 | } |
1685 | 1685 | ||
1686 | static bool dapm_idle_bias_off(struct snd_soc_dapm_context *dapm) | ||
1687 | { | ||
1688 | if (dapm->idle_bias_off) | ||
1689 | return true; | ||
1690 | |||
1691 | switch (snd_power_get_state(dapm->card->snd_card)) { | ||
1692 | case SNDRV_CTL_POWER_D3hot: | ||
1693 | case SNDRV_CTL_POWER_D3cold: | ||
1694 | return dapm->suspend_bias_off; | ||
1695 | default: | ||
1696 | break; | ||
1697 | } | ||
1698 | |||
1699 | return false; | ||
1700 | } | ||
1701 | |||
1686 | /* | 1702 | /* |
1687 | * Scan each dapm widget for complete audio path. | 1703 | * Scan each dapm widget for complete audio path. |
1688 | * A complete path is a route that has valid endpoints i.e.:- | 1704 | * A complete path is a route that has valid endpoints i.e.:- |
@@ -1706,7 +1722,7 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event) | |||
1706 | trace_snd_soc_dapm_start(card); | 1722 | trace_snd_soc_dapm_start(card); |
1707 | 1723 | ||
1708 | list_for_each_entry(d, &card->dapm_list, list) { | 1724 | list_for_each_entry(d, &card->dapm_list, list) { |
1709 | if (d->idle_bias_off) | 1725 | if (dapm_idle_bias_off(d)) |
1710 | d->target_bias_level = SND_SOC_BIAS_OFF; | 1726 | d->target_bias_level = SND_SOC_BIAS_OFF; |
1711 | else | 1727 | else |
1712 | d->target_bias_level = SND_SOC_BIAS_STANDBY; | 1728 | d->target_bias_level = SND_SOC_BIAS_STANDBY; |
@@ -1772,7 +1788,7 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event) | |||
1772 | if (d->target_bias_level > bias) | 1788 | if (d->target_bias_level > bias) |
1773 | bias = d->target_bias_level; | 1789 | bias = d->target_bias_level; |
1774 | list_for_each_entry(d, &card->dapm_list, list) | 1790 | list_for_each_entry(d, &card->dapm_list, list) |
1775 | if (!d->idle_bias_off) | 1791 | if (!dapm_idle_bias_off(d)) |
1776 | d->target_bias_level = bias; | 1792 | d->target_bias_level = bias; |
1777 | 1793 | ||
1778 | trace_snd_soc_dapm_walk_done(card); | 1794 | trace_snd_soc_dapm_walk_done(card); |