diff --git a/include/sound/soc.h b/include/sound/soc.h index eb030bad423e..31b860fef19e 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1090,6 +1090,7 @@ struct snd_soc_card { struct mutex mutex; struct mutex dapm_mutex; + struct mutex dapm_power_mutex; bool instantiated; diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 08c6fba97ba1..e016ea04f65c 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2436,6 +2436,7 @@ int snd_soc_register_card(struct snd_soc_card *card) card->instantiated = 0; mutex_init(&card->mutex); mutex_init(&card->dapm_mutex); + mutex_init(&card->dapm_power_mutex); ret = snd_soc_instantiate_card(card); if (ret != 0) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 7d009428934a..9f16ce9566d0 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -1481,7 +1481,7 @@ static void dapm_seq_run(struct snd_soc_card *card, /* Do we need to apply any queued changes? */ if (sort[w->id] != cur_sort || w->reg != cur_reg || w->dapm != cur_dapm || w->subseq != cur_subseq) { - if (!list_empty(&pending)) + if (cur_dapm && !list_empty(&pending)) dapm_seq_run_coalesced(card, &pending); if (cur_dapm && cur_dapm->seq_notifier) { @@ -1544,7 +1544,7 @@ static void dapm_seq_run(struct snd_soc_card *card, "ASoC: Failed to apply widget power: %d\n", ret); } - if (!list_empty(&pending)) + if (cur_dapm && !list_empty(&pending)) dapm_seq_run_coalesced(card, &pending); if (cur_dapm && cur_dapm->seq_notifier) { @@ -1780,6 +1780,7 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event) lockdep_assert_held(&card->dapm_mutex); trace_snd_soc_dapm_start(card); + mutex_lock(&dapm->card->dapm_power_mutex); list_for_each_entry(d, &card->dapm_list, list) { if (dapm_idle_bias_off(d)) @@ -1898,6 +1899,7 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event) pop_dbg(card->dev, card->pop_time, "DAPM sequencing finished, waiting %dms\n", card->pop_time); pop_wait(card->pop_time); + mutex_unlock(&dapm->card->dapm_power_mutex); trace_snd_soc_dapm_done(card);