|
@@ -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)
|
|
@@ -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.:-
|
|
@@ -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);
|
|
@@ -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:
|
|
@@ -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;
|
|
@@ -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 */
|