ASoC: Only run power_check() on a widget once per run
authorMark Brown <broonie@opensource.wolfsonmicro.com>
Tue, 4 Oct 2011 21:15:59 +0000 (22:15 +0100)
committerMark Brown <broonie@opensource.wolfsonmicro.com>
Wed, 5 Oct 2011 10:22:22 +0000 (11:22 +0100)
Some widgets will get power_check() run on them more than once during a
DAPM run, most commonly due to supply widgets checking to see if their
consumers are powered up. It's wasteful to do this so cache the result
of power_check() during a run. For one system I tested this on I got an
improvement of:

           Power    Path   Neighbour
Before:    106      970    1186
After:     69       727    905

from this.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
include/sound/soc-dapm.h
sound/soc/soc-dapm.c

index c080635b3c3551d45aa039c5e5bce2230ee1d115..e2853daf802ce0b1106c3fba3ab90a95778e3e27 100644 (file)
@@ -473,6 +473,8 @@ struct snd_soc_dapm_widget {
        unsigned char ext:1;                    /* has external widgets */
        unsigned char force:1;                  /* force state */
        unsigned char ignore_suspend:1;         /* kept enabled over suspend */
+       unsigned char new_power:1;              /* power from this run */
+       unsigned char power_checked:1;          /* power checked this run */
        int subseq;                             /* sort within widget type */
 
        int (*power_check)(struct snd_soc_dapm_widget *w);
index e6a08822227e207b54bfbb710cce47ede4311327..c39146d435e227217ce12cb68376332230863cc1 100644 (file)
@@ -787,10 +787,17 @@ EXPORT_SYMBOL_GPL(dapm_reg_event);
 
 static int dapm_widget_power_check(struct snd_soc_dapm_widget *w)
 {
+       if (w->power_checked)
+               return w->new_power;
+
        if (w->force)
-               return 1;
+               w->new_power = 1;
        else
-               return w->power_check(w);
+               w->new_power = w->power_check(w);
+
+       w->power_checked = true;
+
+       return w->new_power;
 }
 
 /* Generic check to see if a widget should be powered.
@@ -1322,6 +1329,10 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
 
        memset(&card->dapm_stats, 0, sizeof(card->dapm_stats));
 
+       list_for_each_entry(w, &card->widgets, list) {
+               w->power_checked = false;
+       }
+
        /* Check which widgets we need to power and store them in
         * lists indicating if they should be powered up or down.  We
         * only check widgets that have been flagged as dirty but note