summaryrefslogtreecommitdiffstats
path: root/sound/soc
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2010-01-19 22:49:43 +0000
committerMark Brown <broonie@opensource.wolfsonmicro.com>2010-01-21 12:04:08 +0000
commita96ca3387382498ec8b501db5acef3ed9eb1bd36 (patch)
tree3bc8d76f8796b0e555585802576fc2fed574587a /sound/soc
parentb91b8fa02482a5a18f598ee5d2cd42970051731b (diff)
downloadlinux-stable-a96ca3387382498ec8b501db5acef3ed9eb1bd36.tar.gz
linux-stable-a96ca3387382498ec8b501db5acef3ed9eb1bd36.tar.bz2
linux-stable-a96ca3387382498ec8b501db5acef3ed9eb1bd36.zip
ASoC: Support turning off bias when the CODEC is idle
Currently ASoC always maintains the bias of the CODEC while the system is active. With older mobile CODECs this is required since the outputs are referenced to a non-zero voltage and enabling or disabling this voltage without audible pops or clicks in the output takes too long to do when starting or stopping audio. As a result of features such as ground referenced outputs and class D speaker drivers current generation devices are able to power on and off much more quickly without these system level issues so provide a new flag idle_bias_off in snd_soc_codec which will cause the core to turn off the CODEC bias. The distinction between STANDBY and OFF is still maintained. This is partly for consistency but also allows for potential future extensions such as per-machine overrides or deferring the bias removal. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Acked-by: Liam Girdwood <lrg@slimlogic.co.uk>
Diffstat (limited to 'sound/soc')
-rw-r--r--sound/soc/soc-dapm.c25
1 files changed, 24 insertions, 1 deletions
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index d8e93749321e..6c3351095786 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -1012,13 +1012,28 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
sys_power = 0;
break;
case SND_SOC_DAPM_STREAM_NOP:
- sys_power = codec->bias_level != SND_SOC_BIAS_STANDBY;
+ switch (codec->bias_level) {
+ case SND_SOC_BIAS_STANDBY:
+ case SND_SOC_BIAS_OFF:
+ sys_power = 0;
+ break;
+ default:
+ sys_power = 1;
+ break;
+ }
break;
default:
break;
}
}
+ if (sys_power && codec->bias_level == SND_SOC_BIAS_OFF) {
+ ret = snd_soc_dapm_set_bias_level(socdev,
+ SND_SOC_BIAS_STANDBY);
+ if (ret != 0)
+ pr_err("Failed to turn on bias: %d\n", ret);
+ }
+
/* If we're changing to all on or all off then prepare */
if ((sys_power && codec->bias_level == SND_SOC_BIAS_STANDBY) ||
(!sys_power && codec->bias_level == SND_SOC_BIAS_ON)) {
@@ -1042,6 +1057,14 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
pr_err("Failed to apply standby bias: %d\n", ret);
}
+ /* If we're in standby and can support bias off then do that */
+ if (codec->bias_level == SND_SOC_BIAS_STANDBY &&
+ codec->idle_bias_off) {
+ ret = snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_OFF);
+ if (ret != 0)
+ pr_err("Failed to turn off bias: %d\n", ret);
+ }
+
/* If we just powered up then move to active bias */
if (codec->bias_level == SND_SOC_BIAS_PREPARE && sys_power) {
ret = snd_soc_dapm_set_bias_level(socdev,