aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars-Peter Clausen <lars@metafoo.de>2014-09-04 13:44:06 -0400
committerMark Brown <broonie@kernel.org>2014-09-04 15:10:25 -0400
commit86dbf2ac6fcb2d2932d4610f2dfe0954aa0633f7 (patch)
treeeca1064e4c727feb98ab402f81f3f8b83e3f0bd1
parent1c325f771a88579f227fe017e4ee77d852cf5435 (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.h3
-rw-r--r--include/sound/soc.h1
-rw-r--r--sound/soc/soc-core.c1
-rw-r--r--sound/soc/soc-dapm.c20
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
1686static 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);