aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/soc-dapm.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/soc-dapm.c')
-rw-r--r--sound/soc/soc-dapm.c604
1 files changed, 275 insertions, 329 deletions
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index dc8ff13187f7..c8a780d0d057 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -70,8 +70,6 @@ static int dapm_up_seq[] = {
70 [snd_soc_dapm_aif_out] = 4, 70 [snd_soc_dapm_aif_out] = 4,
71 [snd_soc_dapm_mic] = 5, 71 [snd_soc_dapm_mic] = 5,
72 [snd_soc_dapm_mux] = 6, 72 [snd_soc_dapm_mux] = 6,
73 [snd_soc_dapm_virt_mux] = 6,
74 [snd_soc_dapm_value_mux] = 6,
75 [snd_soc_dapm_dac] = 7, 73 [snd_soc_dapm_dac] = 7,
76 [snd_soc_dapm_switch] = 8, 74 [snd_soc_dapm_switch] = 8,
77 [snd_soc_dapm_mixer] = 8, 75 [snd_soc_dapm_mixer] = 8,
@@ -102,8 +100,6 @@ static int dapm_down_seq[] = {
102 [snd_soc_dapm_mic] = 7, 100 [snd_soc_dapm_mic] = 7,
103 [snd_soc_dapm_micbias] = 8, 101 [snd_soc_dapm_micbias] = 8,
104 [snd_soc_dapm_mux] = 9, 102 [snd_soc_dapm_mux] = 9,
105 [snd_soc_dapm_virt_mux] = 9,
106 [snd_soc_dapm_value_mux] = 9,
107 [snd_soc_dapm_aif_in] = 10, 103 [snd_soc_dapm_aif_in] = 10,
108 [snd_soc_dapm_aif_out] = 10, 104 [snd_soc_dapm_aif_out] = 10,
109 [snd_soc_dapm_dai_in] = 10, 105 [snd_soc_dapm_dai_in] = 10,
@@ -115,6 +111,12 @@ static int dapm_down_seq[] = {
115 [snd_soc_dapm_post] = 14, 111 [snd_soc_dapm_post] = 14,
116}; 112};
117 113
114static void dapm_assert_locked(struct snd_soc_dapm_context *dapm)
115{
116 if (dapm->card && dapm->card->instantiated)
117 lockdep_assert_held(&dapm->card->dapm_mutex);
118}
119
118static void pop_wait(u32 pop_time) 120static void pop_wait(u32 pop_time)
119{ 121{
120 if (pop_time) 122 if (pop_time)
@@ -146,15 +148,16 @@ static bool dapm_dirty_widget(struct snd_soc_dapm_widget *w)
146 return !list_empty(&w->dirty); 148 return !list_empty(&w->dirty);
147} 149}
148 150
149void dapm_mark_dirty(struct snd_soc_dapm_widget *w, const char *reason) 151static void dapm_mark_dirty(struct snd_soc_dapm_widget *w, const char *reason)
150{ 152{
153 dapm_assert_locked(w->dapm);
154
151 if (!dapm_dirty_widget(w)) { 155 if (!dapm_dirty_widget(w)) {
152 dev_vdbg(w->dapm->dev, "Marking %s dirty due to %s\n", 156 dev_vdbg(w->dapm->dev, "Marking %s dirty due to %s\n",
153 w->name, reason); 157 w->name, reason);
154 list_add_tail(&w->dirty, &w->dapm->card->dapm_dirty); 158 list_add_tail(&w->dirty, &w->dapm->card->dapm_dirty);
155 } 159 }
156} 160}
157EXPORT_SYMBOL_GPL(dapm_mark_dirty);
158 161
159void dapm_mark_io_dirty(struct snd_soc_dapm_context *dapm) 162void dapm_mark_io_dirty(struct snd_soc_dapm_context *dapm)
160{ 163{
@@ -361,6 +364,8 @@ static void dapm_reset(struct snd_soc_card *card)
361{ 364{
362 struct snd_soc_dapm_widget *w; 365 struct snd_soc_dapm_widget *w;
363 366
367 lockdep_assert_held(&card->dapm_mutex);
368
364 memset(&card->dapm_stats, 0, sizeof(card->dapm_stats)); 369 memset(&card->dapm_stats, 0, sizeof(card->dapm_stats));
365 370
366 list_for_each_entry(w, &card->widgets, list) { 371 list_for_each_entry(w, &card->widgets, list) {
@@ -386,7 +391,8 @@ static int soc_widget_read(struct snd_soc_dapm_widget *w, int reg,
386 return -1; 391 return -1;
387} 392}
388 393
389static int soc_widget_write(struct snd_soc_dapm_widget *w, int reg, int val) 394static int soc_widget_write(struct snd_soc_dapm_widget *w, int reg,
395 unsigned int val)
390{ 396{
391 if (w->codec) 397 if (w->codec)
392 return snd_soc_write(w->codec, reg, val); 398 return snd_soc_write(w->codec, reg, val);
@@ -498,131 +504,40 @@ out:
498 return ret; 504 return ret;
499} 505}
500 506
501/* set up initial codec paths */ 507/* connect mux widget to its interconnecting audio paths */
502static void dapm_set_path_status(struct snd_soc_dapm_widget *w, 508static int dapm_connect_mux(struct snd_soc_dapm_context *dapm,
503 struct snd_soc_dapm_path *p, int i) 509 struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest,
510 struct snd_soc_dapm_path *path, const char *control_name,
511 const struct snd_kcontrol_new *kcontrol)
504{ 512{
505 switch (w->id) { 513 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
506 case snd_soc_dapm_switch: 514 unsigned int val, item;
507 case snd_soc_dapm_mixer: 515 int i;
508 case snd_soc_dapm_mixer_named_ctl: {
509 int val;
510 struct soc_mixer_control *mc = (struct soc_mixer_control *)
511 w->kcontrol_news[i].private_value;
512 int reg = mc->reg;
513 unsigned int shift = mc->shift;
514 int max = mc->max;
515 unsigned int mask = (1 << fls(max)) - 1;
516 unsigned int invert = mc->invert;
517
518 if (reg != SND_SOC_NOPM) {
519 soc_widget_read(w, reg, &val);
520 val = (val >> shift) & mask;
521 if (invert)
522 val = max - val;
523 p->connect = !!val;
524 } else {
525 p->connect = 0;
526 }
527
528 }
529 break;
530 case snd_soc_dapm_mux: {
531 struct soc_enum *e = (struct soc_enum *)
532 w->kcontrol_news[i].private_value;
533 int val, item;
534
535 soc_widget_read(w, e->reg, &val);
536 item = (val >> e->shift_l) & e->mask;
537
538 if (item < e->max && !strcmp(p->name, e->texts[item]))
539 p->connect = 1;
540 else
541 p->connect = 0;
542 }
543 break;
544 case snd_soc_dapm_virt_mux: {
545 struct soc_enum *e = (struct soc_enum *)
546 w->kcontrol_news[i].private_value;
547 516
548 p->connect = 0; 517 if (e->reg != SND_SOC_NOPM) {
518 soc_widget_read(dest, e->reg, &val);
519 val = (val >> e->shift_l) & e->mask;
520 item = snd_soc_enum_val_to_item(e, val);
521 } else {
549 /* since a virtual mux has no backing registers to 522 /* since a virtual mux has no backing registers to
550 * decide which path to connect, it will try to match 523 * decide which path to connect, it will try to match
551 * with the first enumeration. This is to ensure 524 * with the first enumeration. This is to ensure
552 * that the default mux choice (the first) will be 525 * that the default mux choice (the first) will be
553 * correctly powered up during initialization. 526 * correctly powered up during initialization.
554 */ 527 */
555 if (!strcmp(p->name, e->texts[0])) 528 item = 0;
556 p->connect = 1;
557 }
558 break;
559 case snd_soc_dapm_value_mux: {
560 struct soc_enum *e = (struct soc_enum *)
561 w->kcontrol_news[i].private_value;
562 int val, item;
563
564 soc_widget_read(w, e->reg, &val);
565 val = (val >> e->shift_l) & e->mask;
566 for (item = 0; item < e->max; item++) {
567 if (val == e->values[item])
568 break;
569 }
570
571 if (item < e->max && !strcmp(p->name, e->texts[item]))
572 p->connect = 1;
573 else
574 p->connect = 0;
575 }
576 break;
577 /* does not affect routing - always connected */
578 case snd_soc_dapm_pga:
579 case snd_soc_dapm_out_drv:
580 case snd_soc_dapm_output:
581 case snd_soc_dapm_adc:
582 case snd_soc_dapm_input:
583 case snd_soc_dapm_siggen:
584 case snd_soc_dapm_dac:
585 case snd_soc_dapm_micbias:
586 case snd_soc_dapm_vmid:
587 case snd_soc_dapm_supply:
588 case snd_soc_dapm_regulator_supply:
589 case snd_soc_dapm_clock_supply:
590 case snd_soc_dapm_aif_in:
591 case snd_soc_dapm_aif_out:
592 case snd_soc_dapm_dai_in:
593 case snd_soc_dapm_dai_out:
594 case snd_soc_dapm_hp:
595 case snd_soc_dapm_mic:
596 case snd_soc_dapm_spk:
597 case snd_soc_dapm_line:
598 case snd_soc_dapm_dai_link:
599 case snd_soc_dapm_kcontrol:
600 p->connect = 1;
601 break;
602 /* does affect routing - dynamically connected */
603 case snd_soc_dapm_pre:
604 case snd_soc_dapm_post:
605 p->connect = 0;
606 break;
607 } 529 }
608}
609
610/* connect mux widget to its interconnecting audio paths */
611static int dapm_connect_mux(struct snd_soc_dapm_context *dapm,
612 struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest,
613 struct snd_soc_dapm_path *path, const char *control_name,
614 const struct snd_kcontrol_new *kcontrol)
615{
616 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
617 int i;
618 530
619 for (i = 0; i < e->max; i++) { 531 for (i = 0; i < e->items; i++) {
620 if (!(strcmp(control_name, e->texts[i]))) { 532 if (!(strcmp(control_name, e->texts[i]))) {
621 list_add(&path->list, &dapm->card->paths); 533 list_add(&path->list, &dapm->card->paths);
622 list_add(&path->list_sink, &dest->sources); 534 list_add(&path->list_sink, &dest->sources);
623 list_add(&path->list_source, &src->sinks); 535 list_add(&path->list_source, &src->sinks);
624 path->name = (char*)e->texts[i]; 536 path->name = (char*)e->texts[i];
625 dapm_set_path_status(dest, path, 0); 537 if (i == item)
538 path->connect = 1;
539 else
540 path->connect = 0;
626 return 0; 541 return 0;
627 } 542 }
628 } 543 }
@@ -630,6 +545,30 @@ static int dapm_connect_mux(struct snd_soc_dapm_context *dapm,
630 return -ENODEV; 545 return -ENODEV;
631} 546}
632 547
548/* set up initial codec paths */
549static void dapm_set_mixer_path_status(struct snd_soc_dapm_widget *w,
550 struct snd_soc_dapm_path *p, int i)
551{
552 struct soc_mixer_control *mc = (struct soc_mixer_control *)
553 w->kcontrol_news[i].private_value;
554 unsigned int reg = mc->reg;
555 unsigned int shift = mc->shift;
556 unsigned int max = mc->max;
557 unsigned int mask = (1 << fls(max)) - 1;
558 unsigned int invert = mc->invert;
559 unsigned int val;
560
561 if (reg != SND_SOC_NOPM) {
562 soc_widget_read(w, reg, &val);
563 val = (val >> shift) & mask;
564 if (invert)
565 val = max - val;
566 p->connect = !!val;
567 } else {
568 p->connect = 0;
569 }
570}
571
633/* connect mixer widget to its interconnecting audio paths */ 572/* connect mixer widget to its interconnecting audio paths */
634static int dapm_connect_mixer(struct snd_soc_dapm_context *dapm, 573static int dapm_connect_mixer(struct snd_soc_dapm_context *dapm,
635 struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest, 574 struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest,
@@ -644,7 +583,7 @@ static int dapm_connect_mixer(struct snd_soc_dapm_context *dapm,
644 list_add(&path->list_sink, &dest->sources); 583 list_add(&path->list_sink, &dest->sources);
645 list_add(&path->list_source, &src->sinks); 584 list_add(&path->list_source, &src->sinks);
646 path->name = dest->kcontrol_news[i].name; 585 path->name = dest->kcontrol_news[i].name;
647 dapm_set_path_status(dest, path, i); 586 dapm_set_mixer_path_status(dest, path, i);
648 return 0; 587 return 0;
649 } 588 }
650 } 589 }
@@ -723,8 +662,6 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w,
723 kcname_in_long_name = true; 662 kcname_in_long_name = true;
724 break; 663 break;
725 case snd_soc_dapm_mux: 664 case snd_soc_dapm_mux:
726 case snd_soc_dapm_virt_mux:
727 case snd_soc_dapm_value_mux:
728 wname_in_long_name = true; 665 wname_in_long_name = true;
729 kcname_in_long_name = false; 666 kcname_in_long_name = false;
730 break; 667 break;
@@ -1218,7 +1155,7 @@ int dapm_regulator_event(struct snd_soc_dapm_widget *w,
1218 ret = regulator_allow_bypass(w->regulator, false); 1155 ret = regulator_allow_bypass(w->regulator, false);
1219 if (ret != 0) 1156 if (ret != 0)
1220 dev_warn(w->dapm->dev, 1157 dev_warn(w->dapm->dev,
1221 "ASoC: Failed to bypass %s: %d\n", 1158 "ASoC: Failed to unbypass %s: %d\n",
1222 w->name, ret); 1159 w->name, ret);
1223 } 1160 }
1224 1161
@@ -1228,7 +1165,7 @@ int dapm_regulator_event(struct snd_soc_dapm_widget *w,
1228 ret = regulator_allow_bypass(w->regulator, true); 1165 ret = regulator_allow_bypass(w->regulator, true);
1229 if (ret != 0) 1166 if (ret != 0)
1230 dev_warn(w->dapm->dev, 1167 dev_warn(w->dapm->dev,
1231 "ASoC: Failed to unbypass %s: %d\n", 1168 "ASoC: Failed to bypass %s: %d\n",
1232 w->name, ret); 1169 w->name, ret);
1233 } 1170 }
1234 1171
@@ -1823,6 +1760,8 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event)
1823 ASYNC_DOMAIN_EXCLUSIVE(async_domain); 1760 ASYNC_DOMAIN_EXCLUSIVE(async_domain);
1824 enum snd_soc_bias_level bias; 1761 enum snd_soc_bias_level bias;
1825 1762
1763 lockdep_assert_held(&card->dapm_mutex);
1764
1826 trace_snd_soc_dapm_start(card); 1765 trace_snd_soc_dapm_start(card);
1827 1766
1828 list_for_each_entry(d, &card->dapm_list, list) { 1767 list_for_each_entry(d, &card->dapm_list, list) {
@@ -1897,10 +1836,14 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event)
1897 1836
1898 trace_snd_soc_dapm_walk_done(card); 1837 trace_snd_soc_dapm_walk_done(card);
1899 1838
1900 /* Run all the bias changes in parallel */ 1839 /* Run card bias changes at first */
1901 list_for_each_entry(d, &card->dapm_list, list) 1840 dapm_pre_sequence_async(&card->dapm, 0);
1902 async_schedule_domain(dapm_pre_sequence_async, d, 1841 /* Run other bias changes in parallel */
1903 &async_domain); 1842 list_for_each_entry(d, &card->dapm_list, list) {
1843 if (d != &card->dapm)
1844 async_schedule_domain(dapm_pre_sequence_async, d,
1845 &async_domain);
1846 }
1904 async_synchronize_full_domain(&async_domain); 1847 async_synchronize_full_domain(&async_domain);
1905 1848
1906 list_for_each_entry(w, &down_list, power_list) { 1849 list_for_each_entry(w, &down_list, power_list) {
@@ -1920,10 +1863,14 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event)
1920 dapm_seq_run(card, &up_list, event, true); 1863 dapm_seq_run(card, &up_list, event, true);
1921 1864
1922 /* Run all the bias changes in parallel */ 1865 /* Run all the bias changes in parallel */
1923 list_for_each_entry(d, &card->dapm_list, list) 1866 list_for_each_entry(d, &card->dapm_list, list) {
1924 async_schedule_domain(dapm_post_sequence_async, d, 1867 if (d != &card->dapm)
1925 &async_domain); 1868 async_schedule_domain(dapm_post_sequence_async, d,
1869 &async_domain);
1870 }
1926 async_synchronize_full_domain(&async_domain); 1871 async_synchronize_full_domain(&async_domain);
1872 /* Run card bias changes at last */
1873 dapm_post_sequence_async(&card->dapm, 0);
1927 1874
1928 /* do we need to notify any clients that DAPM event is complete */ 1875 /* do we need to notify any clients that DAPM event is complete */
1929 list_for_each_entry(d, &card->dapm_list, list) { 1876 list_for_each_entry(d, &card->dapm_list, list) {
@@ -2110,6 +2057,8 @@ static int soc_dapm_mux_update_power(struct snd_soc_card *card,
2110 struct snd_soc_dapm_path *path; 2057 struct snd_soc_dapm_path *path;
2111 int found = 0; 2058 int found = 0;
2112 2059
2060 lockdep_assert_held(&card->dapm_mutex);
2061
2113 /* find dapm widget path assoc with kcontrol */ 2062 /* find dapm widget path assoc with kcontrol */
2114 dapm_kcontrol_for_each_path(path, kcontrol) { 2063 dapm_kcontrol_for_each_path(path, kcontrol) {
2115 if (!path->name || !e->texts[mux]) 2064 if (!path->name || !e->texts[mux])
@@ -2160,6 +2109,8 @@ static int soc_dapm_mixer_update_power(struct snd_soc_card *card,
2160 struct snd_soc_dapm_path *path; 2109 struct snd_soc_dapm_path *path;
2161 int found = 0; 2110 int found = 0;
2162 2111
2112 lockdep_assert_held(&card->dapm_mutex);
2113
2163 /* find dapm widget path assoc with kcontrol */ 2114 /* find dapm widget path assoc with kcontrol */
2164 dapm_kcontrol_for_each_path(path, kcontrol) { 2115 dapm_kcontrol_for_each_path(path, kcontrol) {
2165 found = 1; 2116 found = 1;
@@ -2325,6 +2276,8 @@ static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm,
2325{ 2276{
2326 struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, true); 2277 struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, true);
2327 2278
2279 dapm_assert_locked(dapm);
2280
2328 if (!w) { 2281 if (!w) {
2329 dev_err(dapm->dev, "ASoC: DAPM unknown pin %s\n", pin); 2282 dev_err(dapm->dev, "ASoC: DAPM unknown pin %s\n", pin);
2330 return -EINVAL; 2283 return -EINVAL;
@@ -2341,18 +2294,18 @@ static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm,
2341} 2294}
2342 2295
2343/** 2296/**
2344 * snd_soc_dapm_sync - scan and power dapm paths 2297 * snd_soc_dapm_sync_unlocked - scan and power dapm paths
2345 * @dapm: DAPM context 2298 * @dapm: DAPM context
2346 * 2299 *
2347 * Walks all dapm audio paths and powers widgets according to their 2300 * Walks all dapm audio paths and powers widgets according to their
2348 * stream or path usage. 2301 * stream or path usage.
2349 * 2302 *
2303 * Requires external locking.
2304 *
2350 * Returns 0 for success. 2305 * Returns 0 for success.
2351 */ 2306 */
2352int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm) 2307int snd_soc_dapm_sync_unlocked(struct snd_soc_dapm_context *dapm)
2353{ 2308{
2354 int ret;
2355
2356 /* 2309 /*
2357 * Suppress early reports (eg, jacks syncing their state) to avoid 2310 * Suppress early reports (eg, jacks syncing their state) to avoid
2358 * silly DAPM runs during card startup. 2311 * silly DAPM runs during card startup.
@@ -2360,8 +2313,25 @@ int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm)
2360 if (!dapm->card || !dapm->card->instantiated) 2313 if (!dapm->card || !dapm->card->instantiated)
2361 return 0; 2314 return 0;
2362 2315
2316 return dapm_power_widgets(dapm->card, SND_SOC_DAPM_STREAM_NOP);
2317}
2318EXPORT_SYMBOL_GPL(snd_soc_dapm_sync_unlocked);
2319
2320/**
2321 * snd_soc_dapm_sync - scan and power dapm paths
2322 * @dapm: DAPM context
2323 *
2324 * Walks all dapm audio paths and powers widgets according to their
2325 * stream or path usage.
2326 *
2327 * Returns 0 for success.
2328 */
2329int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm)
2330{
2331 int ret;
2332
2363 mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); 2333 mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
2364 ret = dapm_power_widgets(dapm->card, SND_SOC_DAPM_STREAM_NOP); 2334 ret = snd_soc_dapm_sync_unlocked(dapm);
2365 mutex_unlock(&dapm->card->dapm_mutex); 2335 mutex_unlock(&dapm->card->dapm_mutex);
2366 return ret; 2336 return ret;
2367} 2337}
@@ -2444,8 +2414,6 @@ static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm,
2444 path->connect = 1; 2414 path->connect = 1;
2445 return 0; 2415 return 0;
2446 case snd_soc_dapm_mux: 2416 case snd_soc_dapm_mux:
2447 case snd_soc_dapm_virt_mux:
2448 case snd_soc_dapm_value_mux:
2449 ret = dapm_connect_mux(dapm, wsource, wsink, path, control, 2417 ret = dapm_connect_mux(dapm, wsource, wsink, path, control,
2450 &wsink->kcontrol_news[0]); 2418 &wsink->kcontrol_news[0]);
2451 if (ret != 0) 2419 if (ret != 0)
@@ -2772,8 +2740,6 @@ int snd_soc_dapm_new_widgets(struct snd_soc_card *card)
2772 dapm_new_mixer(w); 2740 dapm_new_mixer(w);
2773 break; 2741 break;
2774 case snd_soc_dapm_mux: 2742 case snd_soc_dapm_mux:
2775 case snd_soc_dapm_virt_mux:
2776 case snd_soc_dapm_value_mux:
2777 dapm_new_mux(w); 2743 dapm_new_mux(w);
2778 break; 2744 break;
2779 case snd_soc_dapm_pga: 2745 case snd_soc_dapm_pga:
@@ -2935,213 +2901,75 @@ int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol,
2935{ 2901{
2936 struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); 2902 struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
2937 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 2903 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
2938 unsigned int val; 2904 unsigned int reg_val, val;
2939
2940 val = snd_soc_read(codec, e->reg);
2941 ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & e->mask;
2942 if (e->shift_l != e->shift_r)
2943 ucontrol->value.enumerated.item[1] =
2944 (val >> e->shift_r) & e->mask;
2945
2946 return 0;
2947}
2948EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_double);
2949
2950/**
2951 * snd_soc_dapm_put_enum_double - dapm enumerated double mixer set callback
2952 * @kcontrol: mixer control
2953 * @ucontrol: control element information
2954 *
2955 * Callback to set the value of a dapm enumerated double mixer control.
2956 *
2957 * Returns 0 for success.
2958 */
2959int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
2960 struct snd_ctl_elem_value *ucontrol)
2961{
2962 struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
2963 struct snd_soc_card *card = codec->card;
2964 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
2965 unsigned int val, mux, change;
2966 unsigned int mask;
2967 struct snd_soc_dapm_update update;
2968 int ret = 0;
2969
2970 if (ucontrol->value.enumerated.item[0] > e->max - 1)
2971 return -EINVAL;
2972 mux = ucontrol->value.enumerated.item[0];
2973 val = mux << e->shift_l;
2974 mask = e->mask << e->shift_l;
2975 if (e->shift_l != e->shift_r) {
2976 if (ucontrol->value.enumerated.item[1] > e->max - 1)
2977 return -EINVAL;
2978 val |= ucontrol->value.enumerated.item[1] << e->shift_r;
2979 mask |= e->mask << e->shift_r;
2980 }
2981
2982 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
2983
2984 change = snd_soc_test_bits(codec, e->reg, mask, val);
2985 if (change) {
2986 update.kcontrol = kcontrol;
2987 update.reg = e->reg;
2988 update.mask = mask;
2989 update.val = val;
2990 card->update = &update;
2991
2992 ret = soc_dapm_mux_update_power(card, kcontrol, mux, e);
2993
2994 card->update = NULL;
2995 }
2996
2997 mutex_unlock(&card->dapm_mutex);
2998 2905
2999 if (ret > 0) 2906 if (e->reg != SND_SOC_NOPM)
3000 soc_dpcm_runtime_update(card); 2907 reg_val = snd_soc_read(codec, e->reg);
3001 2908 else
3002 return change; 2909 reg_val = dapm_kcontrol_get_value(kcontrol);
3003}
3004EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double);
3005
3006/**
3007 * snd_soc_dapm_get_enum_virt - Get virtual DAPM mux
3008 * @kcontrol: mixer control
3009 * @ucontrol: control element information
3010 *
3011 * Returns 0 for success.
3012 */
3013int snd_soc_dapm_get_enum_virt(struct snd_kcontrol *kcontrol,
3014 struct snd_ctl_elem_value *ucontrol)
3015{
3016 ucontrol->value.enumerated.item[0] = dapm_kcontrol_get_value(kcontrol);
3017 return 0;
3018}
3019EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_virt);
3020
3021/**
3022 * snd_soc_dapm_put_enum_virt - Set virtual DAPM mux
3023 * @kcontrol: mixer control
3024 * @ucontrol: control element information
3025 *
3026 * Returns 0 for success.
3027 */
3028int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol,
3029 struct snd_ctl_elem_value *ucontrol)
3030{
3031 struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
3032 struct snd_soc_card *card = codec->card;
3033 unsigned int value;
3034 struct soc_enum *e =
3035 (struct soc_enum *)kcontrol->private_value;
3036 int change;
3037 int ret = 0;
3038
3039 if (ucontrol->value.enumerated.item[0] >= e->max)
3040 return -EINVAL;
3041
3042 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
3043
3044 value = ucontrol->value.enumerated.item[0];
3045 change = dapm_kcontrol_set_value(kcontrol, value);
3046 if (change)
3047 ret = soc_dapm_mux_update_power(card, kcontrol, value, e);
3048
3049 mutex_unlock(&card->dapm_mutex);
3050
3051 if (ret > 0)
3052 soc_dpcm_runtime_update(card);
3053
3054 return change;
3055}
3056EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_virt);
3057
3058/**
3059 * snd_soc_dapm_get_value_enum_double - dapm semi enumerated double mixer get
3060 * callback
3061 * @kcontrol: mixer control
3062 * @ucontrol: control element information
3063 *
3064 * Callback to get the value of a dapm semi enumerated double mixer control.
3065 *
3066 * Semi enumerated mixer: the enumerated items are referred as values. Can be
3067 * used for handling bitfield coded enumeration for example.
3068 *
3069 * Returns 0 for success.
3070 */
3071int snd_soc_dapm_get_value_enum_double(struct snd_kcontrol *kcontrol,
3072 struct snd_ctl_elem_value *ucontrol)
3073{
3074 struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
3075 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
3076 unsigned int reg_val, val, mux;
3077 2910
3078 reg_val = snd_soc_read(codec, e->reg);
3079 val = (reg_val >> e->shift_l) & e->mask; 2911 val = (reg_val >> e->shift_l) & e->mask;
3080 for (mux = 0; mux < e->max; mux++) { 2912 ucontrol->value.enumerated.item[0] = snd_soc_enum_val_to_item(e, val);
3081 if (val == e->values[mux])
3082 break;
3083 }
3084 ucontrol->value.enumerated.item[0] = mux;
3085 if (e->shift_l != e->shift_r) { 2913 if (e->shift_l != e->shift_r) {
3086 val = (reg_val >> e->shift_r) & e->mask; 2914 val = (reg_val >> e->shift_r) & e->mask;
3087 for (mux = 0; mux < e->max; mux++) { 2915 val = snd_soc_enum_val_to_item(e, val);
3088 if (val == e->values[mux]) 2916 ucontrol->value.enumerated.item[1] = val;
3089 break;
3090 }
3091 ucontrol->value.enumerated.item[1] = mux;
3092 } 2917 }
3093 2918
3094 return 0; 2919 return 0;
3095} 2920}
3096EXPORT_SYMBOL_GPL(snd_soc_dapm_get_value_enum_double); 2921EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_double);
3097 2922
3098/** 2923/**
3099 * snd_soc_dapm_put_value_enum_double - dapm semi enumerated double mixer set 2924 * snd_soc_dapm_put_enum_double - dapm enumerated double mixer set callback
3100 * callback
3101 * @kcontrol: mixer control 2925 * @kcontrol: mixer control
3102 * @ucontrol: control element information 2926 * @ucontrol: control element information
3103 * 2927 *
3104 * Callback to set the value of a dapm semi enumerated double mixer control. 2928 * Callback to set the value of a dapm enumerated double mixer control.
3105 *
3106 * Semi enumerated mixer: the enumerated items are referred as values. Can be
3107 * used for handling bitfield coded enumeration for example.
3108 * 2929 *
3109 * Returns 0 for success. 2930 * Returns 0 for success.
3110 */ 2931 */
3111int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol, 2932int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
3112 struct snd_ctl_elem_value *ucontrol) 2933 struct snd_ctl_elem_value *ucontrol)
3113{ 2934{
3114 struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); 2935 struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
3115 struct snd_soc_card *card = codec->card; 2936 struct snd_soc_card *card = codec->card;
3116 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 2937 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
3117 unsigned int val, mux, change; 2938 unsigned int *item = ucontrol->value.enumerated.item;
2939 unsigned int val, change;
3118 unsigned int mask; 2940 unsigned int mask;
3119 struct snd_soc_dapm_update update; 2941 struct snd_soc_dapm_update update;
3120 int ret = 0; 2942 int ret = 0;
3121 2943
3122 if (ucontrol->value.enumerated.item[0] > e->max - 1) 2944 if (item[0] >= e->items)
3123 return -EINVAL; 2945 return -EINVAL;
3124 mux = ucontrol->value.enumerated.item[0]; 2946
3125 val = e->values[ucontrol->value.enumerated.item[0]] << e->shift_l; 2947 val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l;
3126 mask = e->mask << e->shift_l; 2948 mask = e->mask << e->shift_l;
3127 if (e->shift_l != e->shift_r) { 2949 if (e->shift_l != e->shift_r) {
3128 if (ucontrol->value.enumerated.item[1] > e->max - 1) 2950 if (item[1] > e->items)
3129 return -EINVAL; 2951 return -EINVAL;
3130 val |= e->values[ucontrol->value.enumerated.item[1]] << e->shift_r; 2952 val |= snd_soc_enum_item_to_val(e, item[1]) << e->shift_l;
3131 mask |= e->mask << e->shift_r; 2953 mask |= e->mask << e->shift_r;
3132 } 2954 }
3133 2955
3134 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); 2956 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
3135 2957
3136 change = snd_soc_test_bits(codec, e->reg, mask, val); 2958 if (e->reg != SND_SOC_NOPM)
2959 change = snd_soc_test_bits(codec, e->reg, mask, val);
2960 else
2961 change = dapm_kcontrol_set_value(kcontrol, val);
2962
3137 if (change) { 2963 if (change) {
3138 update.kcontrol = kcontrol; 2964 if (e->reg != SND_SOC_NOPM) {
3139 update.reg = e->reg; 2965 update.kcontrol = kcontrol;
3140 update.mask = mask; 2966 update.reg = e->reg;
3141 update.val = val; 2967 update.mask = mask;
3142 card->update = &update; 2968 update.val = val;
2969 card->update = &update;
2970 }
3143 2971
3144 ret = soc_dapm_mux_update_power(card, kcontrol, mux, e); 2972 ret = soc_dapm_mux_update_power(card, kcontrol, item[0], e);
3145 2973
3146 card->update = NULL; 2974 card->update = NULL;
3147 } 2975 }
@@ -3153,7 +2981,7 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
3153 2981
3154 return change; 2982 return change;
3155} 2983}
3156EXPORT_SYMBOL_GPL(snd_soc_dapm_put_value_enum_double); 2984EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double);
3157 2985
3158/** 2986/**
3159 * snd_soc_dapm_info_pin_switch - Info for a pin switch 2987 * snd_soc_dapm_info_pin_switch - Info for a pin switch
@@ -3210,15 +3038,11 @@ int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol,
3210 struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); 3038 struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
3211 const char *pin = (const char *)kcontrol->private_value; 3039 const char *pin = (const char *)kcontrol->private_value;
3212 3040
3213 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
3214
3215 if (ucontrol->value.integer.value[0]) 3041 if (ucontrol->value.integer.value[0])
3216 snd_soc_dapm_enable_pin(&card->dapm, pin); 3042 snd_soc_dapm_enable_pin(&card->dapm, pin);
3217 else 3043 else
3218 snd_soc_dapm_disable_pin(&card->dapm, pin); 3044 snd_soc_dapm_disable_pin(&card->dapm, pin);
3219 3045
3220 mutex_unlock(&card->dapm_mutex);
3221
3222 snd_soc_dapm_sync(&card->dapm); 3046 snd_soc_dapm_sync(&card->dapm);
3223 return 0; 3047 return 0;
3224} 3048}
@@ -3248,7 +3072,7 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
3248 ret = regulator_allow_bypass(w->regulator, true); 3072 ret = regulator_allow_bypass(w->regulator, true);
3249 if (ret != 0) 3073 if (ret != 0)
3250 dev_warn(w->dapm->dev, 3074 dev_warn(w->dapm->dev,
3251 "ASoC: Failed to unbypass %s: %d\n", 3075 "ASoC: Failed to bypass %s: %d\n",
3252 w->name, ret); 3076 w->name, ret);
3253 } 3077 }
3254 break; 3078 break;
@@ -3287,8 +3111,6 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
3287 w->power_check = dapm_generic_check_power; 3111 w->power_check = dapm_generic_check_power;
3288 break; 3112 break;
3289 case snd_soc_dapm_mux: 3113 case snd_soc_dapm_mux:
3290 case snd_soc_dapm_virt_mux:
3291 case snd_soc_dapm_value_mux:
3292 w->power_check = dapm_generic_check_power; 3114 w->power_check = dapm_generic_check_power;
3293 break; 3115 break;
3294 case snd_soc_dapm_dai_out: 3116 case snd_soc_dapm_dai_out:
@@ -3767,23 +3589,52 @@ void snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
3767} 3589}
3768 3590
3769/** 3591/**
3592 * snd_soc_dapm_enable_pin_unlocked - enable pin.
3593 * @dapm: DAPM context
3594 * @pin: pin name
3595 *
3596 * Enables input/output pin and its parents or children widgets iff there is
3597 * a valid audio route and active audio stream.
3598 *
3599 * Requires external locking.
3600 *
3601 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
3602 * do any widget power switching.
3603 */
3604int snd_soc_dapm_enable_pin_unlocked(struct snd_soc_dapm_context *dapm,
3605 const char *pin)
3606{
3607 return snd_soc_dapm_set_pin(dapm, pin, 1);
3608}
3609EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin_unlocked);
3610
3611/**
3770 * snd_soc_dapm_enable_pin - enable pin. 3612 * snd_soc_dapm_enable_pin - enable pin.
3771 * @dapm: DAPM context 3613 * @dapm: DAPM context
3772 * @pin: pin name 3614 * @pin: pin name
3773 * 3615 *
3774 * Enables input/output pin and its parents or children widgets iff there is 3616 * Enables input/output pin and its parents or children widgets iff there is
3775 * a valid audio route and active audio stream. 3617 * a valid audio route and active audio stream.
3618 *
3776 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to 3619 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
3777 * do any widget power switching. 3620 * do any widget power switching.
3778 */ 3621 */
3779int snd_soc_dapm_enable_pin(struct snd_soc_dapm_context *dapm, const char *pin) 3622int snd_soc_dapm_enable_pin(struct snd_soc_dapm_context *dapm, const char *pin)
3780{ 3623{
3781 return snd_soc_dapm_set_pin(dapm, pin, 1); 3624 int ret;
3625
3626 mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
3627
3628 ret = snd_soc_dapm_set_pin(dapm, pin, 1);
3629
3630 mutex_unlock(&dapm->card->dapm_mutex);
3631
3632 return ret;
3782} 3633}
3783EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin); 3634EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin);
3784 3635
3785/** 3636/**
3786 * snd_soc_dapm_force_enable_pin - force a pin to be enabled 3637 * snd_soc_dapm_force_enable_pin_unlocked - force a pin to be enabled
3787 * @dapm: DAPM context 3638 * @dapm: DAPM context
3788 * @pin: pin name 3639 * @pin: pin name
3789 * 3640 *
@@ -3791,11 +3642,13 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin);
3791 * intended for use with microphone bias supplies used in microphone 3642 * intended for use with microphone bias supplies used in microphone
3792 * jack detection. 3643 * jack detection.
3793 * 3644 *
3645 * Requires external locking.
3646 *
3794 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to 3647 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
3795 * do any widget power switching. 3648 * do any widget power switching.
3796 */ 3649 */
3797int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm, 3650int snd_soc_dapm_force_enable_pin_unlocked(struct snd_soc_dapm_context *dapm,
3798 const char *pin) 3651 const char *pin)
3799{ 3652{
3800 struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, true); 3653 struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, true);
3801 3654
@@ -3811,25 +3664,103 @@ int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm,
3811 3664
3812 return 0; 3665 return 0;
3813} 3666}
3667EXPORT_SYMBOL_GPL(snd_soc_dapm_force_enable_pin_unlocked);
3668
3669/**
3670 * snd_soc_dapm_force_enable_pin - force a pin to be enabled
3671 * @dapm: DAPM context
3672 * @pin: pin name
3673 *
3674 * Enables input/output pin regardless of any other state. This is
3675 * intended for use with microphone bias supplies used in microphone
3676 * jack detection.
3677 *
3678 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
3679 * do any widget power switching.
3680 */
3681int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm,
3682 const char *pin)
3683{
3684 int ret;
3685
3686 mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
3687
3688 ret = snd_soc_dapm_force_enable_pin_unlocked(dapm, pin);
3689
3690 mutex_unlock(&dapm->card->dapm_mutex);
3691
3692 return ret;
3693}
3814EXPORT_SYMBOL_GPL(snd_soc_dapm_force_enable_pin); 3694EXPORT_SYMBOL_GPL(snd_soc_dapm_force_enable_pin);
3815 3695
3816/** 3696/**
3697 * snd_soc_dapm_disable_pin_unlocked - disable pin.
3698 * @dapm: DAPM context
3699 * @pin: pin name
3700 *
3701 * Disables input/output pin and its parents or children widgets.
3702 *
3703 * Requires external locking.
3704 *
3705 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
3706 * do any widget power switching.
3707 */
3708int snd_soc_dapm_disable_pin_unlocked(struct snd_soc_dapm_context *dapm,
3709 const char *pin)
3710{
3711 return snd_soc_dapm_set_pin(dapm, pin, 0);
3712}
3713EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin_unlocked);
3714
3715/**
3817 * snd_soc_dapm_disable_pin - disable pin. 3716 * snd_soc_dapm_disable_pin - disable pin.
3818 * @dapm: DAPM context 3717 * @dapm: DAPM context
3819 * @pin: pin name 3718 * @pin: pin name
3820 * 3719 *
3821 * Disables input/output pin and its parents or children widgets. 3720 * Disables input/output pin and its parents or children widgets.
3721 *
3822 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to 3722 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
3823 * do any widget power switching. 3723 * do any widget power switching.
3824 */ 3724 */
3825int snd_soc_dapm_disable_pin(struct snd_soc_dapm_context *dapm, 3725int snd_soc_dapm_disable_pin(struct snd_soc_dapm_context *dapm,
3826 const char *pin) 3726 const char *pin)
3827{ 3727{
3828 return snd_soc_dapm_set_pin(dapm, pin, 0); 3728 int ret;
3729
3730 mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
3731
3732 ret = snd_soc_dapm_set_pin(dapm, pin, 0);
3733
3734 mutex_unlock(&dapm->card->dapm_mutex);
3735
3736 return ret;
3829} 3737}
3830EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin); 3738EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin);
3831 3739
3832/** 3740/**
3741 * snd_soc_dapm_nc_pin_unlocked - permanently disable pin.
3742 * @dapm: DAPM context
3743 * @pin: pin name
3744 *
3745 * Marks the specified pin as being not connected, disabling it along
3746 * any parent or child widgets. At present this is identical to
3747 * snd_soc_dapm_disable_pin() but in future it will be extended to do
3748 * additional things such as disabling controls which only affect
3749 * paths through the pin.
3750 *
3751 * Requires external locking.
3752 *
3753 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
3754 * do any widget power switching.
3755 */
3756int snd_soc_dapm_nc_pin_unlocked(struct snd_soc_dapm_context *dapm,
3757 const char *pin)
3758{
3759 return snd_soc_dapm_set_pin(dapm, pin, 0);
3760}
3761EXPORT_SYMBOL_GPL(snd_soc_dapm_nc_pin_unlocked);
3762
3763/**
3833 * snd_soc_dapm_nc_pin - permanently disable pin. 3764 * snd_soc_dapm_nc_pin - permanently disable pin.
3834 * @dapm: DAPM context 3765 * @dapm: DAPM context
3835 * @pin: pin name 3766 * @pin: pin name
@@ -3845,7 +3776,15 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin);
3845 */ 3776 */
3846int snd_soc_dapm_nc_pin(struct snd_soc_dapm_context *dapm, const char *pin) 3777int snd_soc_dapm_nc_pin(struct snd_soc_dapm_context *dapm, const char *pin)
3847{ 3778{
3848 return snd_soc_dapm_set_pin(dapm, pin, 0); 3779 int ret;
3780
3781 mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
3782
3783 ret = snd_soc_dapm_set_pin(dapm, pin, 0);
3784
3785 mutex_unlock(&dapm->card->dapm_mutex);
3786
3787 return ret;
3849} 3788}
3850EXPORT_SYMBOL_GPL(snd_soc_dapm_nc_pin); 3789EXPORT_SYMBOL_GPL(snd_soc_dapm_nc_pin);
3851 3790
@@ -3985,7 +3924,7 @@ void snd_soc_dapm_free(struct snd_soc_dapm_context *dapm)
3985} 3924}
3986EXPORT_SYMBOL_GPL(snd_soc_dapm_free); 3925EXPORT_SYMBOL_GPL(snd_soc_dapm_free);
3987 3926
3988static void soc_dapm_shutdown_codec(struct snd_soc_dapm_context *dapm) 3927static void soc_dapm_shutdown_dapm(struct snd_soc_dapm_context *dapm)
3989{ 3928{
3990 struct snd_soc_card *card = dapm->card; 3929 struct snd_soc_card *card = dapm->card;
3991 struct snd_soc_dapm_widget *w; 3930 struct snd_soc_dapm_widget *w;
@@ -4025,14 +3964,21 @@ static void soc_dapm_shutdown_codec(struct snd_soc_dapm_context *dapm)
4025 */ 3964 */
4026void snd_soc_dapm_shutdown(struct snd_soc_card *card) 3965void snd_soc_dapm_shutdown(struct snd_soc_card *card)
4027{ 3966{
4028 struct snd_soc_codec *codec; 3967 struct snd_soc_dapm_context *dapm;
4029 3968
4030 list_for_each_entry(codec, &card->codec_dev_list, card_list) { 3969 list_for_each_entry(dapm, &card->dapm_list, list) {
4031 soc_dapm_shutdown_codec(&codec->dapm); 3970 if (dapm != &card->dapm) {
4032 if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) 3971 soc_dapm_shutdown_dapm(dapm);
4033 snd_soc_dapm_set_bias_level(&codec->dapm, 3972 if (dapm->bias_level == SND_SOC_BIAS_STANDBY)
4034 SND_SOC_BIAS_OFF); 3973 snd_soc_dapm_set_bias_level(dapm,
3974 SND_SOC_BIAS_OFF);
3975 }
4035 } 3976 }
3977
3978 soc_dapm_shutdown_dapm(&card->dapm);
3979 if (card->dapm.bias_level == SND_SOC_BIAS_STANDBY)
3980 snd_soc_dapm_set_bias_level(&card->dapm,
3981 SND_SOC_BIAS_OFF);
4036} 3982}
4037 3983
4038/* Module information */ 3984/* Module information */