From fe4fda5d8f28d06ae8f1482f4bde8a83be16e44b Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 3 Oct 2011 22:36:57 +0100 Subject: [PATCH] ASoC: Reduce the number of neigbours we mark dirty when updating power If two widgets are not currently connected then there is no need to propagate a power state change between them as we mark the affected widgets when we change a connection. Similarly if a neighbour widget is already in the state being set for the current widget then there is no need to recheck. On one system I tested this gave: Power Path Neighbour Before: 114 1066 1327 After: 106 970 1186 which is an improvement, although relatively small. Signed-off-by: Mark Brown --- sound/soc/soc-dapm.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 9d6bb33..214a709 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -1215,6 +1215,21 @@ static void dapm_post_sequence_async(void *data, async_cookie_t cookie) } } +static void dapm_widget_set_peer_power(struct snd_soc_dapm_widget *peer, + bool power, bool connect) +{ + /* If a connection is being made or broken then that update + * will have marked the peer dirty, otherwise the widgets are + * not connected and this update has no impact. */ + if (!connect) + return; + + /* If the peer is already in the state we're moving to then we + * won't have an impact on it. */ + if (power != peer->power) + dapm_mark_dirty(peer); +} + static void dapm_widget_set_power(struct snd_soc_dapm_widget *w, bool power, struct list_head *up_list, struct list_head *down_list) @@ -1227,19 +1242,18 @@ static void dapm_widget_set_power(struct snd_soc_dapm_widget *w, bool power, trace_snd_soc_dapm_widget_power(w, power); /* If we changed our power state perhaps our neigbours changed - * also. We're not yet smart enough to update relevant - * neighbours when we change the state of a widget, this acts - * as a proxy for that. It will notify more neighbours than - * is ideal. + * also. */ list_for_each_entry(path, &w->sources, list_sink) { if (path->source) { - dapm_mark_dirty(path->source); + dapm_widget_set_peer_power(path->source, power, + path->connect); } } list_for_each_entry(path, &w->sinks, list_source) { if (path->sink) { - dapm_mark_dirty(path->sink); + dapm_widget_set_peer_power(path->sink, power, + path->connect); } } -- 2.7.4