summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 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);