diff options
-rw-r--r-- | include/sound/soc-dapm.h | 2 | ||||
-rw-r--r-- | include/sound/soc.h | 8 | ||||
-rw-r--r-- | sound/soc/soc-dapm.c | 60 |
3 files changed, 38 insertions, 32 deletions
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index c46e7d8..7415878 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -510,7 +510,7 @@ struct snd_soc_dapm_context { struct snd_soc_card *card; /* parent card */ /* used during DAPM updates */ - int dev_power; + enum snd_soc_bias_level target_bias_level; struct list_head list; #ifdef CONFIG_DEBUG_FS diff --git a/include/sound/soc.h b/include/sound/soc.h index f1de3e0..0f29700 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -214,10 +214,10 @@ * @OFF: Power Off. No restrictions on transition times. */ enum snd_soc_bias_level { - SND_SOC_BIAS_OFF, - SND_SOC_BIAS_STANDBY, - SND_SOC_BIAS_PREPARE, - SND_SOC_BIAS_ON, + SND_SOC_BIAS_OFF = 0, + SND_SOC_BIAS_STANDBY = 1, + SND_SOC_BIAS_PREPARE = 2, + SND_SOC_BIAS_ON = 3, }; struct snd_jack; diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 776e6f4..0bbded4 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -1042,16 +1042,17 @@ static void dapm_pre_sequence_async(void *data, async_cookie_t cookie) struct snd_soc_dapm_context *d = data; int ret; - if (d->dev_power && d->bias_level == SND_SOC_BIAS_OFF) { + /* If we're off and we're not supposed to be go into STANDBY */ + if (d->bias_level == SND_SOC_BIAS_OFF && + d->target_bias_level != SND_SOC_BIAS_OFF) { ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_STANDBY); if (ret != 0) dev_err(d->dev, "Failed to turn on bias: %d\n", ret); } - /* If we're changing to all on or all off then prepare */ - if ((d->dev_power && d->bias_level == SND_SOC_BIAS_STANDBY) || - (!d->dev_power && d->bias_level == SND_SOC_BIAS_ON)) { + /* Prepare for a STADDBY->ON or ON->STANDBY transition */ + if (d->bias_level != d->target_bias_level) { ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_PREPARE); if (ret != 0) dev_err(d->dev, @@ -1068,7 +1069,9 @@ static void dapm_post_sequence_async(void *data, async_cookie_t cookie) int ret; /* If we just powered the last thing off drop to standby bias */ - if (d->bias_level == SND_SOC_BIAS_PREPARE && !d->dev_power) { + if (d->bias_level == SND_SOC_BIAS_PREPARE && + (d->target_bias_level == SND_SOC_BIAS_STANDBY || + d->target_bias_level == SND_SOC_BIAS_OFF)) { ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_STANDBY); if (ret != 0) dev_err(d->dev, "Failed to apply standby bias: %d\n", @@ -1076,14 +1079,16 @@ static void dapm_post_sequence_async(void *data, async_cookie_t cookie) } /* If we're in standby and can support bias off then do that */ - if (d->bias_level == SND_SOC_BIAS_STANDBY && d->idle_bias_off) { + if (d->bias_level == SND_SOC_BIAS_STANDBY && + d->target_bias_level == SND_SOC_BIAS_OFF) { ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_OFF); if (ret != 0) dev_err(d->dev, "Failed to turn off bias: %d\n", ret); } /* If we just powered up then move to active bias */ - if (d->bias_level == SND_SOC_BIAS_PREPARE && d->dev_power) { + if (d->bias_level == SND_SOC_BIAS_PREPARE && + d->target_bias_level == SND_SOC_BIAS_ON) { ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_ON); if (ret != 0) dev_err(d->dev, "Failed to apply active bias: %d\n", @@ -1108,13 +1113,19 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event) LIST_HEAD(up_list); LIST_HEAD(down_list); LIST_HEAD(async_domain); + enum snd_soc_bias_level bias; int power; trace_snd_soc_dapm_start(card); - list_for_each_entry(d, &card->dapm_list, list) - if (d->n_widgets || d->codec == NULL) - d->dev_power = 0; + list_for_each_entry(d, &card->dapm_list, list) { + if (d->n_widgets || d->codec == NULL) { + if (d->idle_bias_off) + d->target_bias_level = SND_SOC_BIAS_OFF; + else + d->target_bias_level = SND_SOC_BIAS_STANDBY; + } + } /* Check which widgets we need to power and store them in * lists indicating if they should be powered up or down. @@ -1137,7 +1148,7 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event) else power = 1; if (power) - w->dapm->dev_power = 1; + w->dapm->target_bias_level = SND_SOC_BIAS_ON; if (w->power == power) continue; @@ -1161,24 +1172,19 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event) switch (event) { case SND_SOC_DAPM_STREAM_START: case SND_SOC_DAPM_STREAM_RESUME: - dapm->dev_power = 1; + dapm->target_bias_level = SND_SOC_BIAS_ON; break; case SND_SOC_DAPM_STREAM_STOP: - dapm->dev_power = !!dapm->codec->active; + if (dapm->codec->active) + dapm->target_bias_level = SND_SOC_BIAS_ON; + else + dapm->target_bias_level = SND_SOC_BIAS_STANDBY; break; case SND_SOC_DAPM_STREAM_SUSPEND: - dapm->dev_power = 0; + dapm->target_bias_level = SND_SOC_BIAS_STANDBY; break; case SND_SOC_DAPM_STREAM_NOP: - switch (dapm->bias_level) { - case SND_SOC_BIAS_STANDBY: - case SND_SOC_BIAS_OFF: - dapm->dev_power = 0; - break; - default: - dapm->dev_power = 1; - break; - } + dapm->target_bias_level = dapm->bias_level; break; default: break; @@ -1186,12 +1192,12 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event) } /* Force all contexts in the card to the same bias state */ - power = 0; + bias = SND_SOC_BIAS_OFF; list_for_each_entry(d, &card->dapm_list, list) - if (d->dev_power) - power = 1; + if (d->target_bias_level > bias) + bias = d->target_bias_level; list_for_each_entry(d, &card->dapm_list, list) - d->dev_power = power; + d->target_bias_level = bias; /* Run all the bias changes in parallel */ |