diff options
Diffstat (limited to 'sound/soc/soc-dapm.c')
-rw-r--r-- | sound/soc/soc-dapm.c | 120 |
1 files changed, 75 insertions, 45 deletions
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index c17c14c394df..2fb0b72d8a3c 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c | |||
@@ -59,31 +59,31 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, | |||
59 | /* dapm power sequences - make this per codec in the future */ | 59 | /* dapm power sequences - make this per codec in the future */ |
60 | static int dapm_up_seq[] = { | 60 | static int dapm_up_seq[] = { |
61 | [snd_soc_dapm_pre] = 0, | 61 | [snd_soc_dapm_pre] = 0, |
62 | [snd_soc_dapm_supply] = 1, | ||
63 | [snd_soc_dapm_regulator_supply] = 1, | 62 | [snd_soc_dapm_regulator_supply] = 1, |
64 | [snd_soc_dapm_clock_supply] = 1, | 63 | [snd_soc_dapm_clock_supply] = 1, |
65 | [snd_soc_dapm_micbias] = 2, | 64 | [snd_soc_dapm_supply] = 2, |
65 | [snd_soc_dapm_micbias] = 3, | ||
66 | [snd_soc_dapm_dai_link] = 2, | 66 | [snd_soc_dapm_dai_link] = 2, |
67 | [snd_soc_dapm_dai_in] = 3, | 67 | [snd_soc_dapm_dai_in] = 4, |
68 | [snd_soc_dapm_dai_out] = 3, | 68 | [snd_soc_dapm_dai_out] = 4, |
69 | [snd_soc_dapm_aif_in] = 3, | 69 | [snd_soc_dapm_aif_in] = 4, |
70 | [snd_soc_dapm_aif_out] = 3, | 70 | [snd_soc_dapm_aif_out] = 4, |
71 | [snd_soc_dapm_mic] = 4, | 71 | [snd_soc_dapm_mic] = 5, |
72 | [snd_soc_dapm_mux] = 5, | 72 | [snd_soc_dapm_mux] = 6, |
73 | [snd_soc_dapm_virt_mux] = 5, | 73 | [snd_soc_dapm_virt_mux] = 6, |
74 | [snd_soc_dapm_value_mux] = 5, | 74 | [snd_soc_dapm_value_mux] = 6, |
75 | [snd_soc_dapm_dac] = 6, | 75 | [snd_soc_dapm_dac] = 7, |
76 | [snd_soc_dapm_switch] = 7, | 76 | [snd_soc_dapm_switch] = 8, |
77 | [snd_soc_dapm_mixer] = 7, | 77 | [snd_soc_dapm_mixer] = 8, |
78 | [snd_soc_dapm_mixer_named_ctl] = 7, | 78 | [snd_soc_dapm_mixer_named_ctl] = 8, |
79 | [snd_soc_dapm_pga] = 8, | 79 | [snd_soc_dapm_pga] = 9, |
80 | [snd_soc_dapm_adc] = 9, | 80 | [snd_soc_dapm_adc] = 10, |
81 | [snd_soc_dapm_out_drv] = 10, | 81 | [snd_soc_dapm_out_drv] = 11, |
82 | [snd_soc_dapm_hp] = 10, | 82 | [snd_soc_dapm_hp] = 11, |
83 | [snd_soc_dapm_spk] = 10, | 83 | [snd_soc_dapm_spk] = 11, |
84 | [snd_soc_dapm_line] = 10, | 84 | [snd_soc_dapm_line] = 11, |
85 | [snd_soc_dapm_kcontrol] = 11, | 85 | [snd_soc_dapm_kcontrol] = 12, |
86 | [snd_soc_dapm_post] = 12, | 86 | [snd_soc_dapm_post] = 13, |
87 | }; | 87 | }; |
88 | 88 | ||
89 | static int dapm_down_seq[] = { | 89 | static int dapm_down_seq[] = { |
@@ -109,10 +109,10 @@ static int dapm_down_seq[] = { | |||
109 | [snd_soc_dapm_dai_in] = 10, | 109 | [snd_soc_dapm_dai_in] = 10, |
110 | [snd_soc_dapm_dai_out] = 10, | 110 | [snd_soc_dapm_dai_out] = 10, |
111 | [snd_soc_dapm_dai_link] = 11, | 111 | [snd_soc_dapm_dai_link] = 11, |
112 | [snd_soc_dapm_clock_supply] = 12, | ||
113 | [snd_soc_dapm_regulator_supply] = 12, | ||
114 | [snd_soc_dapm_supply] = 12, | 112 | [snd_soc_dapm_supply] = 12, |
115 | [snd_soc_dapm_post] = 13, | 113 | [snd_soc_dapm_clock_supply] = 13, |
114 | [snd_soc_dapm_regulator_supply] = 13, | ||
115 | [snd_soc_dapm_post] = 14, | ||
116 | }; | 116 | }; |
117 | 117 | ||
118 | static void pop_wait(u32 pop_time) | 118 | static void pop_wait(u32 pop_time) |
@@ -409,6 +409,12 @@ static inline void soc_widget_unlock(struct snd_soc_dapm_widget *w) | |||
409 | mutex_unlock(&w->platform->mutex); | 409 | mutex_unlock(&w->platform->mutex); |
410 | } | 410 | } |
411 | 411 | ||
412 | static void soc_dapm_async_complete(struct snd_soc_dapm_context *dapm) | ||
413 | { | ||
414 | if (dapm->codec && dapm->codec->using_regmap) | ||
415 | regmap_async_complete(dapm->codec->control_data); | ||
416 | } | ||
417 | |||
412 | static int soc_widget_update_bits_locked(struct snd_soc_dapm_widget *w, | 418 | static int soc_widget_update_bits_locked(struct snd_soc_dapm_widget *w, |
413 | unsigned short reg, unsigned int mask, unsigned int value) | 419 | unsigned short reg, unsigned int mask, unsigned int value) |
414 | { | 420 | { |
@@ -417,8 +423,9 @@ static int soc_widget_update_bits_locked(struct snd_soc_dapm_widget *w, | |||
417 | int ret; | 423 | int ret; |
418 | 424 | ||
419 | if (w->codec && w->codec->using_regmap) { | 425 | if (w->codec && w->codec->using_regmap) { |
420 | ret = regmap_update_bits_check(w->codec->control_data, | 426 | ret = regmap_update_bits_check_async(w->codec->control_data, |
421 | reg, mask, value, &change); | 427 | reg, mask, value, |
428 | &change); | ||
422 | if (ret != 0) | 429 | if (ret != 0) |
423 | return ret; | 430 | return ret; |
424 | } else { | 431 | } else { |
@@ -499,18 +506,22 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, | |||
499 | int val; | 506 | int val; |
500 | struct soc_mixer_control *mc = (struct soc_mixer_control *) | 507 | struct soc_mixer_control *mc = (struct soc_mixer_control *) |
501 | w->kcontrol_news[i].private_value; | 508 | w->kcontrol_news[i].private_value; |
502 | unsigned int reg = mc->reg; | 509 | int reg = mc->reg; |
503 | unsigned int shift = mc->shift; | 510 | unsigned int shift = mc->shift; |
504 | int max = mc->max; | 511 | int max = mc->max; |
505 | unsigned int mask = (1 << fls(max)) - 1; | 512 | unsigned int mask = (1 << fls(max)) - 1; |
506 | unsigned int invert = mc->invert; | 513 | unsigned int invert = mc->invert; |
507 | 514 | ||
508 | val = soc_widget_read(w, reg); | 515 | if (reg != SND_SOC_NOPM) { |
509 | val = (val >> shift) & mask; | 516 | val = soc_widget_read(w, reg); |
510 | if (invert) | 517 | val = (val >> shift) & mask; |
511 | val = max - val; | 518 | if (invert) |
519 | val = max - val; | ||
520 | p->connect = !!val; | ||
521 | } else { | ||
522 | p->connect = 0; | ||
523 | } | ||
512 | 524 | ||
513 | p->connect = !!val; | ||
514 | } | 525 | } |
515 | break; | 526 | break; |
516 | case snd_soc_dapm_mux: { | 527 | case snd_soc_dapm_mux: { |
@@ -1197,6 +1208,8 @@ int dapm_regulator_event(struct snd_soc_dapm_widget *w, | |||
1197 | { | 1208 | { |
1198 | int ret; | 1209 | int ret; |
1199 | 1210 | ||
1211 | soc_dapm_async_complete(w->dapm); | ||
1212 | |||
1200 | if (SND_SOC_DAPM_EVENT_ON(event)) { | 1213 | if (SND_SOC_DAPM_EVENT_ON(event)) { |
1201 | if (w->on_val & SND_SOC_DAPM_REGULATOR_BYPASS) { | 1214 | if (w->on_val & SND_SOC_DAPM_REGULATOR_BYPASS) { |
1202 | ret = regulator_allow_bypass(w->regulator, false); | 1215 | ret = regulator_allow_bypass(w->regulator, false); |
@@ -1230,6 +1243,8 @@ int dapm_clock_event(struct snd_soc_dapm_widget *w, | |||
1230 | if (!w->clk) | 1243 | if (!w->clk) |
1231 | return -EIO; | 1244 | return -EIO; |
1232 | 1245 | ||
1246 | soc_dapm_async_complete(w->dapm); | ||
1247 | |||
1233 | #ifdef CONFIG_HAVE_CLK | 1248 | #ifdef CONFIG_HAVE_CLK |
1234 | if (SND_SOC_DAPM_EVENT_ON(event)) { | 1249 | if (SND_SOC_DAPM_EVENT_ON(event)) { |
1235 | return clk_prepare_enable(w->clk); | 1250 | return clk_prepare_enable(w->clk); |
@@ -1422,6 +1437,7 @@ static void dapm_seq_check_event(struct snd_soc_card *card, | |||
1422 | if (w->event && (w->event_flags & event)) { | 1437 | if (w->event && (w->event_flags & event)) { |
1423 | pop_dbg(w->dapm->dev, card->pop_time, "pop test : %s %s\n", | 1438 | pop_dbg(w->dapm->dev, card->pop_time, "pop test : %s %s\n", |
1424 | w->name, ev_name); | 1439 | w->name, ev_name); |
1440 | soc_dapm_async_complete(w->dapm); | ||
1425 | trace_snd_soc_dapm_widget_event_start(w, event); | 1441 | trace_snd_soc_dapm_widget_event_start(w, event); |
1426 | ret = w->event(w, NULL, event); | 1442 | ret = w->event(w, NULL, event); |
1427 | trace_snd_soc_dapm_widget_event_done(w, event); | 1443 | trace_snd_soc_dapm_widget_event_done(w, event); |
@@ -1494,6 +1510,7 @@ static void dapm_seq_run(struct snd_soc_card *card, | |||
1494 | struct list_head *list, int event, bool power_up) | 1510 | struct list_head *list, int event, bool power_up) |
1495 | { | 1511 | { |
1496 | struct snd_soc_dapm_widget *w, *n; | 1512 | struct snd_soc_dapm_widget *w, *n; |
1513 | struct snd_soc_dapm_context *d; | ||
1497 | LIST_HEAD(pending); | 1514 | LIST_HEAD(pending); |
1498 | int cur_sort = -1; | 1515 | int cur_sort = -1; |
1499 | int cur_subseq = -1; | 1516 | int cur_subseq = -1; |
@@ -1524,6 +1541,9 @@ static void dapm_seq_run(struct snd_soc_card *card, | |||
1524 | cur_subseq); | 1541 | cur_subseq); |
1525 | } | 1542 | } |
1526 | 1543 | ||
1544 | if (cur_dapm && w->dapm != cur_dapm) | ||
1545 | soc_dapm_async_complete(cur_dapm); | ||
1546 | |||
1527 | INIT_LIST_HEAD(&pending); | 1547 | INIT_LIST_HEAD(&pending); |
1528 | cur_sort = -1; | 1548 | cur_sort = -1; |
1529 | cur_subseq = INT_MIN; | 1549 | cur_subseq = INT_MIN; |
@@ -1582,6 +1602,10 @@ static void dapm_seq_run(struct snd_soc_card *card, | |||
1582 | cur_dapm->seq_notifier(cur_dapm, | 1602 | cur_dapm->seq_notifier(cur_dapm, |
1583 | i, cur_subseq); | 1603 | i, cur_subseq); |
1584 | } | 1604 | } |
1605 | |||
1606 | list_for_each_entry(d, &card->dapm_list, list) { | ||
1607 | soc_dapm_async_complete(d); | ||
1608 | } | ||
1585 | } | 1609 | } |
1586 | 1610 | ||
1587 | static void dapm_widget_update(struct snd_soc_card *card) | 1611 | static void dapm_widget_update(struct snd_soc_card *card) |
@@ -1840,6 +1864,7 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event) | |||
1840 | */ | 1864 | */ |
1841 | switch (w->id) { | 1865 | switch (w->id) { |
1842 | case snd_soc_dapm_siggen: | 1866 | case snd_soc_dapm_siggen: |
1867 | case snd_soc_dapm_vmid: | ||
1843 | break; | 1868 | break; |
1844 | case snd_soc_dapm_supply: | 1869 | case snd_soc_dapm_supply: |
1845 | case snd_soc_dapm_regulator_supply: | 1870 | case snd_soc_dapm_regulator_supply: |
@@ -2791,7 +2816,7 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, | |||
2791 | struct snd_soc_card *card = codec->card; | 2816 | struct snd_soc_card *card = codec->card; |
2792 | struct soc_mixer_control *mc = | 2817 | struct soc_mixer_control *mc = |
2793 | (struct soc_mixer_control *)kcontrol->private_value; | 2818 | (struct soc_mixer_control *)kcontrol->private_value; |
2794 | unsigned int reg = mc->reg; | 2819 | int reg = mc->reg; |
2795 | unsigned int shift = mc->shift; | 2820 | unsigned int shift = mc->shift; |
2796 | int max = mc->max; | 2821 | int max = mc->max; |
2797 | unsigned int mask = (1 << fls(max)) - 1; | 2822 | unsigned int mask = (1 << fls(max)) - 1; |
@@ -2804,7 +2829,7 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, | |||
2804 | kcontrol->id.name); | 2829 | kcontrol->id.name); |
2805 | 2830 | ||
2806 | mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); | 2831 | mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); |
2807 | if (dapm_kcontrol_is_powered(kcontrol)) | 2832 | if (dapm_kcontrol_is_powered(kcontrol) && reg != SND_SOC_NOPM) |
2808 | val = (snd_soc_read(codec, reg) >> shift) & mask; | 2833 | val = (snd_soc_read(codec, reg) >> shift) & mask; |
2809 | else | 2834 | else |
2810 | val = dapm_kcontrol_get_value(kcontrol); | 2835 | val = dapm_kcontrol_get_value(kcontrol); |
@@ -2835,7 +2860,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, | |||
2835 | struct snd_soc_card *card = codec->card; | 2860 | struct snd_soc_card *card = codec->card; |
2836 | struct soc_mixer_control *mc = | 2861 | struct soc_mixer_control *mc = |
2837 | (struct soc_mixer_control *)kcontrol->private_value; | 2862 | (struct soc_mixer_control *)kcontrol->private_value; |
2838 | unsigned int reg = mc->reg; | 2863 | int reg = mc->reg; |
2839 | unsigned int shift = mc->shift; | 2864 | unsigned int shift = mc->shift; |
2840 | int max = mc->max; | 2865 | int max = mc->max; |
2841 | unsigned int mask = (1 << fls(max)) - 1; | 2866 | unsigned int mask = (1 << fls(max)) - 1; |
@@ -2857,19 +2882,24 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, | |||
2857 | 2882 | ||
2858 | mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); | 2883 | mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); |
2859 | 2884 | ||
2860 | dapm_kcontrol_set_value(kcontrol, val); | 2885 | change = dapm_kcontrol_set_value(kcontrol, val); |
2886 | |||
2887 | if (reg != SND_SOC_NOPM) { | ||
2888 | mask = mask << shift; | ||
2889 | val = val << shift; | ||
2861 | 2890 | ||
2862 | mask = mask << shift; | 2891 | change = snd_soc_test_bits(codec, reg, mask, val); |
2863 | val = val << shift; | 2892 | } |
2864 | 2893 | ||
2865 | change = snd_soc_test_bits(codec, reg, mask, val); | ||
2866 | if (change) { | 2894 | if (change) { |
2867 | update.kcontrol = kcontrol; | 2895 | if (reg != SND_SOC_NOPM) { |
2868 | update.reg = reg; | 2896 | update.kcontrol = kcontrol; |
2869 | update.mask = mask; | 2897 | update.reg = reg; |
2870 | update.val = val; | 2898 | update.mask = mask; |
2899 | update.val = val; | ||
2871 | 2900 | ||
2872 | card->update = &update; | 2901 | card->update = &update; |
2902 | } | ||
2873 | 2903 | ||
2874 | soc_dapm_mixer_update_power(card, kcontrol, connect); | 2904 | soc_dapm_mixer_update_power(card, kcontrol, connect); |
2875 | 2905 | ||