From 1ae80bd2b0e8d0aa1d9222df9ac8ffae66cdb58e Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sat, 16 May 2009 17:47:29 +0100 Subject: [PATCH] --- yaml --- r: 148284 b: refs/heads/master c: 6d3ddc81f5762d54ce7d1db70eb757c6c12fabbc h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/include/sound/soc-dapm.h | 3 ++ trunk/include/sound/soc.h | 2 + trunk/sound/soc/soc-dapm.c | 81 +++++++++++++++++++++++----------- 4 files changed, 62 insertions(+), 26 deletions(-) diff --git a/[refs] b/[refs] index f296d9e35877..0a17883e4732 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: b7a755a8a145a7e34e735bda9c452317de7a538a +refs/heads/master: 6d3ddc81f5762d54ce7d1db70eb757c6c12fabbc diff --git a/trunk/include/sound/soc-dapm.h b/trunk/include/sound/soc-dapm.h index 533f9f256496..b3f789d0cee8 100644 --- a/trunk/include/sound/soc-dapm.h +++ b/trunk/include/sound/soc-dapm.h @@ -385,6 +385,9 @@ struct snd_soc_dapm_widget { /* widget input and outputs */ struct list_head sources; struct list_head sinks; + + /* used during DAPM updates */ + struct list_head power_list; }; #endif diff --git a/trunk/include/sound/soc.h b/trunk/include/sound/soc.h index 6ab80bf7abd2..8309ce81cf3b 100644 --- a/trunk/include/sound/soc.h +++ b/trunk/include/sound/soc.h @@ -372,6 +372,8 @@ struct snd_soc_codec { enum snd_soc_bias_level bias_level; enum snd_soc_bias_level suspend_bias_level; struct delayed_work delayed_work; + struct list_head up_list; + struct list_head down_list; /* codec DAI's */ struct snd_soc_dai *dai; diff --git a/trunk/sound/soc/soc-dapm.c b/trunk/sound/soc/soc-dapm.c index 7847f80e96d1..04ef84106d7c 100644 --- a/trunk/sound/soc/soc-dapm.c +++ b/trunk/sound/soc/soc-dapm.c @@ -658,7 +658,7 @@ static int dapm_supply_check_power(struct snd_soc_dapm_widget *w) static int dapm_power_widget(struct snd_soc_codec *codec, int event, struct snd_soc_dapm_widget *w) { - int power, ret; + int ret; switch (w->id) { case snd_soc_dapm_pre: @@ -696,18 +696,8 @@ static int dapm_power_widget(struct snd_soc_codec *codec, int event, return 0; default: - break; + return dapm_generic_apply_power(w); } - - if (!w->power_check) - return 0; - - power = w->power_check(w); - if (w->power == power) - return 0; - w->power = power; - - return dapm_generic_apply_power(w); } /* @@ -722,27 +712,68 @@ static int dapm_power_widget(struct snd_soc_codec *codec, int event, static int dapm_power_widgets(struct snd_soc_codec *codec, int event) { struct snd_soc_dapm_widget *w; - int i, c = 1, *seq = NULL, ret = 0; - - /* do we have a sequenced stream event */ - if (event == SND_SOC_DAPM_STREAM_START) { - c = ARRAY_SIZE(dapm_up_seq); - seq = dapm_up_seq; - } else if (event == SND_SOC_DAPM_STREAM_STOP) { - c = ARRAY_SIZE(dapm_down_seq); - seq = dapm_down_seq; + int ret = 0; + int i, power; + + INIT_LIST_HEAD(&codec->up_list); + INIT_LIST_HEAD(&codec->down_list); + + /* Check which widgets we need to power and store them in + * lists indicating if they should be powered up or down. + */ + list_for_each_entry(w, &codec->dapm_widgets, list) { + switch (w->id) { + case snd_soc_dapm_pre: + list_add_tail(&codec->down_list, &w->power_list); + break; + case snd_soc_dapm_post: + list_add_tail(&codec->up_list, &w->power_list); + break; + + default: + if (!w->power_check) + continue; + + power = w->power_check(w); + if (w->power == power) + continue; + + if (power) + list_add_tail(&w->power_list, &codec->up_list); + else + list_add_tail(&w->power_list, + &codec->down_list); + + w->power = power; + break; + } } - for (i = 0; i < c; i++) { - list_for_each_entry(w, &codec->dapm_widgets, list) { + /* Power down widgets first; try to avoid amplifying pops. */ + for (i = 0; i < ARRAY_SIZE(dapm_down_seq); i++) { + list_for_each_entry(w, &codec->down_list, power_list) { + /* is widget in stream order */ + if (w->id != dapm_down_seq[i]) + continue; + + ret = dapm_power_widget(codec, event, w); + if (ret != 0) + pr_err("Failed to power down %s: %d\n", + w->name, ret); + } + } + /* Now power up. */ + for (i = 0; i < ARRAY_SIZE(dapm_up_seq); i++) { + list_for_each_entry(w, &codec->up_list, power_list) { /* is widget in stream order */ - if (seq && seq[i] && w->id != seq[i]) + if (w->id != dapm_up_seq[i]) continue; ret = dapm_power_widget(codec, event, w); if (ret != 0) - return ret; + pr_err("Failed to power up %s: %d\n", + w->name, ret); } }