aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sound/soc-dapm.h199
-rw-r--r--include/sound/soc-dpcm.h2
-rw-r--r--include/sound/soc.h29
-rw-r--r--sound/soc/codecs/tlv320aic3x.c52
-rw-r--r--sound/soc/codecs/twl6040.c4
-rw-r--r--sound/soc/codecs/wm8903.c4
-rw-r--r--sound/soc/codecs/wm8994.c4
-rw-r--r--sound/soc/codecs/wm8995.c5
-rw-r--r--sound/soc/codecs/wm_hubs.c8
-rw-r--r--sound/soc/soc-dapm.c804
-rw-r--r--sound/soc/soc-pcm.c10
11 files changed, 628 insertions, 493 deletions
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h
index 3e479f4e15f5..c728d28ae9a5 100644
--- a/include/sound/soc-dapm.h
+++ b/include/sound/soc-dapm.h
@@ -70,121 +70,144 @@ struct device;
70 .num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \ 70 .num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \
71 .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD} 71 .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD}
72 72
73#define SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert) \
74 .reg = wreg, .mask = 1, .shift = wshift, \
75 .on_val = winvert ? 0 : 1, .off_val = winvert ? 1 : 0
76
73/* path domain */ 77/* path domain */
74#define SND_SOC_DAPM_PGA(wname, wreg, wshift, winvert,\ 78#define SND_SOC_DAPM_PGA(wname, wreg, wshift, winvert,\
75 wcontrols, wncontrols) \ 79 wcontrols, wncontrols) \
76{ .id = snd_soc_dapm_pga, .name = wname, .reg = wreg, .shift = wshift, \ 80{ .id = snd_soc_dapm_pga, .name = wname, \
77 .invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = wncontrols} 81 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
82 .kcontrol_news = wcontrols, .num_kcontrols = wncontrols}
78#define SND_SOC_DAPM_OUT_DRV(wname, wreg, wshift, winvert,\ 83#define SND_SOC_DAPM_OUT_DRV(wname, wreg, wshift, winvert,\
79 wcontrols, wncontrols) \ 84 wcontrols, wncontrols) \
80{ .id = snd_soc_dapm_out_drv, .name = wname, .reg = wreg, .shift = wshift, \ 85{ .id = snd_soc_dapm_out_drv, .name = wname, \
81 .invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = wncontrols} 86 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
87 .kcontrol_news = wcontrols, .num_kcontrols = wncontrols}
82#define SND_SOC_DAPM_MIXER(wname, wreg, wshift, winvert, \ 88#define SND_SOC_DAPM_MIXER(wname, wreg, wshift, winvert, \
83 wcontrols, wncontrols)\ 89 wcontrols, wncontrols)\
84{ .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \ 90{ .id = snd_soc_dapm_mixer, .name = wname, \
85 .invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = wncontrols} 91 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
92 .kcontrol_news = wcontrols, .num_kcontrols = wncontrols}
86#define SND_SOC_DAPM_MIXER_NAMED_CTL(wname, wreg, wshift, winvert, \ 93#define SND_SOC_DAPM_MIXER_NAMED_CTL(wname, wreg, wshift, winvert, \
87 wcontrols, wncontrols)\ 94 wcontrols, wncontrols)\
88{ .id = snd_soc_dapm_mixer_named_ctl, .name = wname, .reg = wreg, \ 95{ .id = snd_soc_dapm_mixer_named_ctl, .name = wname, \
89 .shift = wshift, .invert = winvert, .kcontrol_news = wcontrols, \ 96 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
90 .num_kcontrols = wncontrols} 97 .kcontrol_news = wcontrols, .num_kcontrols = wncontrols}
91#define SND_SOC_DAPM_MICBIAS(wname, wreg, wshift, winvert) \ 98#define SND_SOC_DAPM_MICBIAS(wname, wreg, wshift, winvert) \
92{ .id = snd_soc_dapm_micbias, .name = wname, .reg = wreg, .shift = wshift, \ 99{ .id = snd_soc_dapm_micbias, .name = wname, \
93 .invert = winvert, .kcontrol_news = NULL, .num_kcontrols = 0} 100 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
101 .kcontrol_news = NULL, .num_kcontrols = 0}
94#define SND_SOC_DAPM_SWITCH(wname, wreg, wshift, winvert, wcontrols) \ 102#define SND_SOC_DAPM_SWITCH(wname, wreg, wshift, winvert, wcontrols) \
95{ .id = snd_soc_dapm_switch, .name = wname, .reg = wreg, .shift = wshift, \ 103{ .id = snd_soc_dapm_switch, .name = wname, \
96 .invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = 1} 104 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
105 .kcontrol_news = wcontrols, .num_kcontrols = 1}
97#define SND_SOC_DAPM_MUX(wname, wreg, wshift, winvert, wcontrols) \ 106#define SND_SOC_DAPM_MUX(wname, wreg, wshift, winvert, wcontrols) \
98{ .id = snd_soc_dapm_mux, .name = wname, .reg = wreg, .shift = wshift, \ 107{ .id = snd_soc_dapm_mux, .name = wname, .reg = wreg, \
99 .invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = 1} 108 .kcontrol_news = wcontrols, .num_kcontrols = 1}
100#define SND_SOC_DAPM_VIRT_MUX(wname, wreg, wshift, winvert, wcontrols) \ 109#define SND_SOC_DAPM_VIRT_MUX(wname, wreg, wshift, winvert, wcontrols) \
101{ .id = snd_soc_dapm_virt_mux, .name = wname, .reg = wreg, .shift = wshift, \ 110{ .id = snd_soc_dapm_virt_mux, .name = wname, \
102 .invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = 1} 111 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
112 .kcontrol_news = wcontrols, .num_kcontrols = 1}
103#define SND_SOC_DAPM_VALUE_MUX(wname, wreg, wshift, winvert, wcontrols) \ 113#define SND_SOC_DAPM_VALUE_MUX(wname, wreg, wshift, winvert, wcontrols) \
104{ .id = snd_soc_dapm_value_mux, .name = wname, .reg = wreg, \ 114{ .id = snd_soc_dapm_value_mux, .name = wname, \
105 .shift = wshift, .invert = winvert, .kcontrol_news = wcontrols, \ 115 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
106 .num_kcontrols = 1} 116 .kcontrol_news = wcontrols, .num_kcontrols = 1}
107 117
108/* Simplified versions of above macros, assuming wncontrols = ARRAY_SIZE(wcontrols) */ 118/* Simplified versions of above macros, assuming wncontrols = ARRAY_SIZE(wcontrols) */
109#define SOC_PGA_ARRAY(wname, wreg, wshift, winvert,\ 119#define SOC_PGA_ARRAY(wname, wreg, wshift, winvert,\
110 wcontrols) \ 120 wcontrols) \
111{ .id = snd_soc_dapm_pga, .name = wname, .reg = wreg, .shift = wshift, \ 121{ .id = snd_soc_dapm_pga, .name = wname, \
112 .invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols)} 122 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
123 .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols)}
113#define SOC_MIXER_ARRAY(wname, wreg, wshift, winvert, \ 124#define SOC_MIXER_ARRAY(wname, wreg, wshift, winvert, \
114 wcontrols)\ 125 wcontrols)\
115{ .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \ 126{ .id = snd_soc_dapm_mixer, .name = wname, \
116 .invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols)} 127 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
128 .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols)}
117#define SOC_MIXER_NAMED_CTL_ARRAY(wname, wreg, wshift, winvert, \ 129#define SOC_MIXER_NAMED_CTL_ARRAY(wname, wreg, wshift, winvert, \
118 wcontrols)\ 130 wcontrols)\
119{ .id = snd_soc_dapm_mixer_named_ctl, .name = wname, .reg = wreg, \ 131{ .id = snd_soc_dapm_mixer_named_ctl, .name = wname, \
120 .shift = wshift, .invert = winvert, .kcontrol_news = wcontrols, \ 132 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
121 .num_kcontrols = ARRAY_SIZE(wcontrols)} 133 .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols)}
122 134
123/* path domain with event - event handler must return 0 for success */ 135/* path domain with event - event handler must return 0 for success */
124#define SND_SOC_DAPM_PGA_E(wname, wreg, wshift, winvert, wcontrols, \ 136#define SND_SOC_DAPM_PGA_E(wname, wreg, wshift, winvert, wcontrols, \
125 wncontrols, wevent, wflags) \ 137 wncontrols, wevent, wflags) \
126{ .id = snd_soc_dapm_pga, .name = wname, .reg = wreg, .shift = wshift, \ 138{ .id = snd_soc_dapm_pga, .name = wname, \
127 .invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = wncontrols, \ 139 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
140 .kcontrol_news = wcontrols, .num_kcontrols = wncontrols, \
128 .event = wevent, .event_flags = wflags} 141 .event = wevent, .event_flags = wflags}
129#define SND_SOC_DAPM_OUT_DRV_E(wname, wreg, wshift, winvert, wcontrols, \ 142#define SND_SOC_DAPM_OUT_DRV_E(wname, wreg, wshift, winvert, wcontrols, \
130 wncontrols, wevent, wflags) \ 143 wncontrols, wevent, wflags) \
131{ .id = snd_soc_dapm_out_drv, .name = wname, .reg = wreg, .shift = wshift, \ 144{ .id = snd_soc_dapm_out_drv, .name = wname, \
132 .invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = wncontrols, \ 145 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
146 .kcontrol_news = wcontrols, .num_kcontrols = wncontrols, \
133 .event = wevent, .event_flags = wflags} 147 .event = wevent, .event_flags = wflags}
134#define SND_SOC_DAPM_MIXER_E(wname, wreg, wshift, winvert, wcontrols, \ 148#define SND_SOC_DAPM_MIXER_E(wname, wreg, wshift, winvert, wcontrols, \
135 wncontrols, wevent, wflags) \ 149 wncontrols, wevent, wflags) \
136{ .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \ 150{ .id = snd_soc_dapm_mixer, .name = wname, \
137 .invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = wncontrols, \ 151 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
152 .kcontrol_news = wcontrols, .num_kcontrols = wncontrols, \
138 .event = wevent, .event_flags = wflags} 153 .event = wevent, .event_flags = wflags}
139#define SND_SOC_DAPM_MIXER_NAMED_CTL_E(wname, wreg, wshift, winvert, \ 154#define SND_SOC_DAPM_MIXER_NAMED_CTL_E(wname, wreg, wshift, winvert, \
140 wcontrols, wncontrols, wevent, wflags) \ 155 wcontrols, wncontrols, wevent, wflags) \
141{ .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \ 156{ .id = snd_soc_dapm_mixer, .name = wname, \
142 .invert = winvert, .kcontrol_news = wcontrols, \ 157 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
158 .kcontrol_news = wcontrols, \
143 .num_kcontrols = wncontrols, .event = wevent, .event_flags = wflags} 159 .num_kcontrols = wncontrols, .event = wevent, .event_flags = wflags}
144#define SND_SOC_DAPM_SWITCH_E(wname, wreg, wshift, winvert, wcontrols, \ 160#define SND_SOC_DAPM_SWITCH_E(wname, wreg, wshift, winvert, wcontrols, \
145 wevent, wflags) \ 161 wevent, wflags) \
146{ .id = snd_soc_dapm_switch, .name = wname, .reg = wreg, .shift = wshift, \ 162{ .id = snd_soc_dapm_switch, .name = wname, \
147 .invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = 1, \ 163 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
164 .kcontrol_news = wcontrols, .num_kcontrols = 1, \
148 .event = wevent, .event_flags = wflags} 165 .event = wevent, .event_flags = wflags}
149#define SND_SOC_DAPM_MUX_E(wname, wreg, wshift, winvert, wcontrols, \ 166#define SND_SOC_DAPM_MUX_E(wname, wreg, wshift, winvert, wcontrols, \
150 wevent, wflags) \ 167 wevent, wflags) \
151{ .id = snd_soc_dapm_mux, .name = wname, .reg = wreg, .shift = wshift, \ 168{ .id = snd_soc_dapm_mux, .name = wname, \
152 .invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = 1, \ 169 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
170 .kcontrol_news = wcontrols, .num_kcontrols = 1, \
153 .event = wevent, .event_flags = wflags} 171 .event = wevent, .event_flags = wflags}
154#define SND_SOC_DAPM_VIRT_MUX_E(wname, wreg, wshift, winvert, wcontrols, \ 172#define SND_SOC_DAPM_VIRT_MUX_E(wname, wreg, wshift, winvert, wcontrols, \
155 wevent, wflags) \ 173 wevent, wflags) \
156{ .id = snd_soc_dapm_virt_mux, .name = wname, .reg = wreg, .shift = wshift, \ 174{ .id = snd_soc_dapm_virt_mux, .name = wname, \
157 .invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = 1, \ 175 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
176 .kcontrol_news = wcontrols, .num_kcontrols = 1, \
158 .event = wevent, .event_flags = wflags} 177 .event = wevent, .event_flags = wflags}
159 178
160/* additional sequencing control within an event type */ 179/* additional sequencing control within an event type */
161#define SND_SOC_DAPM_PGA_S(wname, wsubseq, wreg, wshift, winvert, \ 180#define SND_SOC_DAPM_PGA_S(wname, wsubseq, wreg, wshift, winvert, \
162 wevent, wflags) \ 181 wevent, wflags) \
163{ .id = snd_soc_dapm_pga, .name = wname, .reg = wreg, .shift = wshift, \ 182{ .id = snd_soc_dapm_pga, .name = wname, \
164 .invert = winvert, .event = wevent, .event_flags = wflags, \ 183 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
184 .event = wevent, .event_flags = wflags, \
165 .subseq = wsubseq} 185 .subseq = wsubseq}
166#define SND_SOC_DAPM_SUPPLY_S(wname, wsubseq, wreg, wshift, winvert, wevent, \ 186#define SND_SOC_DAPM_SUPPLY_S(wname, wsubseq, wreg, wshift, winvert, wevent, \
167 wflags) \ 187 wflags) \
168{ .id = snd_soc_dapm_supply, .name = wname, .reg = wreg, \ 188{ .id = snd_soc_dapm_supply, .name = wname, \
169 .shift = wshift, .invert = winvert, .event = wevent, \ 189 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
170 .event_flags = wflags, .subseq = wsubseq} 190 .event = wevent, .event_flags = wflags, .subseq = wsubseq}
171 191
172/* Simplified versions of above macros, assuming wncontrols = ARRAY_SIZE(wcontrols) */ 192/* Simplified versions of above macros, assuming wncontrols = ARRAY_SIZE(wcontrols) */
173#define SOC_PGA_E_ARRAY(wname, wreg, wshift, winvert, wcontrols, \ 193#define SOC_PGA_E_ARRAY(wname, wreg, wshift, winvert, wcontrols, \
174 wevent, wflags) \ 194 wevent, wflags) \
175{ .id = snd_soc_dapm_pga, .name = wname, .reg = wreg, .shift = wshift, \ 195{ .id = snd_soc_dapm_pga, .name = wname, \
176 .invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols), \ 196 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
197 .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols), \
177 .event = wevent, .event_flags = wflags} 198 .event = wevent, .event_flags = wflags}
178#define SOC_MIXER_E_ARRAY(wname, wreg, wshift, winvert, wcontrols, \ 199#define SOC_MIXER_E_ARRAY(wname, wreg, wshift, winvert, wcontrols, \
179 wevent, wflags) \ 200 wevent, wflags) \
180{ .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \ 201{ .id = snd_soc_dapm_mixer, .name = wname, \
181 .invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols), \ 202 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
203 .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols), \
182 .event = wevent, .event_flags = wflags} 204 .event = wevent, .event_flags = wflags}
183#define SOC_MIXER_NAMED_CTL_E_ARRAY(wname, wreg, wshift, winvert, \ 205#define SOC_MIXER_NAMED_CTL_E_ARRAY(wname, wreg, wshift, winvert, \
184 wcontrols, wevent, wflags) \ 206 wcontrols, wevent, wflags) \
185{ .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \ 207{ .id = snd_soc_dapm_mixer, .name = wname, \
186 .invert = winvert, .kcontrol_news = wcontrols, \ 208 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
187 .num_kcontrols = ARRAY_SIZE(wcontrols), .event = wevent, .event_flags = wflags} 209 .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols), \
210 .event = wevent, .event_flags = wflags}
188 211
189/* events that are pre and post DAPM */ 212/* events that are pre and post DAPM */
190#define SND_SOC_DAPM_PRE(wname, wevent) \ 213#define SND_SOC_DAPM_PRE(wname, wevent) \
@@ -199,35 +222,36 @@ struct device;
199/* stream domain */ 222/* stream domain */
200#define SND_SOC_DAPM_AIF_IN(wname, stname, wslot, wreg, wshift, winvert) \ 223#define SND_SOC_DAPM_AIF_IN(wname, stname, wslot, wreg, wshift, winvert) \
201{ .id = snd_soc_dapm_aif_in, .name = wname, .sname = stname, \ 224{ .id = snd_soc_dapm_aif_in, .name = wname, .sname = stname, \
202 .reg = wreg, .shift = wshift, .invert = winvert } 225 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), }
203#define SND_SOC_DAPM_AIF_IN_E(wname, stname, wslot, wreg, wshift, winvert, \ 226#define SND_SOC_DAPM_AIF_IN_E(wname, stname, wslot, wreg, wshift, winvert, \
204 wevent, wflags) \ 227 wevent, wflags) \
205{ .id = snd_soc_dapm_aif_in, .name = wname, .sname = stname, \ 228{ .id = snd_soc_dapm_aif_in, .name = wname, .sname = stname, \
206 .reg = wreg, .shift = wshift, .invert = winvert, \ 229 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
207 .event = wevent, .event_flags = wflags } 230 .event = wevent, .event_flags = wflags }
208#define SND_SOC_DAPM_AIF_OUT(wname, stname, wslot, wreg, wshift, winvert) \ 231#define SND_SOC_DAPM_AIF_OUT(wname, stname, wslot, wreg, wshift, winvert) \
209{ .id = snd_soc_dapm_aif_out, .name = wname, .sname = stname, \ 232{ .id = snd_soc_dapm_aif_out, .name = wname, .sname = stname, \
210 .reg = wreg, .shift = wshift, .invert = winvert } 233 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), }
211#define SND_SOC_DAPM_AIF_OUT_E(wname, stname, wslot, wreg, wshift, winvert, \ 234#define SND_SOC_DAPM_AIF_OUT_E(wname, stname, wslot, wreg, wshift, winvert, \
212 wevent, wflags) \ 235 wevent, wflags) \
213{ .id = snd_soc_dapm_aif_out, .name = wname, .sname = stname, \ 236{ .id = snd_soc_dapm_aif_out, .name = wname, .sname = stname, \
214 .reg = wreg, .shift = wshift, .invert = winvert, \ 237 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
215 .event = wevent, .event_flags = wflags } 238 .event = wevent, .event_flags = wflags }
216#define SND_SOC_DAPM_DAC(wname, stname, wreg, wshift, winvert) \ 239#define SND_SOC_DAPM_DAC(wname, stname, wreg, wshift, winvert) \
217{ .id = snd_soc_dapm_dac, .name = wname, .sname = stname, .reg = wreg, \ 240{ .id = snd_soc_dapm_dac, .name = wname, .sname = stname, \
218 .shift = wshift, .invert = winvert} 241 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert) }
219#define SND_SOC_DAPM_DAC_E(wname, stname, wreg, wshift, winvert, \ 242#define SND_SOC_DAPM_DAC_E(wname, stname, wreg, wshift, winvert, \
220 wevent, wflags) \ 243 wevent, wflags) \
221{ .id = snd_soc_dapm_dac, .name = wname, .sname = stname, .reg = wreg, \ 244{ .id = snd_soc_dapm_dac, .name = wname, .sname = stname, \
222 .shift = wshift, .invert = winvert, \ 245 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
223 .event = wevent, .event_flags = wflags} 246 .event = wevent, .event_flags = wflags}
247
224#define SND_SOC_DAPM_ADC(wname, stname, wreg, wshift, winvert) \ 248#define SND_SOC_DAPM_ADC(wname, stname, wreg, wshift, winvert) \
225{ .id = snd_soc_dapm_adc, .name = wname, .sname = stname, .reg = wreg, \ 249{ .id = snd_soc_dapm_adc, .name = wname, .sname = stname, \
226 .shift = wshift, .invert = winvert} 250 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), }
227#define SND_SOC_DAPM_ADC_E(wname, stname, wreg, wshift, winvert, \ 251#define SND_SOC_DAPM_ADC_E(wname, stname, wreg, wshift, winvert, \
228 wevent, wflags) \ 252 wevent, wflags) \
229{ .id = snd_soc_dapm_adc, .name = wname, .sname = stname, .reg = wreg, \ 253{ .id = snd_soc_dapm_adc, .name = wname, .sname = stname, \
230 .shift = wshift, .invert = winvert, \ 254 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
231 .event = wevent, .event_flags = wflags} 255 .event = wevent, .event_flags = wflags}
232#define SND_SOC_DAPM_CLOCK_SUPPLY(wname) \ 256#define SND_SOC_DAPM_CLOCK_SUPPLY(wname) \
233{ .id = snd_soc_dapm_clock_supply, .name = wname, \ 257{ .id = snd_soc_dapm_clock_supply, .name = wname, \
@@ -241,14 +265,14 @@ struct device;
241 .on_val = won_val, .off_val = woff_val, .event = dapm_reg_event, \ 265 .on_val = won_val, .off_val = woff_val, .event = dapm_reg_event, \
242 .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD} 266 .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD}
243#define SND_SOC_DAPM_SUPPLY(wname, wreg, wshift, winvert, wevent, wflags) \ 267#define SND_SOC_DAPM_SUPPLY(wname, wreg, wshift, winvert, wevent, wflags) \
244{ .id = snd_soc_dapm_supply, .name = wname, .reg = wreg, \ 268{ .id = snd_soc_dapm_supply, .name = wname, \
245 .shift = wshift, .invert = winvert, .event = wevent, \ 269 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
246 .event_flags = wflags} 270 .event = wevent, .event_flags = wflags}
247#define SND_SOC_DAPM_REGULATOR_SUPPLY(wname, wdelay, wflags) \ 271#define SND_SOC_DAPM_REGULATOR_SUPPLY(wname, wdelay, wflags) \
248{ .id = snd_soc_dapm_regulator_supply, .name = wname, \ 272{ .id = snd_soc_dapm_regulator_supply, .name = wname, \
249 .reg = SND_SOC_NOPM, .shift = wdelay, .event = dapm_regulator_event, \ 273 .reg = SND_SOC_NOPM, .shift = wdelay, .event = dapm_regulator_event, \
250 .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD, \ 274 .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD, \
251 .invert = wflags} 275 .on_val = wflags}
252 276
253 277
254/* dapm kcontrol types */ 278/* dapm kcontrol types */
@@ -256,14 +280,26 @@ struct device;
256{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ 280{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
257 .info = snd_soc_info_volsw, \ 281 .info = snd_soc_info_volsw, \
258 .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \ 282 .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
259 .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) } 283 .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) }
284#define SOC_DAPM_SINGLE_AUTODISABLE(xname, reg, shift, max, invert) \
285{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
286 .info = snd_soc_info_volsw, \
287 .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
288 .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 1) }
260#define SOC_DAPM_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \ 289#define SOC_DAPM_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \
261{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ 290{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
262 .info = snd_soc_info_volsw, \ 291 .info = snd_soc_info_volsw, \
263 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE,\ 292 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE,\
264 .tlv.p = (tlv_array), \ 293 .tlv.p = (tlv_array), \
265 .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \ 294 .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
266 .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) } 295 .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) }
296#define SOC_DAPM_SINGLE_TLV_AUTODISABLE(xname, reg, shift, max, invert, tlv_array) \
297{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
298 .info = snd_soc_info_volsw, \
299 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE,\
300 .tlv.p = (tlv_array), \
301 .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
302 .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) }
267#define SOC_DAPM_ENUM(xname, xenum) \ 303#define SOC_DAPM_ENUM(xname, xenum) \
268{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ 304{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
269 .info = snd_soc_info_enum_double, \ 305 .info = snd_soc_info_enum_double, \
@@ -333,6 +369,7 @@ struct snd_soc_dapm_route;
333struct snd_soc_dapm_context; 369struct snd_soc_dapm_context;
334struct regulator; 370struct regulator;
335struct snd_soc_dapm_widget_list; 371struct snd_soc_dapm_widget_list;
372struct snd_soc_dapm_update;
336 373
337int dapm_reg_event(struct snd_soc_dapm_widget *w, 374int dapm_reg_event(struct snd_soc_dapm_widget *w,
338 struct snd_kcontrol *kcontrol, int event); 375 struct snd_kcontrol *kcontrol, int event);
@@ -391,10 +428,12 @@ void snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
391void snd_soc_dapm_shutdown(struct snd_soc_card *card); 428void snd_soc_dapm_shutdown(struct snd_soc_card *card);
392 429
393/* external DAPM widget events */ 430/* external DAPM widget events */
394int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_widget *widget, 431int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_context *dapm,
395 struct snd_kcontrol *kcontrol, int connect); 432 struct snd_kcontrol *kcontrol, int connect,
396int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_widget *widget, 433 struct snd_soc_dapm_update *update);
397 struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e); 434int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_context *dapm,
435 struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e,
436 struct snd_soc_dapm_update *update);
398 437
399/* dapm sys fs - used by the core */ 438/* dapm sys fs - used by the core */
400int snd_soc_dapm_sys_add(struct device *dev); 439int snd_soc_dapm_sys_add(struct device *dev);
@@ -424,6 +463,8 @@ void dapm_mark_io_dirty(struct snd_soc_dapm_context *dapm);
424int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream, 463int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream,
425 struct snd_soc_dapm_widget_list **list); 464 struct snd_soc_dapm_widget_list **list);
426 465
466struct snd_soc_codec *snd_soc_dapm_kcontrol_codec(struct snd_kcontrol *kcontrol);
467
427/* dapm widget types */ 468/* dapm widget types */
428enum snd_soc_dapm_type { 469enum snd_soc_dapm_type {
429 snd_soc_dapm_input = 0, /* input pin */ 470 snd_soc_dapm_input = 0, /* input pin */
@@ -455,6 +496,7 @@ enum snd_soc_dapm_type {
455 snd_soc_dapm_dai_in, /* link to DAI structure */ 496 snd_soc_dapm_dai_in, /* link to DAI structure */
456 snd_soc_dapm_dai_out, 497 snd_soc_dapm_dai_out,
457 snd_soc_dapm_dai_link, /* link between two DAI structures */ 498 snd_soc_dapm_dai_link, /* link between two DAI structures */
499 snd_soc_dapm_kcontrol, /* Auto-disabled kcontrol */
458}; 500};
459 501
460enum snd_soc_dapm_subclass { 502enum snd_soc_dapm_subclass {
@@ -485,7 +527,6 @@ struct snd_soc_dapm_path {
485 /* source (input) and sink (output) widgets */ 527 /* source (input) and sink (output) widgets */
486 struct snd_soc_dapm_widget *source; 528 struct snd_soc_dapm_widget *source;
487 struct snd_soc_dapm_widget *sink; 529 struct snd_soc_dapm_widget *sink;
488 struct snd_kcontrol *kcontrol;
489 530
490 /* status */ 531 /* status */
491 u32 connect:1; /* source and sink widgets are connected */ 532 u32 connect:1; /* source and sink widgets are connected */
@@ -498,6 +539,7 @@ struct snd_soc_dapm_path {
498 539
499 struct list_head list_source; 540 struct list_head list_source;
500 struct list_head list_sink; 541 struct list_head list_sink;
542 struct list_head list_kcontrol;
501 struct list_head list; 543 struct list_head list;
502}; 544};
503 545
@@ -518,12 +560,10 @@ struct snd_soc_dapm_widget {
518 /* dapm control */ 560 /* dapm control */
519 int reg; /* negative reg = no direct dapm */ 561 int reg; /* negative reg = no direct dapm */
520 unsigned char shift; /* bits to shift */ 562 unsigned char shift; /* bits to shift */
521 unsigned int value; /* widget current value */
522 unsigned int mask; /* non-shifted mask */ 563 unsigned int mask; /* non-shifted mask */
523 unsigned int on_val; /* on state value */ 564 unsigned int on_val; /* on state value */
524 unsigned int off_val; /* off state value */ 565 unsigned int off_val; /* off state value */
525 unsigned char power:1; /* block power status */ 566 unsigned char power:1; /* block power status */
526 unsigned char invert:1; /* invert the power bit */
527 unsigned char active:1; /* active stream on DAC, ADC's */ 567 unsigned char active:1; /* active stream on DAC, ADC's */
528 unsigned char connected:1; /* connected codec pin */ 568 unsigned char connected:1; /* connected codec pin */
529 unsigned char new:1; /* cnew complete */ 569 unsigned char new:1; /* cnew complete */
@@ -559,7 +599,6 @@ struct snd_soc_dapm_widget {
559}; 599};
560 600
561struct snd_soc_dapm_update { 601struct snd_soc_dapm_update {
562 struct snd_soc_dapm_widget *widget;
563 struct snd_kcontrol *kcontrol; 602 struct snd_kcontrol *kcontrol;
564 int reg; 603 int reg;
565 int mask; 604 int mask;
@@ -573,8 +612,6 @@ struct snd_soc_dapm_context {
573 struct delayed_work delayed_work; 612 struct delayed_work delayed_work;
574 unsigned int idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */ 613 unsigned int idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */
575 614
576 struct snd_soc_dapm_update *update;
577
578 void (*seq_notifier)(struct snd_soc_dapm_context *, 615 void (*seq_notifier)(struct snd_soc_dapm_context *,
579 enum snd_soc_dapm_type, int); 616 enum snd_soc_dapm_type, int);
580 617
diff --git a/include/sound/soc-dpcm.h b/include/sound/soc-dpcm.h
index 04598f1efd77..047d657c331c 100644
--- a/include/sound/soc-dpcm.h
+++ b/include/sound/soc-dpcm.h
@@ -133,6 +133,6 @@ void snd_soc_dpcm_be_set_state(struct snd_soc_pcm_runtime *be, int stream,
133/* internal use only */ 133/* internal use only */
134int soc_dpcm_be_digital_mute(struct snd_soc_pcm_runtime *fe, int mute); 134int soc_dpcm_be_digital_mute(struct snd_soc_pcm_runtime *fe, int mute);
135int soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd); 135int soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd);
136int soc_dpcm_runtime_update(struct snd_soc_dapm_widget *); 136int soc_dpcm_runtime_update(struct snd_soc_card *);
137 137
138#endif 138#endif
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 6f86a4187f58..d57a04e7553d 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -30,13 +30,13 @@
30/* 30/*
31 * Convenience kcontrol builders 31 * Convenience kcontrol builders
32 */ 32 */
33#define SOC_DOUBLE_VALUE(xreg, shift_left, shift_right, xmax, xinvert) \ 33#define SOC_DOUBLE_VALUE(xreg, shift_left, shift_right, xmax, xinvert, xautodisable) \
34 ((unsigned long)&(struct soc_mixer_control) \ 34 ((unsigned long)&(struct soc_mixer_control) \
35 {.reg = xreg, .rreg = xreg, .shift = shift_left, \ 35 {.reg = xreg, .rreg = xreg, .shift = shift_left, \
36 .rshift = shift_right, .max = xmax, .platform_max = xmax, \ 36 .rshift = shift_right, .max = xmax, .platform_max = xmax, \
37 .invert = xinvert}) 37 .invert = xinvert, .autodisable = xautodisable})
38#define SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert) \ 38#define SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert, xautodisable) \
39 SOC_DOUBLE_VALUE(xreg, xshift, xshift, xmax, xinvert) 39 SOC_DOUBLE_VALUE(xreg, xshift, xshift, xmax, xinvert, xautodisable)
40#define SOC_SINGLE_VALUE_EXT(xreg, xmax, xinvert) \ 40#define SOC_SINGLE_VALUE_EXT(xreg, xmax, xinvert) \
41 ((unsigned long)&(struct soc_mixer_control) \ 41 ((unsigned long)&(struct soc_mixer_control) \
42 {.reg = xreg, .max = xmax, .platform_max = xmax, .invert = xinvert}) 42 {.reg = xreg, .max = xmax, .platform_max = xmax, .invert = xinvert})
@@ -52,7 +52,7 @@
52{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ 52{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
53 .info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\ 53 .info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\
54 .put = snd_soc_put_volsw, \ 54 .put = snd_soc_put_volsw, \
55 .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) } 55 .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) }
56#define SOC_SINGLE_RANGE(xname, xreg, xshift, xmin, xmax, xinvert) \ 56#define SOC_SINGLE_RANGE(xname, xreg, xshift, xmin, xmax, xinvert) \
57{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ 57{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
58 .info = snd_soc_info_volsw_range, .get = snd_soc_get_volsw_range, \ 58 .info = snd_soc_info_volsw_range, .get = snd_soc_get_volsw_range, \
@@ -68,7 +68,7 @@
68 .tlv.p = (tlv_array), \ 68 .tlv.p = (tlv_array), \
69 .info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\ 69 .info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\
70 .put = snd_soc_put_volsw, \ 70 .put = snd_soc_put_volsw, \
71 .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) } 71 .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) }
72#define SOC_SINGLE_SX_TLV(xname, xreg, xshift, xmin, xmax, tlv_array) \ 72#define SOC_SINGLE_SX_TLV(xname, xreg, xshift, xmin, xmax, tlv_array) \
73{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ 73{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
74 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ 74 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
@@ -97,7 +97,7 @@
97 .info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \ 97 .info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \
98 .put = snd_soc_put_volsw, \ 98 .put = snd_soc_put_volsw, \
99 .private_value = SOC_DOUBLE_VALUE(reg, shift_left, shift_right, \ 99 .private_value = SOC_DOUBLE_VALUE(reg, shift_left, shift_right, \
100 max, invert) } 100 max, invert, 0) }
101#define SOC_DOUBLE_R(xname, reg_left, reg_right, xshift, xmax, xinvert) \ 101#define SOC_DOUBLE_R(xname, reg_left, reg_right, xshift, xmax, xinvert) \
102{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ 102{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
103 .info = snd_soc_info_volsw, \ 103 .info = snd_soc_info_volsw, \
@@ -119,7 +119,7 @@
119 .info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \ 119 .info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \
120 .put = snd_soc_put_volsw, \ 120 .put = snd_soc_put_volsw, \
121 .private_value = SOC_DOUBLE_VALUE(reg, shift_left, shift_right, \ 121 .private_value = SOC_DOUBLE_VALUE(reg, shift_left, shift_right, \
122 max, invert) } 122 max, invert, 0) }
123#define SOC_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert, tlv_array) \ 123#define SOC_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert, tlv_array) \
124{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ 124{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
125 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ 125 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
@@ -190,14 +190,14 @@
190{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ 190{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
191 .info = snd_soc_info_volsw, \ 191 .info = snd_soc_info_volsw, \
192 .get = xhandler_get, .put = xhandler_put, \ 192 .get = xhandler_get, .put = xhandler_put, \
193 .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert) } 193 .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert, 0) }
194#define SOC_DOUBLE_EXT(xname, reg, shift_left, shift_right, max, invert,\ 194#define SOC_DOUBLE_EXT(xname, reg, shift_left, shift_right, max, invert,\
195 xhandler_get, xhandler_put) \ 195 xhandler_get, xhandler_put) \
196{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ 196{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
197 .info = snd_soc_info_volsw, \ 197 .info = snd_soc_info_volsw, \
198 .get = xhandler_get, .put = xhandler_put, \ 198 .get = xhandler_get, .put = xhandler_put, \
199 .private_value = \ 199 .private_value = \
200 SOC_DOUBLE_VALUE(reg, shift_left, shift_right, max, invert) } 200 SOC_DOUBLE_VALUE(reg, shift_left, shift_right, max, invert, 0) }
201#define SOC_SINGLE_EXT_TLV(xname, xreg, xshift, xmax, xinvert,\ 201#define SOC_SINGLE_EXT_TLV(xname, xreg, xshift, xmax, xinvert,\
202 xhandler_get, xhandler_put, tlv_array) \ 202 xhandler_get, xhandler_put, tlv_array) \
203{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ 203{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
@@ -206,7 +206,7 @@
206 .tlv.p = (tlv_array), \ 206 .tlv.p = (tlv_array), \
207 .info = snd_soc_info_volsw, \ 207 .info = snd_soc_info_volsw, \
208 .get = xhandler_get, .put = xhandler_put, \ 208 .get = xhandler_get, .put = xhandler_put, \
209 .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert) } 209 .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert, 0) }
210#define SOC_DOUBLE_EXT_TLV(xname, xreg, shift_left, shift_right, xmax, xinvert,\ 210#define SOC_DOUBLE_EXT_TLV(xname, xreg, shift_left, shift_right, xmax, xinvert,\
211 xhandler_get, xhandler_put, tlv_array) \ 211 xhandler_get, xhandler_put, tlv_array) \
212{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ 212{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
@@ -216,7 +216,7 @@
216 .info = snd_soc_info_volsw, \ 216 .info = snd_soc_info_volsw, \
217 .get = xhandler_get, .put = xhandler_put, \ 217 .get = xhandler_get, .put = xhandler_put, \
218 .private_value = SOC_DOUBLE_VALUE(xreg, shift_left, shift_right, \ 218 .private_value = SOC_DOUBLE_VALUE(xreg, shift_left, shift_right, \
219 xmax, xinvert) } 219 xmax, xinvert, 0) }
220#define SOC_DOUBLE_R_EXT_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert,\ 220#define SOC_DOUBLE_R_EXT_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert,\
221 xhandler_get, xhandler_put, tlv_array) \ 221 xhandler_get, xhandler_put, tlv_array) \
222{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ 222{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
@@ -1038,6 +1038,7 @@ struct snd_soc_card {
1038 /* Generic DAPM context for the card */ 1038 /* Generic DAPM context for the card */
1039 struct snd_soc_dapm_context dapm; 1039 struct snd_soc_dapm_context dapm;
1040 struct snd_soc_dapm_stats dapm_stats; 1040 struct snd_soc_dapm_stats dapm_stats;
1041 struct snd_soc_dapm_update *update;
1041 1042
1042#ifdef CONFIG_DEBUG_FS 1043#ifdef CONFIG_DEBUG_FS
1043 struct dentry *debugfs_card_root; 1044 struct dentry *debugfs_card_root;
@@ -1083,7 +1084,9 @@ struct snd_soc_pcm_runtime {
1083/* mixer control */ 1084/* mixer control */
1084struct soc_mixer_control { 1085struct soc_mixer_control {
1085 int min, max, platform_max; 1086 int min, max, platform_max;
1086 unsigned int reg, rreg, shift, rshift, invert; 1087 unsigned int reg, rreg, shift, rshift;
1088 unsigned int invert:1;
1089 unsigned int autodisable:1;
1087}; 1090};
1088 1091
1089struct soc_bytes { 1092struct soc_bytes {
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index e5b926883131..fec0db04262d 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -138,8 +138,7 @@ static const u8 aic3x_reg[AIC3X_CACHEREGNUM] = {
138static int snd_soc_dapm_put_volsw_aic3x(struct snd_kcontrol *kcontrol, 138static int snd_soc_dapm_put_volsw_aic3x(struct snd_kcontrol *kcontrol,
139 struct snd_ctl_elem_value *ucontrol) 139 struct snd_ctl_elem_value *ucontrol)
140{ 140{
141 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); 141 struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
142 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
143 struct soc_mixer_control *mc = 142 struct soc_mixer_control *mc =
144 (struct soc_mixer_control *)kcontrol->private_value; 143 (struct soc_mixer_control *)kcontrol->private_value;
145 unsigned int reg = mc->reg; 144 unsigned int reg = mc->reg;
@@ -147,10 +146,9 @@ static int snd_soc_dapm_put_volsw_aic3x(struct snd_kcontrol *kcontrol,
147 int max = mc->max; 146 int max = mc->max;
148 unsigned int mask = (1 << fls(max)) - 1; 147 unsigned int mask = (1 << fls(max)) - 1;
149 unsigned int invert = mc->invert; 148 unsigned int invert = mc->invert;
150 unsigned short val, val_mask; 149 unsigned short val;
151 int ret; 150 struct snd_soc_dapm_update update;
152 struct snd_soc_dapm_path *path; 151 int connect, change;
153 int found = 0;
154 152
155 val = (ucontrol->value.integer.value[0] & mask); 153 val = (ucontrol->value.integer.value[0] & mask);
156 154
@@ -158,42 +156,26 @@ static int snd_soc_dapm_put_volsw_aic3x(struct snd_kcontrol *kcontrol,
158 if (val) 156 if (val)
159 val = mask; 157 val = mask;
160 158
159 connect = !!val;
160
161 if (invert) 161 if (invert)
162 val = mask - val; 162 val = mask - val;
163 val_mask = mask << shift;
164 val = val << shift;
165
166 mutex_lock(&widget->codec->mutex);
167 163
168 if (snd_soc_test_bits(widget->codec, reg, val_mask, val)) { 164 mask <<= shift;
169 /* find dapm widget path assoc with kcontrol */ 165 val <<= shift;
170 list_for_each_entry(path, &widget->dapm->card->paths, list) {
171 if (path->kcontrol != kcontrol)
172 continue;
173 166
174 /* found, now check type */ 167 change = snd_soc_test_bits(codec, val, mask, reg);
175 found = 1; 168 if (change) {
176 if (val) 169 update.kcontrol = kcontrol;
177 /* new connection */ 170 update.reg = reg;
178 path->connect = invert ? 0 : 1; 171 update.mask = mask;
179 else 172 update.val = val;
180 /* old connection must be powered down */
181 path->connect = invert ? 1 : 0;
182 173
183 dapm_mark_dirty(path->source, "tlv320aic3x source"); 174 snd_soc_dapm_mixer_update_power(&codec->dapm, kcontrol, connect,
184 dapm_mark_dirty(path->sink, "tlv320aic3x sink"); 175 &update);
185
186 break;
187 }
188 } 176 }
189 177
190 mutex_unlock(&widget->codec->mutex); 178 return change;
191
192 if (found)
193 snd_soc_dapm_sync(widget->dapm);
194
195 ret = snd_soc_update_bits_locked(widget->codec, reg, val_mask, val);
196 return ret;
197} 179}
198 180
199/* 181/*
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c
index 44621ddc332d..d6c5bf14179a 100644
--- a/sound/soc/codecs/twl6040.c
+++ b/sound/soc/codecs/twl6040.c
@@ -437,9 +437,7 @@ static irqreturn_t twl6040_audio_handler(int irq, void *data)
437static int twl6040_soc_dapm_put_vibra_enum(struct snd_kcontrol *kcontrol, 437static int twl6040_soc_dapm_put_vibra_enum(struct snd_kcontrol *kcontrol,
438 struct snd_ctl_elem_value *ucontrol) 438 struct snd_ctl_elem_value *ucontrol)
439{ 439{
440 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); 440 struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
441 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
442 struct snd_soc_codec *codec = widget->codec;
443 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 441 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
444 unsigned int val; 442 unsigned int val;
445 443
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c
index fa24cedee687..eebcb1da3b7b 100644
--- a/sound/soc/codecs/wm8903.c
+++ b/sound/soc/codecs/wm8903.c
@@ -364,9 +364,7 @@ static void wm8903_seq_notifier(struct snd_soc_dapm_context *dapm,
364static int wm8903_class_w_put(struct snd_kcontrol *kcontrol, 364static int wm8903_class_w_put(struct snd_kcontrol *kcontrol,
365 struct snd_ctl_elem_value *ucontrol) 365 struct snd_ctl_elem_value *ucontrol)
366{ 366{
367 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); 367 struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
368 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
369 struct snd_soc_codec *codec = widget->codec;
370 struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); 368 struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
371 u16 reg; 369 u16 reg;
372 int ret; 370 int ret;
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index ba832b77c543..eee2a01f2691 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -1437,9 +1437,7 @@ SOC_DAPM_SINGLE("AIF1.1 Switch", WM8994_DAC2_RIGHT_MIXER_ROUTING,
1437static int wm8994_put_class_w(struct snd_kcontrol *kcontrol, 1437static int wm8994_put_class_w(struct snd_kcontrol *kcontrol,
1438 struct snd_ctl_elem_value *ucontrol) 1438 struct snd_ctl_elem_value *ucontrol)
1439{ 1439{
1440 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); 1440 struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
1441 struct snd_soc_dapm_widget *w = wlist->widgets[0];
1442 struct snd_soc_codec *codec = w->codec;
1443 int ret; 1441 int ret;
1444 1442
1445 ret = snd_soc_dapm_put_volsw(kcontrol, ucontrol); 1443 ret = snd_soc_dapm_put_volsw(kcontrol, ucontrol);
diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c
index 90a65c427541..da2899e6c401 100644
--- a/sound/soc/codecs/wm8995.c
+++ b/sound/soc/codecs/wm8995.c
@@ -549,12 +549,9 @@ static int check_clk_sys(struct snd_soc_dapm_widget *source,
549static int wm8995_put_class_w(struct snd_kcontrol *kcontrol, 549static int wm8995_put_class_w(struct snd_kcontrol *kcontrol,
550 struct snd_ctl_elem_value *ucontrol) 550 struct snd_ctl_elem_value *ucontrol)
551{ 551{
552 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); 552 struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
553 struct snd_soc_dapm_widget *w = wlist->widgets[0];
554 struct snd_soc_codec *codec;
555 int ret; 553 int ret;
556 554
557 codec = w->codec;
558 ret = snd_soc_dapm_put_volsw(kcontrol, ucontrol); 555 ret = snd_soc_dapm_put_volsw(kcontrol, ucontrol);
559 wm8995_update_class_w(codec); 556 wm8995_update_class_w(codec);
560 return ret; 557 return ret;
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c
index 2d9e099415a5..8b50e5958de5 100644
--- a/sound/soc/codecs/wm_hubs.c
+++ b/sound/soc/codecs/wm_hubs.c
@@ -699,9 +699,7 @@ EXPORT_SYMBOL_GPL(wm_hubs_update_class_w);
699static int class_w_put_volsw(struct snd_kcontrol *kcontrol, 699static int class_w_put_volsw(struct snd_kcontrol *kcontrol,
700 struct snd_ctl_elem_value *ucontrol) 700 struct snd_ctl_elem_value *ucontrol)
701{ 701{
702 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); 702 struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
703 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
704 struct snd_soc_codec *codec = widget->codec;
705 int ret; 703 int ret;
706 704
707 ret = snd_soc_dapm_put_volsw(kcontrol, ucontrol); 705 ret = snd_soc_dapm_put_volsw(kcontrol, ucontrol);
@@ -721,9 +719,7 @@ static int class_w_put_volsw(struct snd_kcontrol *kcontrol,
721static int class_w_put_double(struct snd_kcontrol *kcontrol, 719static int class_w_put_double(struct snd_kcontrol *kcontrol,
722 struct snd_ctl_elem_value *ucontrol) 720 struct snd_ctl_elem_value *ucontrol)
723{ 721{
724 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); 722 struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
725 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
726 struct snd_soc_codec *codec = widget->codec;
727 int ret; 723 int ret;
728 724
729 ret = snd_soc_dapm_put_enum_double(kcontrol, ucontrol); 725 ret = snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 105f7c4bef81..7e9afbc49ef2 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -47,6 +47,15 @@
47 47
48#define DAPM_UPDATE_STAT(widget, val) widget->dapm->card->dapm_stats.val++; 48#define DAPM_UPDATE_STAT(widget, val) widget->dapm->card->dapm_stats.val++;
49 49
50static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm,
51 struct snd_soc_dapm_widget *wsource, struct snd_soc_dapm_widget *wsink,
52 const char *control,
53 int (*connected)(struct snd_soc_dapm_widget *source,
54 struct snd_soc_dapm_widget *sink));
55static struct snd_soc_dapm_widget *
56snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
57 const struct snd_soc_dapm_widget *widget);
58
50/* dapm power sequences - make this per codec in the future */ 59/* dapm power sequences - make this per codec in the future */
51static int dapm_up_seq[] = { 60static int dapm_up_seq[] = {
52 [snd_soc_dapm_pre] = 0, 61 [snd_soc_dapm_pre] = 0,
@@ -73,16 +82,18 @@ static int dapm_up_seq[] = {
73 [snd_soc_dapm_hp] = 10, 82 [snd_soc_dapm_hp] = 10,
74 [snd_soc_dapm_spk] = 10, 83 [snd_soc_dapm_spk] = 10,
75 [snd_soc_dapm_line] = 10, 84 [snd_soc_dapm_line] = 10,
76 [snd_soc_dapm_post] = 11, 85 [snd_soc_dapm_kcontrol] = 11,
86 [snd_soc_dapm_post] = 12,
77}; 87};
78 88
79static int dapm_down_seq[] = { 89static int dapm_down_seq[] = {
80 [snd_soc_dapm_pre] = 0, 90 [snd_soc_dapm_pre] = 0,
81 [snd_soc_dapm_adc] = 1, 91 [snd_soc_dapm_kcontrol] = 1,
82 [snd_soc_dapm_hp] = 2, 92 [snd_soc_dapm_adc] = 2,
83 [snd_soc_dapm_spk] = 2, 93 [snd_soc_dapm_hp] = 3,
84 [snd_soc_dapm_line] = 2, 94 [snd_soc_dapm_spk] = 3,
85 [snd_soc_dapm_out_drv] = 2, 95 [snd_soc_dapm_line] = 3,
96 [snd_soc_dapm_out_drv] = 3,
86 [snd_soc_dapm_pga] = 4, 97 [snd_soc_dapm_pga] = 4,
87 [snd_soc_dapm_switch] = 5, 98 [snd_soc_dapm_switch] = 5,
88 [snd_soc_dapm_mixer_named_ctl] = 5, 99 [snd_soc_dapm_mixer_named_ctl] = 5,
@@ -174,6 +185,176 @@ static inline struct snd_soc_dapm_widget *dapm_cnew_widget(
174 return kmemdup(_widget, sizeof(*_widget), GFP_KERNEL); 185 return kmemdup(_widget, sizeof(*_widget), GFP_KERNEL);
175} 186}
176 187
188struct dapm_kcontrol_data {
189 unsigned int value;
190 struct snd_soc_dapm_widget *widget;
191 struct list_head paths;
192 struct snd_soc_dapm_widget_list *wlist;
193};
194
195static int dapm_kcontrol_data_alloc(struct snd_soc_dapm_widget *widget,
196 struct snd_kcontrol *kcontrol)
197{
198 struct dapm_kcontrol_data *data;
199 struct soc_mixer_control *mc;
200
201 data = kzalloc(sizeof(*data), GFP_KERNEL);
202 if (!data) {
203 dev_err(widget->dapm->dev,
204 "ASoC: can't allocate kcontrol data for %s\n",
205 widget->name);
206 return -ENOMEM;
207 }
208
209 INIT_LIST_HEAD(&data->paths);
210
211 switch (widget->id) {
212 case snd_soc_dapm_switch:
213 case snd_soc_dapm_mixer:
214 case snd_soc_dapm_mixer_named_ctl:
215 mc = (struct soc_mixer_control *)kcontrol->private_value;
216
217 if (mc->autodisable) {
218 struct snd_soc_dapm_widget template;
219
220 memset(&template, 0, sizeof(template));
221 template.reg = mc->reg;
222 template.mask = (1 << fls(mc->max)) - 1;
223 template.shift = mc->shift;
224 if (mc->invert)
225 template.off_val = mc->max;
226 else
227 template.off_val = 0;
228 template.on_val = template.off_val;
229 template.id = snd_soc_dapm_kcontrol;
230 template.name = kcontrol->id.name;
231
232 data->widget = snd_soc_dapm_new_control(widget->dapm,
233 &template);
234 if (!data->widget) {
235 kfree(data);
236 return -ENOMEM;
237 }
238 }
239 break;
240 default:
241 break;
242 }
243
244 kcontrol->private_data = data;
245
246 return 0;
247}
248
249static void dapm_kcontrol_free(struct snd_kcontrol *kctl)
250{
251 struct dapm_kcontrol_data *data = snd_kcontrol_chip(kctl);
252 kfree(data->widget);
253 kfree(data->wlist);
254 kfree(data);
255}
256
257static struct snd_soc_dapm_widget_list *dapm_kcontrol_get_wlist(
258 const struct snd_kcontrol *kcontrol)
259{
260 struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol);
261
262 return data->wlist;
263}
264
265static int dapm_kcontrol_add_widget(struct snd_kcontrol *kcontrol,
266 struct snd_soc_dapm_widget *widget)
267{
268 struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol);
269 struct snd_soc_dapm_widget_list *new_wlist;
270 unsigned int n;
271
272 if (data->wlist)
273 n = data->wlist->num_widgets + 1;
274 else
275 n = 1;
276
277 new_wlist = krealloc(data->wlist,
278 sizeof(*new_wlist) + sizeof(widget) * n, GFP_KERNEL);
279 if (!new_wlist)
280 return -ENOMEM;
281
282 new_wlist->widgets[n - 1] = widget;
283 new_wlist->num_widgets = n;
284
285 data->wlist = new_wlist;
286
287 return 0;
288}
289
290static void dapm_kcontrol_add_path(const struct snd_kcontrol *kcontrol,
291 struct snd_soc_dapm_path *path)
292{
293 struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol);
294
295 list_add_tail(&path->list_kcontrol, &data->paths);
296
297 if (data->widget) {
298 snd_soc_dapm_add_path(data->widget->dapm, data->widget,
299 path->source, NULL, NULL);
300 }
301}
302
303static bool dapm_kcontrol_is_powered(const struct snd_kcontrol *kcontrol)
304{
305 struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol);
306
307 if (!data->widget)
308 return true;
309
310 return data->widget->power;
311}
312
313static struct list_head *dapm_kcontrol_get_path_list(
314 const struct snd_kcontrol *kcontrol)
315{
316 struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol);
317
318 return &data->paths;
319}
320
321#define dapm_kcontrol_for_each_path(path, kcontrol) \
322 list_for_each_entry(path, dapm_kcontrol_get_path_list(kcontrol), \
323 list_kcontrol)
324
325static unsigned int dapm_kcontrol_get_value(const struct snd_kcontrol *kcontrol)
326{
327 struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol);
328
329 return data->value;
330}
331
332static bool dapm_kcontrol_set_value(const struct snd_kcontrol *kcontrol,
333 unsigned int value)
334{
335 struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol);
336
337 if (data->value == value)
338 return false;
339
340 if (data->widget)
341 data->widget->on_val = value;
342
343 data->value = value;
344
345 return true;
346}
347
348/**
349 * snd_soc_dapm_kcontrol_codec() - Returns the codec associated to a kcontrol
350 * @kcontrol: The kcontrol
351 */
352struct snd_soc_codec *snd_soc_dapm_kcontrol_codec(struct snd_kcontrol *kcontrol)
353{
354 return dapm_kcontrol_get_wlist(kcontrol)->widgets[0]->codec;
355}
356EXPORT_SYMBOL_GPL(snd_soc_dapm_kcontrol_codec);
357
177static void dapm_reset(struct snd_soc_card *card) 358static void dapm_reset(struct snd_soc_card *card)
178{ 359{
179 struct snd_soc_dapm_widget *w; 360 struct snd_soc_dapm_widget *w;
@@ -181,6 +362,7 @@ static void dapm_reset(struct snd_soc_card *card)
181 memset(&card->dapm_stats, 0, sizeof(card->dapm_stats)); 362 memset(&card->dapm_stats, 0, sizeof(card->dapm_stats));
182 363
183 list_for_each_entry(w, &card->widgets, list) { 364 list_for_each_entry(w, &card->widgets, list) {
365 w->new_power = w->power;
184 w->power_checked = false; 366 w->power_checked = false;
185 w->inputs = -1; 367 w->inputs = -1;
186 w->outputs = -1; 368 w->outputs = -1;
@@ -398,6 +580,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
398 case snd_soc_dapm_spk: 580 case snd_soc_dapm_spk:
399 case snd_soc_dapm_line: 581 case snd_soc_dapm_line:
400 case snd_soc_dapm_dai_link: 582 case snd_soc_dapm_dai_link:
583 case snd_soc_dapm_kcontrol:
401 p->connect = 1; 584 p->connect = 1;
402 break; 585 break;
403 /* does affect routing - dynamically connected */ 586 /* does affect routing - dynamically connected */
@@ -477,17 +660,12 @@ static int dapm_is_shared_kcontrol(struct snd_soc_dapm_context *dapm,
477 return 0; 660 return 0;
478} 661}
479 662
480static void dapm_kcontrol_free(struct snd_kcontrol *kctl)
481{
482 kfree(kctl->private_data);
483}
484
485/* 663/*
486 * Determine if a kcontrol is shared. If it is, look it up. If it isn't, 664 * Determine if a kcontrol is shared. If it is, look it up. If it isn't,
487 * create it. Either way, add the widget into the control's widget list 665 * create it. Either way, add the widget into the control's widget list
488 */ 666 */
489static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w, 667static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w,
490 int kci, struct snd_soc_dapm_path *path) 668 int kci)
491{ 669{
492 struct snd_soc_dapm_context *dapm = w->dapm; 670 struct snd_soc_dapm_context *dapm = w->dapm;
493 struct snd_card *card = dapm->card->snd_card; 671 struct snd_card *card = dapm->card->snd_card;
@@ -495,9 +673,6 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w,
495 size_t prefix_len; 673 size_t prefix_len;
496 int shared; 674 int shared;
497 struct snd_kcontrol *kcontrol; 675 struct snd_kcontrol *kcontrol;
498 struct snd_soc_dapm_widget_list *wlist;
499 int wlistentries;
500 size_t wlistsize;
501 bool wname_in_long_name, kcname_in_long_name; 676 bool wname_in_long_name, kcname_in_long_name;
502 char *long_name; 677 char *long_name;
503 const char *name; 678 const char *name;
@@ -516,25 +691,6 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w,
516 shared = dapm_is_shared_kcontrol(dapm, w, &w->kcontrol_news[kci], 691 shared = dapm_is_shared_kcontrol(dapm, w, &w->kcontrol_news[kci],
517 &kcontrol); 692 &kcontrol);
518 693
519 if (kcontrol) {
520 wlist = kcontrol->private_data;
521 wlistentries = wlist->num_widgets + 1;
522 } else {
523 wlist = NULL;
524 wlistentries = 1;
525 }
526
527 wlistsize = sizeof(struct snd_soc_dapm_widget_list) +
528 wlistentries * sizeof(struct snd_soc_dapm_widget *);
529 wlist = krealloc(wlist, wlistsize, GFP_KERNEL);
530 if (wlist == NULL) {
531 dev_err(dapm->dev, "ASoC: can't allocate widget list for %s\n",
532 w->name);
533 return -ENOMEM;
534 }
535 wlist->num_widgets = wlistentries;
536 wlist->widgets[wlistentries - 1] = w;
537
538 if (!kcontrol) { 694 if (!kcontrol) {
539 if (shared) { 695 if (shared) {
540 wname_in_long_name = false; 696 wname_in_long_name = false;
@@ -557,7 +713,6 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w,
557 kcname_in_long_name = false; 713 kcname_in_long_name = false;
558 break; 714 break;
559 default: 715 default:
560 kfree(wlist);
561 return -EINVAL; 716 return -EINVAL;
562 } 717 }
563 } 718 }
@@ -572,10 +727,8 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w,
572 long_name = kasprintf(GFP_KERNEL, "%s %s", 727 long_name = kasprintf(GFP_KERNEL, "%s %s",
573 w->name + prefix_len, 728 w->name + prefix_len,
574 w->kcontrol_news[kci].name); 729 w->kcontrol_news[kci].name);
575 if (long_name == NULL) { 730 if (long_name == NULL)
576 kfree(wlist);
577 return -ENOMEM; 731 return -ENOMEM;
578 }
579 732
580 name = long_name; 733 name = long_name;
581 } else if (wname_in_long_name) { 734 } else if (wname_in_long_name) {
@@ -586,23 +739,33 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w,
586 name = w->kcontrol_news[kci].name; 739 name = w->kcontrol_news[kci].name;
587 } 740 }
588 741
589 kcontrol = snd_soc_cnew(&w->kcontrol_news[kci], wlist, name, 742 kcontrol = snd_soc_cnew(&w->kcontrol_news[kci], NULL, name,
590 prefix); 743 prefix);
591 kcontrol->private_free = dapm_kcontrol_free;
592 kfree(long_name); 744 kfree(long_name);
745 if (!kcontrol)
746 return -ENOMEM;
747 kcontrol->private_free = dapm_kcontrol_free;
748
749 ret = dapm_kcontrol_data_alloc(w, kcontrol);
750 if (ret) {
751 snd_ctl_free_one(kcontrol);
752 return ret;
753 }
754
593 ret = snd_ctl_add(card, kcontrol); 755 ret = snd_ctl_add(card, kcontrol);
594 if (ret < 0) { 756 if (ret < 0) {
595 dev_err(dapm->dev, 757 dev_err(dapm->dev,
596 "ASoC: failed to add widget %s dapm kcontrol %s: %d\n", 758 "ASoC: failed to add widget %s dapm kcontrol %s: %d\n",
597 w->name, name, ret); 759 w->name, name, ret);
598 kfree(wlist);
599 return ret; 760 return ret;
600 } 761 }
601 } 762 }
602 763
603 kcontrol->private_data = wlist; 764 ret = dapm_kcontrol_add_widget(kcontrol, w);
765 if (ret)
766 return ret;
767
604 w->kcontrols[kci] = kcontrol; 768 w->kcontrols[kci] = kcontrol;
605 path->kcontrol = kcontrol;
606 769
607 return 0; 770 return 0;
608} 771}
@@ -622,13 +785,15 @@ static int dapm_new_mixer(struct snd_soc_dapm_widget *w)
622 continue; 785 continue;
623 786
624 if (w->kcontrols[i]) { 787 if (w->kcontrols[i]) {
625 path->kcontrol = w->kcontrols[i]; 788 dapm_kcontrol_add_path(w->kcontrols[i], path);
626 continue; 789 continue;
627 } 790 }
628 791
629 ret = dapm_create_or_share_mixmux_kcontrol(w, i, path); 792 ret = dapm_create_or_share_mixmux_kcontrol(w, i);
630 if (ret < 0) 793 if (ret < 0)
631 return ret; 794 return ret;
795
796 dapm_kcontrol_add_path(w->kcontrols[i], path);
632 } 797 }
633 } 798 }
634 799
@@ -654,15 +819,12 @@ static int dapm_new_mux(struct snd_soc_dapm_widget *w)
654 return -EINVAL; 819 return -EINVAL;
655 } 820 }
656 821
657 path = list_first_entry(&w->sources, struct snd_soc_dapm_path, 822 ret = dapm_create_or_share_mixmux_kcontrol(w, 0);
658 list_sink);
659
660 ret = dapm_create_or_share_mixmux_kcontrol(w, 0, path);
661 if (ret < 0) 823 if (ret < 0)
662 return ret; 824 return ret;
663 825
664 list_for_each_entry(path, &w->sources, list_sink) 826 list_for_each_entry(path, &w->sources, list_sink)
665 path->kcontrol = w->kcontrols[0]; 827 dapm_kcontrol_add_path(w->kcontrols[0], path);
666 828
667 return 0; 829 return 0;
668} 830}
@@ -783,6 +945,7 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget,
783 case snd_soc_dapm_supply: 945 case snd_soc_dapm_supply:
784 case snd_soc_dapm_regulator_supply: 946 case snd_soc_dapm_regulator_supply:
785 case snd_soc_dapm_clock_supply: 947 case snd_soc_dapm_clock_supply:
948 case snd_soc_dapm_kcontrol:
786 return 0; 949 return 0;
787 default: 950 default:
788 break; 951 break;
@@ -878,6 +1041,7 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget,
878 case snd_soc_dapm_supply: 1041 case snd_soc_dapm_supply:
879 case snd_soc_dapm_regulator_supply: 1042 case snd_soc_dapm_regulator_supply:
880 case snd_soc_dapm_clock_supply: 1043 case snd_soc_dapm_clock_supply:
1044 case snd_soc_dapm_kcontrol:
881 return 0; 1045 return 0;
882 default: 1046 default:
883 break; 1047 break;
@@ -1032,7 +1196,7 @@ int dapm_regulator_event(struct snd_soc_dapm_widget *w,
1032 int ret; 1196 int ret;
1033 1197
1034 if (SND_SOC_DAPM_EVENT_ON(event)) { 1198 if (SND_SOC_DAPM_EVENT_ON(event)) {
1035 if (w->invert & SND_SOC_DAPM_REGULATOR_BYPASS) { 1199 if (w->on_val & SND_SOC_DAPM_REGULATOR_BYPASS) {
1036 ret = regulator_allow_bypass(w->regulator, false); 1200 ret = regulator_allow_bypass(w->regulator, false);
1037 if (ret != 0) 1201 if (ret != 0)
1038 dev_warn(w->dapm->dev, 1202 dev_warn(w->dapm->dev,
@@ -1042,7 +1206,7 @@ int dapm_regulator_event(struct snd_soc_dapm_widget *w,
1042 1206
1043 return regulator_enable(w->regulator); 1207 return regulator_enable(w->regulator);
1044 } else { 1208 } else {
1045 if (w->invert & SND_SOC_DAPM_REGULATOR_BYPASS) { 1209 if (w->on_val & SND_SOC_DAPM_REGULATOR_BYPASS) {
1046 ret = regulator_allow_bypass(w->regulator, true); 1210 ret = regulator_allow_bypass(w->regulator, true);
1047 if (ret != 0) 1211 if (ret != 0)
1048 dev_warn(w->dapm->dev, 1212 dev_warn(w->dapm->dev,
@@ -1214,10 +1378,9 @@ static void dapm_seq_insert(struct snd_soc_dapm_widget *new_widget,
1214 list_add_tail(&new_widget->power_list, list); 1378 list_add_tail(&new_widget->power_list, list);
1215} 1379}
1216 1380
1217static void dapm_seq_check_event(struct snd_soc_dapm_context *dapm, 1381static void dapm_seq_check_event(struct snd_soc_card *card,
1218 struct snd_soc_dapm_widget *w, int event) 1382 struct snd_soc_dapm_widget *w, int event)
1219{ 1383{
1220 struct snd_soc_card *card = dapm->card;
1221 const char *ev_name; 1384 const char *ev_name;
1222 int power, ret; 1385 int power, ret;
1223 1386
@@ -1251,55 +1414,50 @@ static void dapm_seq_check_event(struct snd_soc_dapm_context *dapm,
1251 return; 1414 return;
1252 } 1415 }
1253 1416
1254 if (w->power != power) 1417 if (w->new_power != power)
1255 return; 1418 return;
1256 1419
1257 if (w->event && (w->event_flags & event)) { 1420 if (w->event && (w->event_flags & event)) {
1258 pop_dbg(dapm->dev, card->pop_time, "pop test : %s %s\n", 1421 pop_dbg(w->dapm->dev, card->pop_time, "pop test : %s %s\n",
1259 w->name, ev_name); 1422 w->name, ev_name);
1260 trace_snd_soc_dapm_widget_event_start(w, event); 1423 trace_snd_soc_dapm_widget_event_start(w, event);
1261 ret = w->event(w, NULL, event); 1424 ret = w->event(w, NULL, event);
1262 trace_snd_soc_dapm_widget_event_done(w, event); 1425 trace_snd_soc_dapm_widget_event_done(w, event);
1263 if (ret < 0) 1426 if (ret < 0)
1264 dev_err(dapm->dev, "ASoC: %s: %s event failed: %d\n", 1427 dev_err(w->dapm->dev, "ASoC: %s: %s event failed: %d\n",
1265 ev_name, w->name, ret); 1428 ev_name, w->name, ret);
1266 } 1429 }
1267} 1430}
1268 1431
1269/* Apply the coalesced changes from a DAPM sequence */ 1432/* Apply the coalesced changes from a DAPM sequence */
1270static void dapm_seq_run_coalesced(struct snd_soc_dapm_context *dapm, 1433static void dapm_seq_run_coalesced(struct snd_soc_card *card,
1271 struct list_head *pending) 1434 struct list_head *pending)
1272{ 1435{
1273 struct snd_soc_card *card = dapm->card;
1274 struct snd_soc_dapm_widget *w; 1436 struct snd_soc_dapm_widget *w;
1275 int reg, power; 1437 int reg;
1276 unsigned int value = 0; 1438 unsigned int value = 0;
1277 unsigned int mask = 0; 1439 unsigned int mask = 0;
1278 unsigned int cur_mask;
1279 1440
1280 reg = list_first_entry(pending, struct snd_soc_dapm_widget, 1441 reg = list_first_entry(pending, struct snd_soc_dapm_widget,
1281 power_list)->reg; 1442 power_list)->reg;
1282 1443
1283 list_for_each_entry(w, pending, power_list) { 1444 list_for_each_entry(w, pending, power_list) {
1284 cur_mask = 1 << w->shift;
1285 BUG_ON(reg != w->reg); 1445 BUG_ON(reg != w->reg);
1446 w->power = w->new_power;
1286 1447
1287 if (w->invert) 1448 mask |= w->mask << w->shift;
1288 power = !w->power; 1449 if (w->power)
1450 value |= w->on_val << w->shift;
1289 else 1451 else
1290 power = w->power; 1452 value |= w->off_val << w->shift;
1291
1292 mask |= cur_mask;
1293 if (power)
1294 value |= cur_mask;
1295 1453
1296 pop_dbg(dapm->dev, card->pop_time, 1454 pop_dbg(w->dapm->dev, card->pop_time,
1297 "pop test : Queue %s: reg=0x%x, 0x%x/0x%x\n", 1455 "pop test : Queue %s: reg=0x%x, 0x%x/0x%x\n",
1298 w->name, reg, value, mask); 1456 w->name, reg, value, mask);
1299 1457
1300 /* Check for events */ 1458 /* Check for events */
1301 dapm_seq_check_event(dapm, w, SND_SOC_DAPM_PRE_PMU); 1459 dapm_seq_check_event(card, w, SND_SOC_DAPM_PRE_PMU);
1302 dapm_seq_check_event(dapm, w, SND_SOC_DAPM_PRE_PMD); 1460 dapm_seq_check_event(card, w, SND_SOC_DAPM_PRE_PMD);
1303 } 1461 }
1304 1462
1305 if (reg >= 0) { 1463 if (reg >= 0) {
@@ -1309,7 +1467,7 @@ static void dapm_seq_run_coalesced(struct snd_soc_dapm_context *dapm,
1309 w = list_first_entry(pending, struct snd_soc_dapm_widget, 1467 w = list_first_entry(pending, struct snd_soc_dapm_widget,
1310 power_list); 1468 power_list);
1311 1469
1312 pop_dbg(dapm->dev, card->pop_time, 1470 pop_dbg(w->dapm->dev, card->pop_time,
1313 "pop test : Applying 0x%x/0x%x to %x in %dms\n", 1471 "pop test : Applying 0x%x/0x%x to %x in %dms\n",
1314 value, mask, reg, card->pop_time); 1472 value, mask, reg, card->pop_time);
1315 pop_wait(card->pop_time); 1473 pop_wait(card->pop_time);
@@ -1317,8 +1475,8 @@ static void dapm_seq_run_coalesced(struct snd_soc_dapm_context *dapm,
1317 } 1475 }
1318 1476
1319 list_for_each_entry(w, pending, power_list) { 1477 list_for_each_entry(w, pending, power_list) {
1320 dapm_seq_check_event(dapm, w, SND_SOC_DAPM_POST_PMU); 1478 dapm_seq_check_event(card, w, SND_SOC_DAPM_POST_PMU);
1321 dapm_seq_check_event(dapm, w, SND_SOC_DAPM_POST_PMD); 1479 dapm_seq_check_event(card, w, SND_SOC_DAPM_POST_PMD);
1322 } 1480 }
1323} 1481}
1324 1482
@@ -1330,8 +1488,8 @@ static void dapm_seq_run_coalesced(struct snd_soc_dapm_context *dapm,
1330 * Currently anything that requires more than a single write is not 1488 * Currently anything that requires more than a single write is not
1331 * handled. 1489 * handled.
1332 */ 1490 */
1333static void dapm_seq_run(struct snd_soc_dapm_context *dapm, 1491static void dapm_seq_run(struct snd_soc_card *card,
1334 struct list_head *list, int event, bool power_up) 1492 struct list_head *list, int event, bool power_up)
1335{ 1493{
1336 struct snd_soc_dapm_widget *w, *n; 1494 struct snd_soc_dapm_widget *w, *n;
1337 LIST_HEAD(pending); 1495 LIST_HEAD(pending);
@@ -1354,7 +1512,7 @@ static void dapm_seq_run(struct snd_soc_dapm_context *dapm,
1354 if (sort[w->id] != cur_sort || w->reg != cur_reg || 1512 if (sort[w->id] != cur_sort || w->reg != cur_reg ||
1355 w->dapm != cur_dapm || w->subseq != cur_subseq) { 1513 w->dapm != cur_dapm || w->subseq != cur_subseq) {
1356 if (!list_empty(&pending)) 1514 if (!list_empty(&pending))
1357 dapm_seq_run_coalesced(cur_dapm, &pending); 1515 dapm_seq_run_coalesced(card, &pending);
1358 1516
1359 if (cur_dapm && cur_dapm->seq_notifier) { 1517 if (cur_dapm && cur_dapm->seq_notifier) {
1360 for (i = 0; i < ARRAY_SIZE(dapm_up_seq); i++) 1518 for (i = 0; i < ARRAY_SIZE(dapm_up_seq); i++)
@@ -1414,7 +1572,7 @@ static void dapm_seq_run(struct snd_soc_dapm_context *dapm,
1414 } 1572 }
1415 1573
1416 if (!list_empty(&pending)) 1574 if (!list_empty(&pending))
1417 dapm_seq_run_coalesced(cur_dapm, &pending); 1575 dapm_seq_run_coalesced(card, &pending);
1418 1576
1419 if (cur_dapm && cur_dapm->seq_notifier) { 1577 if (cur_dapm && cur_dapm->seq_notifier) {
1420 for (i = 0; i < ARRAY_SIZE(dapm_up_seq); i++) 1578 for (i = 0; i < ARRAY_SIZE(dapm_up_seq); i++)
@@ -1424,37 +1582,48 @@ static void dapm_seq_run(struct snd_soc_dapm_context *dapm,
1424 } 1582 }
1425} 1583}
1426 1584
1427static void dapm_widget_update(struct snd_soc_dapm_context *dapm) 1585static void dapm_widget_update(struct snd_soc_card *card)
1428{ 1586{
1429 struct snd_soc_dapm_update *update = dapm->update; 1587 struct snd_soc_dapm_update *update = card->update;
1430 struct snd_soc_dapm_widget *w; 1588 struct snd_soc_dapm_widget_list *wlist;
1589 struct snd_soc_dapm_widget *w = NULL;
1590 unsigned int wi;
1431 int ret; 1591 int ret;
1432 1592
1433 if (!update) 1593 if (!update || !dapm_kcontrol_is_powered(update->kcontrol))
1434 return; 1594 return;
1435 1595
1436 w = update->widget; 1596 wlist = dapm_kcontrol_get_wlist(update->kcontrol);
1437 1597
1438 if (w->event && 1598 for (wi = 0; wi < wlist->num_widgets; wi++) {
1439 (w->event_flags & SND_SOC_DAPM_PRE_REG)) { 1599 w = wlist->widgets[wi];
1440 ret = w->event(w, update->kcontrol, SND_SOC_DAPM_PRE_REG); 1600
1441 if (ret != 0) 1601 if (w->event && (w->event_flags & SND_SOC_DAPM_PRE_REG)) {
1442 dev_err(dapm->dev, "ASoC: %s DAPM pre-event failed: %d\n", 1602 ret = w->event(w, update->kcontrol, SND_SOC_DAPM_PRE_REG);
1443 w->name, ret); 1603 if (ret != 0)
1604 dev_err(w->dapm->dev, "ASoC: %s DAPM pre-event failed: %d\n",
1605 w->name, ret);
1606 }
1444 } 1607 }
1445 1608
1609 if (!w)
1610 return;
1611
1446 ret = soc_widget_update_bits_locked(w, update->reg, update->mask, 1612 ret = soc_widget_update_bits_locked(w, update->reg, update->mask,
1447 update->val); 1613 update->val);
1448 if (ret < 0) 1614 if (ret < 0)
1449 dev_err(dapm->dev, "ASoC: %s DAPM update failed: %d\n", 1615 dev_err(w->dapm->dev, "ASoC: %s DAPM update failed: %d\n",
1450 w->name, ret); 1616 w->name, ret);
1451 1617
1452 if (w->event && 1618 for (wi = 0; wi < wlist->num_widgets; wi++) {
1453 (w->event_flags & SND_SOC_DAPM_POST_REG)) { 1619 w = wlist->widgets[wi];
1454 ret = w->event(w, update->kcontrol, SND_SOC_DAPM_POST_REG); 1620
1455 if (ret != 0) 1621 if (w->event && (w->event_flags & SND_SOC_DAPM_POST_REG)) {
1456 dev_err(dapm->dev, "ASoC: %s DAPM post-event failed: %d\n", 1622 ret = w->event(w, update->kcontrol, SND_SOC_DAPM_POST_REG);
1457 w->name, ret); 1623 if (ret != 0)
1624 dev_err(w->dapm->dev, "ASoC: %s DAPM post-event failed: %d\n",
1625 w->name, ret);
1626 }
1458 } 1627 }
1459} 1628}
1460 1629
@@ -1566,6 +1735,7 @@ static void dapm_widget_set_power(struct snd_soc_dapm_widget *w, bool power,
1566 case snd_soc_dapm_supply: 1735 case snd_soc_dapm_supply:
1567 case snd_soc_dapm_regulator_supply: 1736 case snd_soc_dapm_regulator_supply:
1568 case snd_soc_dapm_clock_supply: 1737 case snd_soc_dapm_clock_supply:
1738 case snd_soc_dapm_kcontrol:
1569 /* Supplies can't affect their outputs, only their inputs */ 1739 /* Supplies can't affect their outputs, only their inputs */
1570 break; 1740 break;
1571 default: 1741 default:
@@ -1582,8 +1752,6 @@ static void dapm_widget_set_power(struct snd_soc_dapm_widget *w, bool power,
1582 dapm_seq_insert(w, up_list, true); 1752 dapm_seq_insert(w, up_list, true);
1583 else 1753 else
1584 dapm_seq_insert(w, down_list, false); 1754 dapm_seq_insert(w, down_list, false);
1585
1586 w->power = power;
1587} 1755}
1588 1756
1589static void dapm_power_one_widget(struct snd_soc_dapm_widget *w, 1757static void dapm_power_one_widget(struct snd_soc_dapm_widget *w,
@@ -1617,9 +1785,8 @@ static void dapm_power_one_widget(struct snd_soc_dapm_widget *w,
1617 * o Input pin to Output pin (bypass, sidetone) 1785 * o Input pin to Output pin (bypass, sidetone)
1618 * o DAC to ADC (loopback). 1786 * o DAC to ADC (loopback).
1619 */ 1787 */
1620static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event) 1788static int dapm_power_widgets(struct snd_soc_card *card, int event)
1621{ 1789{
1622 struct snd_soc_card *card = dapm->card;
1623 struct snd_soc_dapm_widget *w; 1790 struct snd_soc_dapm_widget *w;
1624 struct snd_soc_dapm_context *d; 1791 struct snd_soc_dapm_context *d;
1625 LIST_HEAD(up_list); 1792 LIST_HEAD(up_list);
@@ -1659,7 +1826,7 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
1659 break; 1826 break;
1660 } 1827 }
1661 1828
1662 if (w->power) { 1829 if (w->new_power) {
1663 d = w->dapm; 1830 d = w->dapm;
1664 1831
1665 /* Supplies and micbiases only bring the 1832 /* Supplies and micbiases only bring the
@@ -1701,29 +1868,29 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
1701 trace_snd_soc_dapm_walk_done(card); 1868 trace_snd_soc_dapm_walk_done(card);
1702 1869
1703 /* Run all the bias changes in parallel */ 1870 /* Run all the bias changes in parallel */
1704 list_for_each_entry(d, &dapm->card->dapm_list, list) 1871 list_for_each_entry(d, &card->dapm_list, list)
1705 async_schedule_domain(dapm_pre_sequence_async, d, 1872 async_schedule_domain(dapm_pre_sequence_async, d,
1706 &async_domain); 1873 &async_domain);
1707 async_synchronize_full_domain(&async_domain); 1874 async_synchronize_full_domain(&async_domain);
1708 1875
1709 list_for_each_entry(w, &down_list, power_list) { 1876 list_for_each_entry(w, &down_list, power_list) {
1710 dapm_seq_check_event(dapm, w, SND_SOC_DAPM_WILL_PMD); 1877 dapm_seq_check_event(card, w, SND_SOC_DAPM_WILL_PMD);
1711 } 1878 }
1712 1879
1713 list_for_each_entry(w, &up_list, power_list) { 1880 list_for_each_entry(w, &up_list, power_list) {
1714 dapm_seq_check_event(dapm, w, SND_SOC_DAPM_WILL_PMU); 1881 dapm_seq_check_event(card, w, SND_SOC_DAPM_WILL_PMU);
1715 } 1882 }
1716 1883
1717 /* Power down widgets first; try to avoid amplifying pops. */ 1884 /* Power down widgets first; try to avoid amplifying pops. */
1718 dapm_seq_run(dapm, &down_list, event, false); 1885 dapm_seq_run(card, &down_list, event, false);
1719 1886
1720 dapm_widget_update(dapm); 1887 dapm_widget_update(card);
1721 1888
1722 /* Now power up. */ 1889 /* Now power up. */
1723 dapm_seq_run(dapm, &up_list, event, true); 1890 dapm_seq_run(card, &up_list, event, true);
1724 1891
1725 /* Run all the bias changes in parallel */ 1892 /* Run all the bias changes in parallel */
1726 list_for_each_entry(d, &dapm->card->dapm_list, list) 1893 list_for_each_entry(d, &card->dapm_list, list)
1727 async_schedule_domain(dapm_post_sequence_async, d, 1894 async_schedule_domain(dapm_post_sequence_async, d,
1728 &async_domain); 1895 &async_domain);
1729 async_synchronize_full_domain(&async_domain); 1896 async_synchronize_full_domain(&async_domain);
@@ -1734,7 +1901,7 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
1734 d->stream_event(d, event); 1901 d->stream_event(d, event);
1735 } 1902 }
1736 1903
1737 pop_dbg(dapm->dev, card->pop_time, 1904 pop_dbg(card->dev, card->pop_time,
1738 "DAPM sequencing finished, waiting %dms\n", card->pop_time); 1905 "DAPM sequencing finished, waiting %dms\n", card->pop_time);
1739 pop_wait(card->pop_time); 1906 pop_wait(card->pop_time);
1740 1907
@@ -1769,8 +1936,8 @@ static ssize_t dapm_widget_power_read_file(struct file *file,
1769 1936
1770 if (w->reg >= 0) 1937 if (w->reg >= 0)
1771 ret += snprintf(buf + ret, PAGE_SIZE - ret, 1938 ret += snprintf(buf + ret, PAGE_SIZE - ret,
1772 " - R%d(0x%x) bit %d", 1939 " - R%d(0x%x) mask 0x%x",
1773 w->reg, w->reg, w->shift); 1940 w->reg, w->reg, w->mask << w->shift);
1774 1941
1775 ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n"); 1942 ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n");
1776 1943
@@ -1907,22 +2074,14 @@ static inline void dapm_debugfs_cleanup(struct snd_soc_dapm_context *dapm)
1907#endif 2074#endif
1908 2075
1909/* test and update the power status of a mux widget */ 2076/* test and update the power status of a mux widget */
1910static int soc_dapm_mux_update_power(struct snd_soc_dapm_widget *widget, 2077static int soc_dapm_mux_update_power(struct snd_soc_card *card,
1911 struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e) 2078 struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e)
1912{ 2079{
1913 struct snd_soc_dapm_path *path; 2080 struct snd_soc_dapm_path *path;
1914 int found = 0; 2081 int found = 0;
1915 2082
1916 if (widget->id != snd_soc_dapm_mux &&
1917 widget->id != snd_soc_dapm_virt_mux &&
1918 widget->id != snd_soc_dapm_value_mux)
1919 return -ENODEV;
1920
1921 /* find dapm widget path assoc with kcontrol */ 2083 /* find dapm widget path assoc with kcontrol */
1922 list_for_each_entry(path, &widget->dapm->card->paths, list) { 2084 dapm_kcontrol_for_each_path(path, kcontrol) {
1923 if (path->kcontrol != kcontrol)
1924 continue;
1925
1926 if (!path->name || !e->texts[mux]) 2085 if (!path->name || !e->texts[mux])
1927 continue; 2086 continue;
1928 2087
@@ -1937,73 +2096,68 @@ static int soc_dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
1937 "mux disconnection"); 2096 "mux disconnection");
1938 path->connect = 0; /* old connection must be powered down */ 2097 path->connect = 0; /* old connection must be powered down */
1939 } 2098 }
2099 dapm_mark_dirty(path->sink, "mux change");
1940 } 2100 }
1941 2101
1942 if (found) { 2102 if (found)
1943 dapm_mark_dirty(widget, "mux change"); 2103 dapm_power_widgets(card, SND_SOC_DAPM_STREAM_NOP);
1944 dapm_power_widgets(widget->dapm, SND_SOC_DAPM_STREAM_NOP);
1945 }
1946 2104
1947 return found; 2105 return found;
1948} 2106}
1949 2107
1950int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_widget *widget, 2108int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_context *dapm,
1951 struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e) 2109 struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e,
2110 struct snd_soc_dapm_update *update)
1952{ 2111{
1953 struct snd_soc_card *card = widget->dapm->card; 2112 struct snd_soc_card *card = dapm->card;
1954 int ret; 2113 int ret;
1955 2114
1956 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); 2115 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
1957 ret = soc_dapm_mux_update_power(widget, kcontrol, mux, e); 2116 card->update = update;
2117 ret = soc_dapm_mux_update_power(card, kcontrol, mux, e);
2118 card->update = NULL;
1958 mutex_unlock(&card->dapm_mutex); 2119 mutex_unlock(&card->dapm_mutex);
1959 if (ret > 0) 2120 if (ret > 0)
1960 soc_dpcm_runtime_update(widget); 2121 soc_dpcm_runtime_update(card);
1961 return ret; 2122 return ret;
1962} 2123}
1963EXPORT_SYMBOL_GPL(snd_soc_dapm_mux_update_power); 2124EXPORT_SYMBOL_GPL(snd_soc_dapm_mux_update_power);
1964 2125
1965/* test and update the power status of a mixer or switch widget */ 2126/* test and update the power status of a mixer or switch widget */
1966static int soc_dapm_mixer_update_power(struct snd_soc_dapm_widget *widget, 2127static int soc_dapm_mixer_update_power(struct snd_soc_card *card,
1967 struct snd_kcontrol *kcontrol, int connect) 2128 struct snd_kcontrol *kcontrol, int connect)
1968{ 2129{
1969 struct snd_soc_dapm_path *path; 2130 struct snd_soc_dapm_path *path;
1970 int found = 0; 2131 int found = 0;
1971 2132
1972 if (widget->id != snd_soc_dapm_mixer &&
1973 widget->id != snd_soc_dapm_mixer_named_ctl &&
1974 widget->id != snd_soc_dapm_switch)
1975 return -ENODEV;
1976
1977 /* find dapm widget path assoc with kcontrol */ 2133 /* find dapm widget path assoc with kcontrol */
1978 list_for_each_entry(path, &widget->dapm->card->paths, list) { 2134 dapm_kcontrol_for_each_path(path, kcontrol) {
1979 if (path->kcontrol != kcontrol)
1980 continue;
1981
1982 /* found, now check type */
1983 found = 1; 2135 found = 1;
1984 path->connect = connect; 2136 path->connect = connect;
1985 dapm_mark_dirty(path->source, "mixer connection"); 2137 dapm_mark_dirty(path->source, "mixer connection");
2138 dapm_mark_dirty(path->sink, "mixer update");
1986 } 2139 }
1987 2140
1988 if (found) { 2141 if (found)
1989 dapm_mark_dirty(widget, "mixer update"); 2142 dapm_power_widgets(card, SND_SOC_DAPM_STREAM_NOP);
1990 dapm_power_widgets(widget->dapm, SND_SOC_DAPM_STREAM_NOP);
1991 }
1992 2143
1993 return found; 2144 return found;
1994} 2145}
1995 2146
1996int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_widget *widget, 2147int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_context *dapm,
1997 struct snd_kcontrol *kcontrol, int connect) 2148 struct snd_kcontrol *kcontrol, int connect,
2149 struct snd_soc_dapm_update *update)
1998{ 2150{
1999 struct snd_soc_card *card = widget->dapm->card; 2151 struct snd_soc_card *card = dapm->card;
2000 int ret; 2152 int ret;
2001 2153
2002 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); 2154 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
2003 ret = soc_dapm_mixer_update_power(widget, kcontrol, connect); 2155 card->update = update;
2156 ret = soc_dapm_mixer_update_power(card, kcontrol, connect);
2157 card->update = NULL;
2004 mutex_unlock(&card->dapm_mutex); 2158 mutex_unlock(&card->dapm_mutex);
2005 if (ret > 0) 2159 if (ret > 0)
2006 soc_dpcm_runtime_update(widget); 2160 soc_dpcm_runtime_update(card);
2007 return ret; 2161 return ret;
2008} 2162}
2009EXPORT_SYMBOL_GPL(snd_soc_dapm_mixer_update_power); 2163EXPORT_SYMBOL_GPL(snd_soc_dapm_mixer_update_power);
@@ -2082,6 +2236,7 @@ static void dapm_free_path(struct snd_soc_dapm_path *path)
2082{ 2236{
2083 list_del(&path->list_sink); 2237 list_del(&path->list_sink);
2084 list_del(&path->list_source); 2238 list_del(&path->list_source);
2239 list_del(&path->list_kcontrol);
2085 list_del(&path->list); 2240 list_del(&path->list);
2086 kfree(path); 2241 kfree(path);
2087} 2242}
@@ -2176,70 +2331,20 @@ int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm)
2176 return 0; 2331 return 0;
2177 2332
2178 mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); 2333 mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
2179 ret = dapm_power_widgets(dapm, SND_SOC_DAPM_STREAM_NOP); 2334 ret = dapm_power_widgets(dapm->card, SND_SOC_DAPM_STREAM_NOP);
2180 mutex_unlock(&dapm->card->dapm_mutex); 2335 mutex_unlock(&dapm->card->dapm_mutex);
2181 return ret; 2336 return ret;
2182} 2337}
2183EXPORT_SYMBOL_GPL(snd_soc_dapm_sync); 2338EXPORT_SYMBOL_GPL(snd_soc_dapm_sync);
2184 2339
2185static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm, 2340static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm,
2186 const struct snd_soc_dapm_route *route) 2341 struct snd_soc_dapm_widget *wsource, struct snd_soc_dapm_widget *wsink,
2342 const char *control,
2343 int (*connected)(struct snd_soc_dapm_widget *source,
2344 struct snd_soc_dapm_widget *sink))
2187{ 2345{
2188 struct snd_soc_dapm_path *path; 2346 struct snd_soc_dapm_path *path;
2189 struct snd_soc_dapm_widget *wsource = NULL, *wsink = NULL, *w; 2347 int ret;
2190 struct snd_soc_dapm_widget *wtsource = NULL, *wtsink = NULL;
2191 const char *sink;
2192 const char *control = route->control;
2193 const char *source;
2194 char prefixed_sink[80];
2195 char prefixed_source[80];
2196 int ret = 0;
2197
2198 if (dapm->codec && dapm->codec->name_prefix) {
2199 snprintf(prefixed_sink, sizeof(prefixed_sink), "%s %s",
2200 dapm->codec->name_prefix, route->sink);
2201 sink = prefixed_sink;
2202 snprintf(prefixed_source, sizeof(prefixed_source), "%s %s",
2203 dapm->codec->name_prefix, route->source);
2204 source = prefixed_source;
2205 } else {
2206 sink = route->sink;
2207 source = route->source;
2208 }
2209
2210 /*
2211 * find src and dest widgets over all widgets but favor a widget from
2212 * current DAPM context
2213 */
2214 list_for_each_entry(w, &dapm->card->widgets, list) {
2215 if (!wsink && !(strcmp(w->name, sink))) {
2216 wtsink = w;
2217 if (w->dapm == dapm)
2218 wsink = w;
2219 continue;
2220 }
2221 if (!wsource && !(strcmp(w->name, source))) {
2222 wtsource = w;
2223 if (w->dapm == dapm)
2224 wsource = w;
2225 }
2226 }
2227 /* use widget from another DAPM context if not found from this */
2228 if (!wsink)
2229 wsink = wtsink;
2230 if (!wsource)
2231 wsource = wtsource;
2232
2233 if (wsource == NULL) {
2234 dev_err(dapm->dev, "ASoC: no source widget found for %s\n",
2235 route->source);
2236 return -ENODEV;
2237 }
2238 if (wsink == NULL) {
2239 dev_err(dapm->dev, "ASoC: no sink widget found for %s\n",
2240 route->sink);
2241 return -ENODEV;
2242 }
2243 2348
2244 path = kzalloc(sizeof(struct snd_soc_dapm_path), GFP_KERNEL); 2349 path = kzalloc(sizeof(struct snd_soc_dapm_path), GFP_KERNEL);
2245 if (!path) 2350 if (!path)
@@ -2247,8 +2352,9 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
2247 2352
2248 path->source = wsource; 2353 path->source = wsource;
2249 path->sink = wsink; 2354 path->sink = wsink;
2250 path->connected = route->connected; 2355 path->connected = connected;
2251 INIT_LIST_HEAD(&path->list); 2356 INIT_LIST_HEAD(&path->list);
2357 INIT_LIST_HEAD(&path->list_kcontrol);
2252 INIT_LIST_HEAD(&path->list_source); 2358 INIT_LIST_HEAD(&path->list_source);
2253 INIT_LIST_HEAD(&path->list_sink); 2359 INIT_LIST_HEAD(&path->list_sink);
2254 2360
@@ -2268,6 +2374,9 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
2268 wsource->ext = 1; 2374 wsource->ext = 1;
2269 } 2375 }
2270 2376
2377 dapm_mark_dirty(wsource, "Route added");
2378 dapm_mark_dirty(wsink, "Route added");
2379
2271 /* connect static paths */ 2380 /* connect static paths */
2272 if (control == NULL) { 2381 if (control == NULL) {
2273 list_add(&path->list, &dapm->card->paths); 2382 list_add(&path->list, &dapm->card->paths);
@@ -2298,6 +2407,7 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
2298 case snd_soc_dapm_dai_in: 2407 case snd_soc_dapm_dai_in:
2299 case snd_soc_dapm_dai_out: 2408 case snd_soc_dapm_dai_out:
2300 case snd_soc_dapm_dai_link: 2409 case snd_soc_dapm_dai_link:
2410 case snd_soc_dapm_kcontrol:
2301 list_add(&path->list, &dapm->card->paths); 2411 list_add(&path->list, &dapm->card->paths);
2302 list_add(&path->list_sink, &wsink->sources); 2412 list_add(&path->list_sink, &wsink->sources);
2303 list_add(&path->list_source, &wsource->sinks); 2413 list_add(&path->list_source, &wsource->sinks);
@@ -2329,15 +2439,78 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
2329 return 0; 2439 return 0;
2330 } 2440 }
2331 2441
2332 dapm_mark_dirty(wsource, "Route added");
2333 dapm_mark_dirty(wsink, "Route added");
2334
2335 return 0; 2442 return 0;
2443err:
2444 kfree(path);
2445 return ret;
2446}
2447
2448static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
2449 const struct snd_soc_dapm_route *route)
2450{
2451 struct snd_soc_dapm_widget *wsource = NULL, *wsink = NULL, *w;
2452 struct snd_soc_dapm_widget *wtsource = NULL, *wtsink = NULL;
2453 const char *sink;
2454 const char *source;
2455 char prefixed_sink[80];
2456 char prefixed_source[80];
2457 int ret;
2458
2459 if (dapm->codec && dapm->codec->name_prefix) {
2460 snprintf(prefixed_sink, sizeof(prefixed_sink), "%s %s",
2461 dapm->codec->name_prefix, route->sink);
2462 sink = prefixed_sink;
2463 snprintf(prefixed_source, sizeof(prefixed_source), "%s %s",
2464 dapm->codec->name_prefix, route->source);
2465 source = prefixed_source;
2466 } else {
2467 sink = route->sink;
2468 source = route->source;
2469 }
2470
2471 /*
2472 * find src and dest widgets over all widgets but favor a widget from
2473 * current DAPM context
2474 */
2475 list_for_each_entry(w, &dapm->card->widgets, list) {
2476 if (!wsink && !(strcmp(w->name, sink))) {
2477 wtsink = w;
2478 if (w->dapm == dapm)
2479 wsink = w;
2480 continue;
2481 }
2482 if (!wsource && !(strcmp(w->name, source))) {
2483 wtsource = w;
2484 if (w->dapm == dapm)
2485 wsource = w;
2486 }
2487 }
2488 /* use widget from another DAPM context if not found from this */
2489 if (!wsink)
2490 wsink = wtsink;
2491 if (!wsource)
2492 wsource = wtsource;
2336 2493
2494 if (wsource == NULL) {
2495 dev_err(dapm->dev, "ASoC: no source widget found for %s\n",
2496 route->source);
2497 return -ENODEV;
2498 }
2499 if (wsink == NULL) {
2500 dev_err(dapm->dev, "ASoC: no sink widget found for %s\n",
2501 route->sink);
2502 return -ENODEV;
2503 }
2504
2505 ret = snd_soc_dapm_add_path(dapm, wsource, wsink, route->control,
2506 route->connected);
2507 if (ret)
2508 goto err;
2509
2510 return 0;
2337err: 2511err:
2338 dev_warn(dapm->dev, "ASoC: no dapm match for %s --> %s --> %s\n", 2512 dev_warn(dapm->dev, "ASoC: no dapm match for %s --> %s --> %s\n",
2339 source, control, sink); 2513 source, route->control, sink);
2340 kfree(path);
2341 return ret; 2514 return ret;
2342} 2515}
2343 2516
@@ -2541,12 +2714,13 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_weak_routes);
2541 */ 2714 */
2542int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm) 2715int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm)
2543{ 2716{
2717 struct snd_soc_card *card = dapm->card;
2544 struct snd_soc_dapm_widget *w; 2718 struct snd_soc_dapm_widget *w;
2545 unsigned int val; 2719 unsigned int val;
2546 2720
2547 mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT); 2721 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT);
2548 2722
2549 list_for_each_entry(w, &dapm->card->widgets, list) 2723 list_for_each_entry(w, &card->widgets, list)
2550 { 2724 {
2551 if (w->new) 2725 if (w->new)
2552 continue; 2726 continue;
@@ -2556,7 +2730,7 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm)
2556 sizeof(struct snd_kcontrol *), 2730 sizeof(struct snd_kcontrol *),
2557 GFP_KERNEL); 2731 GFP_KERNEL);
2558 if (!w->kcontrols) { 2732 if (!w->kcontrols) {
2559 mutex_unlock(&dapm->card->dapm_mutex); 2733 mutex_unlock(&card->dapm_mutex);
2560 return -ENOMEM; 2734 return -ENOMEM;
2561 } 2735 }
2562 } 2736 }
@@ -2582,12 +2756,9 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm)
2582 2756
2583 /* Read the initial power state from the device */ 2757 /* Read the initial power state from the device */
2584 if (w->reg >= 0) { 2758 if (w->reg >= 0) {
2585 val = soc_widget_read(w, w->reg); 2759 val = soc_widget_read(w, w->reg) >> w->shift;
2586 val &= 1 << w->shift; 2760 val &= w->mask;
2587 if (w->invert) 2761 if (val == w->on_val)
2588 val = !val;
2589
2590 if (val)
2591 w->power = 1; 2762 w->power = 1;
2592 } 2763 }
2593 2764
@@ -2597,8 +2768,8 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm)
2597 dapm_debugfs_add_widget(w); 2768 dapm_debugfs_add_widget(w);
2598 } 2769 }
2599 2770
2600 dapm_power_widgets(dapm, SND_SOC_DAPM_STREAM_NOP); 2771 dapm_power_widgets(card, SND_SOC_DAPM_STREAM_NOP);
2601 mutex_unlock(&dapm->card->dapm_mutex); 2772 mutex_unlock(&card->dapm_mutex);
2602 return 0; 2773 return 0;
2603} 2774}
2604EXPORT_SYMBOL_GPL(snd_soc_dapm_new_widgets); 2775EXPORT_SYMBOL_GPL(snd_soc_dapm_new_widgets);
@@ -2615,8 +2786,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_new_widgets);
2615int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, 2786int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol,
2616 struct snd_ctl_elem_value *ucontrol) 2787 struct snd_ctl_elem_value *ucontrol)
2617{ 2788{
2618 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); 2789 struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
2619 struct snd_soc_dapm_widget *widget = wlist->widgets[0]; 2790 struct snd_soc_card *card = codec->card;
2620 struct soc_mixer_control *mc = 2791 struct soc_mixer_control *mc =
2621 (struct soc_mixer_control *)kcontrol->private_value; 2792 (struct soc_mixer_control *)kcontrol->private_value;
2622 unsigned int reg = mc->reg; 2793 unsigned int reg = mc->reg;
@@ -2624,17 +2795,24 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol,
2624 int max = mc->max; 2795 int max = mc->max;
2625 unsigned int mask = (1 << fls(max)) - 1; 2796 unsigned int mask = (1 << fls(max)) - 1;
2626 unsigned int invert = mc->invert; 2797 unsigned int invert = mc->invert;
2798 unsigned int val;
2627 2799
2628 if (snd_soc_volsw_is_stereo(mc)) 2800 if (snd_soc_volsw_is_stereo(mc))
2629 dev_warn(widget->dapm->dev, 2801 dev_warn(codec->dapm.dev,
2630 "ASoC: Control '%s' is stereo, which is not supported\n", 2802 "ASoC: Control '%s' is stereo, which is not supported\n",
2631 kcontrol->id.name); 2803 kcontrol->id.name);
2632 2804
2633 ucontrol->value.integer.value[0] = 2805 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
2634 (snd_soc_read(widget->codec, reg) >> shift) & mask; 2806 if (dapm_kcontrol_is_powered(kcontrol))
2807 val = (snd_soc_read(codec, reg) >> shift) & mask;
2808 else
2809 val = dapm_kcontrol_get_value(kcontrol);
2810 mutex_unlock(&card->dapm_mutex);
2811
2635 if (invert) 2812 if (invert)
2636 ucontrol->value.integer.value[0] = 2813 ucontrol->value.integer.value[0] = max - val;
2637 max - ucontrol->value.integer.value[0]; 2814 else
2815 ucontrol->value.integer.value[0] = val;
2638 2816
2639 return 0; 2817 return 0;
2640} 2818}
@@ -2652,9 +2830,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_volsw);
2652int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, 2830int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
2653 struct snd_ctl_elem_value *ucontrol) 2831 struct snd_ctl_elem_value *ucontrol)
2654{ 2832{
2655 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); 2833 struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
2656 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
2657 struct snd_soc_codec *codec = widget->codec;
2658 struct snd_soc_card *card = codec->card; 2834 struct snd_soc_card *card = codec->card;
2659 struct soc_mixer_control *mc = 2835 struct soc_mixer_control *mc =
2660 (struct soc_mixer_control *)kcontrol->private_value; 2836 (struct soc_mixer_control *)kcontrol->private_value;
@@ -2666,10 +2842,9 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
2666 unsigned int val; 2842 unsigned int val;
2667 int connect, change; 2843 int connect, change;
2668 struct snd_soc_dapm_update update; 2844 struct snd_soc_dapm_update update;
2669 int wi;
2670 2845
2671 if (snd_soc_volsw_is_stereo(mc)) 2846 if (snd_soc_volsw_is_stereo(mc))
2672 dev_warn(widget->dapm->dev, 2847 dev_warn(codec->dapm.dev,
2673 "ASoC: Control '%s' is stereo, which is not supported\n", 2848 "ASoC: Control '%s' is stereo, which is not supported\n",
2674 kcontrol->id.name); 2849 kcontrol->id.name);
2675 2850
@@ -2678,29 +2853,26 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
2678 2853
2679 if (invert) 2854 if (invert)
2680 val = max - val; 2855 val = max - val;
2681 mask = mask << shift;
2682 val = val << shift;
2683 2856
2684 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); 2857 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
2685 2858
2686 change = snd_soc_test_bits(widget->codec, reg, mask, val); 2859 dapm_kcontrol_set_value(kcontrol, val);
2687 if (change) {
2688 for (wi = 0; wi < wlist->num_widgets; wi++) {
2689 widget = wlist->widgets[wi];
2690 2860
2691 widget->value = val; 2861 mask = mask << shift;
2862 val = val << shift;
2692 2863
2693 update.kcontrol = kcontrol; 2864 change = snd_soc_test_bits(codec, reg, mask, val);
2694 update.widget = widget; 2865 if (change) {
2695 update.reg = reg; 2866 update.kcontrol = kcontrol;
2696 update.mask = mask; 2867 update.reg = reg;
2697 update.val = val; 2868 update.mask = mask;
2698 widget->dapm->update = &update; 2869 update.val = val;
2699 2870
2700 soc_dapm_mixer_update_power(widget, kcontrol, connect); 2871 card->update = &update;
2701 2872
2702 widget->dapm->update = NULL; 2873 soc_dapm_mixer_update_power(card, kcontrol, connect);
2703 } 2874
2875 card->update = NULL;
2704 } 2876 }
2705 2877
2706 mutex_unlock(&card->dapm_mutex); 2878 mutex_unlock(&card->dapm_mutex);
@@ -2720,12 +2892,11 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw);
2720int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol, 2892int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol,
2721 struct snd_ctl_elem_value *ucontrol) 2893 struct snd_ctl_elem_value *ucontrol)
2722{ 2894{
2723 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); 2895 struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
2724 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
2725 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 2896 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
2726 unsigned int val; 2897 unsigned int val;
2727 2898
2728 val = snd_soc_read(widget->codec, e->reg); 2899 val = snd_soc_read(codec, e->reg);
2729 ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & e->mask; 2900 ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & e->mask;
2730 if (e->shift_l != e->shift_r) 2901 if (e->shift_l != e->shift_r)
2731 ucontrol->value.enumerated.item[1] = 2902 ucontrol->value.enumerated.item[1] =
@@ -2747,15 +2918,12 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_double);
2747int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, 2918int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
2748 struct snd_ctl_elem_value *ucontrol) 2919 struct snd_ctl_elem_value *ucontrol)
2749{ 2920{
2750 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); 2921 struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
2751 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
2752 struct snd_soc_codec *codec = widget->codec;
2753 struct snd_soc_card *card = codec->card; 2922 struct snd_soc_card *card = codec->card;
2754 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 2923 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
2755 unsigned int val, mux, change; 2924 unsigned int val, mux, change;
2756 unsigned int mask; 2925 unsigned int mask;
2757 struct snd_soc_dapm_update update; 2926 struct snd_soc_dapm_update update;
2758 int wi;
2759 2927
2760 if (ucontrol->value.enumerated.item[0] > e->max - 1) 2928 if (ucontrol->value.enumerated.item[0] > e->max - 1)
2761 return -EINVAL; 2929 return -EINVAL;
@@ -2771,24 +2939,17 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
2771 2939
2772 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); 2940 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
2773 2941
2774 change = snd_soc_test_bits(widget->codec, e->reg, mask, val); 2942 change = snd_soc_test_bits(codec, e->reg, mask, val);
2775 if (change) { 2943 if (change) {
2776 for (wi = 0; wi < wlist->num_widgets; wi++) { 2944 update.kcontrol = kcontrol;
2777 widget = wlist->widgets[wi]; 2945 update.reg = e->reg;
2778 2946 update.mask = mask;
2779 widget->value = val; 2947 update.val = val;
2948 card->update = &update;
2780 2949
2781 update.kcontrol = kcontrol; 2950 soc_dapm_mux_update_power(card, kcontrol, mux, e);
2782 update.widget = widget;
2783 update.reg = e->reg;
2784 update.mask = mask;
2785 update.val = val;
2786 widget->dapm->update = &update;
2787 2951
2788 soc_dapm_mux_update_power(widget, kcontrol, mux, e); 2952 card->update = NULL;
2789
2790 widget->dapm->update = NULL;
2791 }
2792 } 2953 }
2793 2954
2794 mutex_unlock(&card->dapm_mutex); 2955 mutex_unlock(&card->dapm_mutex);
@@ -2806,11 +2967,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double);
2806int snd_soc_dapm_get_enum_virt(struct snd_kcontrol *kcontrol, 2967int snd_soc_dapm_get_enum_virt(struct snd_kcontrol *kcontrol,
2807 struct snd_ctl_elem_value *ucontrol) 2968 struct snd_ctl_elem_value *ucontrol)
2808{ 2969{
2809 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); 2970 ucontrol->value.enumerated.item[0] = dapm_kcontrol_get_value(kcontrol);
2810 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
2811
2812 ucontrol->value.enumerated.item[0] = widget->value;
2813
2814 return 0; 2971 return 0;
2815} 2972}
2816EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_virt); 2973EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_virt);
@@ -2825,30 +2982,22 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_virt);
2825int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol, 2982int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol,
2826 struct snd_ctl_elem_value *ucontrol) 2983 struct snd_ctl_elem_value *ucontrol)
2827{ 2984{
2828 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); 2985 struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
2829 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
2830 struct snd_soc_codec *codec = widget->codec;
2831 struct snd_soc_card *card = codec->card; 2986 struct snd_soc_card *card = codec->card;
2987 unsigned int value;
2832 struct soc_enum *e = 2988 struct soc_enum *e =
2833 (struct soc_enum *)kcontrol->private_value; 2989 (struct soc_enum *)kcontrol->private_value;
2834 int change; 2990 int change;
2835 int wi;
2836 2991
2837 if (ucontrol->value.enumerated.item[0] >= e->max) 2992 if (ucontrol->value.enumerated.item[0] >= e->max)
2838 return -EINVAL; 2993 return -EINVAL;
2839 2994
2840 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); 2995 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
2841 2996
2842 change = widget->value != ucontrol->value.enumerated.item[0]; 2997 value = ucontrol->value.enumerated.item[0];
2843 if (change) { 2998 change = dapm_kcontrol_set_value(kcontrol, value);
2844 for (wi = 0; wi < wlist->num_widgets; wi++) { 2999 if (change)
2845 widget = wlist->widgets[wi]; 3000 soc_dapm_mux_update_power(card, kcontrol, value, e);
2846
2847 widget->value = ucontrol->value.enumerated.item[0];
2848
2849 soc_dapm_mux_update_power(widget, kcontrol, widget->value, e);
2850 }
2851 }
2852 3001
2853 mutex_unlock(&card->dapm_mutex); 3002 mutex_unlock(&card->dapm_mutex);
2854 return change; 3003 return change;
@@ -2871,12 +3020,11 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_virt);
2871int snd_soc_dapm_get_value_enum_double(struct snd_kcontrol *kcontrol, 3020int snd_soc_dapm_get_value_enum_double(struct snd_kcontrol *kcontrol,
2872 struct snd_ctl_elem_value *ucontrol) 3021 struct snd_ctl_elem_value *ucontrol)
2873{ 3022{
2874 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); 3023 struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
2875 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
2876 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 3024 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
2877 unsigned int reg_val, val, mux; 3025 unsigned int reg_val, val, mux;
2878 3026
2879 reg_val = snd_soc_read(widget->codec, e->reg); 3027 reg_val = snd_soc_read(codec, e->reg);
2880 val = (reg_val >> e->shift_l) & e->mask; 3028 val = (reg_val >> e->shift_l) & e->mask;
2881 for (mux = 0; mux < e->max; mux++) { 3029 for (mux = 0; mux < e->max; mux++) {
2882 if (val == e->values[mux]) 3030 if (val == e->values[mux])
@@ -2912,15 +3060,12 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_value_enum_double);
2912int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol, 3060int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
2913 struct snd_ctl_elem_value *ucontrol) 3061 struct snd_ctl_elem_value *ucontrol)
2914{ 3062{
2915 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); 3063 struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
2916 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
2917 struct snd_soc_codec *codec = widget->codec;
2918 struct snd_soc_card *card = codec->card; 3064 struct snd_soc_card *card = codec->card;
2919 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 3065 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
2920 unsigned int val, mux, change; 3066 unsigned int val, mux, change;
2921 unsigned int mask; 3067 unsigned int mask;
2922 struct snd_soc_dapm_update update; 3068 struct snd_soc_dapm_update update;
2923 int wi;
2924 3069
2925 if (ucontrol->value.enumerated.item[0] > e->max - 1) 3070 if (ucontrol->value.enumerated.item[0] > e->max - 1)
2926 return -EINVAL; 3071 return -EINVAL;
@@ -2936,24 +3081,17 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
2936 3081
2937 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); 3082 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
2938 3083
2939 change = snd_soc_test_bits(widget->codec, e->reg, mask, val); 3084 change = snd_soc_test_bits(codec, e->reg, mask, val);
2940 if (change) { 3085 if (change) {
2941 for (wi = 0; wi < wlist->num_widgets; wi++) { 3086 update.kcontrol = kcontrol;
2942 widget = wlist->widgets[wi]; 3087 update.reg = e->reg;
2943 3088 update.mask = mask;
2944 widget->value = val; 3089 update.val = val;
3090 card->update = &update;
2945 3091
2946 update.kcontrol = kcontrol; 3092 soc_dapm_mux_update_power(card, kcontrol, mux, e);
2947 update.widget = widget;
2948 update.reg = e->reg;
2949 update.mask = mask;
2950 update.val = val;
2951 widget->dapm->update = &update;
2952 3093
2953 soc_dapm_mux_update_power(widget, kcontrol, mux, e); 3094 card->update = NULL;
2954
2955 widget->dapm->update = NULL;
2956 }
2957 } 3095 }
2958 3096
2959 mutex_unlock(&card->dapm_mutex); 3097 mutex_unlock(&card->dapm_mutex);
@@ -3050,7 +3188,7 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
3050 return NULL; 3188 return NULL;
3051 } 3189 }
3052 3190
3053 if (w->invert & SND_SOC_DAPM_REGULATOR_BYPASS) { 3191 if (w->on_val & SND_SOC_DAPM_REGULATOR_BYPASS) {
3054 ret = regulator_allow_bypass(w->regulator, true); 3192 ret = regulator_allow_bypass(w->regulator, true);
3055 if (ret != 0) 3193 if (ret != 0)
3056 dev_warn(w->dapm->dev, 3194 dev_warn(w->dapm->dev,
@@ -3097,16 +3235,16 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
3097 case snd_soc_dapm_value_mux: 3235 case snd_soc_dapm_value_mux:
3098 w->power_check = dapm_generic_check_power; 3236 w->power_check = dapm_generic_check_power;
3099 break; 3237 break;
3100 case snd_soc_dapm_adc:
3101 case snd_soc_dapm_aif_out:
3102 case snd_soc_dapm_dai_out: 3238 case snd_soc_dapm_dai_out:
3103 w->power_check = dapm_adc_check_power; 3239 w->power_check = dapm_adc_check_power;
3104 break; 3240 break;
3105 case snd_soc_dapm_dac:
3106 case snd_soc_dapm_aif_in:
3107 case snd_soc_dapm_dai_in: 3241 case snd_soc_dapm_dai_in:
3108 w->power_check = dapm_dac_check_power; 3242 w->power_check = dapm_dac_check_power;
3109 break; 3243 break;
3244 case snd_soc_dapm_adc:
3245 case snd_soc_dapm_aif_out:
3246 case snd_soc_dapm_dac:
3247 case snd_soc_dapm_aif_in:
3110 case snd_soc_dapm_pga: 3248 case snd_soc_dapm_pga:
3111 case snd_soc_dapm_out_drv: 3249 case snd_soc_dapm_out_drv:
3112 case snd_soc_dapm_input: 3250 case snd_soc_dapm_input:
@@ -3122,6 +3260,7 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
3122 case snd_soc_dapm_supply: 3260 case snd_soc_dapm_supply:
3123 case snd_soc_dapm_regulator_supply: 3261 case snd_soc_dapm_regulator_supply:
3124 case snd_soc_dapm_clock_supply: 3262 case snd_soc_dapm_clock_supply:
3263 case snd_soc_dapm_kcontrol:
3125 w->power_check = dapm_supply_check_power; 3264 w->power_check = dapm_supply_check_power;
3126 break; 3265 break;
3127 default: 3266 default:
@@ -3386,9 +3525,6 @@ int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card)
3386{ 3525{
3387 struct snd_soc_dapm_widget *dai_w, *w; 3526 struct snd_soc_dapm_widget *dai_w, *w;
3388 struct snd_soc_dai *dai; 3527 struct snd_soc_dai *dai;
3389 struct snd_soc_dapm_route r;
3390
3391 memset(&r, 0, sizeof(r));
3392 3528
3393 /* For each DAI widget... */ 3529 /* For each DAI widget... */
3394 list_for_each_entry(dai_w, &card->widgets, list) { 3530 list_for_each_entry(dai_w, &card->widgets, list) {
@@ -3415,29 +3551,27 @@ int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card)
3415 break; 3551 break;
3416 } 3552 }
3417 3553
3418 if (!w->sname) 3554 if (!w->sname || !strstr(w->sname, dai_w->name))
3419 continue; 3555 continue;
3420 3556
3421 if (dai->driver->playback.stream_name && 3557 if (dai->driver->playback.stream_name &&
3422 strstr(w->sname, 3558 strstr(w->sname,
3423 dai->driver->playback.stream_name)) { 3559 dai->driver->playback.stream_name)) {
3424 r.source = dai->playback_widget->name;
3425 r.sink = w->name;
3426 dev_dbg(dai->dev, "%s -> %s\n", 3560 dev_dbg(dai->dev, "%s -> %s\n",
3427 r.source, r.sink); 3561 dai->playback_widget->name, w->name);
3428 3562
3429 snd_soc_dapm_add_route(w->dapm, &r); 3563 snd_soc_dapm_add_path(w->dapm,
3564 dai->playback_widget, w, NULL, NULL);
3430 } 3565 }
3431 3566
3432 if (dai->driver->capture.stream_name && 3567 if (dai->driver->capture.stream_name &&
3433 strstr(w->sname, 3568 strstr(w->sname,
3434 dai->driver->capture.stream_name)) { 3569 dai->driver->capture.stream_name)) {
3435 r.source = w->name;
3436 r.sink = dai->capture_widget->name;
3437 dev_dbg(dai->dev, "%s -> %s\n", 3570 dev_dbg(dai->dev, "%s -> %s\n",
3438 r.source, r.sink); 3571 w->name, dai->capture_widget->name);
3439 3572
3440 snd_soc_dapm_add_route(w->dapm, &r); 3573 snd_soc_dapm_add_path(w->dapm, w,
3574 dai->capture_widget, NULL, NULL);
3441 } 3575 }
3442 } 3576 }
3443 } 3577 }
@@ -3499,7 +3633,7 @@ static void soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
3499 } 3633 }
3500 } 3634 }
3501 3635
3502 dapm_power_widgets(&rtd->card->dapm, event); 3636 dapm_power_widgets(rtd->card, event);
3503} 3637}
3504 3638
3505/** 3639/**
@@ -3768,7 +3902,7 @@ static void soc_dapm_shutdown_codec(struct snd_soc_dapm_context *dapm)
3768 if (dapm->bias_level == SND_SOC_BIAS_ON) 3902 if (dapm->bias_level == SND_SOC_BIAS_ON)
3769 snd_soc_dapm_set_bias_level(dapm, 3903 snd_soc_dapm_set_bias_level(dapm,
3770 SND_SOC_BIAS_PREPARE); 3904 SND_SOC_BIAS_PREPARE);
3771 dapm_seq_run(dapm, &down_list, 0, false); 3905 dapm_seq_run(card, &down_list, 0, false);
3772 if (dapm->bias_level == SND_SOC_BIAS_PREPARE) 3906 if (dapm->bias_level == SND_SOC_BIAS_PREPARE)
3773 snd_soc_dapm_set_bias_level(dapm, 3907 snd_soc_dapm_set_bias_level(dapm,
3774 SND_SOC_BIAS_STANDBY); 3908 SND_SOC_BIAS_STANDBY);
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index f4f68cb3cb00..fb70fbe26862 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -1833,18 +1833,10 @@ static int dpcm_run_old_update(struct snd_soc_pcm_runtime *fe, int stream)
1833/* Called by DAPM mixer/mux changes to update audio routing between PCMs and 1833/* Called by DAPM mixer/mux changes to update audio routing between PCMs and
1834 * any DAI links. 1834 * any DAI links.
1835 */ 1835 */
1836int soc_dpcm_runtime_update(struct snd_soc_dapm_widget *widget) 1836int soc_dpcm_runtime_update(struct snd_soc_card *card)
1837{ 1837{
1838 struct snd_soc_card *card;
1839 int i, old, new, paths; 1838 int i, old, new, paths;
1840 1839
1841 if (widget->codec)
1842 card = widget->codec->card;
1843 else if (widget->platform)
1844 card = widget->platform->card;
1845 else
1846 return -EINVAL;
1847
1848 mutex_lock_nested(&card->mutex, SND_SOC_CARD_CLASS_RUNTIME); 1840 mutex_lock_nested(&card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
1849 for (i = 0; i < card->num_rtd; i++) { 1841 for (i = 0; i < card->num_rtd; i++) {
1850 struct snd_soc_dapm_widget_list *list; 1842 struct snd_soc_dapm_widget_list *list;