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.c157
1 files changed, 117 insertions, 40 deletions
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 8de6f9dec4a2..0d294ef72590 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -719,6 +719,10 @@ static int dapm_supply_check_power(struct snd_soc_dapm_widget *w)
719 719
720 /* Check if one of our outputs is connected */ 720 /* Check if one of our outputs is connected */
721 list_for_each_entry(path, &w->sinks, list_source) { 721 list_for_each_entry(path, &w->sinks, list_source) {
722 if (path->connected &&
723 !path->connected(path->source, path->sink))
724 continue;
725
722 if (path->sink && path->sink->power_check && 726 if (path->sink && path->sink->power_check &&
723 path->sink->power_check(path->sink)) { 727 path->sink->power_check(path->sink)) {
724 power = 1; 728 power = 1;
@@ -973,9 +977,19 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
973 if (!w->power_check) 977 if (!w->power_check)
974 continue; 978 continue;
975 979
976 power = w->power_check(w); 980 /* If we're suspending then pull down all the
977 if (power) 981 * power. */
978 sys_power = 1; 982 switch (event) {
983 case SND_SOC_DAPM_STREAM_SUSPEND:
984 power = 0;
985 break;
986
987 default:
988 power = w->power_check(w);
989 if (power)
990 sys_power = 1;
991 break;
992 }
979 993
980 if (w->power == power) 994 if (w->power == power)
981 continue; 995 continue;
@@ -999,8 +1013,12 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
999 case SND_SOC_DAPM_STREAM_RESUME: 1013 case SND_SOC_DAPM_STREAM_RESUME:
1000 sys_power = 1; 1014 sys_power = 1;
1001 break; 1015 break;
1016 case SND_SOC_DAPM_STREAM_SUSPEND:
1017 sys_power = 0;
1018 break;
1002 case SND_SOC_DAPM_STREAM_NOP: 1019 case SND_SOC_DAPM_STREAM_NOP:
1003 sys_power = codec->bias_level != SND_SOC_BIAS_STANDBY; 1020 sys_power = codec->bias_level != SND_SOC_BIAS_STANDBY;
1021 break;
1004 default: 1022 default:
1005 break; 1023 break;
1006 } 1024 }
@@ -1138,6 +1156,9 @@ static ssize_t dapm_widget_power_read_file(struct file *file,
1138 w->active ? "active" : "inactive"); 1156 w->active ? "active" : "inactive");
1139 1157
1140 list_for_each_entry(p, &w->sources, list_sink) { 1158 list_for_each_entry(p, &w->sources, list_sink) {
1159 if (p->connected && !p->connected(w, p->sink))
1160 continue;
1161
1141 if (p->connect) 1162 if (p->connect)
1142 ret += snprintf(buf + ret, PAGE_SIZE - ret, 1163 ret += snprintf(buf + ret, PAGE_SIZE - ret,
1143 " in %s %s\n", 1164 " in %s %s\n",
@@ -1145,6 +1166,9 @@ static ssize_t dapm_widget_power_read_file(struct file *file,
1145 p->source->name); 1166 p->source->name);
1146 } 1167 }
1147 list_for_each_entry(p, &w->sinks, list_source) { 1168 list_for_each_entry(p, &w->sinks, list_source) {
1169 if (p->connected && !p->connected(w, p->sink))
1170 continue;
1171
1148 if (p->connect) 1172 if (p->connect)
1149 ret += snprintf(buf + ret, PAGE_SIZE - ret, 1173 ret += snprintf(buf + ret, PAGE_SIZE - ret,
1150 " out %s %s\n", 1174 " out %s %s\n",
@@ -1192,8 +1216,8 @@ void snd_soc_dapm_debugfs_init(struct snd_soc_codec *codec)
1192 1216
1193/* test and update the power status of a mux widget */ 1217/* test and update the power status of a mux widget */
1194static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget, 1218static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
1195 struct snd_kcontrol *kcontrol, int mask, 1219 struct snd_kcontrol *kcontrol, int change,
1196 int mux, int val, struct soc_enum *e) 1220 int mux, struct soc_enum *e)
1197{ 1221{
1198 struct snd_soc_dapm_path *path; 1222 struct snd_soc_dapm_path *path;
1199 int found = 0; 1223 int found = 0;
@@ -1202,7 +1226,7 @@ static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
1202 widget->id != snd_soc_dapm_value_mux) 1226 widget->id != snd_soc_dapm_value_mux)
1203 return -ENODEV; 1227 return -ENODEV;
1204 1228
1205 if (!snd_soc_test_bits(widget->codec, e->reg, mask, val)) 1229 if (!change)
1206 return 0; 1230 return 0;
1207 1231
1208 /* find dapm widget path assoc with kcontrol */ 1232 /* find dapm widget path assoc with kcontrol */
@@ -1387,10 +1411,13 @@ int snd_soc_dapm_sync(struct snd_soc_codec *codec)
1387EXPORT_SYMBOL_GPL(snd_soc_dapm_sync); 1411EXPORT_SYMBOL_GPL(snd_soc_dapm_sync);
1388 1412
1389static int snd_soc_dapm_add_route(struct snd_soc_codec *codec, 1413static int snd_soc_dapm_add_route(struct snd_soc_codec *codec,
1390 const char *sink, const char *control, const char *source) 1414 const struct snd_soc_dapm_route *route)
1391{ 1415{
1392 struct snd_soc_dapm_path *path; 1416 struct snd_soc_dapm_path *path;
1393 struct snd_soc_dapm_widget *wsource = NULL, *wsink = NULL, *w; 1417 struct snd_soc_dapm_widget *wsource = NULL, *wsink = NULL, *w;
1418 const char *sink = route->sink;
1419 const char *control = route->control;
1420 const char *source = route->source;
1394 int ret = 0; 1421 int ret = 0;
1395 1422
1396 /* find src and dest widgets */ 1423 /* find src and dest widgets */
@@ -1414,6 +1441,7 @@ static int snd_soc_dapm_add_route(struct snd_soc_codec *codec,
1414 1441
1415 path->source = wsource; 1442 path->source = wsource;
1416 path->sink = wsink; 1443 path->sink = wsink;
1444 path->connected = route->connected;
1417 INIT_LIST_HEAD(&path->list); 1445 INIT_LIST_HEAD(&path->list);
1418 INIT_LIST_HEAD(&path->list_source); 1446 INIT_LIST_HEAD(&path->list_source);
1419 INIT_LIST_HEAD(&path->list_sink); 1447 INIT_LIST_HEAD(&path->list_sink);
@@ -1514,8 +1542,7 @@ int snd_soc_dapm_add_routes(struct snd_soc_codec *codec,
1514 int i, ret; 1542 int i, ret;
1515 1543
1516 for (i = 0; i < num; i++) { 1544 for (i = 0; i < num; i++) {
1517 ret = snd_soc_dapm_add_route(codec, route->sink, 1545 ret = snd_soc_dapm_add_route(codec, route);
1518 route->control, route->source);
1519 if (ret < 0) { 1546 if (ret < 0) {
1520 printk(KERN_ERR "Failed to add route %s->%s\n", 1547 printk(KERN_ERR "Failed to add route %s->%s\n",
1521 route->source, 1548 route->source,
@@ -1752,7 +1779,7 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
1752{ 1779{
1753 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); 1780 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
1754 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 1781 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1755 unsigned int val, mux; 1782 unsigned int val, mux, change;
1756 unsigned int mask, bitmask; 1783 unsigned int mask, bitmask;
1757 int ret = 0; 1784 int ret = 0;
1758 1785
@@ -1772,20 +1799,21 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
1772 1799
1773 mutex_lock(&widget->codec->mutex); 1800 mutex_lock(&widget->codec->mutex);
1774 widget->value = val; 1801 widget->value = val;
1775 dapm_mux_update_power(widget, kcontrol, mask, mux, val, e); 1802 change = snd_soc_test_bits(widget->codec, e->reg, mask, val);
1776 if (widget->event) { 1803 dapm_mux_update_power(widget, kcontrol, change, mux, e);
1777 if (widget->event_flags & SND_SOC_DAPM_PRE_REG) { 1804
1778 ret = widget->event(widget, 1805 if (widget->event_flags & SND_SOC_DAPM_PRE_REG) {
1779 kcontrol, SND_SOC_DAPM_PRE_REG); 1806 ret = widget->event(widget,
1780 if (ret < 0) 1807 kcontrol, SND_SOC_DAPM_PRE_REG);
1781 goto out; 1808 if (ret < 0)
1782 } 1809 goto out;
1783 ret = snd_soc_update_bits(widget->codec, e->reg, mask, val); 1810 }
1784 if (widget->event_flags & SND_SOC_DAPM_POST_REG) 1811
1785 ret = widget->event(widget, 1812 ret = snd_soc_update_bits(widget->codec, e->reg, mask, val);
1786 kcontrol, SND_SOC_DAPM_POST_REG); 1813
1787 } else 1814 if (widget->event_flags & SND_SOC_DAPM_POST_REG)
1788 ret = snd_soc_update_bits(widget->codec, e->reg, mask, val); 1815 ret = widget->event(widget,
1816 kcontrol, SND_SOC_DAPM_POST_REG);
1789 1817
1790out: 1818out:
1791 mutex_unlock(&widget->codec->mutex); 1819 mutex_unlock(&widget->codec->mutex);
@@ -1794,6 +1822,54 @@ out:
1794EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double); 1822EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double);
1795 1823
1796/** 1824/**
1825 * snd_soc_dapm_get_enum_virt - Get virtual DAPM mux
1826 * @kcontrol: mixer control
1827 * @ucontrol: control element information
1828 *
1829 * Returns 0 for success.
1830 */
1831int snd_soc_dapm_get_enum_virt(struct snd_kcontrol *kcontrol,
1832 struct snd_ctl_elem_value *ucontrol)
1833{
1834 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
1835
1836 ucontrol->value.enumerated.item[0] = widget->value;
1837
1838 return 0;
1839}
1840EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_virt);
1841
1842/**
1843 * snd_soc_dapm_put_enum_virt - Set virtual DAPM mux
1844 * @kcontrol: mixer control
1845 * @ucontrol: control element information
1846 *
1847 * Returns 0 for success.
1848 */
1849int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol,
1850 struct snd_ctl_elem_value *ucontrol)
1851{
1852 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
1853 struct soc_enum *e =
1854 (struct soc_enum *)kcontrol->private_value;
1855 int change;
1856 int ret = 0;
1857
1858 if (ucontrol->value.enumerated.item[0] >= e->max)
1859 return -EINVAL;
1860
1861 mutex_lock(&widget->codec->mutex);
1862
1863 change = widget->value != ucontrol->value.enumerated.item[0];
1864 widget->value = ucontrol->value.enumerated.item[0];
1865 dapm_mux_update_power(widget, kcontrol, change, widget->value, e);
1866
1867 mutex_unlock(&widget->codec->mutex);
1868 return ret;
1869}
1870EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_virt);
1871
1872/**
1797 * snd_soc_dapm_get_value_enum_double - dapm semi enumerated double mixer get 1873 * snd_soc_dapm_get_value_enum_double - dapm semi enumerated double mixer get
1798 * callback 1874 * callback
1799 * @kcontrol: mixer control 1875 * @kcontrol: mixer control
@@ -1851,7 +1927,7 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
1851{ 1927{
1852 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); 1928 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
1853 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 1929 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1854 unsigned int val, mux; 1930 unsigned int val, mux, change;
1855 unsigned int mask; 1931 unsigned int mask;
1856 int ret = 0; 1932 int ret = 0;
1857 1933
@@ -1869,20 +1945,21 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
1869 1945
1870 mutex_lock(&widget->codec->mutex); 1946 mutex_lock(&widget->codec->mutex);
1871 widget->value = val; 1947 widget->value = val;
1872 dapm_mux_update_power(widget, kcontrol, mask, mux, val, e); 1948 change = snd_soc_test_bits(widget->codec, e->reg, mask, val);
1873 if (widget->event) { 1949 dapm_mux_update_power(widget, kcontrol, change, mux, e);
1874 if (widget->event_flags & SND_SOC_DAPM_PRE_REG) { 1950
1875 ret = widget->event(widget, 1951 if (widget->event_flags & SND_SOC_DAPM_PRE_REG) {
1876 kcontrol, SND_SOC_DAPM_PRE_REG); 1952 ret = widget->event(widget,
1877 if (ret < 0) 1953 kcontrol, SND_SOC_DAPM_PRE_REG);
1878 goto out; 1954 if (ret < 0)
1879 } 1955 goto out;
1880 ret = snd_soc_update_bits(widget->codec, e->reg, mask, val); 1956 }
1881 if (widget->event_flags & SND_SOC_DAPM_POST_REG) 1957
1882 ret = widget->event(widget, 1958 ret = snd_soc_update_bits(widget->codec, e->reg, mask, val);
1883 kcontrol, SND_SOC_DAPM_POST_REG); 1959
1884 } else 1960 if (widget->event_flags & SND_SOC_DAPM_POST_REG)
1885 ret = snd_soc_update_bits(widget->codec, e->reg, mask, val); 1961 ret = widget->event(widget,
1962 kcontrol, SND_SOC_DAPM_POST_REG);
1886 1963
1887out: 1964out:
1888 mutex_unlock(&widget->codec->mutex); 1965 mutex_unlock(&widget->codec->mutex);
@@ -2072,9 +2149,9 @@ int snd_soc_dapm_stream_event(struct snd_soc_codec *codec,
2072 } 2149 }
2073 } 2150 }
2074 } 2151 }
2075 mutex_unlock(&codec->mutex);
2076 2152
2077 dapm_power_widgets(codec, event); 2153 dapm_power_widgets(codec, event);
2154 mutex_unlock(&codec->mutex);
2078 dump_dapm(codec, __func__); 2155 dump_dapm(codec, __func__);
2079 return 0; 2156 return 0;
2080} 2157}