|
@@ -59,31 +59,31 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
|
|
|
/* dapm power sequences - make this per codec in the future */
|
|
|
static int dapm_up_seq[] = {
|
|
|
[snd_soc_dapm_pre] = 0,
|
|
|
- [snd_soc_dapm_supply] = 1,
|
|
|
[snd_soc_dapm_regulator_supply] = 1,
|
|
|
[snd_soc_dapm_clock_supply] = 1,
|
|
|
- [snd_soc_dapm_micbias] = 2,
|
|
|
+ [snd_soc_dapm_supply] = 2,
|
|
|
+ [snd_soc_dapm_micbias] = 3,
|
|
|
[snd_soc_dapm_dai_link] = 2,
|
|
|
- [snd_soc_dapm_dai_in] = 3,
|
|
|
- [snd_soc_dapm_dai_out] = 3,
|
|
|
- [snd_soc_dapm_aif_in] = 3,
|
|
|
- [snd_soc_dapm_aif_out] = 3,
|
|
|
- [snd_soc_dapm_mic] = 4,
|
|
|
- [snd_soc_dapm_mux] = 5,
|
|
|
- [snd_soc_dapm_virt_mux] = 5,
|
|
|
- [snd_soc_dapm_value_mux] = 5,
|
|
|
- [snd_soc_dapm_dac] = 6,
|
|
|
- [snd_soc_dapm_switch] = 7,
|
|
|
- [snd_soc_dapm_mixer] = 7,
|
|
|
- [snd_soc_dapm_mixer_named_ctl] = 7,
|
|
|
- [snd_soc_dapm_pga] = 8,
|
|
|
- [snd_soc_dapm_adc] = 9,
|
|
|
- [snd_soc_dapm_out_drv] = 10,
|
|
|
- [snd_soc_dapm_hp] = 10,
|
|
|
- [snd_soc_dapm_spk] = 10,
|
|
|
- [snd_soc_dapm_line] = 10,
|
|
|
- [snd_soc_dapm_kcontrol] = 11,
|
|
|
- [snd_soc_dapm_post] = 12,
|
|
|
+ [snd_soc_dapm_dai_in] = 4,
|
|
|
+ [snd_soc_dapm_dai_out] = 4,
|
|
|
+ [snd_soc_dapm_aif_in] = 4,
|
|
|
+ [snd_soc_dapm_aif_out] = 4,
|
|
|
+ [snd_soc_dapm_mic] = 5,
|
|
|
+ [snd_soc_dapm_mux] = 6,
|
|
|
+ [snd_soc_dapm_virt_mux] = 6,
|
|
|
+ [snd_soc_dapm_value_mux] = 6,
|
|
|
+ [snd_soc_dapm_dac] = 7,
|
|
|
+ [snd_soc_dapm_switch] = 8,
|
|
|
+ [snd_soc_dapm_mixer] = 8,
|
|
|
+ [snd_soc_dapm_mixer_named_ctl] = 8,
|
|
|
+ [snd_soc_dapm_pga] = 9,
|
|
|
+ [snd_soc_dapm_adc] = 10,
|
|
|
+ [snd_soc_dapm_out_drv] = 11,
|
|
|
+ [snd_soc_dapm_hp] = 11,
|
|
|
+ [snd_soc_dapm_spk] = 11,
|
|
|
+ [snd_soc_dapm_line] = 11,
|
|
|
+ [snd_soc_dapm_kcontrol] = 12,
|
|
|
+ [snd_soc_dapm_post] = 13,
|
|
|
};
|
|
|
|
|
|
static int dapm_down_seq[] = {
|
|
@@ -109,10 +109,10 @@ static int dapm_down_seq[] = {
|
|
|
[snd_soc_dapm_dai_in] = 10,
|
|
|
[snd_soc_dapm_dai_out] = 10,
|
|
|
[snd_soc_dapm_dai_link] = 11,
|
|
|
- [snd_soc_dapm_clock_supply] = 12,
|
|
|
- [snd_soc_dapm_regulator_supply] = 12,
|
|
|
[snd_soc_dapm_supply] = 12,
|
|
|
- [snd_soc_dapm_post] = 13,
|
|
|
+ [snd_soc_dapm_clock_supply] = 13,
|
|
|
+ [snd_soc_dapm_regulator_supply] = 13,
|
|
|
+ [snd_soc_dapm_post] = 14,
|
|
|
};
|
|
|
|
|
|
static void pop_wait(u32 pop_time)
|
|
@@ -409,6 +409,12 @@ static inline void soc_widget_unlock(struct snd_soc_dapm_widget *w)
|
|
|
mutex_unlock(&w->platform->mutex);
|
|
|
}
|
|
|
|
|
|
+static void soc_dapm_async_complete(struct snd_soc_dapm_context *dapm)
|
|
|
+{
|
|
|
+ if (dapm->codec && dapm->codec->using_regmap)
|
|
|
+ regmap_async_complete(dapm->codec->control_data);
|
|
|
+}
|
|
|
+
|
|
|
static int soc_widget_update_bits_locked(struct snd_soc_dapm_widget *w,
|
|
|
unsigned short reg, unsigned int mask, unsigned int value)
|
|
|
{
|
|
@@ -417,8 +423,9 @@ static int soc_widget_update_bits_locked(struct snd_soc_dapm_widget *w,
|
|
|
int ret;
|
|
|
|
|
|
if (w->codec && w->codec->using_regmap) {
|
|
|
- ret = regmap_update_bits_check(w->codec->control_data,
|
|
|
- reg, mask, value, &change);
|
|
|
+ ret = regmap_update_bits_check_async(w->codec->control_data,
|
|
|
+ reg, mask, value,
|
|
|
+ &change);
|
|
|
if (ret != 0)
|
|
|
return ret;
|
|
|
} else {
|
|
@@ -499,18 +506,22 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
|
|
|
int val;
|
|
|
struct soc_mixer_control *mc = (struct soc_mixer_control *)
|
|
|
w->kcontrol_news[i].private_value;
|
|
|
- unsigned int reg = mc->reg;
|
|
|
+ int reg = mc->reg;
|
|
|
unsigned int shift = mc->shift;
|
|
|
int max = mc->max;
|
|
|
unsigned int mask = (1 << fls(max)) - 1;
|
|
|
unsigned int invert = mc->invert;
|
|
|
|
|
|
- val = soc_widget_read(w, reg);
|
|
|
- val = (val >> shift) & mask;
|
|
|
- if (invert)
|
|
|
- val = max - val;
|
|
|
+ if (reg != SND_SOC_NOPM) {
|
|
|
+ val = soc_widget_read(w, reg);
|
|
|
+ val = (val >> shift) & mask;
|
|
|
+ if (invert)
|
|
|
+ val = max - val;
|
|
|
+ p->connect = !!val;
|
|
|
+ } else {
|
|
|
+ p->connect = 0;
|
|
|
+ }
|
|
|
|
|
|
- p->connect = !!val;
|
|
|
}
|
|
|
break;
|
|
|
case snd_soc_dapm_mux: {
|
|
@@ -1197,6 +1208,8 @@ int dapm_regulator_event(struct snd_soc_dapm_widget *w,
|
|
|
{
|
|
|
int ret;
|
|
|
|
|
|
+ soc_dapm_async_complete(w->dapm);
|
|
|
+
|
|
|
if (SND_SOC_DAPM_EVENT_ON(event)) {
|
|
|
if (w->on_val & SND_SOC_DAPM_REGULATOR_BYPASS) {
|
|
|
ret = regulator_allow_bypass(w->regulator, false);
|
|
@@ -1230,6 +1243,8 @@ int dapm_clock_event(struct snd_soc_dapm_widget *w,
|
|
|
if (!w->clk)
|
|
|
return -EIO;
|
|
|
|
|
|
+ soc_dapm_async_complete(w->dapm);
|
|
|
+
|
|
|
#ifdef CONFIG_HAVE_CLK
|
|
|
if (SND_SOC_DAPM_EVENT_ON(event)) {
|
|
|
return clk_prepare_enable(w->clk);
|
|
@@ -1422,6 +1437,7 @@ static void dapm_seq_check_event(struct snd_soc_card *card,
|
|
|
if (w->event && (w->event_flags & event)) {
|
|
|
pop_dbg(w->dapm->dev, card->pop_time, "pop test : %s %s\n",
|
|
|
w->name, ev_name);
|
|
|
+ soc_dapm_async_complete(w->dapm);
|
|
|
trace_snd_soc_dapm_widget_event_start(w, event);
|
|
|
ret = w->event(w, NULL, event);
|
|
|
trace_snd_soc_dapm_widget_event_done(w, event);
|
|
@@ -1494,6 +1510,7 @@ static void dapm_seq_run(struct snd_soc_card *card,
|
|
|
struct list_head *list, int event, bool power_up)
|
|
|
{
|
|
|
struct snd_soc_dapm_widget *w, *n;
|
|
|
+ struct snd_soc_dapm_context *d;
|
|
|
LIST_HEAD(pending);
|
|
|
int cur_sort = -1;
|
|
|
int cur_subseq = -1;
|
|
@@ -1524,6 +1541,9 @@ static void dapm_seq_run(struct snd_soc_card *card,
|
|
|
cur_subseq);
|
|
|
}
|
|
|
|
|
|
+ if (cur_dapm && w->dapm != cur_dapm)
|
|
|
+ soc_dapm_async_complete(cur_dapm);
|
|
|
+
|
|
|
INIT_LIST_HEAD(&pending);
|
|
|
cur_sort = -1;
|
|
|
cur_subseq = INT_MIN;
|
|
@@ -1582,6 +1602,10 @@ static void dapm_seq_run(struct snd_soc_card *card,
|
|
|
cur_dapm->seq_notifier(cur_dapm,
|
|
|
i, cur_subseq);
|
|
|
}
|
|
|
+
|
|
|
+ list_for_each_entry(d, &card->dapm_list, list) {
|
|
|
+ soc_dapm_async_complete(d);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
static void dapm_widget_update(struct snd_soc_card *card)
|
|
@@ -1840,6 +1864,7 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event)
|
|
|
*/
|
|
|
switch (w->id) {
|
|
|
case snd_soc_dapm_siggen:
|
|
|
+ case snd_soc_dapm_vmid:
|
|
|
break;
|
|
|
case snd_soc_dapm_supply:
|
|
|
case snd_soc_dapm_regulator_supply:
|
|
@@ -2791,7 +2816,7 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol,
|
|
|
struct snd_soc_card *card = codec->card;
|
|
|
struct soc_mixer_control *mc =
|
|
|
(struct soc_mixer_control *)kcontrol->private_value;
|
|
|
- unsigned int reg = mc->reg;
|
|
|
+ int reg = mc->reg;
|
|
|
unsigned int shift = mc->shift;
|
|
|
int max = mc->max;
|
|
|
unsigned int mask = (1 << fls(max)) - 1;
|
|
@@ -2804,7 +2829,7 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol,
|
|
|
kcontrol->id.name);
|
|
|
|
|
|
mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
|
|
|
- if (dapm_kcontrol_is_powered(kcontrol))
|
|
|
+ if (dapm_kcontrol_is_powered(kcontrol) && reg != SND_SOC_NOPM)
|
|
|
val = (snd_soc_read(codec, reg) >> shift) & mask;
|
|
|
else
|
|
|
val = dapm_kcontrol_get_value(kcontrol);
|
|
@@ -2835,7 +2860,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
|
|
|
struct snd_soc_card *card = codec->card;
|
|
|
struct soc_mixer_control *mc =
|
|
|
(struct soc_mixer_control *)kcontrol->private_value;
|
|
|
- unsigned int reg = mc->reg;
|
|
|
+ int reg = mc->reg;
|
|
|
unsigned int shift = mc->shift;
|
|
|
int max = mc->max;
|
|
|
unsigned int mask = (1 << fls(max)) - 1;
|
|
@@ -2857,19 +2882,24 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
|
|
|
|
|
|
mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
|
|
|
|
|
|
- dapm_kcontrol_set_value(kcontrol, val);
|
|
|
+ change = dapm_kcontrol_set_value(kcontrol, val);
|
|
|
+
|
|
|
+ if (reg != SND_SOC_NOPM) {
|
|
|
+ mask = mask << shift;
|
|
|
+ val = val << shift;
|
|
|
|
|
|
- mask = mask << shift;
|
|
|
- val = val << shift;
|
|
|
+ change = snd_soc_test_bits(codec, reg, mask, val);
|
|
|
+ }
|
|
|
|
|
|
- change = snd_soc_test_bits(codec, reg, mask, val);
|
|
|
if (change) {
|
|
|
- update.kcontrol = kcontrol;
|
|
|
- update.reg = reg;
|
|
|
- update.mask = mask;
|
|
|
- update.val = val;
|
|
|
+ if (reg != SND_SOC_NOPM) {
|
|
|
+ update.kcontrol = kcontrol;
|
|
|
+ update.reg = reg;
|
|
|
+ update.mask = mask;
|
|
|
+ update.val = val;
|
|
|
|
|
|
- card->update = &update;
|
|
|
+ card->update = &update;
|
|
|
+ }
|
|
|
|
|
|
soc_dapm_mixer_update_power(card, kcontrol, connect);
|
|
|
|