Skip to content

Commit

Permalink
ASoC: Sort DAPM power sequences while building lists
Browse files Browse the repository at this point in the history
In the past the DAPM power sequencing was done by iterating over the list
of widgets once for each widget type and powering widgets of that type.
Instead of doing that do the sorting at the time we insert the widgets
into the lists of widgets to apply power changes to. This reduces the
amount of computation required for seqencing still further, though the
costs are generally dwarfed by the costs of the register writes
implementing them.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
  • Loading branch information
Mark Brown committed Jun 7, 2009
1 parent 74b8f95 commit 38357ab
Showing 1 changed file with 71 additions and 38 deletions.
109 changes: 71 additions & 38 deletions sound/soc/soc-dapm.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,19 +52,37 @@

/* dapm power sequences - make this per codec in the future */
static int dapm_up_seq[] = {
snd_soc_dapm_pre, snd_soc_dapm_supply, snd_soc_dapm_micbias,
snd_soc_dapm_mic, snd_soc_dapm_mux, snd_soc_dapm_value_mux,
snd_soc_dapm_dac, snd_soc_dapm_mixer, snd_soc_dapm_mixer_named_ctl,
snd_soc_dapm_pga, snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk,
snd_soc_dapm_post
[snd_soc_dapm_pre] = 0,
[snd_soc_dapm_supply] = 1,
[snd_soc_dapm_micbias] = 2,
[snd_soc_dapm_mic] = 3,
[snd_soc_dapm_mux] = 4,
[snd_soc_dapm_value_mux] = 5,
[snd_soc_dapm_dac] = 6,
[snd_soc_dapm_mixer] = 7,
[snd_soc_dapm_mixer_named_ctl] = 8,
[snd_soc_dapm_pga] = 9,
[snd_soc_dapm_adc] = 10,
[snd_soc_dapm_hp] = 11,
[snd_soc_dapm_spk] = 12,
[snd_soc_dapm_post] = 13,
};

static int dapm_down_seq[] = {
snd_soc_dapm_pre, snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk,
snd_soc_dapm_pga, snd_soc_dapm_mixer_named_ctl, snd_soc_dapm_mixer,
snd_soc_dapm_dac, snd_soc_dapm_mic, snd_soc_dapm_micbias,
snd_soc_dapm_mux, snd_soc_dapm_value_mux, snd_soc_dapm_supply,
snd_soc_dapm_post
[snd_soc_dapm_pre] = 0,
[snd_soc_dapm_adc] = 1,
[snd_soc_dapm_hp] = 2,
[snd_soc_dapm_spk] = 3,
[snd_soc_dapm_pga] = 4,
[snd_soc_dapm_mixer_named_ctl] = 5,
[snd_soc_dapm_mixer] = 6,
[snd_soc_dapm_dac] = 7,
[snd_soc_dapm_mic] = 8,
[snd_soc_dapm_micbias] = 9,
[snd_soc_dapm_mux] = 10,
[snd_soc_dapm_value_mux] = 11,
[snd_soc_dapm_supply] = 12,
[snd_soc_dapm_post] = 13,
};

static void pop_wait(u32 pop_time)
Expand Down Expand Up @@ -738,6 +756,32 @@ static int dapm_power_widget(struct snd_soc_codec *codec, int event,
}
}

static int dapm_seq_compare(struct snd_soc_dapm_widget *a,
struct snd_soc_dapm_widget *b,
int sort[])
{
if (sort[a->id] != sort[b->id])
return sort[a->id] - sort[b->id];

return 0;
}

/* Insert a widget in order into a DAPM power sequence. */
static void dapm_seq_insert(struct snd_soc_dapm_widget *new_widget,
struct list_head *list,
int sort[])
{
struct snd_soc_dapm_widget *w;

list_for_each_entry(w, list, power_list)
if (dapm_seq_compare(new_widget, w, sort) < 0) {
list_add_tail(&new_widget->power_list, &w->power_list);
return;
}

list_add_tail(&new_widget->power_list, list);
}

/*
* Scan each dapm widget for complete audio path.
* A complete path is a route that has valid endpoints i.e.:-
Expand All @@ -752,7 +796,7 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
struct snd_soc_device *socdev = codec->socdev;
struct snd_soc_dapm_widget *w;
int ret = 0;
int i, power;
int power;
int sys_power = 0;

INIT_LIST_HEAD(&codec->up_list);
Expand All @@ -764,10 +808,10 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
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);
dapm_seq_insert(w, &codec->down_list, dapm_down_seq);
break;
case snd_soc_dapm_post:
list_add_tail(&codec->up_list, &w->power_list);
dapm_seq_insert(w, &codec->up_list, dapm_up_seq);
break;

default:
Expand All @@ -782,10 +826,11 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
continue;

if (power)
list_add_tail(&w->power_list, &codec->up_list);
dapm_seq_insert(w, &codec->up_list,
dapm_up_seq);
else
list_add_tail(&w->power_list,
&codec->down_list);
dapm_seq_insert(w, &codec->down_list,
dapm_down_seq);

w->power = power;
break;
Expand All @@ -802,31 +847,19 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
}

/* 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);
}
list_for_each_entry(w, &codec->down_list, power_list) {
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 (w->id != dapm_up_seq[i])
continue;

ret = dapm_power_widget(codec, event, w);
if (ret != 0)
pr_err("Failed to power up %s: %d\n",
w->name, ret);
}
list_for_each_entry(w, &codec->up_list, power_list) {
ret = dapm_power_widget(codec, event, w);
if (ret != 0)
pr_err("Failed to power up %s: %d\n",
w->name, ret);
}

/* If we just powered the last thing off drop to standby bias */
Expand Down

0 comments on commit 38357ab

Please sign in to comment.