summaryrefslogtreecommitdiff
path: root/sound/soc/soc-dapm.c
diff options
context:
space:
mode:
authorCharles Keepax <ckeepax@opensource.wolfsonmicro.com>2015-05-11 13:50:30 +0100
committerMark Brown <broonie@kernel.org>2015-05-12 11:41:46 +0100
commit45a110a1377d9f7afbbf53e351b72cf813ac426e (patch)
tree111da54078309b4eda6a371832162a5835ccf8a5 /sound/soc/soc-dapm.c
parentca60bc41fb97b8bdda8bba3fdefac6d51ab9ffb4 (diff)
ASoC: dapm: Add cache to speed up adding of routes
Some CODECs have a significant number of DAPM routes and for each route, when it is added to the card, the entire card widget list must be searched. When adding routes it is very likely, however, that adjacent routes will require adjacent widgets. For example all the routes for a mux are likely added in a block and the sink widget will be the same each time and it is also quite likely that the source widgets are sequential located in the widget list. This patch adds a cache to the DAPM context, this cache will hold the source and sink widgets from the last call to snd_soc_dapm_add_route for that context. A small search of the widget list will be made from those points for both the sink and source. Currently this search only checks both the last widget and the one adjacent to it. On wm8280 which has approximately 500 widgets and 30000 routes (one of the largest CODECs in mainline), the number of paths that hit the cache is 24000, which significantly improves probe time. Signed-off-by: Charles Keepax <ckeepax@opensource.wolfsonmicro.com> Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound/soc/soc-dapm.c')
-rw-r--r--sound/soc/soc-dapm.c39
1 files changed, 39 insertions, 0 deletions
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 63748526d630..10fb7087c405 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -572,6 +572,35 @@ static void soc_dapm_async_complete(struct snd_soc_dapm_context *dapm)
snd_soc_component_async_complete(dapm->component);
}
+static struct snd_soc_dapm_widget *
+dapm_wcache_lookup(struct snd_soc_dapm_wcache *wcache, const char *name)
+{
+ struct snd_soc_dapm_widget *w = wcache->widget;
+ struct list_head *wlist;
+ const int depth = 2;
+ int i = 0;
+
+ if (w) {
+ wlist = &w->dapm->card->widgets;
+
+ list_for_each_entry_from(w, wlist, list) {
+ if (!strcmp(name, w->name))
+ return w;
+
+ if (++i == depth)
+ break;
+ }
+ }
+
+ return NULL;
+}
+
+static inline void dapm_wcache_update(struct snd_soc_dapm_wcache *wcache,
+ struct snd_soc_dapm_widget *w)
+{
+ wcache->widget = w;
+}
+
/**
* snd_soc_dapm_force_bias_level() - Sets the DAPM bias level
* @dapm: The DAPM context for which to set the level
@@ -2610,6 +2639,12 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
source = route->source;
}
+ wsource = dapm_wcache_lookup(&dapm->path_source_cache, source);
+ wsink = dapm_wcache_lookup(&dapm->path_sink_cache, sink);
+
+ if (wsink && wsource)
+ goto skip_search;
+
/*
* find src and dest widgets over all widgets but favor a widget from
* current DAPM context
@@ -2650,6 +2685,10 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
return -ENODEV;
}
+skip_search:
+ dapm_wcache_update(&dapm->path_sink_cache, wsink);
+ dapm_wcache_update(&dapm->path_source_cache, wsource);
+
ret = snd_soc_dapm_add_path(dapm, wsource, wsink, route->control,
route->connected);
if (ret)