ASoC: dapm: Add a flag to mark paths connected to supply widgets
authorLars-Peter Clausen <lars@metafoo.de>
Sat, 25 Oct 2014 15:42:00 +0000 (17:42 +0200)
committerMark Brown <broonie@kernel.org>
Tue, 28 Oct 2014 00:19:59 +0000 (00:19 +0000)
Supply widgets do not count towards the input and output widgets of their
neighbors and for supply widgets themselves we do not care for the number
of input or output paths. This means that a path that connects to a supply
widget effectively behaves the same as a path that as the weak property set.
This patch adds a new path flag that gets set to true when the path is
connected to at least one supply widget. If a path with the flag set is
encountered in is_connected_{input,output}_ep() is is skipped in the same
way that weak paths are skipped. This slightly brings down the number of
path checks.

Since both the weak and the supply flag are implemented as bitfields which
are stored in the same word there is no runtime overhead due to checking
both rather than just one and also the size of the path struct is not
increased by this patch. Another advantage is that we do not have to handle
supply widgets in is_connected_{input,output}_ep() anymore since it will
never be called for supply widgets. The only exception is from
dapm_widget_power_read_file() where a check is added to special case supply
widgets.

Testing with the ADAU1761, which has a handful of supply widgets, shows the
following changes in the DAPM stats for a playback stream start.

         Power  Path  Neighbour
Before:  34     78    117
After:   34     48    117

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Mark Brown <broonie@kernel.org>
include/sound/soc-dapm.h
sound/soc/soc-dapm.c

index 8cf3aad3086487060e9246cc1678ba143c2d0948..e7ebeb7174820e3c7e24eb8e38fbd46509a7d490 100644 (file)
@@ -510,6 +510,7 @@ struct snd_soc_dapm_path {
        u32 connect:1;  /* source and sink widgets are connected */
        u32 walking:1;  /* path is in the process of being walked */
        u32 weak:1;     /* path ignored for power management */
+       u32 is_supply:1;        /* At least one of the connected widgets is a supply */
 
        int (*connected)(struct snd_soc_dapm_widget *source,
                         struct snd_soc_dapm_widget *sink);
index 2cad5f77ec60cf7655e2628ef88a49d5f14ce94b..d89be153a9e0196c280e14f4f782b114fb8caa70 100644 (file)
@@ -821,9 +821,6 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget,
 
        DAPM_UPDATE_STAT(widget, path_checks);
 
-       if (widget->is_supply)
-               return 0;
-
        if (widget->is_sink && widget->connected) {
                widget->outputs = snd_soc_dapm_suspend_check(widget);
                return widget->outputs;
@@ -832,7 +829,7 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget,
        list_for_each_entry(path, &widget->sinks, list_source) {
                DAPM_UPDATE_STAT(widget, neighbour_checks);
 
-               if (path->weak)
+               if (path->weak || path->is_supply)
                        continue;
 
                if (path->walking)
@@ -882,9 +879,6 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget,
 
        DAPM_UPDATE_STAT(widget, path_checks);
 
-       if (widget->is_supply)
-               return 0;
-
        if (widget->is_source && widget->connected) {
                widget->inputs = snd_soc_dapm_suspend_check(widget);
                return widget->inputs;
@@ -893,7 +887,7 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget,
        list_for_each_entry(path, &widget->sources, list_sink) {
                DAPM_UPDATE_STAT(widget, neighbour_checks);
 
-               if (path->weak)
+               if (path->weak || path->is_supply)
                        continue;
 
                if (path->walking)
@@ -1691,8 +1685,14 @@ static ssize_t dapm_widget_power_read_file(struct file *file,
        if (!buf)
                return -ENOMEM;
 
-       in = is_connected_input_ep(w, NULL);
-       out = is_connected_output_ep(w, NULL);
+       /* Supply widgets are not handled by is_connected_{input,output}_ep() */
+       if (w->is_supply) {
+               in = 0;
+               out = 0;
+       } else {
+               in = is_connected_input_ep(w, NULL);
+               out = is_connected_output_ep(w, NULL);
+       }
 
        ret = snprintf(buf, PAGE_SIZE, "%s: %s%s  in %d out %d",
                       w->name, w->power ? "On" : "Off",
@@ -2213,6 +2213,9 @@ static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm,
        INIT_LIST_HEAD(&path->list_source);
        INIT_LIST_HEAD(&path->list_sink);
 
+       if (wsource->is_supply || wsink->is_supply)
+               path->is_supply = 1;
+
        /* connect static paths */
        if (control == NULL) {
                path->connect = 1;