ASoC: dapm: Keep a list of paths per kcontrol
authorLars-Peter Clausen <lars@metafoo.de>
Mon, 29 Jul 2013 15:14:00 +0000 (17:14 +0200)
committerMark Brown <broonie@linaro.org>
Mon, 29 Jul 2013 17:41:00 +0000 (18:41 +0100)
Currently we store for each path which control (if any at all) is associated
with that control. But we are only ever interested in the reverse relationship,
i.e. we want to know all the paths a certain control is associated with. This is
currently implemented by always iterating over all paths. This patch updates the
code to keep a list for each control which contains all the paths that are
associated with that control. This improves the run time of e.g.
soc_dapm_mixer_update_power() and soc_dapm_mux_update_power() from O(n) (with n
being the number of paths for the card) to O(1).

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

index d7d26cc8e3fc9aa7833e8740bcd5ca75b7f59bd2..693c75bbd5d12e5ddb7e365a1837499120203559 100644 (file)
@@ -490,7 +490,6 @@ struct snd_soc_dapm_path {
        /* source (input) and sink (output) widgets */
        struct snd_soc_dapm_widget *source;
        struct snd_soc_dapm_widget *sink;
-       struct snd_kcontrol *kcontrol;
 
        /* status */
        u32 connect:1;  /* source and sink widgets are connected */
@@ -503,6 +502,7 @@ struct snd_soc_dapm_path {
 
        struct list_head list_source;
        struct list_head list_sink;
+       struct list_head list_kcontrol;
        struct list_head list;
 };
 
index bad6f6db74c93c34b2b561de46b7af091eee9c7d..b779d36d5b3acfb456d06c0475850075442f6abf 100644 (file)
@@ -176,6 +176,7 @@ static inline struct snd_soc_dapm_widget *dapm_cnew_widget(
 
 struct dapm_kcontrol_data {
        unsigned int value;
+       struct list_head paths;
        struct snd_soc_dapm_widget_list wlist;
 };
 
@@ -194,6 +195,7 @@ static int dapm_kcontrol_data_alloc(struct snd_soc_dapm_widget *widget,
 
        data->wlist.widgets[0] = widget;
        data->wlist.num_widgets = 1;
+       INIT_LIST_HEAD(&data->paths);
 
        kcontrol->private_data = data;
 
@@ -234,6 +236,26 @@ static int dapm_kcontrol_add_widget(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
+static void dapm_kcontrol_add_path(const struct snd_kcontrol *kcontrol,
+       struct snd_soc_dapm_path *path)
+{
+       struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol);
+
+       list_add_tail(&path->list_kcontrol, &data->paths);
+}
+
+static struct list_head *dapm_kcontrol_get_path_list(
+       const struct snd_kcontrol *kcontrol)
+{
+       struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol);
+
+       return &data->paths;
+}
+
+#define dapm_kcontrol_for_each_path(path, kcontrol) \
+       list_for_each_entry(path, dapm_kcontrol_get_path_list(kcontrol), \
+               list_kcontrol)
+
 static unsigned int dapm_kcontrol_get_value(const struct snd_kcontrol *kcontrol)
 {
        struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol);
@@ -671,7 +693,7 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w,
        }
 
        w->kcontrols[kci] = kcontrol;
-       path->kcontrol = kcontrol;
+       dapm_kcontrol_add_path(kcontrol, path);
 
        return 0;
 }
@@ -691,7 +713,7 @@ static int dapm_new_mixer(struct snd_soc_dapm_widget *w)
                                continue;
 
                        if (w->kcontrols[i]) {
-                               path->kcontrol = w->kcontrols[i];
+                               dapm_kcontrol_add_path(w->kcontrols[i], path);
                                continue;
                        }
 
@@ -730,7 +752,7 @@ static int dapm_new_mux(struct snd_soc_dapm_widget *w)
                return ret;
 
        list_for_each_entry(path, &w->sources, list_sink)
-               path->kcontrol = w->kcontrols[0];
+               dapm_kcontrol_add_path(w->kcontrols[0], path);
 
        return 0;
 }
@@ -1990,10 +2012,7 @@ static int soc_dapm_mux_update_power(struct snd_soc_card *card,
        int found = 0;
 
        /* find dapm widget path assoc with kcontrol */
-       list_for_each_entry(path, &card->paths, list) {
-               if (path->kcontrol != kcontrol)
-                       continue;
-
+       dapm_kcontrol_for_each_path(path, kcontrol) {
                if (!path->name || !e->texts[mux])
                        continue;
 
@@ -2043,11 +2062,7 @@ static int soc_dapm_mixer_update_power(struct snd_soc_card *card,
        int found = 0;
 
        /* find dapm widget path assoc with kcontrol */
-       list_for_each_entry(path, &card->paths, list) {
-               if (path->kcontrol != kcontrol)
-                       continue;
-
-               /* found, now check type */
+       dapm_kcontrol_for_each_path(path, kcontrol) {
                found = 1;
                path->connect = connect;
                dapm_mark_dirty(path->source, "mixer connection");
@@ -2152,6 +2167,7 @@ static void dapm_free_path(struct snd_soc_dapm_path *path)
 {
        list_del(&path->list_sink);
        list_del(&path->list_source);
+       list_del(&path->list_kcontrol);
        list_del(&path->list);
        kfree(path);
 }