diff options
-rw-r--r-- | include/sound/soc-dapm.h | 10 | ||||
-rw-r--r-- | sound/soc/soc-dapm.c | 130 |
2 files changed, 82 insertions, 58 deletions
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 98783510d2f1..540872fc1390 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h | |||
@@ -460,6 +460,14 @@ struct snd_soc_dapm_widget { | |||
460 | struct list_head power_list; | 460 | struct list_head power_list; |
461 | }; | 461 | }; |
462 | 462 | ||
463 | struct snd_soc_dapm_update { | ||
464 | struct snd_soc_dapm_widget *widget; | ||
465 | struct snd_kcontrol *kcontrol; | ||
466 | int reg; | ||
467 | int mask; | ||
468 | int val; | ||
469 | }; | ||
470 | |||
463 | /* DAPM context */ | 471 | /* DAPM context */ |
464 | struct snd_soc_dapm_context { | 472 | struct snd_soc_dapm_context { |
465 | int n_widgets; /* number of widgets in this context */ | 473 | int n_widgets; /* number of widgets in this context */ |
@@ -468,6 +476,8 @@ struct snd_soc_dapm_context { | |||
468 | struct delayed_work delayed_work; | 476 | struct delayed_work delayed_work; |
469 | unsigned int idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */ | 477 | unsigned int idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */ |
470 | 478 | ||
479 | struct snd_soc_dapm_update *update; | ||
480 | |||
471 | struct device *dev; /* from parent - for debug */ | 481 | struct device *dev; /* from parent - for debug */ |
472 | struct snd_soc_codec *codec; /* parent codec */ | 482 | struct snd_soc_codec *codec; /* parent codec */ |
473 | struct snd_soc_card *card; /* parent card */ | 483 | struct snd_soc_card *card; /* parent card */ |
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index f362d1de78f3..1debc3b05665 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c | |||
@@ -920,6 +920,41 @@ static void dapm_seq_run(struct snd_soc_dapm_context *dapm, | |||
920 | dapm_seq_run_coalesced(dapm, &pending); | 920 | dapm_seq_run_coalesced(dapm, &pending); |
921 | } | 921 | } |
922 | 922 | ||
923 | static void dapm_widget_update(struct snd_soc_dapm_context *dapm) | ||
924 | { | ||
925 | struct snd_soc_dapm_update *update = dapm->update; | ||
926 | struct snd_soc_dapm_widget *w; | ||
927 | int ret; | ||
928 | |||
929 | if (!update) | ||
930 | return; | ||
931 | |||
932 | w = update->widget; | ||
933 | |||
934 | if (w->event && | ||
935 | (w->event_flags & SND_SOC_DAPM_PRE_REG)) { | ||
936 | ret = w->event(w, update->kcontrol, SND_SOC_DAPM_PRE_REG); | ||
937 | if (ret != 0) | ||
938 | pr_err("%s DAPM pre-event failed: %d\n", | ||
939 | w->name, ret); | ||
940 | } | ||
941 | |||
942 | ret = snd_soc_update_bits(w->codec, update->reg, update->mask, | ||
943 | update->val); | ||
944 | if (ret < 0) | ||
945 | pr_err("%s DAPM update failed: %d\n", w->name, ret); | ||
946 | |||
947 | if (w->event && | ||
948 | (w->event_flags & SND_SOC_DAPM_POST_REG)) { | ||
949 | ret = w->event(w, update->kcontrol, SND_SOC_DAPM_POST_REG); | ||
950 | if (ret != 0) | ||
951 | pr_err("%s DAPM post-event failed: %d\n", | ||
952 | w->name, ret); | ||
953 | } | ||
954 | } | ||
955 | |||
956 | |||
957 | |||
923 | /* | 958 | /* |
924 | * Scan each dapm widget for complete audio path. | 959 | * Scan each dapm widget for complete audio path. |
925 | * A complete path is a route that has valid endpoints i.e.:- | 960 | * A complete path is a route that has valid endpoints i.e.:- |
@@ -1037,6 +1072,8 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event) | |||
1037 | /* Power down widgets first; try to avoid amplifying pops. */ | 1072 | /* Power down widgets first; try to avoid amplifying pops. */ |
1038 | dapm_seq_run(dapm, &down_list, event, dapm_down_seq); | 1073 | dapm_seq_run(dapm, &down_list, event, dapm_down_seq); |
1039 | 1074 | ||
1075 | dapm_widget_update(dapm); | ||
1076 | |||
1040 | /* Now power up. */ | 1077 | /* Now power up. */ |
1041 | dapm_seq_run(dapm, &up_list, event, dapm_up_seq); | 1078 | dapm_seq_run(dapm, &up_list, event, dapm_up_seq); |
1042 | 1079 | ||
@@ -1683,13 +1720,12 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, | |||
1683 | (struct soc_mixer_control *)kcontrol->private_value; | 1720 | (struct soc_mixer_control *)kcontrol->private_value; |
1684 | unsigned int reg = mc->reg; | 1721 | unsigned int reg = mc->reg; |
1685 | unsigned int shift = mc->shift; | 1722 | unsigned int shift = mc->shift; |
1686 | unsigned int rshift = mc->rshift; | ||
1687 | int max = mc->max; | 1723 | int max = mc->max; |
1688 | unsigned int mask = (1 << fls(max)) - 1; | 1724 | unsigned int mask = (1 << fls(max)) - 1; |
1689 | unsigned int invert = mc->invert; | 1725 | unsigned int invert = mc->invert; |
1690 | unsigned int val, val2, val_mask; | 1726 | unsigned int val, val_mask; |
1691 | int connect; | 1727 | int connect, change; |
1692 | int ret; | 1728 | struct snd_soc_dapm_update update; |
1693 | 1729 | ||
1694 | val = (ucontrol->value.integer.value[0] & mask); | 1730 | val = (ucontrol->value.integer.value[0] & mask); |
1695 | 1731 | ||
@@ -1697,18 +1733,12 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, | |||
1697 | val = max - val; | 1733 | val = max - val; |
1698 | val_mask = mask << shift; | 1734 | val_mask = mask << shift; |
1699 | val = val << shift; | 1735 | val = val << shift; |
1700 | if (shift != rshift) { | ||
1701 | val2 = (ucontrol->value.integer.value[1] & mask); | ||
1702 | if (invert) | ||
1703 | val2 = max - val2; | ||
1704 | val_mask |= mask << rshift; | ||
1705 | val |= val2 << rshift; | ||
1706 | } | ||
1707 | 1736 | ||
1708 | mutex_lock(&widget->codec->mutex); | 1737 | mutex_lock(&widget->codec->mutex); |
1709 | widget->value = val; | 1738 | widget->value = val; |
1710 | 1739 | ||
1711 | if (snd_soc_test_bits(widget->codec, reg, val_mask, val)) { | 1740 | change = snd_soc_test_bits(widget->codec, reg, val_mask, val); |
1741 | if (change) { | ||
1712 | if (val) | 1742 | if (val) |
1713 | /* new connection */ | 1743 | /* new connection */ |
1714 | connect = invert ? 0:1; | 1744 | connect = invert ? 0:1; |
@@ -1716,28 +1746,20 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, | |||
1716 | /* old connection must be powered down */ | 1746 | /* old connection must be powered down */ |
1717 | connect = invert ? 1:0; | 1747 | connect = invert ? 1:0; |
1718 | 1748 | ||
1749 | update.kcontrol = kcontrol; | ||
1750 | update.widget = widget; | ||
1751 | update.reg = reg; | ||
1752 | update.mask = mask; | ||
1753 | update.val = val; | ||
1754 | widget->dapm->update = &update; | ||
1755 | |||
1719 | dapm_mixer_update_power(widget, kcontrol, connect); | 1756 | dapm_mixer_update_power(widget, kcontrol, connect); |
1757 | |||
1758 | widget->dapm->update = NULL; | ||
1720 | } | 1759 | } |
1721 | 1760 | ||
1722 | if (widget->event) { | ||
1723 | if (widget->event_flags & SND_SOC_DAPM_PRE_REG) { | ||
1724 | ret = widget->event(widget, kcontrol, | ||
1725 | SND_SOC_DAPM_PRE_REG); | ||
1726 | if (ret < 0) { | ||
1727 | ret = 1; | ||
1728 | goto out; | ||
1729 | } | ||
1730 | } | ||
1731 | ret = snd_soc_update_bits(widget->codec, reg, val_mask, val); | ||
1732 | if (widget->event_flags & SND_SOC_DAPM_POST_REG) | ||
1733 | ret = widget->event(widget, kcontrol, | ||
1734 | SND_SOC_DAPM_POST_REG); | ||
1735 | } else | ||
1736 | ret = snd_soc_update_bits(widget->codec, reg, val_mask, val); | ||
1737 | |||
1738 | out: | ||
1739 | mutex_unlock(&widget->codec->mutex); | 1761 | mutex_unlock(&widget->codec->mutex); |
1740 | return ret; | 1762 | return 0; |
1741 | } | 1763 | } |
1742 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw); | 1764 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw); |
1743 | 1765 | ||
@@ -1785,7 +1807,7 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, | |||
1785 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | 1807 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
1786 | unsigned int val, mux, change; | 1808 | unsigned int val, mux, change; |
1787 | unsigned int mask, bitmask; | 1809 | unsigned int mask, bitmask; |
1788 | int ret = 0; | 1810 | struct snd_soc_dapm_update update; |
1789 | 1811 | ||
1790 | for (bitmask = 1; bitmask < e->max; bitmask <<= 1) | 1812 | for (bitmask = 1; bitmask < e->max; bitmask <<= 1) |
1791 | ; | 1813 | ; |
@@ -1804,24 +1826,20 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, | |||
1804 | mutex_lock(&widget->codec->mutex); | 1826 | mutex_lock(&widget->codec->mutex); |
1805 | widget->value = val; | 1827 | widget->value = val; |
1806 | change = snd_soc_test_bits(widget->codec, e->reg, mask, val); | 1828 | change = snd_soc_test_bits(widget->codec, e->reg, mask, val); |
1807 | dapm_mux_update_power(widget, kcontrol, change, mux, e); | ||
1808 | 1829 | ||
1809 | if (widget->event_flags & SND_SOC_DAPM_PRE_REG) { | 1830 | update.kcontrol = kcontrol; |
1810 | ret = widget->event(widget, | 1831 | update.widget = widget; |
1811 | kcontrol, SND_SOC_DAPM_PRE_REG); | 1832 | update.reg = e->reg; |
1812 | if (ret < 0) | 1833 | update.mask = mask; |
1813 | goto out; | 1834 | update.val = val; |
1814 | } | 1835 | widget->dapm->update = &update; |
1815 | 1836 | ||
1816 | ret = snd_soc_update_bits(widget->codec, e->reg, mask, val); | 1837 | dapm_mux_update_power(widget, kcontrol, change, mux, e); |
1817 | 1838 | ||
1818 | if (widget->event_flags & SND_SOC_DAPM_POST_REG) | 1839 | widget->dapm->update = NULL; |
1819 | ret = widget->event(widget, | ||
1820 | kcontrol, SND_SOC_DAPM_POST_REG); | ||
1821 | 1840 | ||
1822 | out: | ||
1823 | mutex_unlock(&widget->codec->mutex); | 1841 | mutex_unlock(&widget->codec->mutex); |
1824 | return ret; | 1842 | return change; |
1825 | } | 1843 | } |
1826 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double); | 1844 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double); |
1827 | 1845 | ||
@@ -1933,7 +1951,7 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol, | |||
1933 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | 1951 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
1934 | unsigned int val, mux, change; | 1952 | unsigned int val, mux, change; |
1935 | unsigned int mask; | 1953 | unsigned int mask; |
1936 | int ret = 0; | 1954 | struct snd_soc_dapm_update update; |
1937 | 1955 | ||
1938 | if (ucontrol->value.enumerated.item[0] > e->max - 1) | 1956 | if (ucontrol->value.enumerated.item[0] > e->max - 1) |
1939 | return -EINVAL; | 1957 | return -EINVAL; |
@@ -1950,24 +1968,20 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol, | |||
1950 | mutex_lock(&widget->codec->mutex); | 1968 | mutex_lock(&widget->codec->mutex); |
1951 | widget->value = val; | 1969 | widget->value = val; |
1952 | change = snd_soc_test_bits(widget->codec, e->reg, mask, val); | 1970 | change = snd_soc_test_bits(widget->codec, e->reg, mask, val); |
1953 | dapm_mux_update_power(widget, kcontrol, change, mux, e); | ||
1954 | 1971 | ||
1955 | if (widget->event_flags & SND_SOC_DAPM_PRE_REG) { | 1972 | update.kcontrol = kcontrol; |
1956 | ret = widget->event(widget, | 1973 | update.widget = widget; |
1957 | kcontrol, SND_SOC_DAPM_PRE_REG); | 1974 | update.reg = e->reg; |
1958 | if (ret < 0) | 1975 | update.mask = mask; |
1959 | goto out; | 1976 | update.val = val; |
1960 | } | 1977 | widget->dapm->update = &update; |
1961 | 1978 | ||
1962 | ret = snd_soc_update_bits(widget->codec, e->reg, mask, val); | 1979 | dapm_mux_update_power(widget, kcontrol, change, mux, e); |
1963 | 1980 | ||
1964 | if (widget->event_flags & SND_SOC_DAPM_POST_REG) | 1981 | widget->dapm->update = NULL; |
1965 | ret = widget->event(widget, | ||
1966 | kcontrol, SND_SOC_DAPM_POST_REG); | ||
1967 | 1982 | ||
1968 | out: | ||
1969 | mutex_unlock(&widget->codec->mutex); | 1983 | mutex_unlock(&widget->codec->mutex); |
1970 | return ret; | 1984 | return change; |
1971 | } | 1985 | } |
1972 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_value_enum_double); | 1986 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_value_enum_double); |
1973 | 1987 | ||