diff options
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/soc-core.c | 1 | ||||
-rw-r--r-- | sound/soc/soc-dapm.c | 60 |
2 files changed, 43 insertions, 18 deletions
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index ef69f5a02709..db2e0f0c00e8 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2897,6 +2897,7 @@ int snd_soc_register_card(struct snd_soc_card *card) INIT_LIST_HEAD(&card->list); card->instantiated = 0; mutex_init(&card->mutex); + mutex_init(&card->dapm_mutex); mutex_lock(&client_mutex); list_add(&card->list, &card_list); diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index d67c637557a7..ffb6af574c7f 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -1719,7 +1719,12 @@ static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm, */ int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm) { - return dapm_power_widgets(dapm, SND_SOC_DAPM_STREAM_NOP); + int ret; + + mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_PCM); + ret = dapm_power_widgets(dapm, SND_SOC_DAPM_STREAM_NOP); + mutex_unlock(&dapm->card->dapm_mutex); + return ret; } EXPORT_SYMBOL_GPL(snd_soc_dapm_sync); @@ -1882,15 +1887,18 @@ int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm, { int i, ret; + mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT); for (i = 0; i < num; i++) { ret = snd_soc_dapm_add_route(dapm, route); if (ret < 0) { dev_err(dapm->dev, "Failed to add route %s->%s\n", route->source, route->sink); + mutex_unlock(&dapm->card->dapm_mutex); return ret; } route++; } + mutex_unlock(&dapm->card->dapm_mutex); return 0; } @@ -1963,12 +1971,14 @@ int snd_soc_dapm_weak_routes(struct snd_soc_dapm_context *dapm, int i, err; int ret = 0; + mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT); for (i = 0; i < num; i++) { err = snd_soc_dapm_weak_route(dapm, route); if (err) ret = err; route++; } + mutex_unlock(&dapm->card->dapm_mutex); return ret; } @@ -1987,6 +1997,8 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm) struct snd_soc_dapm_widget *w; unsigned int val; + mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT); + list_for_each_entry(w, &dapm->card->widgets, list) { if (w->new) @@ -1996,8 +2008,10 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm) w->kcontrols = kzalloc(w->num_kcontrols * sizeof(struct snd_kcontrol *), GFP_KERNEL); - if (!w->kcontrols) + if (!w->kcontrols) { + mutex_unlock(&dapm->card->dapm_mutex); return -ENOMEM; + } } switch(w->id) { @@ -2060,6 +2074,7 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm) } dapm_power_widgets(dapm, SND_SOC_DAPM_STREAM_NOP); + mutex_unlock(&dapm->card->dapm_mutex); return 0; } EXPORT_SYMBOL_GPL(snd_soc_dapm_new_widgets); @@ -2119,6 +2134,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, 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_card *card = codec->card; struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; unsigned int reg = mc->reg; @@ -2145,7 +2161,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, /* old connection must be powered down */ connect = invert ? 1 : 0; - mutex_lock(&codec->mutex); + mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_PCM); change = snd_soc_test_bits(widget->codec, reg, mask, val); if (change) { @@ -2167,7 +2183,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, } } - mutex_unlock(&codec->mutex); + mutex_unlock(&card->dapm_mutex); return 0; } EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw); @@ -2216,6 +2232,7 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, 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_card *card = codec->card; struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; unsigned int val, mux, change; unsigned int mask, bitmask; @@ -2236,7 +2253,7 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, mask |= (bitmask - 1) << e->shift_r; } - mutex_lock(&codec->mutex); + mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_PCM); change = snd_soc_test_bits(widget->codec, e->reg, mask, val); if (change) { @@ -2258,7 +2275,7 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, } } - mutex_unlock(&codec->mutex); + mutex_unlock(&card->dapm_mutex); return change; } EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double); @@ -2295,6 +2312,7 @@ int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol, 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_card *card = codec->card; struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; int change; @@ -2304,7 +2322,7 @@ int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol, if (ucontrol->value.enumerated.item[0] >= e->max) return -EINVAL; - mutex_lock(&codec->mutex); + mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_PCM); change = widget->value != ucontrol->value.enumerated.item[0]; if (change) { @@ -2318,7 +2336,7 @@ int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol, } } - mutex_unlock(&codec->mutex); + mutex_unlock(&card->dapm_mutex); return ret; } EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_virt); @@ -2383,6 +2401,7 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol, 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_card *card = codec->card; struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; unsigned int val, mux, change; unsigned int mask; @@ -2401,7 +2420,7 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol, mask |= e->mask << e->shift_r; } - mutex_lock(&codec->mutex); + mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_PCM); change = snd_soc_test_bits(widget->codec, e->reg, mask, val); if (change) { @@ -2423,7 +2442,7 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol, } } - mutex_unlock(&codec->mutex); + mutex_unlock(&card->dapm_mutex); return change; } EXPORT_SYMBOL_GPL(snd_soc_dapm_put_value_enum_double); @@ -2458,14 +2477,15 @@ int snd_soc_dapm_get_pin_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct snd_soc_card *card = codec->card; const char *pin = (const char *)kcontrol->private_value; - mutex_lock(&codec->mutex); + mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_PCM); ucontrol->value.integer.value[0] = snd_soc_dapm_get_pin_status(&codec->dapm, pin); - mutex_unlock(&codec->mutex); + mutex_unlock(&card->dapm_mutex); return 0; } @@ -2481,19 +2501,19 @@ int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct snd_soc_card *card = codec->card; const char *pin = (const char *)kcontrol->private_value; - mutex_lock(&codec->mutex); + mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_PCM); if (ucontrol->value.integer.value[0]) snd_soc_dapm_enable_pin(&codec->dapm, pin); else snd_soc_dapm_disable_pin(&codec->dapm, pin); - snd_soc_dapm_sync(&codec->dapm); - - mutex_unlock(&codec->mutex); + mutex_unlock(&card->dapm_mutex); + snd_soc_dapm_sync(&codec->dapm); return 0; } EXPORT_SYMBOL_GPL(snd_soc_dapm_put_pin_switch); @@ -2561,16 +2581,19 @@ int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm, { int i, ret; + mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT); for (i = 0; i < num; i++) { ret = snd_soc_dapm_new_control(dapm, widget); if (ret < 0) { dev_err(dapm->dev, "ASoC: Failed to create DAPM control %s: %d\n", widget->name, ret); + mutex_unlock(&dapm->card->dapm_mutex); return ret; } widget++; } + mutex_unlock(&dapm->card->dapm_mutex); return 0; } EXPORT_SYMBOL_GPL(snd_soc_dapm_new_controls); @@ -2621,13 +2644,14 @@ int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, const char *stream, int event) { struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_card *card = rtd->card; if (stream == NULL) return 0; - mutex_lock(&codec->mutex); + mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_PCM); soc_dapm_stream_event(&codec->dapm, stream, event); - mutex_unlock(&codec->mutex); + mutex_unlock(&card->dapm_mutex); return 0; } |