aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sound/soc-dapm.h10
-rw-r--r--sound/soc/soc-dapm.c130
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
463struct 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 */
464struct snd_soc_dapm_context { 472struct 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
923static 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
1738out:
1739 mutex_unlock(&widget->codec->mutex); 1761 mutex_unlock(&widget->codec->mutex);
1740 return ret; 1762 return 0;
1741} 1763}
1742EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw); 1764EXPORT_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
1822out:
1823 mutex_unlock(&widget->codec->mutex); 1841 mutex_unlock(&widget->codec->mutex);
1824 return ret; 1842 return change;
1825} 1843}
1826EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double); 1844EXPORT_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
1968out:
1969 mutex_unlock(&widget->codec->mutex); 1983 mutex_unlock(&widget->codec->mutex);
1970 return ret; 1984 return change;
1971} 1985}
1972EXPORT_SYMBOL_GPL(snd_soc_dapm_put_value_enum_double); 1986EXPORT_SYMBOL_GPL(snd_soc_dapm_put_value_enum_double);
1973 1987