summaryrefslogtreecommitdiff
path: root/sound/soc/soc-dapm.c
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2009-05-18 00:41:23 +0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2009-05-18 18:53:16 +0400
commit452c5eaa0d5162e02ffee742ea17540887bc2904 (patch)
tree7dbac625d69e3ff01445d7f1b1fa321aa35fcae5 /sound/soc/soc-dapm.c
parentaef908434cd24dd5529065bf5d781773fad21125 (diff)
downloadlinux-452c5eaa0d5162e02ffee742ea17540887bc2904.tar.xz
ASoC: Integrate bias management with DAPM power management
Rather than managing the bias level of the system based on if there is an active audio stream manage it based on there being an active DAPM widget. This simplifies the code a little, moving the power handling into one place, and improves audio performance for bypass paths when no playbacks or captures are active. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/soc-dapm.c')
-rw-r--r--sound/soc/soc-dapm.c78
1 files changed, 54 insertions, 24 deletions
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index d130602b3072..4ca5e56388a3 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -94,6 +94,30 @@ static inline struct snd_soc_dapm_widget *dapm_cnew_widget(
return kmemdup(_widget, sizeof(*_widget), GFP_KERNEL);
}
+/**
+ * snd_soc_dapm_set_bias_level - set the bias level for the system
+ * @socdev: audio device
+ * @level: level to configure
+ *
+ * Configure the bias (power) levels for the SoC audio device.
+ *
+ * Returns 0 for success else error.
+ */
+static int snd_soc_dapm_set_bias_level(struct snd_soc_device *socdev,
+ enum snd_soc_bias_level level)
+{
+ struct snd_soc_card *card = socdev->card;
+ struct snd_soc_codec *codec = socdev->card->codec;
+ int ret = 0;
+
+ if (card->set_bias_level)
+ ret = card->set_bias_level(card, level);
+ if (ret == 0 && codec->set_bias_level)
+ ret = codec->set_bias_level(codec, level);
+
+ return ret;
+}
+
/* set up initial codec paths */
static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
struct snd_soc_dapm_path *p, int i)
@@ -707,9 +731,11 @@ static int dapm_power_widget(struct snd_soc_codec *codec, int event,
*/
static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
{
+ struct snd_soc_device *socdev = codec->socdev;
struct snd_soc_dapm_widget *w;
int ret = 0;
int i, power;
+ int sys_power = 0;
INIT_LIST_HEAD(&codec->up_list);
INIT_LIST_HEAD(&codec->down_list);
@@ -731,6 +757,9 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
continue;
power = w->power_check(w);
+ if (power)
+ sys_power = 1;
+
if (w->power == power)
continue;
@@ -745,6 +774,15 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
}
}
+ /* 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)) {
+ ret = snd_soc_dapm_set_bias_level(socdev,
+ SND_SOC_BIAS_PREPARE);
+ if (ret != 0)
+ pr_err("Failed to prepare bias: %d\n", ret);
+ }
+
/* Power down widgets first; try to avoid amplifying pops. */
for (i = 0; i < ARRAY_SIZE(dapm_down_seq); i++) {
list_for_each_entry(w, &codec->down_list, power_list) {
@@ -773,6 +811,22 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
}
}
+ /* If we just powered the last thing off drop to standby bias */
+ if (codec->bias_level == SND_SOC_BIAS_PREPARE && !sys_power) {
+ ret = snd_soc_dapm_set_bias_level(socdev,
+ SND_SOC_BIAS_STANDBY);
+ if (ret != 0)
+ pr_err("Failed to apply standby 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,
+ SND_SOC_BIAS_ON);
+ if (ret != 0)
+ pr_err("Failed to apply active bias: %d\n", ret);
+ }
+
return 0;
}
@@ -1721,30 +1775,6 @@ int snd_soc_dapm_stream_event(struct snd_soc_codec *codec,
EXPORT_SYMBOL_GPL(snd_soc_dapm_stream_event);
/**
- * snd_soc_dapm_set_bias_level - set the bias level for the system
- * @socdev: audio device
- * @level: level to configure
- *
- * Configure the bias (power) levels for the SoC audio device.
- *
- * Returns 0 for success else error.
- */
-int snd_soc_dapm_set_bias_level(struct snd_soc_device *socdev,
- enum snd_soc_bias_level level)
-{
- struct snd_soc_card *card = socdev->card;
- struct snd_soc_codec *codec = socdev->card->codec;
- int ret = 0;
-
- if (card->set_bias_level)
- ret = card->set_bias_level(card, level);
- if (ret == 0 && codec->set_bias_level)
- ret = codec->set_bias_level(codec, level);
-
- return ret;
-}
-
-/**
* snd_soc_dapm_enable_pin - enable pin.
* @codec: SoC codec
* @pin: pin name