diff options
author | Lars-Peter Clausen <lars@metafoo.de> | 2014-09-04 19:44:06 +0200 |
---|---|---|
committer | Zidan Wang <zidan.wang@freescale.com> | 2015-10-30 14:58:01 +0800 |
commit | f42914b80a3ef5d04cd9ac56b57b1f6b9c94f09a (patch) | |
tree | 3b81c86529f07285eaffaa44ffa2e43d5c5c6f67 | |
parent | b2ac46adf4c2f49f3c94f3c15c33d4abf27b7a6a (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>
(cherry picked from commit 86dbf2ac6fcb2d2932d4610f2dfe0954aa0633f7)
Conflicts:
sound/soc/soc-core.c
-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 13412ab158ee..5f2ce73096c8 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -625,7 +625,8 @@ struct snd_soc_dapm_context { enum snd_soc_bias_level suspend_bias_level; struct delayed_work delayed_work; unsigned int idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */ - + /* Go to BIAS_OFF in suspend if the DAPM context is idle */ + unsigned int suspend_bias_off:1; void (*seq_notifier)(struct snd_soc_dapm_context *, enum snd_soc_dapm_type, int); diff --git a/include/sound/soc.h b/include/sound/soc.h index 59a47851f5c8..91a9efd80b16 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -774,6 +774,7 @@ struct snd_soc_codec_driver { int (*set_bias_level)(struct snd_soc_codec *, enum snd_soc_bias_level level); bool idle_bias_off; + bool suspend_bias_off; void (*seq_notifier)(struct snd_soc_dapm_context *, enum snd_soc_dapm_type, int); diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 56a21e726b67..e00ce586994a 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -4375,6 +4375,7 @@ int snd_soc_register_codec(struct device *dev, codec->dapm.codec = codec; codec->dapm.seq_notifier = codec_drv->seq_notifier; codec->dapm.stream_event = codec_drv->stream_event; + codec->dapm.suspend_bias_off = codec_drv->suspend_bias_off; codec->dev = dev; codec->driver = codec_drv; codec->num_dai = num_dai; diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index f504fae027a2..331a4403a64b 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -1807,6 +1807,22 @@ static void dapm_power_one_widget(struct snd_soc_dapm_widget *w, } } +static bool dapm_idle_bias_off(struct snd_soc_dapm_context *dapm) +{ + if (dapm->idle_bias_off) + return true; + + switch (snd_power_get_state(dapm->card->snd_card)) { + case SNDRV_CTL_POWER_D3hot: + case SNDRV_CTL_POWER_D3cold: + return dapm->suspend_bias_off; + default: + break; + } + + return false; +} + /* * Scan each dapm widget for complete audio path. * A complete path is a route that has valid endpoints i.e.:- @@ -1828,7 +1844,7 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event) trace_snd_soc_dapm_start(card); list_for_each_entry(d, &card->dapm_list, list) { - if (d->idle_bias_off) + if (dapm_idle_bias_off(d)) d->target_bias_level = SND_SOC_BIAS_OFF; else d->target_bias_level = SND_SOC_BIAS_STANDBY; @@ -1894,7 +1910,7 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event) if (d->target_bias_level > bias) bias = d->target_bias_level; list_for_each_entry(d, &card->dapm_list, list) - if (!d->idle_bias_off) + if (!dapm_idle_bias_off(d)) d->target_bias_level = bias; trace_snd_soc_dapm_walk_done(card); |