ASoC: dapm: Keep a list of paths per kcontrol
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>
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index bad6f6d..b779d36 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -176,6 +176,7 @@
struct dapm_kcontrol_data {
unsigned int value;
+ struct list_head paths;
struct snd_soc_dapm_widget_list wlist;
};
@@ -194,6 +195,7 @@
data->wlist.widgets[0] = widget;
data->wlist.num_widgets = 1;
+ INIT_LIST_HEAD(&data->paths);
kcontrol->private_data = data;
@@ -234,6 +236,26 @@
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 @@
}
w->kcontrols[kci] = kcontrol;
- path->kcontrol = kcontrol;
+ dapm_kcontrol_add_path(kcontrol, path);
return 0;
}
@@ -691,7 +713,7 @@
continue;
if (w->kcontrols[i]) {
- path->kcontrol = w->kcontrols[i];
+ dapm_kcontrol_add_path(w->kcontrols[i], path);
continue;
}
@@ -730,7 +752,7 @@
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 @@
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 @@
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 @@
{
list_del(&path->list_sink);
list_del(&path->list_source);
+ list_del(&path->list_kcontrol);
list_del(&path->list);
kfree(path);
}