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.c278
1 files changed, 151 insertions, 127 deletions
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 66d4c165f99b..7c28f401f436 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -38,19 +38,13 @@
38#include <linux/platform_device.h> 38#include <linux/platform_device.h>
39#include <linux/jiffies.h> 39#include <linux/jiffies.h>
40#include <linux/debugfs.h> 40#include <linux/debugfs.h>
41#include <linux/slab.h>
41#include <sound/core.h> 42#include <sound/core.h>
42#include <sound/pcm.h> 43#include <sound/pcm.h>
43#include <sound/pcm_params.h> 44#include <sound/pcm_params.h>
44#include <sound/soc-dapm.h> 45#include <sound/soc-dapm.h>
45#include <sound/initval.h> 46#include <sound/initval.h>
46 47
47/* debug */
48#ifdef DEBUG
49#define dump_dapm(codec, action) dbg_dump_dapm(codec, action)
50#else
51#define dump_dapm(codec, action)
52#endif
53
54/* dapm power sequences - make this per codec in the future */ 48/* dapm power sequences - make this per codec in the future */
55static int dapm_up_seq[] = { 49static int dapm_up_seq[] = {
56 [snd_soc_dapm_pre] = 0, 50 [snd_soc_dapm_pre] = 0,
@@ -719,6 +713,10 @@ static int dapm_supply_check_power(struct snd_soc_dapm_widget *w)
719 713
720 /* Check if one of our outputs is connected */ 714 /* Check if one of our outputs is connected */
721 list_for_each_entry(path, &w->sinks, list_source) { 715 list_for_each_entry(path, &w->sinks, list_source) {
716 if (path->connected &&
717 !path->connected(path->source, path->sink))
718 continue;
719
722 if (path->sink && path->sink->power_check && 720 if (path->sink && path->sink->power_check &&
723 path->sink->power_check(path->sink)) { 721 path->sink->power_check(path->sink)) {
724 power = 1; 722 power = 1;
@@ -735,6 +733,8 @@ static int dapm_seq_compare(struct snd_soc_dapm_widget *a,
735 struct snd_soc_dapm_widget *b, 733 struct snd_soc_dapm_widget *b,
736 int sort[]) 734 int sort[])
737{ 735{
736 if (a->codec != b->codec)
737 return (unsigned long)a - (unsigned long)b;
738 if (sort[a->id] != sort[b->id]) 738 if (sort[a->id] != sort[b->id])
739 return sort[a->id] - sort[b->id]; 739 return sort[a->id] - sort[b->id];
740 if (a->reg != b->reg) 740 if (a->reg != b->reg)
@@ -1013,13 +1013,28 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
1013 sys_power = 0; 1013 sys_power = 0;
1014 break; 1014 break;
1015 case SND_SOC_DAPM_STREAM_NOP: 1015 case SND_SOC_DAPM_STREAM_NOP:
1016 sys_power = codec->bias_level != SND_SOC_BIAS_STANDBY; 1016 switch (codec->bias_level) {
1017 case SND_SOC_BIAS_STANDBY:
1018 case SND_SOC_BIAS_OFF:
1019 sys_power = 0;
1020 break;
1021 default:
1022 sys_power = 1;
1023 break;
1024 }
1017 break; 1025 break;
1018 default: 1026 default:
1019 break; 1027 break;
1020 } 1028 }
1021 } 1029 }
1022 1030
1031 if (sys_power && codec->bias_level == SND_SOC_BIAS_OFF) {
1032 ret = snd_soc_dapm_set_bias_level(socdev,
1033 SND_SOC_BIAS_STANDBY);
1034 if (ret != 0)
1035 pr_err("Failed to turn on bias: %d\n", ret);
1036 }
1037
1023 /* If we're changing to all on or all off then prepare */ 1038 /* If we're changing to all on or all off then prepare */
1024 if ((sys_power && codec->bias_level == SND_SOC_BIAS_STANDBY) || 1039 if ((sys_power && codec->bias_level == SND_SOC_BIAS_STANDBY) ||
1025 (!sys_power && codec->bias_level == SND_SOC_BIAS_ON)) { 1040 (!sys_power && codec->bias_level == SND_SOC_BIAS_ON)) {
@@ -1043,6 +1058,14 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
1043 pr_err("Failed to apply standby bias: %d\n", ret); 1058 pr_err("Failed to apply standby bias: %d\n", ret);
1044 } 1059 }
1045 1060
1061 /* If we're in standby and can support bias off then do that */
1062 if (codec->bias_level == SND_SOC_BIAS_STANDBY &&
1063 codec->idle_bias_off) {
1064 ret = snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_OFF);
1065 if (ret != 0)
1066 pr_err("Failed to turn off bias: %d\n", ret);
1067 }
1068
1046 /* If we just powered up then move to active bias */ 1069 /* If we just powered up then move to active bias */
1047 if (codec->bias_level == SND_SOC_BIAS_PREPARE && sys_power) { 1070 if (codec->bias_level == SND_SOC_BIAS_PREPARE && sys_power) {
1048 ret = snd_soc_dapm_set_bias_level(socdev, 1071 ret = snd_soc_dapm_set_bias_level(socdev,
@@ -1057,66 +1080,6 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
1057 return 0; 1080 return 0;
1058} 1081}
1059 1082
1060#ifdef DEBUG
1061static void dbg_dump_dapm(struct snd_soc_codec* codec, const char *action)
1062{
1063 struct snd_soc_dapm_widget *w;
1064 struct snd_soc_dapm_path *p = NULL;
1065 int in, out;
1066
1067 printk("DAPM %s %s\n", codec->name, action);
1068
1069 list_for_each_entry(w, &codec->dapm_widgets, list) {
1070
1071 /* only display widgets that effect routing */
1072 switch (w->id) {
1073 case snd_soc_dapm_pre:
1074 case snd_soc_dapm_post:
1075 case snd_soc_dapm_vmid:
1076 continue;
1077 case snd_soc_dapm_mux:
1078 case snd_soc_dapm_value_mux:
1079 case snd_soc_dapm_output:
1080 case snd_soc_dapm_input:
1081 case snd_soc_dapm_switch:
1082 case snd_soc_dapm_hp:
1083 case snd_soc_dapm_mic:
1084 case snd_soc_dapm_spk:
1085 case snd_soc_dapm_line:
1086 case snd_soc_dapm_micbias:
1087 case snd_soc_dapm_dac:
1088 case snd_soc_dapm_adc:
1089 case snd_soc_dapm_pga:
1090 case snd_soc_dapm_mixer:
1091 case snd_soc_dapm_mixer_named_ctl:
1092 case snd_soc_dapm_supply:
1093 case snd_soc_dapm_aif_in:
1094 case snd_soc_dapm_aif_out:
1095 if (w->name) {
1096 in = is_connected_input_ep(w);
1097 dapm_clear_walk(w->codec);
1098 out = is_connected_output_ep(w);
1099 dapm_clear_walk(w->codec);
1100 printk("%s: %s in %d out %d\n", w->name,
1101 w->power ? "On":"Off",in, out);
1102
1103 list_for_each_entry(p, &w->sources, list_sink) {
1104 if (p->connect)
1105 printk(" in %s %s\n", p->name ? p->name : "static",
1106 p->source->name);
1107 }
1108 list_for_each_entry(p, &w->sinks, list_source) {
1109 if (p->connect)
1110 printk(" out %s %s\n", p->name ? p->name : "static",
1111 p->sink->name);
1112 }
1113 }
1114 break;
1115 }
1116 }
1117}
1118#endif
1119
1120#ifdef CONFIG_DEBUG_FS 1083#ifdef CONFIG_DEBUG_FS
1121static int dapm_widget_power_open_file(struct inode *inode, struct file *file) 1084static int dapm_widget_power_open_file(struct inode *inode, struct file *file)
1122{ 1085{
@@ -1143,15 +1106,25 @@ static ssize_t dapm_widget_power_read_file(struct file *file,
1143 out = is_connected_output_ep(w); 1106 out = is_connected_output_ep(w);
1144 dapm_clear_walk(w->codec); 1107 dapm_clear_walk(w->codec);
1145 1108
1146 ret = snprintf(buf, PAGE_SIZE, "%s: %s in %d out %d\n", 1109 ret = snprintf(buf, PAGE_SIZE, "%s: %s in %d out %d",
1147 w->name, w->power ? "On" : "Off", in, out); 1110 w->name, w->power ? "On" : "Off", in, out);
1148 1111
1112 if (w->reg >= 0)
1113 ret += snprintf(buf + ret, PAGE_SIZE - ret,
1114 " - R%d(0x%x) bit %d",
1115 w->reg, w->reg, w->shift);
1116
1117 ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n");
1118
1149 if (w->sname) 1119 if (w->sname)
1150 ret += snprintf(buf + ret, PAGE_SIZE - ret, " stream %s %s\n", 1120 ret += snprintf(buf + ret, PAGE_SIZE - ret, " stream %s %s\n",
1151 w->sname, 1121 w->sname,
1152 w->active ? "active" : "inactive"); 1122 w->active ? "active" : "inactive");
1153 1123
1154 list_for_each_entry(p, &w->sources, list_sink) { 1124 list_for_each_entry(p, &w->sources, list_sink) {
1125 if (p->connected && !p->connected(w, p->sink))
1126 continue;
1127
1155 if (p->connect) 1128 if (p->connect)
1156 ret += snprintf(buf + ret, PAGE_SIZE - ret, 1129 ret += snprintf(buf + ret, PAGE_SIZE - ret,
1157 " in %s %s\n", 1130 " in %s %s\n",
@@ -1159,6 +1132,9 @@ static ssize_t dapm_widget_power_read_file(struct file *file,
1159 p->source->name); 1132 p->source->name);
1160 } 1133 }
1161 list_for_each_entry(p, &w->sinks, list_source) { 1134 list_for_each_entry(p, &w->sinks, list_source) {
1135 if (p->connected && !p->connected(w, p->sink))
1136 continue;
1137
1162 if (p->connect) 1138 if (p->connect)
1163 ret += snprintf(buf + ret, PAGE_SIZE - ret, 1139 ret += snprintf(buf + ret, PAGE_SIZE - ret,
1164 " out %s %s\n", 1140 " out %s %s\n",
@@ -1206,8 +1182,8 @@ void snd_soc_dapm_debugfs_init(struct snd_soc_codec *codec)
1206 1182
1207/* test and update the power status of a mux widget */ 1183/* test and update the power status of a mux widget */
1208static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget, 1184static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
1209 struct snd_kcontrol *kcontrol, int mask, 1185 struct snd_kcontrol *kcontrol, int change,
1210 int mux, int val, struct soc_enum *e) 1186 int mux, struct soc_enum *e)
1211{ 1187{
1212 struct snd_soc_dapm_path *path; 1188 struct snd_soc_dapm_path *path;
1213 int found = 0; 1189 int found = 0;
@@ -1216,7 +1192,7 @@ static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
1216 widget->id != snd_soc_dapm_value_mux) 1192 widget->id != snd_soc_dapm_value_mux)
1217 return -ENODEV; 1193 return -ENODEV;
1218 1194
1219 if (!snd_soc_test_bits(widget->codec, e->reg, mask, val)) 1195 if (!change)
1220 return 0; 1196 return 0;
1221 1197
1222 /* find dapm widget path assoc with kcontrol */ 1198 /* find dapm widget path assoc with kcontrol */
@@ -1235,18 +1211,15 @@ static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
1235 path->connect = 0; /* old connection must be powered down */ 1211 path->connect = 0; /* old connection must be powered down */
1236 } 1212 }
1237 1213
1238 if (found) { 1214 if (found)
1239 dapm_power_widgets(widget->codec, SND_SOC_DAPM_STREAM_NOP); 1215 dapm_power_widgets(widget->codec, SND_SOC_DAPM_STREAM_NOP);
1240 dump_dapm(widget->codec, "mux power update");
1241 }
1242 1216
1243 return 0; 1217 return 0;
1244} 1218}
1245 1219
1246/* test and update the power status of a mixer or switch widget */ 1220/* test and update the power status of a mixer or switch widget */
1247static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget, 1221static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
1248 struct snd_kcontrol *kcontrol, int reg, 1222 struct snd_kcontrol *kcontrol, int connect)
1249 int val_mask, int val, int invert)
1250{ 1223{
1251 struct snd_soc_dapm_path *path; 1224 struct snd_soc_dapm_path *path;
1252 int found = 0; 1225 int found = 0;
@@ -1256,9 +1229,6 @@ static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
1256 widget->id != snd_soc_dapm_switch) 1229 widget->id != snd_soc_dapm_switch)
1257 return -ENODEV; 1230 return -ENODEV;
1258 1231
1259 if (!snd_soc_test_bits(widget->codec, reg, val_mask, val))
1260 return 0;
1261
1262 /* find dapm widget path assoc with kcontrol */ 1232 /* find dapm widget path assoc with kcontrol */
1263 list_for_each_entry(path, &widget->codec->dapm_paths, list) { 1233 list_for_each_entry(path, &widget->codec->dapm_paths, list) {
1264 if (path->kcontrol != kcontrol) 1234 if (path->kcontrol != kcontrol)
@@ -1266,19 +1236,12 @@ static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
1266 1236
1267 /* found, now check type */ 1237 /* found, now check type */
1268 found = 1; 1238 found = 1;
1269 if (val) 1239 path->connect = connect;
1270 /* new connection */
1271 path->connect = invert ? 0:1;
1272 else
1273 /* old connection must be powered down */
1274 path->connect = invert ? 1:0;
1275 break; 1240 break;
1276 } 1241 }
1277 1242
1278 if (found) { 1243 if (found)
1279 dapm_power_widgets(widget->codec, SND_SOC_DAPM_STREAM_NOP); 1244 dapm_power_widgets(widget->codec, SND_SOC_DAPM_STREAM_NOP);
1280 dump_dapm(widget->codec, "mixer power update");
1281 }
1282 1245
1283 return 0; 1246 return 0;
1284} 1247}
@@ -1394,17 +1357,18 @@ static int snd_soc_dapm_set_pin(struct snd_soc_codec *codec,
1394 */ 1357 */
1395int snd_soc_dapm_sync(struct snd_soc_codec *codec) 1358int snd_soc_dapm_sync(struct snd_soc_codec *codec)
1396{ 1359{
1397 int ret = dapm_power_widgets(codec, SND_SOC_DAPM_STREAM_NOP); 1360 return dapm_power_widgets(codec, SND_SOC_DAPM_STREAM_NOP);
1398 dump_dapm(codec, "sync");
1399 return ret;
1400} 1361}
1401EXPORT_SYMBOL_GPL(snd_soc_dapm_sync); 1362EXPORT_SYMBOL_GPL(snd_soc_dapm_sync);
1402 1363
1403static int snd_soc_dapm_add_route(struct snd_soc_codec *codec, 1364static int snd_soc_dapm_add_route(struct snd_soc_codec *codec,
1404 const char *sink, const char *control, const char *source) 1365 const struct snd_soc_dapm_route *route)
1405{ 1366{
1406 struct snd_soc_dapm_path *path; 1367 struct snd_soc_dapm_path *path;
1407 struct snd_soc_dapm_widget *wsource = NULL, *wsink = NULL, *w; 1368 struct snd_soc_dapm_widget *wsource = NULL, *wsink = NULL, *w;
1369 const char *sink = route->sink;
1370 const char *control = route->control;
1371 const char *source = route->source;
1408 int ret = 0; 1372 int ret = 0;
1409 1373
1410 /* find src and dest widgets */ 1374 /* find src and dest widgets */
@@ -1428,6 +1392,7 @@ static int snd_soc_dapm_add_route(struct snd_soc_codec *codec,
1428 1392
1429 path->source = wsource; 1393 path->source = wsource;
1430 path->sink = wsink; 1394 path->sink = wsink;
1395 path->connected = route->connected;
1431 INIT_LIST_HEAD(&path->list); 1396 INIT_LIST_HEAD(&path->list);
1432 INIT_LIST_HEAD(&path->list_source); 1397 INIT_LIST_HEAD(&path->list_source);
1433 INIT_LIST_HEAD(&path->list_sink); 1398 INIT_LIST_HEAD(&path->list_sink);
@@ -1528,8 +1493,7 @@ int snd_soc_dapm_add_routes(struct snd_soc_codec *codec,
1528 int i, ret; 1493 int i, ret;
1529 1494
1530 for (i = 0; i < num; i++) { 1495 for (i = 0; i < num; i++) {
1531 ret = snd_soc_dapm_add_route(codec, route->sink, 1496 ret = snd_soc_dapm_add_route(codec, route);
1532 route->control, route->source);
1533 if (ret < 0) { 1497 if (ret < 0) {
1534 printk(KERN_ERR "Failed to add route %s->%s\n", 1498 printk(KERN_ERR "Failed to add route %s->%s\n",
1535 route->source, 1499 route->source,
@@ -1675,6 +1639,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
1675 unsigned int mask = (1 << fls(max)) - 1; 1639 unsigned int mask = (1 << fls(max)) - 1;
1676 unsigned int invert = mc->invert; 1640 unsigned int invert = mc->invert;
1677 unsigned int val, val2, val_mask; 1641 unsigned int val, val2, val_mask;
1642 int connect;
1678 int ret; 1643 int ret;
1679 1644
1680 val = (ucontrol->value.integer.value[0] & mask); 1645 val = (ucontrol->value.integer.value[0] & mask);
@@ -1701,7 +1666,17 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
1701 return 1; 1666 return 1;
1702 } 1667 }
1703 1668
1704 dapm_mixer_update_power(widget, kcontrol, reg, val_mask, val, invert); 1669 if (snd_soc_test_bits(widget->codec, reg, val_mask, val)) {
1670 if (val)
1671 /* new connection */
1672 connect = invert ? 0:1;
1673 else
1674 /* old connection must be powered down */
1675 connect = invert ? 1:0;
1676
1677 dapm_mixer_update_power(widget, kcontrol, connect);
1678 }
1679
1705 if (widget->event) { 1680 if (widget->event) {
1706 if (widget->event_flags & SND_SOC_DAPM_PRE_REG) { 1681 if (widget->event_flags & SND_SOC_DAPM_PRE_REG) {
1707 ret = widget->event(widget, kcontrol, 1682 ret = widget->event(widget, kcontrol,
@@ -1766,7 +1741,7 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
1766{ 1741{
1767 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); 1742 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
1768 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 1743 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1769 unsigned int val, mux; 1744 unsigned int val, mux, change;
1770 unsigned int mask, bitmask; 1745 unsigned int mask, bitmask;
1771 int ret = 0; 1746 int ret = 0;
1772 1747
@@ -1786,20 +1761,21 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
1786 1761
1787 mutex_lock(&widget->codec->mutex); 1762 mutex_lock(&widget->codec->mutex);
1788 widget->value = val; 1763 widget->value = val;
1789 dapm_mux_update_power(widget, kcontrol, mask, mux, val, e); 1764 change = snd_soc_test_bits(widget->codec, e->reg, mask, val);
1790 if (widget->event) { 1765 dapm_mux_update_power(widget, kcontrol, change, mux, e);
1791 if (widget->event_flags & SND_SOC_DAPM_PRE_REG) { 1766
1792 ret = widget->event(widget, 1767 if (widget->event_flags & SND_SOC_DAPM_PRE_REG) {
1793 kcontrol, SND_SOC_DAPM_PRE_REG); 1768 ret = widget->event(widget,
1794 if (ret < 0) 1769 kcontrol, SND_SOC_DAPM_PRE_REG);
1795 goto out; 1770 if (ret < 0)
1796 } 1771 goto out;
1797 ret = snd_soc_update_bits(widget->codec, e->reg, mask, val); 1772 }
1798 if (widget->event_flags & SND_SOC_DAPM_POST_REG) 1773
1799 ret = widget->event(widget, 1774 ret = snd_soc_update_bits(widget->codec, e->reg, mask, val);
1800 kcontrol, SND_SOC_DAPM_POST_REG); 1775
1801 } else 1776 if (widget->event_flags & SND_SOC_DAPM_POST_REG)
1802 ret = snd_soc_update_bits(widget->codec, e->reg, mask, val); 1777 ret = widget->event(widget,
1778 kcontrol, SND_SOC_DAPM_POST_REG);
1803 1779
1804out: 1780out:
1805 mutex_unlock(&widget->codec->mutex); 1781 mutex_unlock(&widget->codec->mutex);
@@ -1808,6 +1784,54 @@ out:
1808EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double); 1784EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double);
1809 1785
1810/** 1786/**
1787 * snd_soc_dapm_get_enum_virt - Get virtual DAPM mux
1788 * @kcontrol: mixer control
1789 * @ucontrol: control element information
1790 *
1791 * Returns 0 for success.
1792 */
1793int snd_soc_dapm_get_enum_virt(struct snd_kcontrol *kcontrol,
1794 struct snd_ctl_elem_value *ucontrol)
1795{
1796 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
1797
1798 ucontrol->value.enumerated.item[0] = widget->value;
1799
1800 return 0;
1801}
1802EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_virt);
1803
1804/**
1805 * snd_soc_dapm_put_enum_virt - Set virtual DAPM mux
1806 * @kcontrol: mixer control
1807 * @ucontrol: control element information
1808 *
1809 * Returns 0 for success.
1810 */
1811int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol,
1812 struct snd_ctl_elem_value *ucontrol)
1813{
1814 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
1815 struct soc_enum *e =
1816 (struct soc_enum *)kcontrol->private_value;
1817 int change;
1818 int ret = 0;
1819
1820 if (ucontrol->value.enumerated.item[0] >= e->max)
1821 return -EINVAL;
1822
1823 mutex_lock(&widget->codec->mutex);
1824
1825 change = widget->value != ucontrol->value.enumerated.item[0];
1826 widget->value = ucontrol->value.enumerated.item[0];
1827 dapm_mux_update_power(widget, kcontrol, change, widget->value, e);
1828
1829 mutex_unlock(&widget->codec->mutex);
1830 return ret;
1831}
1832EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_virt);
1833
1834/**
1811 * snd_soc_dapm_get_value_enum_double - dapm semi enumerated double mixer get 1835 * snd_soc_dapm_get_value_enum_double - dapm semi enumerated double mixer get
1812 * callback 1836 * callback
1813 * @kcontrol: mixer control 1837 * @kcontrol: mixer control
@@ -1865,7 +1889,7 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
1865{ 1889{
1866 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); 1890 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
1867 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 1891 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1868 unsigned int val, mux; 1892 unsigned int val, mux, change;
1869 unsigned int mask; 1893 unsigned int mask;
1870 int ret = 0; 1894 int ret = 0;
1871 1895
@@ -1883,20 +1907,21 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
1883 1907
1884 mutex_lock(&widget->codec->mutex); 1908 mutex_lock(&widget->codec->mutex);
1885 widget->value = val; 1909 widget->value = val;
1886 dapm_mux_update_power(widget, kcontrol, mask, mux, val, e); 1910 change = snd_soc_test_bits(widget->codec, e->reg, mask, val);
1887 if (widget->event) { 1911 dapm_mux_update_power(widget, kcontrol, change, mux, e);
1888 if (widget->event_flags & SND_SOC_DAPM_PRE_REG) { 1912
1889 ret = widget->event(widget, 1913 if (widget->event_flags & SND_SOC_DAPM_PRE_REG) {
1890 kcontrol, SND_SOC_DAPM_PRE_REG); 1914 ret = widget->event(widget,
1891 if (ret < 0) 1915 kcontrol, SND_SOC_DAPM_PRE_REG);
1892 goto out; 1916 if (ret < 0)
1893 } 1917 goto out;
1894 ret = snd_soc_update_bits(widget->codec, e->reg, mask, val); 1918 }
1895 if (widget->event_flags & SND_SOC_DAPM_POST_REG) 1919
1896 ret = widget->event(widget, 1920 ret = snd_soc_update_bits(widget->codec, e->reg, mask, val);
1897 kcontrol, SND_SOC_DAPM_POST_REG); 1921
1898 } else 1922 if (widget->event_flags & SND_SOC_DAPM_POST_REG)
1899 ret = snd_soc_update_bits(widget->codec, e->reg, mask, val); 1923 ret = widget->event(widget,
1924 kcontrol, SND_SOC_DAPM_POST_REG);
1900 1925
1901out: 1926out:
1902 mutex_unlock(&widget->codec->mutex); 1927 mutex_unlock(&widget->codec->mutex);
@@ -2089,7 +2114,6 @@ int snd_soc_dapm_stream_event(struct snd_soc_codec *codec,
2089 2114
2090 dapm_power_widgets(codec, event); 2115 dapm_power_widgets(codec, event);
2091 mutex_unlock(&codec->mutex); 2116 mutex_unlock(&codec->mutex);
2092 dump_dapm(codec, __func__);
2093 return 0; 2117 return 0;
2094} 2118}
2095EXPORT_SYMBOL_GPL(snd_soc_dapm_stream_event); 2119EXPORT_SYMBOL_GPL(snd_soc_dapm_stream_event);