]> git.karo-electronics.de Git - linux-beck.git/commitdiff
ASoC: dapm: Fix handling of loops
authorMark Brown <broonie@opensource.wolfsonmicro.com>
Fri, 22 Feb 2013 17:48:15 +0000 (17:48 +0000)
committerMark Brown <broonie@opensource.wolfsonmicro.com>
Mon, 25 Feb 2013 13:51:22 +0000 (13:51 +0000)
Currently if a path loops back on itself we correctly skip over it to
avoid going into an infinite loop but this causes us to ignore the need
to power up the path as we don't count the loop for the purposes of
counting inputs and outputs. This means that internal loopbacks within a
device that have powered devices on them won't be powered up.

Fix this by treating any path that is currently in the process of being
recursed as having a single input or output so that it is counted for
the purposes of power decisions.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Acked-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
include/sound/soc-dapm.h
sound/soc/soc-dapm.c

index e1ef63d4a5c453b17630b279d5780b32f1e722c3..44a30b1086835d1d1fcc2840bb5328d5a2ce19b2 100644 (file)
@@ -488,6 +488,7 @@ struct snd_soc_dapm_path {
        /* status */
        u32 connect:1;  /* source and sink widgets are connected */
        u32 walked:1;   /* path has been walked */
+       u32 walking:1;  /* path is in the process of being walked */
        u32 weak:1;     /* path ignored for power management */
 
        int (*connected)(struct snd_soc_dapm_widget *source,
index 258acadb9e7d238a97b7af6508ffc21bd1a4488e..f3255517de798fef0df171afbc9699ce9b59a667 100644 (file)
@@ -821,6 +821,7 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget,
                    (widget->id == snd_soc_dapm_line &&
                     !list_empty(&widget->sources))) {
                        widget->outputs = snd_soc_dapm_suspend_check(widget);
+                       path->walking = 0;
                        return widget->outputs;
                }
        }
@@ -831,6 +832,9 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget,
                if (path->weak)
                        continue;
 
+               if (path->walking)
+                       return 1;
+
                if (path->walked)
                        continue;
 
@@ -838,6 +842,7 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget,
 
                if (path->sink && path->connect) {
                        path->walked = 1;
+                       path->walking = 1;
 
                        /* do we need to add this widget to the list ? */
                        if (list) {
@@ -847,11 +852,14 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget,
                                        dev_err(widget->dapm->dev,
                                                "ASoC: could not add widget %s\n",
                                                widget->name);
+                                       path->walking = 0;
                                        return con;
                                }
                        }
 
                        con += is_connected_output_ep(path->sink, list);
+
+                       path->walking = 0;
                }
        }
 
@@ -931,6 +939,9 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget,
                if (path->weak)
                        continue;
 
+               if (path->walking)
+                       return 1;
+
                if (path->walked)
                        continue;
 
@@ -938,6 +949,7 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget,
 
                if (path->source && path->connect) {
                        path->walked = 1;
+                       path->walking = 1;
 
                        /* do we need to add this widget to the list ? */
                        if (list) {
@@ -947,11 +959,14 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget,
                                        dev_err(widget->dapm->dev,
                                                "ASoC: could not add widget %s\n",
                                                widget->name);
+                                       path->walking = 0;
                                        return con;
                                }
                        }
 
                        con += is_connected_input_ep(path->source, list);
+
+                       path->walking = 0;
                }
        }