|
@@ -115,6 +115,12 @@ static int dapm_down_seq[] = {
|
|
|
[snd_soc_dapm_post] = 14,
|
|
|
};
|
|
|
|
|
|
+static void dapm_assert_locked(struct snd_soc_dapm_context *dapm)
|
|
|
+{
|
|
|
+ if (dapm->card && dapm->card->instantiated)
|
|
|
+ lockdep_assert_held(&dapm->card->dapm_mutex);
|
|
|
+}
|
|
|
+
|
|
|
static void pop_wait(u32 pop_time)
|
|
|
{
|
|
|
if (pop_time)
|
|
@@ -146,15 +152,16 @@ static bool dapm_dirty_widget(struct snd_soc_dapm_widget *w)
|
|
|
return !list_empty(&w->dirty);
|
|
|
}
|
|
|
|
|
|
-void dapm_mark_dirty(struct snd_soc_dapm_widget *w, const char *reason)
|
|
|
+static void dapm_mark_dirty(struct snd_soc_dapm_widget *w, const char *reason)
|
|
|
{
|
|
|
+ dapm_assert_locked(w->dapm);
|
|
|
+
|
|
|
if (!dapm_dirty_widget(w)) {
|
|
|
dev_vdbg(w->dapm->dev, "Marking %s dirty due to %s\n",
|
|
|
w->name, reason);
|
|
|
list_add_tail(&w->dirty, &w->dapm->card->dapm_dirty);
|
|
|
}
|
|
|
}
|
|
|
-EXPORT_SYMBOL_GPL(dapm_mark_dirty);
|
|
|
|
|
|
void dapm_mark_io_dirty(struct snd_soc_dapm_context *dapm)
|
|
|
{
|
|
@@ -361,6 +368,8 @@ static void dapm_reset(struct snd_soc_card *card)
|
|
|
{
|
|
|
struct snd_soc_dapm_widget *w;
|
|
|
|
|
|
+ lockdep_assert_held(&card->dapm_mutex);
|
|
|
+
|
|
|
memset(&card->dapm_stats, 0, sizeof(card->dapm_stats));
|
|
|
|
|
|
list_for_each_entry(w, &card->widgets, list) {
|
|
@@ -386,7 +395,8 @@ static int soc_widget_read(struct snd_soc_dapm_widget *w, int reg,
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
-static int soc_widget_write(struct snd_soc_dapm_widget *w, int reg, int val)
|
|
|
+static int soc_widget_write(struct snd_soc_dapm_widget *w, int reg,
|
|
|
+ unsigned int val)
|
|
|
{
|
|
|
if (w->codec)
|
|
|
return snd_soc_write(w->codec, reg, val);
|
|
@@ -506,7 +516,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
|
|
|
case snd_soc_dapm_switch:
|
|
|
case snd_soc_dapm_mixer:
|
|
|
case snd_soc_dapm_mixer_named_ctl: {
|
|
|
- int val;
|
|
|
+ unsigned int val;
|
|
|
struct soc_mixer_control *mc = (struct soc_mixer_control *)
|
|
|
w->kcontrol_news[i].private_value;
|
|
|
int reg = mc->reg;
|
|
@@ -530,7 +540,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
|
|
|
case snd_soc_dapm_mux: {
|
|
|
struct soc_enum *e = (struct soc_enum *)
|
|
|
w->kcontrol_news[i].private_value;
|
|
|
- int val, item;
|
|
|
+ unsigned int val, item;
|
|
|
|
|
|
soc_widget_read(w, e->reg, &val);
|
|
|
item = (val >> e->shift_l) & e->mask;
|
|
@@ -559,7 +569,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
|
|
|
case snd_soc_dapm_value_mux: {
|
|
|
struct soc_enum *e = (struct soc_enum *)
|
|
|
w->kcontrol_news[i].private_value;
|
|
|
- int val, item;
|
|
|
+ unsigned int val, item;
|
|
|
|
|
|
soc_widget_read(w, e->reg, &val);
|
|
|
val = (val >> e->shift_l) & e->mask;
|
|
@@ -1218,7 +1228,7 @@ int dapm_regulator_event(struct snd_soc_dapm_widget *w,
|
|
|
ret = regulator_allow_bypass(w->regulator, false);
|
|
|
if (ret != 0)
|
|
|
dev_warn(w->dapm->dev,
|
|
|
- "ASoC: Failed to bypass %s: %d\n",
|
|
|
+ "ASoC: Failed to unbypass %s: %d\n",
|
|
|
w->name, ret);
|
|
|
}
|
|
|
|
|
@@ -1228,7 +1238,7 @@ int dapm_regulator_event(struct snd_soc_dapm_widget *w,
|
|
|
ret = regulator_allow_bypass(w->regulator, true);
|
|
|
if (ret != 0)
|
|
|
dev_warn(w->dapm->dev,
|
|
|
- "ASoC: Failed to unbypass %s: %d\n",
|
|
|
+ "ASoC: Failed to bypass %s: %d\n",
|
|
|
w->name, ret);
|
|
|
}
|
|
|
|
|
@@ -1823,6 +1833,8 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event)
|
|
|
ASYNC_DOMAIN_EXCLUSIVE(async_domain);
|
|
|
enum snd_soc_bias_level bias;
|
|
|
|
|
|
+ lockdep_assert_held(&card->dapm_mutex);
|
|
|
+
|
|
|
trace_snd_soc_dapm_start(card);
|
|
|
|
|
|
list_for_each_entry(d, &card->dapm_list, list) {
|
|
@@ -1897,10 +1909,14 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event)
|
|
|
|
|
|
trace_snd_soc_dapm_walk_done(card);
|
|
|
|
|
|
- /* Run all the bias changes in parallel */
|
|
|
- list_for_each_entry(d, &card->dapm_list, list)
|
|
|
- async_schedule_domain(dapm_pre_sequence_async, d,
|
|
|
- &async_domain);
|
|
|
+ /* Run card bias changes at first */
|
|
|
+ dapm_pre_sequence_async(&card->dapm, 0);
|
|
|
+ /* Run other bias changes in parallel */
|
|
|
+ list_for_each_entry(d, &card->dapm_list, list) {
|
|
|
+ if (d != &card->dapm)
|
|
|
+ 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) {
|
|
@@ -1920,10 +1936,14 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event)
|
|
|
dapm_seq_run(card, &up_list, event, true);
|
|
|
|
|
|
/* Run all the bias changes in parallel */
|
|
|
- list_for_each_entry(d, &card->dapm_list, list)
|
|
|
- async_schedule_domain(dapm_post_sequence_async, d,
|
|
|
- &async_domain);
|
|
|
+ list_for_each_entry(d, &card->dapm_list, list) {
|
|
|
+ if (d != &card->dapm)
|
|
|
+ async_schedule_domain(dapm_post_sequence_async, d,
|
|
|
+ &async_domain);
|
|
|
+ }
|
|
|
async_synchronize_full_domain(&async_domain);
|
|
|
+ /* Run card bias changes at last */
|
|
|
+ dapm_post_sequence_async(&card->dapm, 0);
|
|
|
|
|
|
/* do we need to notify any clients that DAPM event is complete */
|
|
|
list_for_each_entry(d, &card->dapm_list, list) {
|
|
@@ -2110,6 +2130,8 @@ static int soc_dapm_mux_update_power(struct snd_soc_card *card,
|
|
|
struct snd_soc_dapm_path *path;
|
|
|
int found = 0;
|
|
|
|
|
|
+ lockdep_assert_held(&card->dapm_mutex);
|
|
|
+
|
|
|
/* find dapm widget path assoc with kcontrol */
|
|
|
dapm_kcontrol_for_each_path(path, kcontrol) {
|
|
|
if (!path->name || !e->texts[mux])
|
|
@@ -2160,6 +2182,8 @@ static int soc_dapm_mixer_update_power(struct snd_soc_card *card,
|
|
|
struct snd_soc_dapm_path *path;
|
|
|
int found = 0;
|
|
|
|
|
|
+ lockdep_assert_held(&card->dapm_mutex);
|
|
|
+
|
|
|
/* find dapm widget path assoc with kcontrol */
|
|
|
dapm_kcontrol_for_each_path(path, kcontrol) {
|
|
|
found = 1;
|
|
@@ -2325,6 +2349,8 @@ static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm,
|
|
|
{
|
|
|
struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, true);
|
|
|
|
|
|
+ dapm_assert_locked(dapm);
|
|
|
+
|
|
|
if (!w) {
|
|
|
dev_err(dapm->dev, "ASoC: DAPM unknown pin %s\n", pin);
|
|
|
return -EINVAL;
|
|
@@ -2341,18 +2367,18 @@ static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm,
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * snd_soc_dapm_sync - scan and power dapm paths
|
|
|
+ * snd_soc_dapm_sync_unlocked - scan and power dapm paths
|
|
|
* @dapm: DAPM context
|
|
|
*
|
|
|
* Walks all dapm audio paths and powers widgets according to their
|
|
|
* stream or path usage.
|
|
|
*
|
|
|
+ * Requires external locking.
|
|
|
+ *
|
|
|
* Returns 0 for success.
|
|
|
*/
|
|
|
-int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm)
|
|
|
+int snd_soc_dapm_sync_unlocked(struct snd_soc_dapm_context *dapm)
|
|
|
{
|
|
|
- int ret;
|
|
|
-
|
|
|
/*
|
|
|
* Suppress early reports (eg, jacks syncing their state) to avoid
|
|
|
* silly DAPM runs during card startup.
|
|
@@ -2360,8 +2386,25 @@ int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm)
|
|
|
if (!dapm->card || !dapm->card->instantiated)
|
|
|
return 0;
|
|
|
|
|
|
+ return dapm_power_widgets(dapm->card, SND_SOC_DAPM_STREAM_NOP);
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(snd_soc_dapm_sync_unlocked);
|
|
|
+
|
|
|
+/**
|
|
|
+ * snd_soc_dapm_sync - scan and power dapm paths
|
|
|
+ * @dapm: DAPM context
|
|
|
+ *
|
|
|
+ * Walks all dapm audio paths and powers widgets according to their
|
|
|
+ * stream or path usage.
|
|
|
+ *
|
|
|
+ * Returns 0 for success.
|
|
|
+ */
|
|
|
+int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm)
|
|
|
+{
|
|
|
+ int ret;
|
|
|
+
|
|
|
mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
|
|
|
- ret = dapm_power_widgets(dapm->card, SND_SOC_DAPM_STREAM_NOP);
|
|
|
+ ret = snd_soc_dapm_sync_unlocked(dapm);
|
|
|
mutex_unlock(&dapm->card->dapm_mutex);
|
|
|
return ret;
|
|
|
}
|
|
@@ -3210,15 +3253,11 @@ int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol,
|
|
|
struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
|
|
|
const char *pin = (const char *)kcontrol->private_value;
|
|
|
|
|
|
- mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
|
|
|
-
|
|
|
if (ucontrol->value.integer.value[0])
|
|
|
snd_soc_dapm_enable_pin(&card->dapm, pin);
|
|
|
else
|
|
|
snd_soc_dapm_disable_pin(&card->dapm, pin);
|
|
|
|
|
|
- mutex_unlock(&card->dapm_mutex);
|
|
|
-
|
|
|
snd_soc_dapm_sync(&card->dapm);
|
|
|
return 0;
|
|
|
}
|
|
@@ -3248,7 +3287,7 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
|
|
|
ret = regulator_allow_bypass(w->regulator, true);
|
|
|
if (ret != 0)
|
|
|
dev_warn(w->dapm->dev,
|
|
|
- "ASoC: Failed to unbypass %s: %d\n",
|
|
|
+ "ASoC: Failed to bypass %s: %d\n",
|
|
|
w->name, ret);
|
|
|
}
|
|
|
break;
|
|
@@ -3766,6 +3805,26 @@ void snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
|
|
|
mutex_unlock(&card->dapm_mutex);
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * snd_soc_dapm_enable_pin_unlocked - enable pin.
|
|
|
+ * @dapm: DAPM context
|
|
|
+ * @pin: pin name
|
|
|
+ *
|
|
|
+ * Enables input/output pin and its parents or children widgets iff there is
|
|
|
+ * a valid audio route and active audio stream.
|
|
|
+ *
|
|
|
+ * Requires external locking.
|
|
|
+ *
|
|
|
+ * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
|
|
|
+ * do any widget power switching.
|
|
|
+ */
|
|
|
+int snd_soc_dapm_enable_pin_unlocked(struct snd_soc_dapm_context *dapm,
|
|
|
+ const char *pin)
|
|
|
+{
|
|
|
+ return snd_soc_dapm_set_pin(dapm, pin, 1);
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin_unlocked);
|
|
|
+
|
|
|
/**
|
|
|
* snd_soc_dapm_enable_pin - enable pin.
|
|
|
* @dapm: DAPM context
|
|
@@ -3773,17 +3832,26 @@ void snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
|
|
|
*
|
|
|
* Enables input/output pin and its parents or children widgets iff there is
|
|
|
* a valid audio route and active audio stream.
|
|
|
+ *
|
|
|
* NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
|
|
|
* do any widget power switching.
|
|
|
*/
|
|
|
int snd_soc_dapm_enable_pin(struct snd_soc_dapm_context *dapm, const char *pin)
|
|
|
{
|
|
|
- return snd_soc_dapm_set_pin(dapm, pin, 1);
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
|
|
|
+
|
|
|
+ ret = snd_soc_dapm_set_pin(dapm, pin, 1);
|
|
|
+
|
|
|
+ mutex_unlock(&dapm->card->dapm_mutex);
|
|
|
+
|
|
|
+ return ret;
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin);
|
|
|
|
|
|
/**
|
|
|
- * snd_soc_dapm_force_enable_pin - force a pin to be enabled
|
|
|
+ * snd_soc_dapm_force_enable_pin_unlocked - force a pin to be enabled
|
|
|
* @dapm: DAPM context
|
|
|
* @pin: pin name
|
|
|
*
|
|
@@ -3791,11 +3859,13 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin);
|
|
|
* intended for use with microphone bias supplies used in microphone
|
|
|
* jack detection.
|
|
|
*
|
|
|
+ * Requires external locking.
|
|
|
+ *
|
|
|
* NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
|
|
|
* do any widget power switching.
|
|
|
*/
|
|
|
-int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm,
|
|
|
- const char *pin)
|
|
|
+int snd_soc_dapm_force_enable_pin_unlocked(struct snd_soc_dapm_context *dapm,
|
|
|
+ const char *pin)
|
|
|
{
|
|
|
struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, true);
|
|
|
|
|
@@ -3811,24 +3881,102 @@ int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm,
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
+EXPORT_SYMBOL_GPL(snd_soc_dapm_force_enable_pin_unlocked);
|
|
|
+
|
|
|
+/**
|
|
|
+ * snd_soc_dapm_force_enable_pin - force a pin to be enabled
|
|
|
+ * @dapm: DAPM context
|
|
|
+ * @pin: pin name
|
|
|
+ *
|
|
|
+ * Enables input/output pin regardless of any other state. This is
|
|
|
+ * intended for use with microphone bias supplies used in microphone
|
|
|
+ * jack detection.
|
|
|
+ *
|
|
|
+ * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
|
|
|
+ * do any widget power switching.
|
|
|
+ */
|
|
|
+int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm,
|
|
|
+ const char *pin)
|
|
|
+{
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
|
|
|
+
|
|
|
+ ret = snd_soc_dapm_force_enable_pin_unlocked(dapm, pin);
|
|
|
+
|
|
|
+ mutex_unlock(&dapm->card->dapm_mutex);
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
EXPORT_SYMBOL_GPL(snd_soc_dapm_force_enable_pin);
|
|
|
|
|
|
+/**
|
|
|
+ * snd_soc_dapm_disable_pin_unlocked - disable pin.
|
|
|
+ * @dapm: DAPM context
|
|
|
+ * @pin: pin name
|
|
|
+ *
|
|
|
+ * Disables input/output pin and its parents or children widgets.
|
|
|
+ *
|
|
|
+ * Requires external locking.
|
|
|
+ *
|
|
|
+ * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
|
|
|
+ * do any widget power switching.
|
|
|
+ */
|
|
|
+int snd_soc_dapm_disable_pin_unlocked(struct snd_soc_dapm_context *dapm,
|
|
|
+ const char *pin)
|
|
|
+{
|
|
|
+ return snd_soc_dapm_set_pin(dapm, pin, 0);
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin_unlocked);
|
|
|
+
|
|
|
/**
|
|
|
* snd_soc_dapm_disable_pin - disable pin.
|
|
|
* @dapm: DAPM context
|
|
|
* @pin: pin name
|
|
|
*
|
|
|
* Disables input/output pin and its parents or children widgets.
|
|
|
+ *
|
|
|
* NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
|
|
|
* do any widget power switching.
|
|
|
*/
|
|
|
int snd_soc_dapm_disable_pin(struct snd_soc_dapm_context *dapm,
|
|
|
const char *pin)
|
|
|
{
|
|
|
- return snd_soc_dapm_set_pin(dapm, pin, 0);
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
|
|
|
+
|
|
|
+ ret = snd_soc_dapm_set_pin(dapm, pin, 0);
|
|
|
+
|
|
|
+ mutex_unlock(&dapm->card->dapm_mutex);
|
|
|
+
|
|
|
+ return ret;
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin);
|
|
|
|
|
|
+/**
|
|
|
+ * snd_soc_dapm_nc_pin_unlocked - permanently disable pin.
|
|
|
+ * @dapm: DAPM context
|
|
|
+ * @pin: pin name
|
|
|
+ *
|
|
|
+ * Marks the specified pin as being not connected, disabling it along
|
|
|
+ * any parent or child widgets. At present this is identical to
|
|
|
+ * snd_soc_dapm_disable_pin() but in future it will be extended to do
|
|
|
+ * additional things such as disabling controls which only affect
|
|
|
+ * paths through the pin.
|
|
|
+ *
|
|
|
+ * Requires external locking.
|
|
|
+ *
|
|
|
+ * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
|
|
|
+ * do any widget power switching.
|
|
|
+ */
|
|
|
+int snd_soc_dapm_nc_pin_unlocked(struct snd_soc_dapm_context *dapm,
|
|
|
+ const char *pin)
|
|
|
+{
|
|
|
+ return snd_soc_dapm_set_pin(dapm, pin, 0);
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(snd_soc_dapm_nc_pin_unlocked);
|
|
|
+
|
|
|
/**
|
|
|
* snd_soc_dapm_nc_pin - permanently disable pin.
|
|
|
* @dapm: DAPM context
|
|
@@ -3845,7 +3993,15 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin);
|
|
|
*/
|
|
|
int snd_soc_dapm_nc_pin(struct snd_soc_dapm_context *dapm, const char *pin)
|
|
|
{
|
|
|
- return snd_soc_dapm_set_pin(dapm, pin, 0);
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
|
|
|
+
|
|
|
+ ret = snd_soc_dapm_set_pin(dapm, pin, 0);
|
|
|
+
|
|
|
+ mutex_unlock(&dapm->card->dapm_mutex);
|
|
|
+
|
|
|
+ return ret;
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(snd_soc_dapm_nc_pin);
|
|
|
|
|
@@ -3985,7 +4141,7 @@ void snd_soc_dapm_free(struct snd_soc_dapm_context *dapm)
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(snd_soc_dapm_free);
|
|
|
|
|
|
-static void soc_dapm_shutdown_codec(struct snd_soc_dapm_context *dapm)
|
|
|
+static void soc_dapm_shutdown_dapm(struct snd_soc_dapm_context *dapm)
|
|
|
{
|
|
|
struct snd_soc_card *card = dapm->card;
|
|
|
struct snd_soc_dapm_widget *w;
|
|
@@ -4025,14 +4181,21 @@ static void soc_dapm_shutdown_codec(struct snd_soc_dapm_context *dapm)
|
|
|
*/
|
|
|
void snd_soc_dapm_shutdown(struct snd_soc_card *card)
|
|
|
{
|
|
|
- struct snd_soc_codec *codec;
|
|
|
-
|
|
|
- list_for_each_entry(codec, &card->codec_dev_list, card_list) {
|
|
|
- soc_dapm_shutdown_codec(&codec->dapm);
|
|
|
- if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY)
|
|
|
- snd_soc_dapm_set_bias_level(&codec->dapm,
|
|
|
- SND_SOC_BIAS_OFF);
|
|
|
+ struct snd_soc_dapm_context *dapm;
|
|
|
+
|
|
|
+ list_for_each_entry(dapm, &card->dapm_list, list) {
|
|
|
+ if (dapm != &card->dapm) {
|
|
|
+ soc_dapm_shutdown_dapm(dapm);
|
|
|
+ if (dapm->bias_level == SND_SOC_BIAS_STANDBY)
|
|
|
+ snd_soc_dapm_set_bias_level(dapm,
|
|
|
+ SND_SOC_BIAS_OFF);
|
|
|
+ }
|
|
|
}
|
|
|
+
|
|
|
+ soc_dapm_shutdown_dapm(&card->dapm);
|
|
|
+ if (card->dapm.bias_level == SND_SOC_BIAS_STANDBY)
|
|
|
+ snd_soc_dapm_set_bias_level(&card->dapm,
|
|
|
+ SND_SOC_BIAS_OFF);
|
|
|
}
|
|
|
|
|
|
/* Module information */
|