aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/soc-dapm.c
diff options
context:
space:
mode:
authorLiam Girdwood <lrg@ti.com>2012-03-06 13:16:19 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2012-04-01 06:28:22 -0400
commit49575fb52bf76bf48e2d29ff034e8dad8d7ba638 (patch)
tree683d0c317b05b1e6854d9cfab928123cded01576 /sound/soc/soc-dapm.c
parenta3cc056b64065efaf98d3e3fe8a6b9d508121492 (diff)
ASoC: DAPM: Make sure DAPM widget IO ops hold the component mutex
Currently not all DAPM widget IO ops are holding their component mutex (codec or platform). Make sure this is now held for DAPM widget IO operations. Signed-off-by: Liam Girdwood <lrg@ti.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/soc-dapm.c')
-rw-r--r--sound/soc/soc-dapm.c34
1 files changed, 28 insertions, 6 deletions
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 42602ddea243..1e449f375d98 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -206,7 +206,23 @@ static int soc_widget_write(struct snd_soc_dapm_widget *w, int reg, int val)
206 return -1; 206 return -1;
207} 207}
208 208
209static int soc_widget_update_bits(struct snd_soc_dapm_widget *w, 209static inline void soc_widget_lock(struct snd_soc_dapm_widget *w)
210{
211 if (w->codec)
212 mutex_lock(&w->codec->mutex);
213 else if (w->platform)
214 mutex_lock(&w->platform->mutex);
215}
216
217static inline void soc_widget_unlock(struct snd_soc_dapm_widget *w)
218{
219 if (w->codec)
220 mutex_unlock(&w->codec->mutex);
221 else if (w->platform)
222 mutex_unlock(&w->platform->mutex);
223}
224
225static int soc_widget_update_bits_locked(struct snd_soc_dapm_widget *w,
210 unsigned short reg, unsigned int mask, unsigned int value) 226 unsigned short reg, unsigned int mask, unsigned int value)
211{ 227{
212 bool change; 228 bool change;
@@ -219,18 +235,24 @@ static int soc_widget_update_bits(struct snd_soc_dapm_widget *w,
219 if (ret != 0) 235 if (ret != 0)
220 return ret; 236 return ret;
221 } else { 237 } else {
238 soc_widget_lock(w);
222 ret = soc_widget_read(w, reg); 239 ret = soc_widget_read(w, reg);
223 if (ret < 0) 240 if (ret < 0) {
241 soc_widget_unlock(w);
224 return ret; 242 return ret;
243 }
225 244
226 old = ret; 245 old = ret;
227 new = (old & ~mask) | (value & mask); 246 new = (old & ~mask) | (value & mask);
228 change = old != new; 247 change = old != new;
229 if (change) { 248 if (change) {
230 ret = soc_widget_write(w, reg, new); 249 ret = soc_widget_write(w, reg, new);
231 if (ret < 0) 250 if (ret < 0) {
251 soc_widget_unlock(w);
232 return ret; 252 return ret;
253 }
233 } 254 }
255 soc_widget_unlock(w);
234 } 256 }
235 257
236 return change; 258 return change;
@@ -847,7 +869,7 @@ int dapm_reg_event(struct snd_soc_dapm_widget *w,
847 else 869 else
848 val = w->off_val; 870 val = w->off_val;
849 871
850 soc_widget_update_bits(w, -(w->reg + 1), 872 soc_widget_update_bits_locked(w, -(w->reg + 1),
851 w->mask << w->shift, val << w->shift); 873 w->mask << w->shift, val << w->shift);
852 874
853 return 0; 875 return 0;
@@ -1105,7 +1127,7 @@ static void dapm_seq_run_coalesced(struct snd_soc_dapm_context *dapm,
1105 "pop test : Applying 0x%x/0x%x to %x in %dms\n", 1127 "pop test : Applying 0x%x/0x%x to %x in %dms\n",
1106 value, mask, reg, card->pop_time); 1128 value, mask, reg, card->pop_time);
1107 pop_wait(card->pop_time); 1129 pop_wait(card->pop_time);
1108 soc_widget_update_bits(w, reg, mask, value); 1130 soc_widget_update_bits_locked(w, reg, mask, value);
1109 } 1131 }
1110 1132
1111 list_for_each_entry(w, pending, power_list) { 1133 list_for_each_entry(w, pending, power_list) {
@@ -1235,7 +1257,7 @@ static void dapm_widget_update(struct snd_soc_dapm_context *dapm)
1235 w->name, ret); 1257 w->name, ret);
1236 } 1258 }
1237 1259
1238 ret = snd_soc_update_bits(w->codec, update->reg, update->mask, 1260 ret = soc_widget_update_bits_locked(w, update->reg, update->mask,
1239 update->val); 1261 update->val);
1240 if (ret < 0) 1262 if (ret < 0)
1241 pr_err("%s DAPM update failed: %d\n", w->name, ret); 1263 pr_err("%s DAPM update failed: %d\n", w->name, ret);