aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sound/soc-dapm.h10
-rw-r--r--sound/soc/soc-dapm.c130
2 files changed, 82 insertions, 58 deletions
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h
index 98783510d2f1..540872fc1390 100644
--- a/include/sound/soc-dapm.h
+++ b/include/sound/soc-dapm.h
@@ -460,6 +460,14 @@ struct snd_soc_dapm_widget {
struct list_head power_list;
};
+struct snd_soc_dapm_update {
+ struct snd_soc_dapm_widget *widget;
+ struct snd_kcontrol *kcontrol;
+ int reg;
+ int mask;
+ int val;
+};
+
/* DAPM context */
struct snd_soc_dapm_context {
int n_widgets; /* number of widgets in this context */
@@ -468,6 +476,8 @@ struct snd_soc_dapm_context {
struct delayed_work delayed_work;
unsigned int idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */
+ struct snd_soc_dapm_update *update;
+
struct device *dev; /* from parent - for debug */
struct snd_soc_codec *codec; /* parent codec */
struct snd_soc_card *card; /* parent card */
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index f362d1de78f3..1debc3b05665 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -920,6 +920,41 @@ static void dapm_seq_run(struct snd_soc_dapm_context *dapm,
dapm_seq_run_coalesced(dapm, &pending);
}
+static void dapm_widget_update(struct snd_soc_dapm_context *dapm)
+{
+ struct snd_soc_dapm_update *update = dapm->update;
+ struct snd_soc_dapm_widget *w;
+ int ret;
+
+ if (!update)
+ return;
+
+ w = update->widget;
+
+ if (w->event &&
+ (w->event_flags & SND_SOC_DAPM_PRE_REG)) {
+ ret = w->event(w, update->kcontrol, SND_SOC_DAPM_PRE_REG);
+ if (ret != 0)
+ pr_err("%s DAPM pre-event failed: %d\n",
+ w->name, ret);
+ }
+
+ ret = snd_soc_update_bits(w->codec, update->reg, update->mask,
+ update->val);
+ if (ret < 0)
+ pr_err("%s DAPM update failed: %d\n", w->name, ret);
+
+ if (w->event &&
+ (w->event_flags & SND_SOC_DAPM_POST_REG)) {
+ ret = w->event(w, update->kcontrol, SND_SOC_DAPM_POST_REG);
+ if (ret != 0)
+ pr_err("%s DAPM post-event failed: %d\n",
+ w->name, ret);
+ }
+}
+
+
+
/*
* Scan each dapm widget for complete audio path.
* A complete path is a route that has valid endpoints i.e.:-
@@ -1037,6 +1072,8 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
/* Power down widgets first; try to avoid amplifying pops. */
dapm_seq_run(dapm, &down_list, event, dapm_down_seq);
+ dapm_widget_update(dapm);
+
/* Now power up. */
dapm_seq_run(dapm, &up_list, event, dapm_up_seq);
@@ -1683,13 +1720,12 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
(struct soc_mixer_control *)kcontrol->private_value;
unsigned int reg = mc->reg;
unsigned int shift = mc->shift;
- unsigned int rshift = mc->rshift;
int max = mc->max;
unsigned int mask = (1 << fls(max)) - 1;
unsigned int invert = mc->invert;
- unsigned int val, val2, val_mask;
- int connect;
- int ret;
+ unsigned int val, val_mask;
+ int connect, change;
+ struct snd_soc_dapm_update update;
val = (ucontrol->value.integer.value[0] & mask);
@@ -1697,18 +1733,12 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
val = max - val;
val_mask = mask << shift;
val = val << shift;
- if (shift != rshift) {
- val2 = (ucontrol->value.integer.value[1] & mask);
- if (invert)
- val2 = max - val2;
- val_mask |= mask << rshift;
- val |= val2 << rshift;
- }
mutex_lock(&widget->codec->mutex);
widget->value = val;
- if (snd_soc_test_bits(widget->codec, reg, val_mask, val)) {
+ change = snd_soc_test_bits(widget->codec, reg, val_mask, val);
+ if (change) {
if (val)
/* new connection */
connect = invert ? 0:1;
@@ -1716,28 +1746,20 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
/* old connection must be powered down */
connect = invert ? 1:0;
+ update.kcontrol = kcontrol;
+ update.widget = widget;
+ update.reg = reg;
+ update.mask = mask;
+ update.val = val;
+ widget->dapm->update = &update;
+
dapm_mixer_update_power(widget, kcontrol, connect);
+
+ widget->dapm->update = NULL;
}
- if (widget->event) {
- if (widget->event_flags & SND_SOC_DAPM_PRE_REG) {
- ret = widget->event(widget, kcontrol,
- SND_SOC_DAPM_PRE_REG);
- if (ret < 0) {
- ret = 1;
- goto out;
- }
- }
- ret = snd_soc_update_bits(widget->codec, reg, val_mask, val);
- if (widget->event_flags & SND_SOC_DAPM_POST_REG)
- ret = widget->event(widget, kcontrol,
- SND_SOC_DAPM_POST_REG);
- } else
- ret = snd_soc_update_bits(widget->codec, reg, val_mask, val);
-
-out:
mutex_unlock(&widget->codec->mutex);
- return ret;
+ return 0;
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw);
@@ -1785,7 +1807,7 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
unsigned int val, mux, change;
unsigned int mask, bitmask;
- int ret = 0;
+ struct snd_soc_dapm_update update;
for (bitmask = 1; bitmask < e->max; bitmask <<= 1)
;
@@ -1804,24 +1826,20 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
mutex_lock(&widget->codec->mutex);
widget->value = val;
change = snd_soc_test_bits(widget->codec, e->reg, mask, val);
- dapm_mux_update_power(widget, kcontrol, change, mux, e);
- if (widget->event_flags & SND_SOC_DAPM_PRE_REG) {
- ret = widget->event(widget,
- kcontrol, SND_SOC_DAPM_PRE_REG);
- if (ret < 0)
- goto out;
- }
+ update.kcontrol = kcontrol;
+ update.widget = widget;
+ update.reg = e->reg;
+ update.mask = mask;
+ update.val = val;
+ widget->dapm->update = &update;
- ret = snd_soc_update_bits(widget->codec, e->reg, mask, val);
+ dapm_mux_update_power(widget, kcontrol, change, mux, e);
- if (widget->event_flags & SND_SOC_DAPM_POST_REG)
- ret = widget->event(widget,
- kcontrol, SND_SOC_DAPM_POST_REG);
+ widget->dapm->update = NULL;
-out:
mutex_unlock(&widget->codec->mutex);
- return ret;
+ return change;
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double);
@@ -1933,7 +1951,7 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
unsigned int val, mux, change;
unsigned int mask;
- int ret = 0;
+ struct snd_soc_dapm_update update;
if (ucontrol->value.enumerated.item[0] > e->max - 1)
return -EINVAL;
@@ -1950,24 +1968,20 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
mutex_lock(&widget->codec->mutex);
widget->value = val;
change = snd_soc_test_bits(widget->codec, e->reg, mask, val);
- dapm_mux_update_power(widget, kcontrol, change, mux, e);
- if (widget->event_flags & SND_SOC_DAPM_PRE_REG) {
- ret = widget->event(widget,
- kcontrol, SND_SOC_DAPM_PRE_REG);
- if (ret < 0)
- goto out;
- }
+ update.kcontrol = kcontrol;
+ update.widget = widget;
+ update.reg = e->reg;
+ update.mask = mask;
+ update.val = val;
+ widget->dapm->update = &update;
- ret = snd_soc_update_bits(widget->codec, e->reg, mask, val);
+ dapm_mux_update_power(widget, kcontrol, change, mux, e);
- if (widget->event_flags & SND_SOC_DAPM_POST_REG)
- ret = widget->event(widget,
- kcontrol, SND_SOC_DAPM_POST_REG);
+ widget->dapm->update = NULL;
-out:
mutex_unlock(&widget->codec->mutex);
- return ret;
+ return change;
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_put_value_enum_double);