From 63c69a6e4134a2085d40e40c02a395dd1bd8c023 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 18 Jul 2013 22:03:01 +0100 Subject: ASoC: dapm: Use generic power check for everything except DAIs As noticed by Lars-Peter Clausen since the move to using widgets to hook into the DAIs we no longer directly manage the power of AIF or DAC/ADC widgets from the stream integration so they can just use the generic power checks instead of the custom stream integration ones they currently do. Signed-off-by: Mark Brown --- sound/soc/soc-dapm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index bd16010441cc..378655839f74 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -3126,16 +3126,16 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, case snd_soc_dapm_value_mux: w->power_check = dapm_generic_check_power; break; - case snd_soc_dapm_adc: - case snd_soc_dapm_aif_out: case snd_soc_dapm_dai_out: w->power_check = dapm_adc_check_power; break; - case snd_soc_dapm_dac: - case snd_soc_dapm_aif_in: case snd_soc_dapm_dai_in: w->power_check = dapm_dac_check_power; break; + case snd_soc_dapm_adc: + case snd_soc_dapm_aif_out: + case snd_soc_dapm_dac: + case snd_soc_dapm_aif_in: case snd_soc_dapm_pga: case snd_soc_dapm_out_drv: case snd_soc_dapm_input: -- cgit v1.2.3 From c3f48ae6fd5a1ebdcaff5efe35f88f31daaee225 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 24 Jul 2013 15:27:36 +0200 Subject: ASoC: dapm: Pass snd_soc_card directly to soc_dpcm_runtime_update() soc_dpcm_runtime_update() operates on a ASoC card as a whole. Currently it takes a snd_soc_dapm_widget as its only parameter though. The widget is then used to look up the card and is otherwise unused. This patch changes the function to take a pointer to the card directly. This makes it possible to to call soc_dpcm_runtime_update() for updates which are not related to one specific widget. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/soc-dapm.c | 4 ++-- sound/soc/soc-pcm.c | 10 +--------- 2 files changed, 3 insertions(+), 11 deletions(-) (limited to 'sound') diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 378655839f74..8d9c09b266fd 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -1986,7 +1986,7 @@ int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_widget *widget, ret = soc_dapm_mux_update_power(widget, kcontrol, mux, e); mutex_unlock(&card->dapm_mutex); if (ret > 0) - soc_dpcm_runtime_update(widget); + soc_dpcm_runtime_update(card); return ret; } EXPORT_SYMBOL_GPL(snd_soc_dapm_mux_update_power); @@ -2032,7 +2032,7 @@ int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_widget *widget, ret = soc_dapm_mixer_update_power(widget, kcontrol, connect); mutex_unlock(&card->dapm_mutex); if (ret > 0) - soc_dpcm_runtime_update(widget); + soc_dpcm_runtime_update(card); return ret; } EXPORT_SYMBOL_GPL(snd_soc_dapm_mixer_update_power); diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index b6c640332a17..5c2c66209808 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1832,18 +1832,10 @@ static int dpcm_run_old_update(struct snd_soc_pcm_runtime *fe, int stream) /* Called by DAPM mixer/mux changes to update audio routing between PCMs and * any DAI links. */ -int soc_dpcm_runtime_update(struct snd_soc_dapm_widget *widget) +int soc_dpcm_runtime_update(struct snd_soc_card *card) { - struct snd_soc_card *card; int i, old, new, paths; - if (widget->codec) - card = widget->codec->card; - else if (widget->platform) - card = widget->platform->card; - else - return -EINVAL; - mutex_lock_nested(&card->mutex, SND_SOC_CARD_CLASS_RUNTIME); for (i = 0; i < card->num_rtd; i++) { struct snd_soc_dapm_widget_list *list; -- cgit v1.2.3 From ce6cfaf1de136cd3e6ed7c0ed984be8d003a58c1 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 24 Jul 2013 15:27:37 +0200 Subject: ASoC: dapm: Run widget updates for shared controls at the same time Currently when updating a control that is shared between multiple widgets the whole power-up/power-down sequence is being run once for each widget. The control register is updated during the first run, which means the CODEC internal routing is also updated for all widgets during this first run. The input and output paths for each widgets are only updated though during the respective run for that widget. This leads to a slight inconsistency between the CODEC's internal state and ASoC's state, which causes non optimal behavior in regard to click and pop avoidance. E.g. consider the following setup where two MUXs share the same control. +------+ A1 ------| | | MUX1 |----- C1 B1 ------| | +------+ | control ---+ | +------+ A2 ------| | | MUX2 |----- C2 B2 ------| | +------+ If the control is updated to switch the MUXs from input A to input B with the current code the power-up/power-down sequence will look like this: Run soc_dapm_mux_update_power for MUX1 Power-down A1 Update MUXing Power-up B1 Run soc_dapm_mux_update_power for MUX2 Power-down A2 (Update MUXing) Power-up B2 Note that the second 'Update Muxing' is a no-op, since the register was already updated. While the preferred order for avoiding pops and clicks should be: Run soc_dapm_mux_update_power for control Power-down A1 Power-down A2 Update MUXing Power-up B1 Power-up B2 This patch changes the behavior to the later by running the updates for all widgets that the control is attached to at the same time. The new code is also a bit simpler since callers of soc_dapm_{mux,muxer}_update_power don't have to loop over each widget anymore and neither do we need to keep track for which of the kcontrol's widgets the current update is. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/soc-dapm.c | 162 +++++++++++++++++++++------------------------------ 1 file changed, 68 insertions(+), 94 deletions(-) (limited to 'sound') diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 8d9c09b266fd..6f8a01bf6ca8 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -1456,34 +1456,45 @@ static void dapm_seq_run(struct snd_soc_dapm_context *dapm, 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; + struct snd_soc_dapm_widget_list *wlist; + struct snd_soc_dapm_widget *w = NULL; + unsigned int wi; int ret; if (!update) return; - w = update->widget; + wlist = snd_kcontrol_chip(update->kcontrol); - 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) - dev_err(dapm->dev, "ASoC: %s DAPM pre-event failed: %d\n", - w->name, ret); + for (wi = 0; wi < wlist->num_widgets; wi++) { + w = wlist->widgets[wi]; + + 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) + dev_err(dapm->dev, "ASoC: %s DAPM pre-event failed: %d\n", + w->name, ret); + } } + if (!w) + return; + ret = soc_widget_update_bits_locked(w, update->reg, update->mask, update->val); if (ret < 0) dev_err(dapm->dev, "ASoC: %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) - dev_err(dapm->dev, "ASoC: %s DAPM post-event failed: %d\n", - w->name, ret); + for (wi = 0; wi < wlist->num_widgets; wi++) { + w = wlist->widgets[wi]; + + 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) + dev_err(dapm->dev, "ASoC: %s DAPM post-event failed: %d\n", + w->name, ret); + } } } @@ -1936,19 +1947,14 @@ static inline void dapm_debugfs_cleanup(struct snd_soc_dapm_context *dapm) #endif /* test and update the power status of a mux widget */ -static int soc_dapm_mux_update_power(struct snd_soc_dapm_widget *widget, +static int soc_dapm_mux_update_power(struct snd_soc_dapm_context *dapm, struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e) { struct snd_soc_dapm_path *path; int found = 0; - if (widget->id != snd_soc_dapm_mux && - widget->id != snd_soc_dapm_virt_mux && - widget->id != snd_soc_dapm_value_mux) - return -ENODEV; - /* find dapm widget path assoc with kcontrol */ - list_for_each_entry(path, &widget->dapm->card->paths, list) { + list_for_each_entry(path, &dapm->card->paths, list) { if (path->kcontrol != kcontrol) continue; @@ -1966,24 +1972,23 @@ static int soc_dapm_mux_update_power(struct snd_soc_dapm_widget *widget, "mux disconnection"); path->connect = 0; /* old connection must be powered down */ } + dapm_mark_dirty(path->sink, "mux change"); } - if (found) { - dapm_mark_dirty(widget, "mux change"); - dapm_power_widgets(widget->dapm, SND_SOC_DAPM_STREAM_NOP); - } + if (found) + dapm_power_widgets(dapm, SND_SOC_DAPM_STREAM_NOP); return found; } -int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_widget *widget, - struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e) +int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_context *dapm, + struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e) { - struct snd_soc_card *card = widget->dapm->card; + struct snd_soc_card *card = dapm->card; int ret; mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); - ret = soc_dapm_mux_update_power(widget, kcontrol, mux, e); + ret = soc_dapm_mux_update_power(dapm, kcontrol, mux, e); mutex_unlock(&card->dapm_mutex); if (ret > 0) soc_dpcm_runtime_update(card); @@ -1992,19 +1997,14 @@ int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_widget *widget, EXPORT_SYMBOL_GPL(snd_soc_dapm_mux_update_power); /* test and update the power status of a mixer or switch widget */ -static int soc_dapm_mixer_update_power(struct snd_soc_dapm_widget *widget, +static int soc_dapm_mixer_update_power(struct snd_soc_dapm_context *dapm, struct snd_kcontrol *kcontrol, int connect) { struct snd_soc_dapm_path *path; int found = 0; - if (widget->id != snd_soc_dapm_mixer && - widget->id != snd_soc_dapm_mixer_named_ctl && - widget->id != snd_soc_dapm_switch) - return -ENODEV; - /* find dapm widget path assoc with kcontrol */ - list_for_each_entry(path, &widget->dapm->card->paths, list) { + list_for_each_entry(path, &dapm->card->paths, list) { if (path->kcontrol != kcontrol) continue; @@ -2012,24 +2012,23 @@ static int soc_dapm_mixer_update_power(struct snd_soc_dapm_widget *widget, found = 1; path->connect = connect; dapm_mark_dirty(path->source, "mixer connection"); + dapm_mark_dirty(path->sink, "mixer update"); } - if (found) { - dapm_mark_dirty(widget, "mixer update"); - dapm_power_widgets(widget->dapm, SND_SOC_DAPM_STREAM_NOP); - } + if (found) + dapm_power_widgets(dapm, SND_SOC_DAPM_STREAM_NOP); return found; } -int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_widget *widget, - struct snd_kcontrol *kcontrol, int connect) +int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_context *dapm, + struct snd_kcontrol *kcontrol, int connect) { - struct snd_soc_card *card = widget->dapm->card; + struct snd_soc_card *card = dapm->card; int ret; mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); - ret = soc_dapm_mixer_update_power(widget, kcontrol, connect); + ret = soc_dapm_mixer_update_power(dapm, kcontrol, connect); mutex_unlock(&card->dapm_mutex); if (ret > 0) soc_dpcm_runtime_update(card); @@ -2695,7 +2694,6 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, unsigned int val; int connect, change; struct snd_soc_dapm_update update; - int wi; if (snd_soc_volsw_is_stereo(mc)) dev_warn(widget->dapm->dev, @@ -2714,22 +2712,16 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, change = snd_soc_test_bits(widget->codec, reg, mask, val); if (change) { - for (wi = 0; wi < wlist->num_widgets; wi++) { - widget = wlist->widgets[wi]; - - widget->value = val; + update.kcontrol = kcontrol; + update.reg = reg; + update.mask = mask; + update.val = val; - update.kcontrol = kcontrol; - update.widget = widget; - update.reg = reg; - update.mask = mask; - update.val = val; - widget->dapm->update = &update; + widget->dapm->update = &update; - soc_dapm_mixer_update_power(widget, kcontrol, connect); + soc_dapm_mixer_update_power(widget->dapm, kcontrol, connect); - widget->dapm->update = NULL; - } + widget->dapm->update = NULL; } mutex_unlock(&card->dapm_mutex); @@ -2784,7 +2776,6 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, unsigned int val, mux, change; unsigned int mask; struct snd_soc_dapm_update update; - int wi; if (ucontrol->value.enumerated.item[0] > e->max - 1) return -EINVAL; @@ -2802,22 +2793,17 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, change = snd_soc_test_bits(widget->codec, e->reg, mask, val); if (change) { - for (wi = 0; wi < wlist->num_widgets; wi++) { - widget = wlist->widgets[wi]; + widget->value = val; - widget->value = val; + update.kcontrol = kcontrol; + update.reg = e->reg; + update.mask = mask; + update.val = val; + widget->dapm->update = &update; - update.kcontrol = kcontrol; - update.widget = widget; - update.reg = e->reg; - update.mask = mask; - update.val = val; - widget->dapm->update = &update; + soc_dapm_mux_update_power(widget->dapm, kcontrol, mux, e); - soc_dapm_mux_update_power(widget, kcontrol, mux, e); - - widget->dapm->update = NULL; - } + widget->dapm->update = NULL; } mutex_unlock(&card->dapm_mutex); @@ -2861,7 +2847,6 @@ int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol, struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; int change; - int wi; if (ucontrol->value.enumerated.item[0] >= e->max) return -EINVAL; @@ -2870,13 +2855,8 @@ int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol, change = widget->value != ucontrol->value.enumerated.item[0]; if (change) { - for (wi = 0; wi < wlist->num_widgets; wi++) { - widget = wlist->widgets[wi]; - - widget->value = ucontrol->value.enumerated.item[0]; - - soc_dapm_mux_update_power(widget, kcontrol, widget->value, e); - } + widget->value = ucontrol->value.enumerated.item[0]; + soc_dapm_mux_update_power(widget->dapm, kcontrol, widget->value, e); } mutex_unlock(&card->dapm_mutex); @@ -2949,7 +2929,6 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol, unsigned int val, mux, change; unsigned int mask; struct snd_soc_dapm_update update; - int wi; if (ucontrol->value.enumerated.item[0] > e->max - 1) return -EINVAL; @@ -2967,22 +2946,17 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol, change = snd_soc_test_bits(widget->codec, e->reg, mask, val); if (change) { - for (wi = 0; wi < wlist->num_widgets; wi++) { - widget = wlist->widgets[wi]; - - widget->value = val; + widget->value = val; - update.kcontrol = kcontrol; - update.widget = widget; - update.reg = e->reg; - update.mask = mask; - update.val = val; - widget->dapm->update = &update; + update.kcontrol = kcontrol; + update.reg = e->reg; + update.mask = mask; + update.val = val; + widget->dapm->update = &update; - soc_dapm_mux_update_power(widget, kcontrol, mux, e); + soc_dapm_mux_update_power(widget->dapm, kcontrol, mux, e); - widget->dapm->update = NULL; - } + widget->dapm->update = NULL; } mutex_unlock(&card->dapm_mutex); -- cgit v1.2.3 From 6b3fc03b3b614ced09df96ca60ab6f627d8c240c Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 24 Jul 2013 15:27:38 +0200 Subject: ASoC: dapm: Add a update parameter to snd_soc_dapm_{mux,mixer}_update_power In order to avoid race conditions the assignment of dapm->update should happen while card->dapm_mutex is being held. To allow CODEC drivers to run a register update when using snd_soc_dapm_mux_update_power() or snd_soc_dapm_mixer_update_power() add a update parameter to these two functions. The update parameter will be assigned to dapm->update while card->dapm_mutex is locked. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/soc-dapm.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 6f8a01bf6ca8..758761146a42 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -1982,13 +1982,16 @@ static int soc_dapm_mux_update_power(struct snd_soc_dapm_context *dapm, } int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_context *dapm, - struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e) + struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e, + struct snd_soc_dapm_update *update) { struct snd_soc_card *card = dapm->card; int ret; mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); + dapm->update = update; ret = soc_dapm_mux_update_power(dapm, kcontrol, mux, e); + dapm->update = NULL; mutex_unlock(&card->dapm_mutex); if (ret > 0) soc_dpcm_runtime_update(card); @@ -2022,13 +2025,16 @@ static int soc_dapm_mixer_update_power(struct snd_soc_dapm_context *dapm, } int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_context *dapm, - struct snd_kcontrol *kcontrol, int connect) + struct snd_kcontrol *kcontrol, int connect, + struct snd_soc_dapm_update *update) { struct snd_soc_card *card = dapm->card; int ret; mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); + dapm->update = update; ret = soc_dapm_mixer_update_power(dapm, kcontrol, connect); + dapm->update = NULL; mutex_unlock(&card->dapm_mutex); if (ret > 0) soc_dpcm_runtime_update(card); -- cgit v1.2.3 From 5d99d778495cb02eafd38292f462c4466fc7189f Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 24 Jul 2013 15:27:39 +0200 Subject: ASoC: tlv320aic3x: Use snd_soc_dapm_mixer_update_power Use snd_soc_dapm_mixer_update_power() instead of reimplementing its functionality. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic3x.c | 49 ++++++++++++++---------------------------- 1 file changed, 16 insertions(+), 33 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index e5b926883131..1325c0c0df50 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c @@ -147,10 +147,9 @@ static int snd_soc_dapm_put_volsw_aic3x(struct snd_kcontrol *kcontrol, int max = mc->max; unsigned int mask = (1 << fls(max)) - 1; unsigned int invert = mc->invert; - unsigned short val, val_mask; - int ret; - struct snd_soc_dapm_path *path; - int found = 0; + unsigned short val; + struct snd_soc_dapm_update update; + int connect, change; val = (ucontrol->value.integer.value[0] & mask); @@ -158,42 +157,26 @@ static int snd_soc_dapm_put_volsw_aic3x(struct snd_kcontrol *kcontrol, if (val) val = mask; + connect = !!val; + if (invert) val = mask - val; - val_mask = mask << shift; - val = val << shift; - - mutex_lock(&widget->codec->mutex); - if (snd_soc_test_bits(widget->codec, reg, val_mask, val)) { - /* find dapm widget path assoc with kcontrol */ - list_for_each_entry(path, &widget->dapm->card->paths, list) { - if (path->kcontrol != kcontrol) - continue; + mask <<= shift; + val <<= shift; - /* found, now check type */ - found = 1; - if (val) - /* new connection */ - path->connect = invert ? 0 : 1; - else - /* old connection must be powered down */ - path->connect = invert ? 1 : 0; + change = snd_soc_test_bits(widget->codec, val, mask, reg); + if (change) { + update.kcontrol = kcontrol; + update.reg = reg; + update.mask = mask; + update.val = val; - dapm_mark_dirty(path->source, "tlv320aic3x source"); - dapm_mark_dirty(path->sink, "tlv320aic3x sink"); - - break; - } + snd_soc_dapm_mixer_update_power(widget->dapm, kcontrol, connect, + &update); } - mutex_unlock(&widget->codec->mutex); - - if (found) - snd_soc_dapm_sync(widget->dapm); - - ret = snd_soc_update_bits_locked(widget->codec, reg, val_mask, val); - return ret; + return change; } /* -- cgit v1.2.3 From 564c65049eddb1a95b48958080db97eda88c98dd Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 29 Jul 2013 17:13:55 +0200 Subject: ASoC: dapm: Move snd_soc_dapm_update from dapm context to card The update field of a DAPM context is only assigned while the card's dapm_mutex is locked, the field is also cleared again while the mutex is stil locked. So there will only ever be one DAPM context at a time with a non-NULL update field. So it is safe to move the update field from the DAPM context struct to the card struct. Doing so will allow further cleanups in this area. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/soc-dapm.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'sound') diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 366daef006ed..7449e27bf133 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -1425,7 +1425,7 @@ static void dapm_seq_run(struct snd_soc_dapm_context *dapm, static void dapm_widget_update(struct snd_soc_dapm_context *dapm) { - struct snd_soc_dapm_update *update = dapm->update; + struct snd_soc_dapm_update *update = dapm->card->update; struct snd_soc_dapm_widget_list *wlist; struct snd_soc_dapm_widget *w = NULL; unsigned int wi; @@ -1959,9 +1959,9 @@ int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_context *dapm, int ret; mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); - dapm->update = update; + card->update = update; ret = soc_dapm_mux_update_power(dapm, kcontrol, mux, e); - dapm->update = NULL; + card->update = NULL; mutex_unlock(&card->dapm_mutex); if (ret > 0) soc_dpcm_runtime_update(card); @@ -2002,9 +2002,9 @@ int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_context *dapm, int ret; mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); - dapm->update = update; + card->update = update; ret = soc_dapm_mixer_update_power(dapm, kcontrol, connect); - dapm->update = NULL; + card->update = NULL; mutex_unlock(&card->dapm_mutex); if (ret > 0) soc_dpcm_runtime_update(card); @@ -2693,11 +2693,11 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, update.mask = mask; update.val = val; - widget->dapm->update = &update; + card->update = &update; soc_dapm_mixer_update_power(widget->dapm, kcontrol, connect); - widget->dapm->update = NULL; + card->update = NULL; } mutex_unlock(&card->dapm_mutex); @@ -2775,11 +2775,11 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, update.reg = e->reg; update.mask = mask; update.val = val; - widget->dapm->update = &update; + card->update = &update; soc_dapm_mux_update_power(widget->dapm, kcontrol, mux, e); - widget->dapm->update = NULL; + card->update = NULL; } mutex_unlock(&card->dapm_mutex); @@ -2928,11 +2928,11 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol, update.reg = e->reg; update.mask = mask; update.val = val; - widget->dapm->update = &update; + card->update = &update; soc_dapm_mux_update_power(widget->dapm, kcontrol, mux, e); - widget->dapm->update = NULL; + card->update = NULL; } mutex_unlock(&card->dapm_mutex); -- cgit v1.2.3 From 95dd5cd6e16d86786f7dc9da404ae477403d8f83 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 29 Jul 2013 17:13:56 +0200 Subject: ASoC: dapm: Pass card instead of dapm context to dapm_power_widgets() DAPM operations are always performed on the card as a whole. Yet (primarily for historic reasons) dapm_power_widgets() takes a DAPM context as its parameter. The DAPM context is mainly used to look up a pointer to the card. The same is true for a couple of functions that are being called from dapm_power_widgets(). This patch changes the signature of dapm_power_widgets() and a couple of related functions to take a snd_soc_card instead of a snd_soc_dapm_context. Some of the functions also use the DAPM's device to print error and debug messages. This can be a bit confusing though since this means the messages for all widgets, also those from other contexts, will be printed with that device. The patch updates those cases to use the device of the widget's DAPM context. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/soc-dapm.c | 100 +++++++++++++++++++++++++-------------------------- 1 file changed, 49 insertions(+), 51 deletions(-) (limited to 'sound') diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 7449e27bf133..5db8df2f8866 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -1213,10 +1213,9 @@ static void dapm_seq_insert(struct snd_soc_dapm_widget *new_widget, list_add_tail(&new_widget->power_list, list); } -static void dapm_seq_check_event(struct snd_soc_dapm_context *dapm, +static void dapm_seq_check_event(struct snd_soc_card *card, struct snd_soc_dapm_widget *w, int event) { - struct snd_soc_card *card = dapm->card; const char *ev_name; int power, ret; @@ -1254,22 +1253,21 @@ static void dapm_seq_check_event(struct snd_soc_dapm_context *dapm, return; if (w->event && (w->event_flags & event)) { - pop_dbg(dapm->dev, card->pop_time, "pop test : %s %s\n", + pop_dbg(w->dapm->dev, card->pop_time, "pop test : %s %s\n", w->name, ev_name); trace_snd_soc_dapm_widget_event_start(w, event); ret = w->event(w, NULL, event); trace_snd_soc_dapm_widget_event_done(w, event); if (ret < 0) - dev_err(dapm->dev, "ASoC: %s: %s event failed: %d\n", + dev_err(w->dapm->dev, "ASoC: %s: %s event failed: %d\n", ev_name, w->name, ret); } } /* Apply the coalesced changes from a DAPM sequence */ -static void dapm_seq_run_coalesced(struct snd_soc_dapm_context *dapm, +static void dapm_seq_run_coalesced(struct snd_soc_card *card, struct list_head *pending) { - struct snd_soc_card *card = dapm->card; struct snd_soc_dapm_widget *w; int reg, power; unsigned int value = 0; @@ -1292,13 +1290,13 @@ static void dapm_seq_run_coalesced(struct snd_soc_dapm_context *dapm, if (power) value |= cur_mask; - pop_dbg(dapm->dev, card->pop_time, + pop_dbg(w->dapm->dev, card->pop_time, "pop test : Queue %s: reg=0x%x, 0x%x/0x%x\n", w->name, reg, value, mask); /* Check for events */ - dapm_seq_check_event(dapm, w, SND_SOC_DAPM_PRE_PMU); - dapm_seq_check_event(dapm, w, SND_SOC_DAPM_PRE_PMD); + dapm_seq_check_event(card, w, SND_SOC_DAPM_PRE_PMU); + dapm_seq_check_event(card, w, SND_SOC_DAPM_PRE_PMD); } if (reg >= 0) { @@ -1308,7 +1306,7 @@ static void dapm_seq_run_coalesced(struct snd_soc_dapm_context *dapm, w = list_first_entry(pending, struct snd_soc_dapm_widget, power_list); - pop_dbg(dapm->dev, card->pop_time, + pop_dbg(w->dapm->dev, card->pop_time, "pop test : Applying 0x%x/0x%x to %x in %dms\n", value, mask, reg, card->pop_time); pop_wait(card->pop_time); @@ -1316,8 +1314,8 @@ static void dapm_seq_run_coalesced(struct snd_soc_dapm_context *dapm, } list_for_each_entry(w, pending, power_list) { - dapm_seq_check_event(dapm, w, SND_SOC_DAPM_POST_PMU); - dapm_seq_check_event(dapm, w, SND_SOC_DAPM_POST_PMD); + dapm_seq_check_event(card, w, SND_SOC_DAPM_POST_PMU); + dapm_seq_check_event(card, w, SND_SOC_DAPM_POST_PMD); } } @@ -1329,8 +1327,8 @@ static void dapm_seq_run_coalesced(struct snd_soc_dapm_context *dapm, * Currently anything that requires more than a single write is not * handled. */ -static void dapm_seq_run(struct snd_soc_dapm_context *dapm, - struct list_head *list, int event, bool power_up) +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; LIST_HEAD(pending); @@ -1353,7 +1351,7 @@ static void dapm_seq_run(struct snd_soc_dapm_context *dapm, if (sort[w->id] != cur_sort || w->reg != cur_reg || w->dapm != cur_dapm || w->subseq != cur_subseq) { if (!list_empty(&pending)) - dapm_seq_run_coalesced(cur_dapm, &pending); + dapm_seq_run_coalesced(card, &pending); if (cur_dapm && cur_dapm->seq_notifier) { for (i = 0; i < ARRAY_SIZE(dapm_up_seq); i++) @@ -1413,7 +1411,7 @@ static void dapm_seq_run(struct snd_soc_dapm_context *dapm, } if (!list_empty(&pending)) - dapm_seq_run_coalesced(cur_dapm, &pending); + dapm_seq_run_coalesced(card, &pending); if (cur_dapm && cur_dapm->seq_notifier) { for (i = 0; i < ARRAY_SIZE(dapm_up_seq); i++) @@ -1423,9 +1421,9 @@ static void dapm_seq_run(struct snd_soc_dapm_context *dapm, } } -static void dapm_widget_update(struct snd_soc_dapm_context *dapm) +static void dapm_widget_update(struct snd_soc_card *card) { - struct snd_soc_dapm_update *update = dapm->card->update; + struct snd_soc_dapm_update *update = card->update; struct snd_soc_dapm_widget_list *wlist; struct snd_soc_dapm_widget *w = NULL; unsigned int wi; @@ -1442,7 +1440,7 @@ static void dapm_widget_update(struct snd_soc_dapm_context *dapm) 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) - dev_err(dapm->dev, "ASoC: %s DAPM pre-event failed: %d\n", + dev_err(w->dapm->dev, "ASoC: %s DAPM pre-event failed: %d\n", w->name, ret); } } @@ -1453,7 +1451,7 @@ static void dapm_widget_update(struct snd_soc_dapm_context *dapm) ret = soc_widget_update_bits_locked(w, update->reg, update->mask, update->val); if (ret < 0) - dev_err(dapm->dev, "ASoC: %s DAPM update failed: %d\n", + dev_err(w->dapm->dev, "ASoC: %s DAPM update failed: %d\n", w->name, ret); for (wi = 0; wi < wlist->num_widgets; wi++) { @@ -1462,7 +1460,7 @@ static void dapm_widget_update(struct snd_soc_dapm_context *dapm) 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) - dev_err(dapm->dev, "ASoC: %s DAPM post-event failed: %d\n", + dev_err(w->dapm->dev, "ASoC: %s DAPM post-event failed: %d\n", w->name, ret); } } @@ -1627,9 +1625,8 @@ static void dapm_power_one_widget(struct snd_soc_dapm_widget *w, * o Input pin to Output pin (bypass, sidetone) * o DAC to ADC (loopback). */ -static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event) +static int dapm_power_widgets(struct snd_soc_card *card, int event) { - struct snd_soc_card *card = dapm->card; struct snd_soc_dapm_widget *w; struct snd_soc_dapm_context *d; LIST_HEAD(up_list); @@ -1711,29 +1708,29 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event) trace_snd_soc_dapm_walk_done(card); /* Run all the bias changes in parallel */ - list_for_each_entry(d, &dapm->card->dapm_list, list) + list_for_each_entry(d, &card->dapm_list, list) async_schedule_domain(dapm_pre_sequence_async, d, &async_domain); async_synchronize_full_domain(&async_domain); list_for_each_entry(w, &down_list, power_list) { - dapm_seq_check_event(dapm, w, SND_SOC_DAPM_WILL_PMD); + dapm_seq_check_event(card, w, SND_SOC_DAPM_WILL_PMD); } list_for_each_entry(w, &up_list, power_list) { - dapm_seq_check_event(dapm, w, SND_SOC_DAPM_WILL_PMU); + dapm_seq_check_event(card, w, SND_SOC_DAPM_WILL_PMU); } /* Power down widgets first; try to avoid amplifying pops. */ - dapm_seq_run(dapm, &down_list, event, false); + dapm_seq_run(card, &down_list, event, false); - dapm_widget_update(dapm); + dapm_widget_update(card); /* Now power up. */ - dapm_seq_run(dapm, &up_list, event, true); + dapm_seq_run(card, &up_list, event, true); /* Run all the bias changes in parallel */ - list_for_each_entry(d, &dapm->card->dapm_list, list) + list_for_each_entry(d, &card->dapm_list, list) async_schedule_domain(dapm_post_sequence_async, d, &async_domain); async_synchronize_full_domain(&async_domain); @@ -1744,7 +1741,7 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event) d->stream_event(d, event); } - pop_dbg(dapm->dev, card->pop_time, + pop_dbg(card->dev, card->pop_time, "DAPM sequencing finished, waiting %dms\n", card->pop_time); pop_wait(card->pop_time); @@ -1917,14 +1914,14 @@ static inline void dapm_debugfs_cleanup(struct snd_soc_dapm_context *dapm) #endif /* test and update the power status of a mux widget */ -static int soc_dapm_mux_update_power(struct snd_soc_dapm_context *dapm, +static int soc_dapm_mux_update_power(struct snd_soc_card *card, struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e) { struct snd_soc_dapm_path *path; int found = 0; /* find dapm widget path assoc with kcontrol */ - list_for_each_entry(path, &dapm->card->paths, list) { + list_for_each_entry(path, &card->paths, list) { if (path->kcontrol != kcontrol) continue; @@ -1946,7 +1943,7 @@ static int soc_dapm_mux_update_power(struct snd_soc_dapm_context *dapm, } if (found) - dapm_power_widgets(dapm, SND_SOC_DAPM_STREAM_NOP); + dapm_power_widgets(card, SND_SOC_DAPM_STREAM_NOP); return found; } @@ -1960,7 +1957,7 @@ int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_context *dapm, mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); card->update = update; - ret = soc_dapm_mux_update_power(dapm, kcontrol, mux, e); + ret = soc_dapm_mux_update_power(card, kcontrol, mux, e); card->update = NULL; mutex_unlock(&card->dapm_mutex); if (ret > 0) @@ -1970,14 +1967,14 @@ int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_context *dapm, EXPORT_SYMBOL_GPL(snd_soc_dapm_mux_update_power); /* test and update the power status of a mixer or switch widget */ -static int soc_dapm_mixer_update_power(struct snd_soc_dapm_context *dapm, +static int soc_dapm_mixer_update_power(struct snd_soc_card *card, struct snd_kcontrol *kcontrol, int connect) { struct snd_soc_dapm_path *path; int found = 0; /* find dapm widget path assoc with kcontrol */ - list_for_each_entry(path, &dapm->card->paths, list) { + list_for_each_entry(path, &card->paths, list) { if (path->kcontrol != kcontrol) continue; @@ -1989,7 +1986,7 @@ static int soc_dapm_mixer_update_power(struct snd_soc_dapm_context *dapm, } if (found) - dapm_power_widgets(dapm, SND_SOC_DAPM_STREAM_NOP); + dapm_power_widgets(card, SND_SOC_DAPM_STREAM_NOP); return found; } @@ -2003,7 +2000,7 @@ int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_context *dapm, mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); card->update = update; - ret = soc_dapm_mixer_update_power(dapm, kcontrol, connect); + ret = soc_dapm_mixer_update_power(card, kcontrol, connect); card->update = NULL; mutex_unlock(&card->dapm_mutex); if (ret > 0) @@ -2180,7 +2177,7 @@ int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm) return 0; mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); - ret = dapm_power_widgets(dapm, SND_SOC_DAPM_STREAM_NOP); + ret = dapm_power_widgets(dapm->card, SND_SOC_DAPM_STREAM_NOP); mutex_unlock(&dapm->card->dapm_mutex); return ret; } @@ -2545,12 +2542,13 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_weak_routes); */ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm) { + struct snd_soc_card *card = dapm->card; struct snd_soc_dapm_widget *w; unsigned int val; - mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT); + mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT); - list_for_each_entry(w, &dapm->card->widgets, list) + list_for_each_entry(w, &card->widgets, list) { if (w->new) continue; @@ -2560,7 +2558,7 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm) sizeof(struct snd_kcontrol *), GFP_KERNEL); if (!w->kcontrols) { - mutex_unlock(&dapm->card->dapm_mutex); + mutex_unlock(&card->dapm_mutex); return -ENOMEM; } } @@ -2601,8 +2599,8 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm) dapm_debugfs_add_widget(w); } - dapm_power_widgets(dapm, SND_SOC_DAPM_STREAM_NOP); - mutex_unlock(&dapm->card->dapm_mutex); + dapm_power_widgets(card, SND_SOC_DAPM_STREAM_NOP); + mutex_unlock(&card->dapm_mutex); return 0; } EXPORT_SYMBOL_GPL(snd_soc_dapm_new_widgets); @@ -2695,7 +2693,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, card->update = &update; - soc_dapm_mixer_update_power(widget->dapm, kcontrol, connect); + soc_dapm_mixer_update_power(card, kcontrol, connect); card->update = NULL; } @@ -2777,7 +2775,7 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, update.val = val; card->update = &update; - soc_dapm_mux_update_power(widget->dapm, kcontrol, mux, e); + soc_dapm_mux_update_power(card, kcontrol, mux, e); card->update = NULL; } @@ -2832,7 +2830,7 @@ int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol, change = widget->value != ucontrol->value.enumerated.item[0]; if (change) { widget->value = ucontrol->value.enumerated.item[0]; - soc_dapm_mux_update_power(widget->dapm, kcontrol, widget->value, e); + soc_dapm_mux_update_power(card, kcontrol, widget->value, e); } mutex_unlock(&card->dapm_mutex); @@ -2930,7 +2928,7 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol, update.val = val; card->update = &update; - soc_dapm_mux_update_power(widget->dapm, kcontrol, mux, e); + soc_dapm_mux_update_power(card, kcontrol, mux, e); card->update = NULL; } @@ -3478,7 +3476,7 @@ static void soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream, } } - dapm_power_widgets(&rtd->card->dapm, event); + dapm_power_widgets(rtd->card, event); } /** @@ -3747,7 +3745,7 @@ static void soc_dapm_shutdown_codec(struct snd_soc_dapm_context *dapm) if (dapm->bias_level == SND_SOC_BIAS_ON) snd_soc_dapm_set_bias_level(dapm, SND_SOC_BIAS_PREPARE); - dapm_seq_run(dapm, &down_list, 0, false); + dapm_seq_run(card, &down_list, 0, false); if (dapm->bias_level == SND_SOC_BIAS_PREPARE) snd_soc_dapm_set_bias_level(dapm, SND_SOC_BIAS_STANDBY); -- cgit v1.2.3 From eee5d7f99ae95059e1a3d1cfa2dea3ed8dbd94ac Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 29 Jul 2013 17:13:57 +0200 Subject: ASoC: dapm: Add a helper to get the CODEC for DAPM kcontrol We use the same 3 lines to get the CODEC for a kcontrol in a quite a few places. This patch puts them into a common helper function. Having this encapsulated in a helper function will also make it more easier to eventually change the data layout of the kcontrol's private data. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic3x.c | 7 +++---- sound/soc/codecs/twl6040.c | 4 +--- sound/soc/codecs/wm8903.c | 4 +--- sound/soc/codecs/wm8994.c | 4 +--- sound/soc/codecs/wm8995.c | 5 +---- sound/soc/codecs/wm_hubs.c | 8 ++------ sound/soc/soc-dapm.c | 40 +++++++++++++++++++++++----------------- 7 files changed, 32 insertions(+), 40 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index 1325c0c0df50..fec0db04262d 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c @@ -138,8 +138,7 @@ static const u8 aic3x_reg[AIC3X_CACHEREGNUM] = { static int snd_soc_dapm_put_volsw_aic3x(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); - struct snd_soc_dapm_widget *widget = wlist->widgets[0]; + struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; unsigned int reg = mc->reg; @@ -165,14 +164,14 @@ static int snd_soc_dapm_put_volsw_aic3x(struct snd_kcontrol *kcontrol, mask <<= shift; val <<= shift; - change = snd_soc_test_bits(widget->codec, val, mask, reg); + change = snd_soc_test_bits(codec, val, mask, reg); if (change) { update.kcontrol = kcontrol; update.reg = reg; update.mask = mask; update.val = val; - snd_soc_dapm_mixer_update_power(widget->dapm, kcontrol, connect, + snd_soc_dapm_mixer_update_power(&codec->dapm, kcontrol, connect, &update); } diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index 44621ddc332d..d6c5bf14179a 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c @@ -437,9 +437,7 @@ static irqreturn_t twl6040_audio_handler(int irq, void *data) static int twl6040_soc_dapm_put_vibra_enum(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); - struct snd_soc_dapm_widget *widget = wlist->widgets[0]; - struct snd_soc_codec *codec = widget->codec; + struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; unsigned int val; diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index fa24cedee687..eebcb1da3b7b 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c @@ -364,9 +364,7 @@ static void wm8903_seq_notifier(struct snd_soc_dapm_context *dapm, static int wm8903_class_w_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); - struct snd_soc_dapm_widget *widget = wlist->widgets[0]; - struct snd_soc_codec *codec = widget->codec; + struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); u16 reg; int ret; diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index ba832b77c543..eee2a01f2691 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -1437,9 +1437,7 @@ SOC_DAPM_SINGLE("AIF1.1 Switch", WM8994_DAC2_RIGHT_MIXER_ROUTING, static int wm8994_put_class_w(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); - struct snd_soc_dapm_widget *w = wlist->widgets[0]; - struct snd_soc_codec *codec = w->codec; + struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); int ret; ret = snd_soc_dapm_put_volsw(kcontrol, ucontrol); diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c index 90a65c427541..da2899e6c401 100644 --- a/sound/soc/codecs/wm8995.c +++ b/sound/soc/codecs/wm8995.c @@ -549,12 +549,9 @@ static int check_clk_sys(struct snd_soc_dapm_widget *source, static int wm8995_put_class_w(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); - struct snd_soc_dapm_widget *w = wlist->widgets[0]; - struct snd_soc_codec *codec; + struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); int ret; - codec = w->codec; ret = snd_soc_dapm_put_volsw(kcontrol, ucontrol); wm8995_update_class_w(codec); return ret; diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index 2d9e099415a5..8b50e5958de5 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c @@ -699,9 +699,7 @@ EXPORT_SYMBOL_GPL(wm_hubs_update_class_w); static int class_w_put_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); - struct snd_soc_dapm_widget *widget = wlist->widgets[0]; - struct snd_soc_codec *codec = widget->codec; + struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); int ret; ret = snd_soc_dapm_put_volsw(kcontrol, ucontrol); @@ -721,9 +719,7 @@ static int class_w_put_volsw(struct snd_kcontrol *kcontrol, static int class_w_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); - struct snd_soc_dapm_widget *widget = wlist->widgets[0]; - struct snd_soc_codec *codec = widget->codec; + struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); int ret; ret = snd_soc_dapm_put_enum_double(kcontrol, ucontrol); diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 5db8df2f8866..b18ac5b1cc2e 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -174,6 +174,17 @@ static inline struct snd_soc_dapm_widget *dapm_cnew_widget( return kmemdup(_widget, sizeof(*_widget), GFP_KERNEL); } +/** + * snd_soc_dapm_kcontrol_codec() - Returns the codec associated to a kcontrol + * @kcontrol: The kcontrol + */ +struct snd_soc_codec *snd_soc_dapm_kcontrol_codec(struct snd_kcontrol *kcontrol) +{ + struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); + return wlist->widgets[0]->codec; +} +EXPORT_SYMBOL_GPL(snd_soc_dapm_kcontrol_codec); + static void dapm_reset(struct snd_soc_card *card) { struct snd_soc_dapm_widget *w; @@ -2617,8 +2628,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_new_widgets); int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); - struct snd_soc_dapm_widget *widget = wlist->widgets[0]; + struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; unsigned int reg = mc->reg; @@ -2628,12 +2638,12 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, unsigned int invert = mc->invert; if (snd_soc_volsw_is_stereo(mc)) - dev_warn(widget->dapm->dev, + dev_warn(codec->dapm.dev, "ASoC: Control '%s' is stereo, which is not supported\n", kcontrol->id.name); ucontrol->value.integer.value[0] = - (snd_soc_read(widget->codec, reg) >> shift) & mask; + (snd_soc_read(codec, reg) >> shift) & mask; if (invert) ucontrol->value.integer.value[0] = max - ucontrol->value.integer.value[0]; @@ -2654,9 +2664,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_volsw); int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); - struct snd_soc_dapm_widget *widget = wlist->widgets[0]; - struct snd_soc_codec *codec = widget->codec; + struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); struct snd_soc_card *card = codec->card; struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; @@ -2670,7 +2678,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, struct snd_soc_dapm_update update; if (snd_soc_volsw_is_stereo(mc)) - dev_warn(widget->dapm->dev, + dev_warn(codec->dapm.dev, "ASoC: Control '%s' is stereo, which is not supported\n", kcontrol->id.name); @@ -2684,7 +2692,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); - change = snd_soc_test_bits(widget->codec, reg, mask, val); + change = snd_soc_test_bits(codec, reg, mask, val); if (change) { update.kcontrol = kcontrol; update.reg = reg; @@ -2715,12 +2723,11 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw); int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); - struct snd_soc_dapm_widget *widget = wlist->widgets[0]; + struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; unsigned int val; - val = snd_soc_read(widget->codec, e->reg); + val = snd_soc_read(codec, e->reg); ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & e->mask; if (e->shift_l != e->shift_r) ucontrol->value.enumerated.item[1] = @@ -2765,7 +2772,7 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); - change = snd_soc_test_bits(widget->codec, e->reg, mask, val); + change = snd_soc_test_bits(codec, e->reg, mask, val); if (change) { widget->value = val; @@ -2854,12 +2861,11 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_virt); int snd_soc_dapm_get_value_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); - struct snd_soc_dapm_widget *widget = wlist->widgets[0]; + struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; unsigned int reg_val, val, mux; - reg_val = snd_soc_read(widget->codec, e->reg); + reg_val = snd_soc_read(codec, e->reg); val = (reg_val >> e->shift_l) & e->mask; for (mux = 0; mux < e->max; mux++) { if (val == e->values[mux]) @@ -2918,7 +2924,7 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol, mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); - change = snd_soc_test_bits(widget->codec, e->reg, mask, val); + change = snd_soc_test_bits(codec, e->reg, mask, val); if (change) { widget->value = val; -- cgit v1.2.3 From e84357f7608f230b905acb18fe668609c9b811f0 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 29 Jul 2013 17:13:58 +0200 Subject: ASoC: dapm: Wrap kcontrol widget list access In preparation for adding additional per control data wrap all access to the widget list in helper functions. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/soc-dapm.c | 119 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 78 insertions(+), 41 deletions(-) (limited to 'sound') diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index b18ac5b1cc2e..da35b10ce6d1 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -174,14 +174,72 @@ static inline struct snd_soc_dapm_widget *dapm_cnew_widget( return kmemdup(_widget, sizeof(*_widget), GFP_KERNEL); } +struct dapm_kcontrol_data { + struct snd_soc_dapm_widget_list wlist; +}; + +static int dapm_kcontrol_data_alloc(struct snd_soc_dapm_widget *widget, + struct snd_kcontrol *kcontrol) +{ + struct dapm_kcontrol_data *data; + + data = kzalloc(sizeof(*data) + sizeof(widget), GFP_KERNEL); + if (!data) { + dev_err(widget->dapm->dev, + "ASoC: can't allocate kcontrol data for %s\n", + widget->name); + return -ENOMEM; + } + + data->wlist.widgets[0] = widget; + data->wlist.num_widgets = 1; + + kcontrol->private_data = data; + + return 0; +} + +static void dapm_kcontrol_free(struct snd_kcontrol *kctl) +{ + struct dapm_kcontrol_data *data = snd_kcontrol_chip(kctl); + kfree(data); +} + +static struct snd_soc_dapm_widget_list *dapm_kcontrol_get_wlist( + const struct snd_kcontrol *kcontrol) +{ + struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol); + + return &data->wlist; +} + +static int dapm_kcontrol_add_widget(struct snd_kcontrol *kcontrol, + struct snd_soc_dapm_widget *widget) +{ + struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol); + struct dapm_kcontrol_data *new_data; + unsigned int n = data->wlist.num_widgets + 1; + + new_data = krealloc(data, sizeof(*data) + sizeof(widget) * n, + GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->wlist.widgets[n - 1] = widget; + data->wlist.num_widgets = n; + + kcontrol->private_data = data; + + return 0; +} + /** * snd_soc_dapm_kcontrol_codec() - Returns the codec associated to a kcontrol * @kcontrol: The kcontrol */ struct snd_soc_codec *snd_soc_dapm_kcontrol_codec(struct snd_kcontrol *kcontrol) { - struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); - return wlist->widgets[0]->codec; + return dapm_kcontrol_get_wlist(kcontrol)->widgets[0]->codec; } EXPORT_SYMBOL_GPL(snd_soc_dapm_kcontrol_codec); @@ -488,11 +546,6 @@ static int dapm_is_shared_kcontrol(struct snd_soc_dapm_context *dapm, return 0; } -static void dapm_kcontrol_free(struct snd_kcontrol *kctl) -{ - kfree(kctl->private_data); -} - /* * Determine if a kcontrol is shared. If it is, look it up. If it isn't, * create it. Either way, add the widget into the control's widget list @@ -506,9 +559,6 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w, size_t prefix_len; int shared; struct snd_kcontrol *kcontrol; - struct snd_soc_dapm_widget_list *wlist; - int wlistentries; - size_t wlistsize; bool wname_in_long_name, kcname_in_long_name; char *long_name; const char *name; @@ -527,25 +577,6 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w, shared = dapm_is_shared_kcontrol(dapm, w, &w->kcontrol_news[kci], &kcontrol); - if (kcontrol) { - wlist = kcontrol->private_data; - wlistentries = wlist->num_widgets + 1; - } else { - wlist = NULL; - wlistentries = 1; - } - - wlistsize = sizeof(struct snd_soc_dapm_widget_list) + - wlistentries * sizeof(struct snd_soc_dapm_widget *); - wlist = krealloc(wlist, wlistsize, GFP_KERNEL); - if (wlist == NULL) { - dev_err(dapm->dev, "ASoC: can't allocate widget list for %s\n", - w->name); - return -ENOMEM; - } - wlist->num_widgets = wlistentries; - wlist->widgets[wlistentries - 1] = w; - if (!kcontrol) { if (shared) { wname_in_long_name = false; @@ -568,7 +599,6 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w, kcname_in_long_name = false; break; default: - kfree(wlist); return -EINVAL; } } @@ -583,10 +613,8 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w, long_name = kasprintf(GFP_KERNEL, "%s %s", w->name + prefix_len, w->kcontrol_news[kci].name); - if (long_name == NULL) { - kfree(wlist); + if (long_name == NULL) return -ENOMEM; - } name = long_name; } else if (wname_in_long_name) { @@ -597,21 +625,30 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w, name = w->kcontrol_news[kci].name; } - kcontrol = snd_soc_cnew(&w->kcontrol_news[kci], wlist, name, + kcontrol = snd_soc_cnew(&w->kcontrol_news[kci], NULL, name, prefix); kcontrol->private_free = dapm_kcontrol_free; kfree(long_name); + + ret = dapm_kcontrol_data_alloc(w, kcontrol); + if (ret) { + snd_ctl_free_one(kcontrol); + return ret; + } + ret = snd_ctl_add(card, kcontrol); if (ret < 0) { dev_err(dapm->dev, "ASoC: failed to add widget %s dapm kcontrol %s: %d\n", w->name, name, ret); - kfree(wlist); return ret; } + } else { + ret = dapm_kcontrol_add_widget(kcontrol, w); + if (ret) + return ret; } - kcontrol->private_data = wlist; w->kcontrols[kci] = kcontrol; path->kcontrol = kcontrol; @@ -1443,7 +1480,7 @@ static void dapm_widget_update(struct snd_soc_card *card) if (!update) return; - wlist = snd_kcontrol_chip(update->kcontrol); + wlist = dapm_kcontrol_get_wlist(update->kcontrol); for (wi = 0; wi < wlist->num_widgets; wi++) { w = wlist->widgets[wi]; @@ -2749,7 +2786,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_double); int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); + struct snd_soc_dapm_widget_list *wlist = dapm_kcontrol_get_wlist(kcontrol); struct snd_soc_dapm_widget *widget = wlist->widgets[0]; struct snd_soc_codec *codec = widget->codec; struct snd_soc_card *card = codec->card; @@ -2802,7 +2839,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double); int snd_soc_dapm_get_enum_virt(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); + struct snd_soc_dapm_widget_list *wlist = dapm_kcontrol_get_wlist(kcontrol); struct snd_soc_dapm_widget *widget = wlist->widgets[0]; ucontrol->value.enumerated.item[0] = widget->value; @@ -2821,7 +2858,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_virt); int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); + struct snd_soc_dapm_widget_list *wlist = dapm_kcontrol_get_wlist(kcontrol); struct snd_soc_dapm_widget *widget = wlist->widgets[0]; struct snd_soc_codec *codec = widget->codec; struct snd_soc_card *card = codec->card; @@ -2901,7 +2938,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_value_enum_double); int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); + struct snd_soc_dapm_widget_list *wlist = dapm_kcontrol_get_wlist(kcontrol); struct snd_soc_dapm_widget *widget = wlist->widgets[0]; struct snd_soc_codec *codec = widget->codec; struct snd_soc_card *card = codec->card; -- cgit v1.2.3 From cf7c1de20c576477d42deae255cbc6e439bb5dc0 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 29 Jul 2013 17:13:59 +0200 Subject: ASoC: dapm: Move 'value' field from widget to control The 'value' field is really per control and not per widget. Currently it is only used for virtual MUXes, which only have one control per widget. So in that case there is not so much of a difference between whether it is stored per widget or per control. Moving the 'value' field from the widget to the control will allow us to use it also for cases where we have more than one control per widget. E.g. for mixers with multiple input controls. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/soc-dapm.c | 53 +++++++++++++++++++++++++++++----------------------- 1 file changed, 30 insertions(+), 23 deletions(-) (limited to 'sound') diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index da35b10ce6d1..bad6f6db74c9 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -175,6 +175,7 @@ static inline struct snd_soc_dapm_widget *dapm_cnew_widget( } struct dapm_kcontrol_data { + unsigned int value; struct snd_soc_dapm_widget_list wlist; }; @@ -233,6 +234,26 @@ static int dapm_kcontrol_add_widget(struct snd_kcontrol *kcontrol, return 0; } +static unsigned int dapm_kcontrol_get_value(const struct snd_kcontrol *kcontrol) +{ + struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol); + + return data->value; +} + +static bool dapm_kcontrol_set_value(const struct snd_kcontrol *kcontrol, + unsigned int value) +{ + struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol); + + if (data->value == value) + return false; + + data->value = value; + + return true; +} + /** * snd_soc_dapm_kcontrol_codec() - Returns the codec associated to a kcontrol * @kcontrol: The kcontrol @@ -2786,9 +2807,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_double); int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_dapm_widget_list *wlist = dapm_kcontrol_get_wlist(kcontrol); - struct snd_soc_dapm_widget *widget = wlist->widgets[0]; - struct snd_soc_codec *codec = widget->codec; + struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); struct snd_soc_card *card = codec->card; struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; unsigned int val, mux, change; @@ -2811,8 +2830,6 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, change = snd_soc_test_bits(codec, e->reg, mask, val); if (change) { - widget->value = val; - update.kcontrol = kcontrol; update.reg = e->reg; update.mask = mask; @@ -2839,11 +2856,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double); int snd_soc_dapm_get_enum_virt(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_dapm_widget_list *wlist = dapm_kcontrol_get_wlist(kcontrol); - struct snd_soc_dapm_widget *widget = wlist->widgets[0]; - - ucontrol->value.enumerated.item[0] = widget->value; - + ucontrol->value.enumerated.item[0] = dapm_kcontrol_get_value(kcontrol); return 0; } EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_virt); @@ -2858,10 +2871,9 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_virt); int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_dapm_widget_list *wlist = dapm_kcontrol_get_wlist(kcontrol); - struct snd_soc_dapm_widget *widget = wlist->widgets[0]; - struct snd_soc_codec *codec = widget->codec; + struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); struct snd_soc_card *card = codec->card; + unsigned int value; struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; int change; @@ -2871,11 +2883,10 @@ int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol, mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); - change = widget->value != ucontrol->value.enumerated.item[0]; - if (change) { - widget->value = ucontrol->value.enumerated.item[0]; - soc_dapm_mux_update_power(card, kcontrol, widget->value, e); - } + value = ucontrol->value.enumerated.item[0]; + change = dapm_kcontrol_set_value(kcontrol, value); + if (change) + soc_dapm_mux_update_power(card, kcontrol, value, e); mutex_unlock(&card->dapm_mutex); return change; @@ -2938,9 +2949,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_value_enum_double); int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_dapm_widget_list *wlist = dapm_kcontrol_get_wlist(kcontrol); - struct snd_soc_dapm_widget *widget = wlist->widgets[0]; - struct snd_soc_codec *codec = widget->codec; + struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); struct snd_soc_card *card = codec->card; struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; unsigned int val, mux, change; @@ -2963,8 +2972,6 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol, change = snd_soc_test_bits(codec, e->reg, mask, val); if (change) { - widget->value = val; - update.kcontrol = kcontrol; update.reg = e->reg; update.mask = mask; -- cgit v1.2.3 From 5106b92f80a2cd37c52cffed80b4f5acfb77ccfd Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 29 Jul 2013 17:14:00 +0200 Subject: ASoC: dapm: Keep a list of paths per kcontrol Currently we store for each path which control (if any at all) is associated with that control. But we are only ever interested in the reverse relationship, i.e. we want to know all the paths a certain control is associated with. This is currently implemented by always iterating over all paths. This patch updates the code to keep a list for each control which contains all the paths that are associated with that control. This improves the run time of e.g. soc_dapm_mixer_update_power() and soc_dapm_mux_update_power() from O(n) (with n being the number of paths for the card) to O(1). Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/soc-dapm.c | 40 ++++++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 12 deletions(-) (limited to 'sound') diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index bad6f6db74c9..b779d36d5b3a 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -176,6 +176,7 @@ static inline struct snd_soc_dapm_widget *dapm_cnew_widget( struct dapm_kcontrol_data { unsigned int value; + struct list_head paths; struct snd_soc_dapm_widget_list wlist; }; @@ -194,6 +195,7 @@ static int dapm_kcontrol_data_alloc(struct snd_soc_dapm_widget *widget, data->wlist.widgets[0] = widget; data->wlist.num_widgets = 1; + INIT_LIST_HEAD(&data->paths