summary refs log tree commit diff
path: root/sound/soc/soc-dapm.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/soc-dapm.c')
-rw-r--r--sound/soc/soc-dapm.c38
1 files changed, 29 insertions, 9 deletions
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 8348352dc2c6..2c456a376ade 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -326,12 +326,13 @@ static struct list_head *dapm_kcontrol_get_path_list(
 	list_for_each_entry(path, dapm_kcontrol_get_path_list(kcontrol), \
 		list_kcontrol)
 
-static unsigned int dapm_kcontrol_get_value(const struct snd_kcontrol *kcontrol)
+unsigned int dapm_kcontrol_get_value(const struct snd_kcontrol *kcontrol)
 {
 	struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol);
 
 	return data->value;
 }
+EXPORT_SYMBOL_GPL(dapm_kcontrol_get_value);
 
 static bool dapm_kcontrol_set_value(const struct snd_kcontrol *kcontrol,
 	unsigned int value)
@@ -1683,6 +1684,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.:-
@@ -1706,7 +1723,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;
@@ -1772,7 +1789,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);
@@ -2860,12 +2877,14 @@ int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol,
 	struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol);
 	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
 	unsigned int reg_val, val;
-	int ret = 0;
 
-	if (e->reg != SND_SOC_NOPM)
-		ret = soc_dapm_read(dapm, e->reg, &reg_val);
-	else
+	if (e->reg != SND_SOC_NOPM) {
+		int ret = soc_dapm_read(dapm, e->reg, &reg_val);
+		if (ret)
+			return ret;
+	} else {
 		reg_val = dapm_kcontrol_get_value(kcontrol);
+	}
 
 	val = (reg_val >> e->shift_l) & e->mask;
 	ucontrol->value.enumerated.item[0] = snd_soc_enum_val_to_item(e, val);
@@ -2875,7 +2894,7 @@ int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol,
 		ucontrol->value.enumerated.item[1] = val;
 	}
 
-	return ret;
+	return 0;
 }
 EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_double);
 
@@ -3107,7 +3126,8 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
 	}
 
 	w->dapm = dapm;
-	w->codec = dapm->codec;
+	if (dapm->component)
+		w->codec = dapm->component->codec;
 	INIT_LIST_HEAD(&w->sources);
 	INIT_LIST_HEAD(&w->sinks);
 	INIT_LIST_HEAD(&w->list);