ASoC: Specify target bias state directly as a bias state
[firefly-linux-kernel-4.4.55.git] / sound / soc / soc-dapm.c
index 776e6f418306fe004936692fd70dab7c89cdec6d..0bbded43e21367471a8273ddf0f1e2a0d41cf850 100644 (file)
@@ -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 */