ASoC: Coalesce power updates for DAPM widgets with events
authorMark Brown <broonie@opensource.wolfsonmicro.com>
Sun, 7 Jun 2009 12:21:24 +0000 (13:21 +0100)
committerMark Brown <broonie@opensource.wolfsonmicro.com>
Mon, 8 Jun 2009 12:51:59 +0000 (13:51 +0100)
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
sound/soc/soc-dapm.c

index 9187db18a0424dec5b2ac581676704b905d7948a..3fc791c28aa83ac9d4d01fb959a64fd840a32df4 100644 (file)
@@ -740,7 +740,7 @@ static void dapm_seq_run_coalesced(struct snd_soc_codec *codec,
                                   struct list_head *pending)
 {
        struct snd_soc_dapm_widget *w;
-       int reg, power;
+       int reg, power, ret;
        unsigned int value = 0;
        unsigned int mask = 0;
        unsigned int cur_mask;
@@ -764,13 +764,62 @@ static void dapm_seq_run_coalesced(struct snd_soc_codec *codec,
                pop_dbg(codec->pop_time,
                        "pop test : Queue %s: reg=0x%x, 0x%x/0x%x\n",
                        w->name, reg, value, mask);
+
+               /* power up pre event */
+               if (w->power && w->event &&
+                   (w->event_flags & SND_SOC_DAPM_PRE_PMU)) {
+                       pop_dbg(codec->pop_time, "pop test : %s PRE_PMU\n",
+                               w->name);
+                       ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMU);
+                       if (ret < 0)
+                               pr_err("%s: pre event failed: %d\n",
+                                      w->name, ret);
+               }
+
+               /* power down pre event */
+               if (!w->power && w->event &&
+                   (w->event_flags & SND_SOC_DAPM_PRE_PMD)) {
+                       pop_dbg(codec->pop_time, "pop test : %s PRE_PMD\n",
+                               w->name);
+                       ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMD);
+                       if (ret < 0)
+                               pr_err("%s: pre event failed: %d\n",
+                                      w->name, ret);
+               }
+       }
+
+       if (reg >= 0) {
+               pop_dbg(codec->pop_time,
+                       "pop test : Applying 0x%x/0x%x to %x in %dms\n",
+                       value, mask, reg, codec->pop_time);
+               pop_wait(codec->pop_time);
+               snd_soc_update_bits(codec, reg, mask, value);
        }
 
-       pop_dbg(codec->pop_time,
-               "pop test : Applying 0x%x/0x%x to %x in %dms\n",
-               value, mask, reg, codec->pop_time);
-       pop_wait(codec->pop_time);
-       snd_soc_update_bits(codec, reg, mask, value);
+       list_for_each_entry(w, pending, power_list) {
+               /* power up post event */
+               if (w->power && w->event &&
+                   (w->event_flags & SND_SOC_DAPM_POST_PMU)) {
+                       pop_dbg(codec->pop_time, "pop test : %s POST_PMU\n",
+                               w->name);
+                       ret = w->event(w,
+                                      NULL, SND_SOC_DAPM_POST_PMU);
+                       if (ret < 0)
+                               pr_err("%s: post event failed: %d\n",
+                                      w->name, ret);
+               }
+
+               /* power down post event */
+               if (!w->power && w->event &&
+                   (w->event_flags & SND_SOC_DAPM_POST_PMD)) {
+                       pop_dbg(codec->pop_time, "pop test : %s POST_PMD\n",
+                               w->name);
+                       ret = w->event(w, NULL, SND_SOC_DAPM_POST_PMD);
+                       if (ret < 0)
+                               pr_err("%s: post event failed: %d\n",
+                                      w->name, ret);
+               }
+       }
 }
 
 /* Apply a DAPM power sequence.
@@ -843,16 +892,11 @@ static void dapm_seq_run(struct snd_soc_codec *codec, struct list_head *list,
                        break;
 
                default:
-                       /* If there's an event or an invalid register
-                        * then run immediately, otherwise store the
-                        * updates so that we can coalesce. */
-                       if (w->reg >= 0 && !w->event) {
-                               cur_sort = sort[w->id];
-                               cur_reg = w->reg;
-                               list_move(&w->power_list, &pending);
-                       } else {
-                               ret = dapm_generic_apply_power(w);
-                       }
+                       /* Queue it up for application */
+                       cur_sort = sort[w->id];
+                       cur_reg = w->reg;
+                       list_move(&w->power_list, &pending);
+                       break;
                }
 
                if (ret < 0)