summaryrefslogtreecommitdiffstats
path: root/sound/soc/soc-dapm.c
diff options
context:
space:
mode:
authorMark Brown2011-10-03 23:36:57 +0200
committerMark Brown2011-10-04 17:50:21 +0200
commitfe4fda5d8f28d06ae8f1482f4bde8a83be16e44b (patch)
tree0c8352c5495db26e53b695f356be424f0ba75bbe /sound/soc/soc-dapm.c
parentASoC: Do DAPM power checks only for widgets changed since last run (diff)
downloadkernel-qcow2-linux-fe4fda5d8f28d06ae8f1482f4bde8a83be16e44b.tar.gz
kernel-qcow2-linux-fe4fda5d8f28d06ae8f1482f4bde8a83be16e44b.tar.xz
kernel-qcow2-linux-fe4fda5d8f28d06ae8f1482f4bde8a83be16e44b.zip
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 <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/soc-dapm.c')
-rw-r--r--sound/soc/soc-dapm.c26
1 files changed, 20 insertions, 6 deletions
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 9d6bb33e6094..214a709128d2 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);
}
}