diff options
Diffstat (limited to 'sound/soc/soc-dapm.c')
-rw-r--r-- | sound/soc/soc-dapm.c | 860 |
1 files changed, 522 insertions, 338 deletions
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index c721502833bc..499730ab5638 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c | |||
@@ -42,9 +42,11 @@ | |||
42 | #include <sound/core.h> | 42 | #include <sound/core.h> |
43 | #include <sound/pcm.h> | 43 | #include <sound/pcm.h> |
44 | #include <sound/pcm_params.h> | 44 | #include <sound/pcm_params.h> |
45 | #include <sound/soc-dapm.h> | 45 | #include <sound/soc.h> |
46 | #include <sound/initval.h> | 46 | #include <sound/initval.h> |
47 | 47 | ||
48 | #include <trace/events/asoc.h> | ||
49 | |||
48 | /* dapm power sequences - make this per codec in the future */ | 50 | /* dapm power sequences - make this per codec in the future */ |
49 | static int dapm_up_seq[] = { | 51 | static int dapm_up_seq[] = { |
50 | [snd_soc_dapm_pre] = 0, | 52 | [snd_soc_dapm_pre] = 0, |
@@ -54,12 +56,14 @@ static int dapm_up_seq[] = { | |||
54 | [snd_soc_dapm_aif_out] = 3, | 56 | [snd_soc_dapm_aif_out] = 3, |
55 | [snd_soc_dapm_mic] = 4, | 57 | [snd_soc_dapm_mic] = 4, |
56 | [snd_soc_dapm_mux] = 5, | 58 | [snd_soc_dapm_mux] = 5, |
59 | [snd_soc_dapm_virt_mux] = 5, | ||
57 | [snd_soc_dapm_value_mux] = 5, | 60 | [snd_soc_dapm_value_mux] = 5, |
58 | [snd_soc_dapm_dac] = 6, | 61 | [snd_soc_dapm_dac] = 6, |
59 | [snd_soc_dapm_mixer] = 7, | 62 | [snd_soc_dapm_mixer] = 7, |
60 | [snd_soc_dapm_mixer_named_ctl] = 7, | 63 | [snd_soc_dapm_mixer_named_ctl] = 7, |
61 | [snd_soc_dapm_pga] = 8, | 64 | [snd_soc_dapm_pga] = 8, |
62 | [snd_soc_dapm_adc] = 9, | 65 | [snd_soc_dapm_adc] = 9, |
66 | [snd_soc_dapm_out_drv] = 10, | ||
63 | [snd_soc_dapm_hp] = 10, | 67 | [snd_soc_dapm_hp] = 10, |
64 | [snd_soc_dapm_spk] = 10, | 68 | [snd_soc_dapm_spk] = 10, |
65 | [snd_soc_dapm_post] = 11, | 69 | [snd_soc_dapm_post] = 11, |
@@ -70,6 +74,7 @@ static int dapm_down_seq[] = { | |||
70 | [snd_soc_dapm_adc] = 1, | 74 | [snd_soc_dapm_adc] = 1, |
71 | [snd_soc_dapm_hp] = 2, | 75 | [snd_soc_dapm_hp] = 2, |
72 | [snd_soc_dapm_spk] = 2, | 76 | [snd_soc_dapm_spk] = 2, |
77 | [snd_soc_dapm_out_drv] = 2, | ||
73 | [snd_soc_dapm_pga] = 4, | 78 | [snd_soc_dapm_pga] = 4, |
74 | [snd_soc_dapm_mixer_named_ctl] = 5, | 79 | [snd_soc_dapm_mixer_named_ctl] = 5, |
75 | [snd_soc_dapm_mixer] = 5, | 80 | [snd_soc_dapm_mixer] = 5, |
@@ -77,6 +82,7 @@ static int dapm_down_seq[] = { | |||
77 | [snd_soc_dapm_mic] = 7, | 82 | [snd_soc_dapm_mic] = 7, |
78 | [snd_soc_dapm_micbias] = 8, | 83 | [snd_soc_dapm_micbias] = 8, |
79 | [snd_soc_dapm_mux] = 9, | 84 | [snd_soc_dapm_mux] = 9, |
85 | [snd_soc_dapm_virt_mux] = 9, | ||
80 | [snd_soc_dapm_value_mux] = 9, | 86 | [snd_soc_dapm_value_mux] = 9, |
81 | [snd_soc_dapm_aif_in] = 10, | 87 | [snd_soc_dapm_aif_in] = 10, |
82 | [snd_soc_dapm_aif_out] = 10, | 88 | [snd_soc_dapm_aif_out] = 10, |
@@ -90,17 +96,24 @@ static void pop_wait(u32 pop_time) | |||
90 | schedule_timeout_uninterruptible(msecs_to_jiffies(pop_time)); | 96 | schedule_timeout_uninterruptible(msecs_to_jiffies(pop_time)); |
91 | } | 97 | } |
92 | 98 | ||
93 | static void pop_dbg(u32 pop_time, const char *fmt, ...) | 99 | static void pop_dbg(struct device *dev, u32 pop_time, const char *fmt, ...) |
94 | { | 100 | { |
95 | va_list args; | 101 | va_list args; |
102 | char *buf; | ||
96 | 103 | ||
97 | va_start(args, fmt); | 104 | if (!pop_time) |
105 | return; | ||
98 | 106 | ||
99 | if (pop_time) { | 107 | buf = kmalloc(PAGE_SIZE, GFP_KERNEL); |
100 | vprintk(fmt, args); | 108 | if (buf == NULL) |
101 | } | 109 | return; |
102 | 110 | ||
111 | va_start(args, fmt); | ||
112 | vsnprintf(buf, PAGE_SIZE, fmt, args); | ||
113 | dev_info(dev, "%s", buf); | ||
103 | va_end(args); | 114 | va_end(args); |
115 | |||
116 | kfree(buf); | ||
104 | } | 117 | } |
105 | 118 | ||
106 | /* create a new dapm widget */ | 119 | /* create a new dapm widget */ |
@@ -120,36 +133,45 @@ static inline struct snd_soc_dapm_widget *dapm_cnew_widget( | |||
120 | * Returns 0 for success else error. | 133 | * Returns 0 for success else error. |
121 | */ | 134 | */ |
122 | static int snd_soc_dapm_set_bias_level(struct snd_soc_card *card, | 135 | static int snd_soc_dapm_set_bias_level(struct snd_soc_card *card, |
123 | struct snd_soc_codec *codec, enum snd_soc_bias_level level) | 136 | struct snd_soc_dapm_context *dapm, |
137 | enum snd_soc_bias_level level) | ||
124 | { | 138 | { |
125 | int ret = 0; | 139 | int ret = 0; |
126 | 140 | ||
127 | switch (level) { | 141 | switch (level) { |
128 | case SND_SOC_BIAS_ON: | 142 | case SND_SOC_BIAS_ON: |
129 | dev_dbg(codec->dev, "Setting full bias\n"); | 143 | dev_dbg(dapm->dev, "Setting full bias\n"); |
130 | break; | 144 | break; |
131 | case SND_SOC_BIAS_PREPARE: | 145 | case SND_SOC_BIAS_PREPARE: |
132 | dev_dbg(codec->dev, "Setting bias prepare\n"); | 146 | dev_dbg(dapm->dev, "Setting bias prepare\n"); |
133 | break; | 147 | break; |
134 | case SND_SOC_BIAS_STANDBY: | 148 | case SND_SOC_BIAS_STANDBY: |
135 | dev_dbg(codec->dev, "Setting standby bias\n"); | 149 | dev_dbg(dapm->dev, "Setting standby bias\n"); |
136 | break; | 150 | break; |
137 | case SND_SOC_BIAS_OFF: | 151 | case SND_SOC_BIAS_OFF: |
138 | dev_dbg(codec->dev, "Setting bias off\n"); | 152 | dev_dbg(dapm->dev, "Setting bias off\n"); |
139 | break; | 153 | break; |
140 | default: | 154 | default: |
141 | dev_err(codec->dev, "Setting invalid bias %d\n", level); | 155 | dev_err(dapm->dev, "Setting invalid bias %d\n", level); |
142 | return -EINVAL; | 156 | return -EINVAL; |
143 | } | 157 | } |
144 | 158 | ||
159 | trace_snd_soc_bias_level_start(card, level); | ||
160 | |||
145 | if (card && card->set_bias_level) | 161 | if (card && card->set_bias_level) |
146 | ret = card->set_bias_level(card, level); | 162 | ret = card->set_bias_level(card, level); |
147 | if (ret == 0) { | 163 | if (ret == 0) { |
148 | if (codec->driver->set_bias_level) | 164 | if (dapm->codec && dapm->codec->driver->set_bias_level) |
149 | ret = codec->driver->set_bias_level(codec, level); | 165 | ret = dapm->codec->driver->set_bias_level(dapm->codec, level); |
150 | else | 166 | else |
151 | codec->bias_level = level; | 167 | dapm->bias_level = level; |
152 | } | 168 | } |
169 | if (ret == 0) { | ||
170 | if (card && card->set_bias_level_post) | ||
171 | ret = card->set_bias_level_post(card, level); | ||
172 | } | ||
173 | |||
174 | trace_snd_soc_bias_level_done(card, level); | ||
153 | 175 | ||
154 | return ret; | 176 | return ret; |
155 | } | 177 | } |
@@ -196,6 +218,20 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, | |||
196 | } | 218 | } |
197 | } | 219 | } |
198 | break; | 220 | break; |
221 | case snd_soc_dapm_virt_mux: { | ||
222 | struct soc_enum *e = (struct soc_enum *)w->kcontrols[i].private_value; | ||
223 | |||
224 | p->connect = 0; | ||
225 | /* since a virtual mux has no backing registers to | ||
226 | * decide which path to connect, it will try to match | ||
227 | * with the first enumeration. This is to ensure | ||
228 | * that the default mux choice (the first) will be | ||
229 | * correctly powered up during initialization. | ||
230 | */ | ||
231 | if (!strcmp(p->name, e->texts[0])) | ||
232 | p->connect = 1; | ||
233 | } | ||
234 | break; | ||
199 | case snd_soc_dapm_value_mux: { | 235 | case snd_soc_dapm_value_mux: { |
200 | struct soc_enum *e = (struct soc_enum *) | 236 | struct soc_enum *e = (struct soc_enum *) |
201 | w->kcontrols[i].private_value; | 237 | w->kcontrols[i].private_value; |
@@ -217,6 +253,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, | |||
217 | break; | 253 | break; |
218 | /* does not effect routing - always connected */ | 254 | /* does not effect routing - always connected */ |
219 | case snd_soc_dapm_pga: | 255 | case snd_soc_dapm_pga: |
256 | case snd_soc_dapm_out_drv: | ||
220 | case snd_soc_dapm_output: | 257 | case snd_soc_dapm_output: |
221 | case snd_soc_dapm_adc: | 258 | case snd_soc_dapm_adc: |
222 | case snd_soc_dapm_input: | 259 | case snd_soc_dapm_input: |
@@ -241,7 +278,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, | |||
241 | } | 278 | } |
242 | 279 | ||
243 | /* connect mux widget to its interconnecting audio paths */ | 280 | /* connect mux widget to its interconnecting audio paths */ |
244 | static int dapm_connect_mux(struct snd_soc_codec *codec, | 281 | static int dapm_connect_mux(struct snd_soc_dapm_context *dapm, |
245 | struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest, | 282 | struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest, |
246 | struct snd_soc_dapm_path *path, const char *control_name, | 283 | struct snd_soc_dapm_path *path, const char *control_name, |
247 | const struct snd_kcontrol_new *kcontrol) | 284 | const struct snd_kcontrol_new *kcontrol) |
@@ -251,7 +288,7 @@ static int dapm_connect_mux(struct snd_soc_codec *codec, | |||
251 | 288 | ||
252 | for (i = 0; i < e->max; i++) { | 289 | for (i = 0; i < e->max; i++) { |
253 | if (!(strcmp(control_name, e->texts[i]))) { | 290 | if (!(strcmp(control_name, e->texts[i]))) { |
254 | list_add(&path->list, &codec->dapm_paths); | 291 | list_add(&path->list, &dapm->card->paths); |
255 | list_add(&path->list_sink, &dest->sources); | 292 | list_add(&path->list_sink, &dest->sources); |
256 | list_add(&path->list_source, &src->sinks); | 293 | list_add(&path->list_source, &src->sinks); |
257 | path->name = (char*)e->texts[i]; | 294 | path->name = (char*)e->texts[i]; |
@@ -264,7 +301,7 @@ static int dapm_connect_mux(struct snd_soc_codec *codec, | |||
264 | } | 301 | } |
265 | 302 | ||
266 | /* connect mixer widget to its interconnecting audio paths */ | 303 | /* connect mixer widget to its interconnecting audio paths */ |
267 | static int dapm_connect_mixer(struct snd_soc_codec *codec, | 304 | static int dapm_connect_mixer(struct snd_soc_dapm_context *dapm, |
268 | struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest, | 305 | struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest, |
269 | struct snd_soc_dapm_path *path, const char *control_name) | 306 | struct snd_soc_dapm_path *path, const char *control_name) |
270 | { | 307 | { |
@@ -273,7 +310,7 @@ static int dapm_connect_mixer(struct snd_soc_codec *codec, | |||
273 | /* search for mixer kcontrol */ | 310 | /* search for mixer kcontrol */ |
274 | for (i = 0; i < dest->num_kcontrols; i++) { | 311 | for (i = 0; i < dest->num_kcontrols; i++) { |
275 | if (!strcmp(control_name, dest->kcontrols[i].name)) { | 312 | if (!strcmp(control_name, dest->kcontrols[i].name)) { |
276 | list_add(&path->list, &codec->dapm_paths); | 313 | list_add(&path->list, &dapm->card->paths); |
277 | list_add(&path->list_sink, &dest->sources); | 314 | list_add(&path->list_sink, &dest->sources); |
278 | list_add(&path->list_source, &src->sinks); | 315 | list_add(&path->list_source, &src->sinks); |
279 | path->name = dest->kcontrols[i].name; | 316 | path->name = dest->kcontrols[i].name; |
@@ -290,6 +327,8 @@ static int dapm_update_bits(struct snd_soc_dapm_widget *widget) | |||
290 | int change, power; | 327 | int change, power; |
291 | unsigned int old, new; | 328 | unsigned int old, new; |
292 | struct snd_soc_codec *codec = widget->codec; | 329 | struct snd_soc_codec *codec = widget->codec; |
330 | struct snd_soc_dapm_context *dapm = widget->dapm; | ||
331 | struct snd_soc_card *card = dapm->card; | ||
293 | 332 | ||
294 | /* check for valid widgets */ | 333 | /* check for valid widgets */ |
295 | if (widget->reg < 0 || widget->id == snd_soc_dapm_input || | 334 | if (widget->reg < 0 || widget->id == snd_soc_dapm_input || |
@@ -309,24 +348,26 @@ static int dapm_update_bits(struct snd_soc_dapm_widget *widget) | |||
309 | 348 | ||
310 | change = old != new; | 349 | change = old != new; |
311 | if (change) { | 350 | if (change) { |
312 | pop_dbg(codec->pop_time, "pop test %s : %s in %d ms\n", | 351 | pop_dbg(dapm->dev, card->pop_time, |
352 | "pop test %s : %s in %d ms\n", | ||
313 | widget->name, widget->power ? "on" : "off", | 353 | widget->name, widget->power ? "on" : "off", |
314 | codec->pop_time); | 354 | card->pop_time); |
315 | pop_wait(codec->pop_time); | 355 | pop_wait(card->pop_time); |
316 | snd_soc_write(codec, widget->reg, new); | 356 | snd_soc_write(codec, widget->reg, new); |
317 | } | 357 | } |
318 | pr_debug("reg %x old %x new %x change %d\n", widget->reg, | 358 | dev_dbg(dapm->dev, "reg %x old %x new %x change %d\n", widget->reg, |
319 | old, new, change); | 359 | old, new, change); |
320 | return change; | 360 | return change; |
321 | } | 361 | } |
322 | 362 | ||
323 | /* create new dapm mixer control */ | 363 | /* create new dapm mixer control */ |
324 | static int dapm_new_mixer(struct snd_soc_codec *codec, | 364 | static int dapm_new_mixer(struct snd_soc_dapm_context *dapm, |
325 | struct snd_soc_dapm_widget *w) | 365 | struct snd_soc_dapm_widget *w) |
326 | { | 366 | { |
327 | int i, ret = 0; | 367 | int i, ret = 0; |
328 | size_t name_len; | 368 | size_t name_len; |
329 | struct snd_soc_dapm_path *path; | 369 | struct snd_soc_dapm_path *path; |
370 | struct snd_card *card = dapm->codec->card->snd_card; | ||
330 | 371 | ||
331 | /* add kcontrol */ | 372 | /* add kcontrol */ |
332 | for (i = 0; i < w->num_kcontrols; i++) { | 373 | for (i = 0; i < w->num_kcontrols; i++) { |
@@ -368,11 +409,11 @@ static int dapm_new_mixer(struct snd_soc_codec *codec, | |||
368 | 409 | ||
369 | path->kcontrol = snd_soc_cnew(&w->kcontrols[i], w, | 410 | path->kcontrol = snd_soc_cnew(&w->kcontrols[i], w, |
370 | path->long_name); | 411 | path->long_name); |
371 | ret = snd_ctl_add(codec->card->snd_card, path->kcontrol); | 412 | ret = snd_ctl_add(card, path->kcontrol); |
372 | if (ret < 0) { | 413 | if (ret < 0) { |
373 | printk(KERN_ERR "asoc: failed to add dapm kcontrol %s: %d\n", | 414 | dev_err(dapm->dev, |
374 | path->long_name, | 415 | "asoc: failed to add dapm kcontrol %s: %d\n", |
375 | ret); | 416 | path->long_name, ret); |
376 | kfree(path->long_name); | 417 | kfree(path->long_name); |
377 | path->long_name = NULL; | 418 | path->long_name = NULL; |
378 | return ret; | 419 | return ret; |
@@ -383,20 +424,22 @@ static int dapm_new_mixer(struct snd_soc_codec *codec, | |||
383 | } | 424 | } |
384 | 425 | ||
385 | /* create new dapm mux control */ | 426 | /* create new dapm mux control */ |
386 | static int dapm_new_mux(struct snd_soc_codec *codec, | 427 | static int dapm_new_mux(struct snd_soc_dapm_context *dapm, |
387 | struct snd_soc_dapm_widget *w) | 428 | struct snd_soc_dapm_widget *w) |
388 | { | 429 | { |
389 | struct snd_soc_dapm_path *path = NULL; | 430 | struct snd_soc_dapm_path *path = NULL; |
390 | struct snd_kcontrol *kcontrol; | 431 | struct snd_kcontrol *kcontrol; |
432 | struct snd_card *card = dapm->codec->card->snd_card; | ||
391 | int ret = 0; | 433 | int ret = 0; |
392 | 434 | ||
393 | if (!w->num_kcontrols) { | 435 | if (!w->num_kcontrols) { |
394 | printk(KERN_ERR "asoc: mux %s has no controls\n", w->name); | 436 | dev_err(dapm->dev, "asoc: mux %s has no controls\n", w->name); |
395 | return -EINVAL; | 437 | return -EINVAL; |
396 | } | 438 | } |
397 | 439 | ||
398 | kcontrol = snd_soc_cnew(&w->kcontrols[0], w, w->name); | 440 | kcontrol = snd_soc_cnew(&w->kcontrols[0], w, w->name); |
399 | ret = snd_ctl_add(codec->card->snd_card, kcontrol); | 441 | ret = snd_ctl_add(card, kcontrol); |
442 | |||
400 | if (ret < 0) | 443 | if (ret < 0) |
401 | goto err; | 444 | goto err; |
402 | 445 | ||
@@ -406,26 +449,27 @@ static int dapm_new_mux(struct snd_soc_codec *codec, | |||
406 | return ret; | 449 | return ret; |
407 | 450 | ||
408 | err: | 451 | err: |
409 | printk(KERN_ERR "asoc: failed to add kcontrol %s\n", w->name); | 452 | dev_err(dapm->dev, "asoc: failed to add kcontrol %s\n", w->name); |
410 | return ret; | 453 | return ret; |
411 | } | 454 | } |
412 | 455 | ||
413 | /* create new dapm volume control */ | 456 | /* create new dapm volume control */ |
414 | static int dapm_new_pga(struct snd_soc_codec *codec, | 457 | static int dapm_new_pga(struct snd_soc_dapm_context *dapm, |
415 | struct snd_soc_dapm_widget *w) | 458 | struct snd_soc_dapm_widget *w) |
416 | { | 459 | { |
417 | if (w->num_kcontrols) | 460 | if (w->num_kcontrols) |
418 | pr_err("asoc: PGA controls not supported: '%s'\n", w->name); | 461 | dev_err(w->dapm->dev, |
462 | "asoc: PGA controls not supported: '%s'\n", w->name); | ||
419 | 463 | ||
420 | return 0; | 464 | return 0; |
421 | } | 465 | } |
422 | 466 | ||
423 | /* reset 'walked' bit for each dapm path */ | 467 | /* reset 'walked' bit for each dapm path */ |
424 | static inline void dapm_clear_walk(struct snd_soc_codec *codec) | 468 | static inline void dapm_clear_walk(struct snd_soc_dapm_context *dapm) |
425 | { | 469 | { |
426 | struct snd_soc_dapm_path *p; | 470 | struct snd_soc_dapm_path *p; |
427 | 471 | ||
428 | list_for_each_entry(p, &codec->dapm_paths, list) | 472 | list_for_each_entry(p, &dapm->card->paths, list) |
429 | p->walked = 0; | 473 | p->walked = 0; |
430 | } | 474 | } |
431 | 475 | ||
@@ -435,13 +479,14 @@ static inline void dapm_clear_walk(struct snd_soc_codec *codec) | |||
435 | */ | 479 | */ |
436 | static int snd_soc_dapm_suspend_check(struct snd_soc_dapm_widget *widget) | 480 | static int snd_soc_dapm_suspend_check(struct snd_soc_dapm_widget *widget) |
437 | { | 481 | { |
438 | int level = snd_power_get_state(widget->codec->card->snd_card); | 482 | int level = snd_power_get_state(widget->dapm->codec->card->snd_card); |
439 | 483 | ||
440 | switch (level) { | 484 | switch (level) { |
441 | case SNDRV_CTL_POWER_D3hot: | 485 | case SNDRV_CTL_POWER_D3hot: |
442 | case SNDRV_CTL_POWER_D3cold: | 486 | case SNDRV_CTL_POWER_D3cold: |
443 | if (widget->ignore_suspend) | 487 | if (widget->ignore_suspend) |
444 | pr_debug("%s ignoring suspend\n", widget->name); | 488 | dev_dbg(widget->dapm->dev, "%s ignoring suspend\n", |
489 | widget->name); | ||
445 | return widget->ignore_suspend; | 490 | return widget->ignore_suspend; |
446 | default: | 491 | default: |
447 | return 1; | 492 | return 1; |
@@ -572,7 +617,7 @@ static int dapm_generic_apply_power(struct snd_soc_dapm_widget *w) | |||
572 | 617 | ||
573 | /* call any power change event handlers */ | 618 | /* call any power change event handlers */ |
574 | if (w->event) | 619 | if (w->event) |
575 | pr_debug("power %s event for %s flags %x\n", | 620 | dev_dbg(w->dapm->dev, "power %s event for %s flags %x\n", |
576 | w->power ? "on" : "off", | 621 | w->power ? "on" : "off", |
577 | w->name, w->event_flags); | 622 | w->name, w->event_flags); |
578 | 623 | ||
@@ -621,9 +666,9 @@ static int dapm_generic_check_power(struct snd_soc_dapm_widget *w) | |||
621 | int in, out; | 666 | int in, out; |
622 | 667 | ||
623 | in = is_connected_input_ep(w); | 668 | in = is_connected_input_ep(w); |
624 | dapm_clear_walk(w->codec); | 669 | dapm_clear_walk(w->dapm); |
625 | out = is_connected_output_ep(w); | 670 | out = is_connected_output_ep(w); |
626 | dapm_clear_walk(w->codec); | 671 | dapm_clear_walk(w->dapm); |
627 | return out != 0 && in != 0; | 672 | return out != 0 && in != 0; |
628 | } | 673 | } |
629 | 674 | ||
@@ -634,7 +679,7 @@ static int dapm_adc_check_power(struct snd_soc_dapm_widget *w) | |||
634 | 679 | ||
635 | if (w->active) { | 680 | if (w->active) { |
636 | in = is_connected_input_ep(w); | 681 | in = is_connected_input_ep(w); |
637 | dapm_clear_walk(w->codec); | 682 | dapm_clear_walk(w->dapm); |
638 | return in != 0; | 683 | return in != 0; |
639 | } else { | 684 | } else { |
640 | return dapm_generic_check_power(w); | 685 | return dapm_generic_check_power(w); |
@@ -648,7 +693,7 @@ static int dapm_dac_check_power(struct snd_soc_dapm_widget *w) | |||
648 | 693 | ||
649 | if (w->active) { | 694 | if (w->active) { |
650 | out = is_connected_output_ep(w); | 695 | out = is_connected_output_ep(w); |
651 | dapm_clear_walk(w->codec); | 696 | dapm_clear_walk(w->dapm); |
652 | return out != 0; | 697 | return out != 0; |
653 | } else { | 698 | } else { |
654 | return dapm_generic_check_power(w); | 699 | return dapm_generic_check_power(w); |
@@ -674,7 +719,7 @@ static int dapm_supply_check_power(struct snd_soc_dapm_widget *w) | |||
674 | } | 719 | } |
675 | } | 720 | } |
676 | 721 | ||
677 | dapm_clear_walk(w->codec); | 722 | dapm_clear_walk(w->dapm); |
678 | 723 | ||
679 | return power; | 724 | return power; |
680 | } | 725 | } |
@@ -687,8 +732,8 @@ static int dapm_seq_compare(struct snd_soc_dapm_widget *a, | |||
687 | return sort[a->id] - sort[b->id]; | 732 | return sort[a->id] - sort[b->id]; |
688 | if (a->reg != b->reg) | 733 | if (a->reg != b->reg) |
689 | return a->reg - b->reg; | 734 | return a->reg - b->reg; |
690 | if (a->codec != b->codec) | 735 | if (a->dapm != b->dapm) |
691 | return (unsigned long)a->codec - (unsigned long)b->codec; | 736 | return (unsigned long)a->dapm - (unsigned long)b->dapm; |
692 | 737 | ||
693 | return 0; | 738 | return 0; |
694 | } | 739 | } |
@@ -709,12 +754,57 @@ static void dapm_seq_insert(struct snd_soc_dapm_widget *new_widget, | |||
709 | list_add_tail(&new_widget->power_list, list); | 754 | list_add_tail(&new_widget->power_list, list); |
710 | } | 755 | } |
711 | 756 | ||
757 | static void dapm_seq_check_event(struct snd_soc_dapm_context *dapm, | ||
758 | struct snd_soc_dapm_widget *w, int event) | ||
759 | { | ||
760 | struct snd_soc_card *card = dapm->card; | ||
761 | const char *ev_name; | ||
762 | int power, ret; | ||
763 | |||
764 | switch (event) { | ||
765 | case SND_SOC_DAPM_PRE_PMU: | ||
766 | ev_name = "PRE_PMU"; | ||
767 | power = 1; | ||
768 | break; | ||
769 | case SND_SOC_DAPM_POST_PMU: | ||
770 | ev_name = "POST_PMU"; | ||
771 | power = 1; | ||
772 | break; | ||
773 | case SND_SOC_DAPM_PRE_PMD: | ||
774 | ev_name = "PRE_PMD"; | ||
775 | power = 0; | ||
776 | break; | ||
777 | case SND_SOC_DAPM_POST_PMD: | ||
778 | ev_name = "POST_PMD"; | ||
779 | power = 0; | ||
780 | break; | ||
781 | default: | ||
782 | BUG(); | ||
783 | return; | ||
784 | } | ||
785 | |||
786 | if (w->power != power) | ||
787 | return; | ||
788 | |||
789 | if (w->event && (w->event_flags & event)) { | ||
790 | pop_dbg(dapm->dev, card->pop_time, "pop test : %s %s\n", | ||
791 | w->name, ev_name); | ||
792 | trace_snd_soc_dapm_widget_event_start(w, event); | ||
793 | ret = w->event(w, NULL, event); | ||
794 | trace_snd_soc_dapm_widget_event_done(w, event); | ||
795 | if (ret < 0) | ||
796 | pr_err("%s: %s event failed: %d\n", | ||
797 | ev_name, w->name, ret); | ||
798 | } | ||
799 | } | ||
800 | |||
712 | /* Apply the coalesced changes from a DAPM sequence */ | 801 | /* Apply the coalesced changes from a DAPM sequence */ |
713 | static void dapm_seq_run_coalesced(struct snd_soc_codec *codec, | 802 | static void dapm_seq_run_coalesced(struct snd_soc_dapm_context *dapm, |
714 | struct list_head *pending) | 803 | struct list_head *pending) |
715 | { | 804 | { |
805 | struct snd_soc_card *card = dapm->card; | ||
716 | struct snd_soc_dapm_widget *w; | 806 | struct snd_soc_dapm_widget *w; |
717 | int reg, power, ret; | 807 | int reg, power; |
718 | unsigned int value = 0; | 808 | unsigned int value = 0; |
719 | unsigned int mask = 0; | 809 | unsigned int mask = 0; |
720 | unsigned int cur_mask; | 810 | unsigned int cur_mask; |
@@ -735,64 +825,26 @@ static void dapm_seq_run_coalesced(struct snd_soc_codec *codec, | |||
735 | if (power) | 825 | if (power) |
736 | value |= cur_mask; | 826 | value |= cur_mask; |
737 | 827 | ||
738 | pop_dbg(codec->pop_time, | 828 | pop_dbg(dapm->dev, card->pop_time, |
739 | "pop test : Queue %s: reg=0x%x, 0x%x/0x%x\n", | 829 | "pop test : Queue %s: reg=0x%x, 0x%x/0x%x\n", |
740 | w->name, reg, value, mask); | 830 | w->name, reg, value, mask); |
741 | 831 | ||
742 | /* power up pre event */ | 832 | /* Check for events */ |
743 | if (w->power && w->event && | 833 | dapm_seq_check_event(dapm, w, SND_SOC_DAPM_PRE_PMU); |
744 | (w->event_flags & SND_SOC_DAPM_PRE_PMU)) { | 834 | dapm_seq_check_event(dapm, w, SND_SOC_DAPM_PRE_PMD); |
745 | pop_dbg(codec->pop_time, "pop test : %s PRE_PMU\n", | ||
746 | w->name); | ||
747 | ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMU); | ||
748 | if (ret < 0) | ||
749 | pr_err("%s: pre event failed: %d\n", | ||
750 | w->name, ret); | ||
751 | } | ||
752 | |||
753 | /* power down pre event */ | ||
754 | if (!w->power && w->event && | ||
755 | (w->event_flags & SND_SOC_DAPM_PRE_PMD)) { | ||
756 | pop_dbg(codec->pop_time, "pop test : %s PRE_PMD\n", | ||
757 | w->name); | ||
758 | ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMD); | ||
759 | if (ret < 0) | ||
760 | pr_err("%s: pre event failed: %d\n", | ||
761 | w->name, ret); | ||
762 | } | ||
763 | } | 835 | } |
764 | 836 | ||
765 | if (reg >= 0) { | 837 | if (reg >= 0) { |
766 | pop_dbg(codec->pop_time, | 838 | pop_dbg(dapm->dev, card->pop_time, |
767 | "pop test : Applying 0x%x/0x%x to %x in %dms\n", | 839 | "pop test : Applying 0x%x/0x%x to %x in %dms\n", |
768 | value, mask, reg, codec->pop_time); | 840 | value, mask, reg, card->pop_time); |
769 | pop_wait(codec->pop_time); | 841 | pop_wait(card->pop_time); |
770 | snd_soc_update_bits(codec, reg, mask, value); | 842 | snd_soc_update_bits(dapm->codec, reg, mask, value); |
771 | } | 843 | } |
772 | 844 | ||
773 | list_for_each_entry(w, pending, power_list) { | 845 | list_for_each_entry(w, pending, power_list) { |
774 | /* power up post event */ | 846 | dapm_seq_check_event(dapm, w, SND_SOC_DAPM_POST_PMU); |
775 | if (w->power && w->event && | 847 | dapm_seq_check_event(dapm, w, SND_SOC_DAPM_POST_PMD); |
776 | (w->event_flags & SND_SOC_DAPM_POST_PMU)) { | ||
777 | pop_dbg(codec->pop_time, "pop test : %s POST_PMU\n", | ||
778 | w->name); | ||
779 | ret = w->event(w, | ||
780 | NULL, SND_SOC_DAPM_POST_PMU); | ||
781 | if (ret < 0) | ||
782 | pr_err("%s: post event failed: %d\n", | ||
783 | w->name, ret); | ||
784 | } | ||
785 | |||
786 | /* power down post event */ | ||
787 | if (!w->power && w->event && | ||
788 | (w->event_flags & SND_SOC_DAPM_POST_PMD)) { | ||
789 | pop_dbg(codec->pop_time, "pop test : %s POST_PMD\n", | ||
790 | w->name); | ||
791 | ret = w->event(w, NULL, SND_SOC_DAPM_POST_PMD); | ||
792 | if (ret < 0) | ||
793 | pr_err("%s: post event failed: %d\n", | ||
794 | w->name, ret); | ||
795 | } | ||
796 | } | 848 | } |
797 | } | 849 | } |
798 | 850 | ||
@@ -804,26 +856,29 @@ static void dapm_seq_run_coalesced(struct snd_soc_codec *codec, | |||
804 | * Currently anything that requires more than a single write is not | 856 | * Currently anything that requires more than a single write is not |
805 | * handled. | 857 | * handled. |
806 | */ | 858 | */ |
807 | static void dapm_seq_run(struct snd_soc_codec *codec, struct list_head *list, | 859 | static void dapm_seq_run(struct snd_soc_dapm_context *dapm, |
808 | int event, int sort[]) | 860 | struct list_head *list, int event, int sort[]) |
809 | { | 861 | { |
810 | struct snd_soc_dapm_widget *w, *n; | 862 | struct snd_soc_dapm_widget *w, *n; |
811 | LIST_HEAD(pending); | 863 | LIST_HEAD(pending); |
812 | int cur_sort = -1; | 864 | int cur_sort = -1; |
813 | int cur_reg = SND_SOC_NOPM; | 865 | int cur_reg = SND_SOC_NOPM; |
866 | struct snd_soc_dapm_context *cur_dapm = NULL; | ||
814 | int ret; | 867 | int ret; |
815 | 868 | ||
816 | list_for_each_entry_safe(w, n, list, power_list) { | 869 | list_for_each_entry_safe(w, n, list, power_list) { |
817 | ret = 0; | 870 | ret = 0; |
818 | 871 | ||
819 | /* Do we need to apply any queued changes? */ | 872 | /* Do we need to apply any queued changes? */ |
820 | if (sort[w->id] != cur_sort || w->reg != cur_reg) { | 873 | if (sort[w->id] != cur_sort || w->reg != cur_reg || |
874 | w->dapm != cur_dapm) { | ||
821 | if (!list_empty(&pending)) | 875 | if (!list_empty(&pending)) |
822 | dapm_seq_run_coalesced(codec, &pending); | 876 | dapm_seq_run_coalesced(cur_dapm, &pending); |
823 | 877 | ||
824 | INIT_LIST_HEAD(&pending); | 878 | INIT_LIST_HEAD(&pending); |
825 | cur_sort = -1; | 879 | cur_sort = -1; |
826 | cur_reg = SND_SOC_NOPM; | 880 | cur_reg = SND_SOC_NOPM; |
881 | cur_dapm = NULL; | ||
827 | } | 882 | } |
828 | 883 | ||
829 | switch (w->id) { | 884 | switch (w->id) { |
@@ -867,19 +922,55 @@ static void dapm_seq_run(struct snd_soc_codec *codec, struct list_head *list, | |||
867 | /* Queue it up for application */ | 922 | /* Queue it up for application */ |
868 | cur_sort = sort[w->id]; | 923 | cur_sort = sort[w->id]; |
869 | cur_reg = w->reg; | 924 | cur_reg = w->reg; |
925 | cur_dapm = w->dapm; | ||
870 | list_move(&w->power_list, &pending); | 926 | list_move(&w->power_list, &pending); |
871 | break; | 927 | break; |
872 | } | 928 | } |
873 | 929 | ||
874 | if (ret < 0) | 930 | if (ret < 0) |
875 | pr_err("Failed to apply widget power: %d\n", | 931 | dev_err(w->dapm->dev, |
876 | ret); | 932 | "Failed to apply widget power: %d\n", ret); |
877 | } | 933 | } |
878 | 934 | ||
879 | if (!list_empty(&pending)) | 935 | if (!list_empty(&pending)) |
880 | dapm_seq_run_coalesced(codec, &pending); | 936 | dapm_seq_run_coalesced(dapm, &pending); |
937 | } | ||
938 | |||
939 | static void dapm_widget_update(struct snd_soc_dapm_context *dapm) | ||
940 | { | ||
941 | struct snd_soc_dapm_update *update = dapm->update; | ||
942 | struct snd_soc_dapm_widget *w; | ||
943 | int ret; | ||
944 | |||
945 | if (!update) | ||
946 | return; | ||
947 | |||
948 | w = update->widget; | ||
949 | |||
950 | if (w->event && | ||
951 | (w->event_flags & SND_SOC_DAPM_PRE_REG)) { | ||
952 | ret = w->event(w, update->kcontrol, SND_SOC_DAPM_PRE_REG); | ||
953 | if (ret != 0) | ||
954 | pr_err("%s DAPM pre-event failed: %d\n", | ||
955 | w->name, ret); | ||
956 | } | ||
957 | |||
958 | ret = snd_soc_update_bits(w->codec, update->reg, update->mask, | ||
959 | update->val); | ||
960 | if (ret < 0) | ||
961 | pr_err("%s DAPM update failed: %d\n", w->name, ret); | ||
962 | |||
963 | if (w->event && | ||
964 | (w->event_flags & SND_SOC_DAPM_POST_REG)) { | ||
965 | ret = w->event(w, update->kcontrol, SND_SOC_DAPM_POST_REG); | ||
966 | if (ret != 0) | ||
967 | pr_err("%s DAPM post-event failed: %d\n", | ||
968 | w->name, ret); | ||
969 | } | ||
881 | } | 970 | } |
882 | 971 | ||
972 | |||
973 | |||
883 | /* | 974 | /* |
884 | * Scan each dapm widget for complete audio path. | 975 | * Scan each dapm widget for complete audio path. |
885 | * A complete path is a route that has valid endpoints i.e.:- | 976 | * A complete path is a route that has valid endpoints i.e.:- |
@@ -889,20 +980,26 @@ static void dapm_seq_run(struct snd_soc_codec *codec, struct list_head *list, | |||
889 | * o Input pin to Output pin (bypass, sidetone) | 980 | * o Input pin to Output pin (bypass, sidetone) |
890 | * o DAC to ADC (loopback). | 981 | * o DAC to ADC (loopback). |
891 | */ | 982 | */ |
892 | static int dapm_power_widgets(struct snd_soc_codec *codec, int event) | 983 | static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event) |
893 | { | 984 | { |
894 | struct snd_soc_card *card = codec->card; | 985 | struct snd_soc_card *card = dapm->codec->card; |
895 | struct snd_soc_dapm_widget *w; | 986 | struct snd_soc_dapm_widget *w; |
987 | struct snd_soc_dapm_context *d; | ||
896 | LIST_HEAD(up_list); | 988 | LIST_HEAD(up_list); |
897 | LIST_HEAD(down_list); | 989 | LIST_HEAD(down_list); |
898 | int ret = 0; | 990 | int ret = 0; |
899 | int power; | 991 | int power; |
900 | int sys_power = 0; | 992 | |
993 | trace_snd_soc_dapm_start(card); | ||
994 | |||
995 | list_for_each_entry(d, &card->dapm_list, list) | ||
996 | if (d->n_widgets) | ||
997 | d->dev_power = 0; | ||
901 | 998 | ||
902 | /* Check which widgets we need to power and store them in | 999 | /* Check which widgets we need to power and store them in |
903 | * lists indicating if they should be powered up or down. | 1000 | * lists indicating if they should be powered up or down. |
904 | */ | 1001 | */ |
905 | list_for_each_entry(w, &codec->dapm_widgets, list) { | 1002 | list_for_each_entry(w, &card->widgets, list) { |
906 | switch (w->id) { | 1003 | switch (w->id) { |
907 | case snd_soc_dapm_pre: | 1004 | case snd_soc_dapm_pre: |
908 | dapm_seq_insert(w, &down_list, dapm_down_seq); | 1005 | dapm_seq_insert(w, &down_list, dapm_down_seq); |
@@ -920,11 +1017,13 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event) | |||
920 | else | 1017 | else |
921 | power = 1; | 1018 | power = 1; |
922 | if (power) | 1019 | if (power) |
923 | sys_power = 1; | 1020 | w->dapm->dev_power = 1; |
924 | 1021 | ||
925 | if (w->power == power) | 1022 | if (w->power == power) |
926 | continue; | 1023 | continue; |
927 | 1024 | ||
1025 | trace_snd_soc_dapm_widget_power(w, power); | ||
1026 | |||
928 | if (power) | 1027 | if (power) |
929 | dapm_seq_insert(w, &up_list, dapm_up_seq); | 1028 | dapm_seq_insert(w, &up_list, dapm_up_seq); |
930 | else | 1029 | else |
@@ -938,26 +1037,26 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event) | |||
938 | /* If there are no DAPM widgets then try to figure out power from the | 1037 | /* If there are no DAPM widgets then try to figure out power from the |
939 | * event type. | 1038 | * event type. |
940 | */ | 1039 | */ |
941 | if (list_empty(&codec->dapm_widgets)) { | 1040 | if (!dapm->n_widgets) { |
942 | switch (event) { | 1041 | switch (event) { |
943 | case SND_SOC_DAPM_STREAM_START: | 1042 | case SND_SOC_DAPM_STREAM_START: |
944 | case SND_SOC_DAPM_STREAM_RESUME: | 1043 | case SND_SOC_DAPM_STREAM_RESUME: |
945 | sys_power = 1; | 1044 | dapm->dev_power = 1; |
946 | break; | 1045 | break; |
947 | case SND_SOC_DAPM_STREAM_STOP: | 1046 | case SND_SOC_DAPM_STREAM_STOP: |
948 | sys_power = !!codec->active; | 1047 | dapm->dev_power = !!dapm->codec->active; |
949 | break; | 1048 | break; |
950 | case SND_SOC_DAPM_STREAM_SUSPEND: | 1049 | case SND_SOC_DAPM_STREAM_SUSPEND: |
951 | sys_power = 0; | 1050 | dapm->dev_power = 0; |
952 | break; | 1051 | break; |
953 | case SND_SOC_DAPM_STREAM_NOP: | 1052 | case SND_SOC_DAPM_STREAM_NOP: |
954 | switch (codec->bias_level) { | 1053 | switch (dapm->bias_level) { |
955 | case SND_SOC_BIAS_STANDBY: | 1054 | case SND_SOC_BIAS_STANDBY: |
956 | case SND_SOC_BIAS_OFF: | 1055 | case SND_SOC_BIAS_OFF: |
957 | sys_power = 0; | 1056 | dapm->dev_power = 0; |
958 | break; | 1057 | break; |
959 | default: | 1058 | default: |
960 | sys_power = 1; | 1059 | dapm->dev_power = 1; |
961 | break; | 1060 | break; |
962 | } | 1061 | } |
963 | break; | 1062 | break; |
@@ -966,52 +1065,71 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event) | |||
966 | } | 1065 | } |
967 | } | 1066 | } |
968 | 1067 | ||
969 | if (sys_power && codec->bias_level == SND_SOC_BIAS_OFF) { | 1068 | list_for_each_entry(d, &dapm->card->dapm_list, list) { |
970 | ret = snd_soc_dapm_set_bias_level(card, codec, | 1069 | if (d->dev_power && d->bias_level == SND_SOC_BIAS_OFF) { |
971 | SND_SOC_BIAS_STANDBY); | 1070 | ret = snd_soc_dapm_set_bias_level(card, d, |
972 | if (ret != 0) | 1071 | SND_SOC_BIAS_STANDBY); |
973 | pr_err("Failed to turn on bias: %d\n", ret); | 1072 | if (ret != 0) |
974 | } | 1073 | dev_err(d->dev, |
1074 | "Failed to turn on bias: %d\n", ret); | ||
1075 | } | ||
975 | 1076 | ||
976 | /* If we're changing to all on or all off then prepare */ | 1077 | /* If we're changing to all on or all off then prepare */ |
977 | if ((sys_power && codec->bias_level == SND_SOC_BIAS_STANDBY) || | 1078 | if ((d->dev_power && d->bias_level == SND_SOC_BIAS_STANDBY) || |
978 | (!sys_power && codec->bias_level == SND_SOC_BIAS_ON)) { | 1079 | (!d->dev_power && d->bias_level == SND_SOC_BIAS_ON)) { |
979 | ret = snd_soc_dapm_set_bias_level(card, codec, SND_SOC_BIAS_PREPARE); | 1080 | ret = snd_soc_dapm_set_bias_level(card, d, |
980 | if (ret != 0) | 1081 | SND_SOC_BIAS_PREPARE); |
981 | pr_err("Failed to prepare bias: %d\n", ret); | 1082 | if (ret != 0) |
1083 | dev_err(d->dev, | ||
1084 | "Failed to prepare bias: %d\n", ret); | ||
1085 | } | ||
982 | } | 1086 | } |
983 | 1087 | ||
984 | /* Power down widgets first; try to avoid amplifying pops. */ | 1088 | /* Power down widgets first; try to avoid amplifying pops. */ |
985 | dapm_seq_run(codec, &down_list, event, dapm_down_seq); | 1089 | dapm_seq_run(dapm, &down_list, event, dapm_down_seq); |
1090 | |||
1091 | dapm_widget_update(dapm); | ||
986 | 1092 | ||
987 | /* Now power up. */ | 1093 | /* Now power up. */ |
988 | dapm_seq_run(codec, &up_list, event, dapm_up_seq); | 1094 | dapm_seq_run(dapm, &up_list, event, dapm_up_seq); |
1095 | |||
1096 | list_for_each_entry(d, &dapm->card->dapm_list, list) { | ||
1097 | /* If we just powered the last thing off drop to standby bias */ | ||
1098 | if (d->bias_level == SND_SOC_BIAS_PREPARE && !d->dev_power) { | ||
1099 | ret = snd_soc_dapm_set_bias_level(card, d, | ||
1100 | SND_SOC_BIAS_STANDBY); | ||
1101 | if (ret != 0) | ||
1102 | dev_err(d->dev, | ||
1103 | "Failed to apply standby bias: %d\n", | ||
1104 | ret); | ||
1105 | } | ||
989 | 1106 | ||
990 | /* If we just powered the last thing off drop to standby bias */ | 1107 | /* If we're in standby and can support bias off then do that */ |
991 | if (codec->bias_level == SND_SOC_BIAS_PREPARE && !sys_power) { | 1108 | if (d->bias_level == SND_SOC_BIAS_STANDBY && |
992 | ret = snd_soc_dapm_set_bias_level(card, codec, SND_SOC_BIAS_STANDBY); | 1109 | d->idle_bias_off) { |
993 | if (ret != 0) | 1110 | ret = snd_soc_dapm_set_bias_level(card, d, |
994 | pr_err("Failed to apply standby bias: %d\n", ret); | 1111 | SND_SOC_BIAS_OFF); |
995 | } | 1112 | if (ret != 0) |
1113 | dev_err(d->dev, | ||
1114 | "Failed to turn off bias: %d\n", ret); | ||
1115 | } | ||
996 | 1116 | ||
997 | /* If we're in standby and can support bias off then do that */ | 1117 | /* If we just powered up then move to active bias */ |
998 | if (codec->bias_level == SND_SOC_BIAS_STANDBY && | 1118 | if (d->bias_level == SND_SOC_BIAS_PREPARE && d->dev_power) { |
999 | codec->idle_bias_off) { | 1119 | ret = snd_soc_dapm_set_bias_level(card, d, |
1000 | ret = snd_soc_dapm_set_bias_level(card, codec, SND_SOC_BIAS_OFF); | 1120 | SND_SOC_BIAS_ON); |
1001 | if (ret != 0) | 1121 | if (ret != 0) |
1002 | pr_err("Failed to turn off bias: %d\n", ret); | 1122 | dev_err(d->dev, |
1123 | "Failed to apply active bias: %d\n", | ||
1124 | ret); | ||
1125 | } | ||
1003 | } | 1126 | } |
1004 | 1127 | ||
1005 | /* If we just powered up then move to active bias */ | 1128 | pop_dbg(dapm->dev, card->pop_time, |
1006 | if (codec->bias_level == SND_SOC_BIAS_PREPARE && sys_power) { | 1129 | "DAPM sequencing finished, waiting %dms\n", card->pop_time); |
1007 | ret = snd_soc_dapm_set_bias_level(card, codec, SND_SOC_BIAS_ON); | 1130 | pop_wait(card->pop_time); |
1008 | if (ret != 0) | ||
1009 | pr_err("Failed to apply active bias: %d\n", ret); | ||
1010 | } | ||
1011 | 1131 | ||
1012 | pop_dbg(codec->pop_time, "DAPM sequencing finished, waiting %dms\n", | 1132 | trace_snd_soc_dapm_done(card); |
1013 | codec->pop_time); | ||
1014 | pop_wait(codec->pop_time); | ||
1015 | 1133 | ||
1016 | return 0; | 1134 | return 0; |
1017 | } | 1135 | } |
@@ -1038,9 +1156,9 @@ static ssize_t dapm_widget_power_read_file(struct file *file, | |||
1038 | return -ENOMEM; | 1156 | return -ENOMEM; |
1039 | 1157 | ||
1040 | in = is_connected_input_ep(w); | 1158 | in = is_connected_input_ep(w); |
1041 | dapm_clear_walk(w->codec); | 1159 | dapm_clear_walk(w->dapm); |
1042 | out = is_connected_output_ep(w); | 1160 | out = is_connected_output_ep(w); |
1043 | dapm_clear_walk(w->codec); | 1161 | dapm_clear_walk(w->dapm); |
1044 | 1162 | ||
1045 | ret = snprintf(buf, PAGE_SIZE, "%s: %s in %d out %d", | 1163 | ret = snprintf(buf, PAGE_SIZE, "%s: %s in %d out %d", |
1046 | w->name, w->power ? "On" : "Off", in, out); | 1164 | w->name, w->power ? "On" : "Off", in, out); |
@@ -1090,29 +1208,29 @@ static const struct file_operations dapm_widget_power_fops = { | |||
1090 | .llseek = default_llseek, | 1208 | .llseek = default_llseek, |
1091 | }; | 1209 | }; |
1092 | 1210 | ||
1093 | void snd_soc_dapm_debugfs_init(struct snd_soc_codec *codec) | 1211 | void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm) |
1094 | { | 1212 | { |
1095 | struct snd_soc_dapm_widget *w; | 1213 | struct snd_soc_dapm_widget *w; |
1096 | struct dentry *d; | 1214 | struct dentry *d; |
1097 | 1215 | ||
1098 | if (!codec->debugfs_dapm) | 1216 | if (!dapm->debugfs_dapm) |
1099 | return; | 1217 | return; |
1100 | 1218 | ||
1101 | list_for_each_entry(w, &codec->dapm_widgets, list) { | 1219 | list_for_each_entry(w, &dapm->card->widgets, list) { |
1102 | if (!w->name) | 1220 | if (!w->name || w->dapm != dapm) |
1103 | continue; | 1221 | continue; |
1104 | 1222 | ||
1105 | d = debugfs_create_file(w->name, 0444, | 1223 | d = debugfs_create_file(w->name, 0444, |
1106 | codec->debugfs_dapm, w, | 1224 | dapm->debugfs_dapm, w, |
1107 | &dapm_widget_power_fops); | 1225 | &dapm_widget_power_fops); |
1108 | if (!d) | 1226 | if (!d) |
1109 | printk(KERN_WARNING | 1227 | dev_warn(w->dapm->dev, |
1110 | "ASoC: Failed to create %s debugfs file\n", | 1228 | "ASoC: Failed to create %s debugfs file\n", |
1111 | w->name); | 1229 | w->name); |
1112 | } | 1230 | } |
1113 | } | 1231 | } |
1114 | #else | 1232 | #else |
1115 | void snd_soc_dapm_debugfs_init(struct snd_soc_codec *codec) | 1233 | void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm) |
1116 | { | 1234 | { |
1117 | } | 1235 | } |
1118 | #endif | 1236 | #endif |
@@ -1126,6 +1244,7 @@ static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget, | |||
1126 | int found = 0; | 1244 | int found = 0; |
1127 | 1245 | ||
1128 | if (widget->id != snd_soc_dapm_mux && | 1246 | if (widget->id != snd_soc_dapm_mux && |
1247 | widget->id != snd_soc_dapm_virt_mux && | ||
1129 | widget->id != snd_soc_dapm_value_mux) | 1248 | widget->id != snd_soc_dapm_value_mux) |
1130 | return -ENODEV; | 1249 | return -ENODEV; |
1131 | 1250 | ||
@@ -1133,7 +1252,7 @@ static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget, | |||
1133 | return 0; | 1252 | return 0; |
1134 | 1253 | ||
1135 | /* find dapm widget path assoc with kcontrol */ | 1254 | /* find dapm widget path assoc with kcontrol */ |
1136 | list_for_each_entry(path, &widget->codec->dapm_paths, list) { | 1255 | list_for_each_entry(path, &widget->dapm->card->paths, list) { |
1137 | if (path->kcontrol != kcontrol) | 1256 | if (path->kcontrol != kcontrol) |
1138 | continue; | 1257 | continue; |
1139 | 1258 | ||
@@ -1149,7 +1268,7 @@ static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget, | |||
1149 | } | 1268 | } |
1150 | 1269 | ||
1151 | if (found) | 1270 | if (found) |
1152 | dapm_power_widgets(widget->codec, SND_SOC_DAPM_STREAM_NOP); | 1271 | dapm_power_widgets(widget->dapm, SND_SOC_DAPM_STREAM_NOP); |
1153 | 1272 | ||
1154 | return 0; | 1273 | return 0; |
1155 | } | 1274 | } |
@@ -1167,7 +1286,7 @@ static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget, | |||
1167 | return -ENODEV; | 1286 | return -ENODEV; |
1168 | 1287 | ||
1169 | /* find dapm widget path assoc with kcontrol */ | 1288 | /* find dapm widget path assoc with kcontrol */ |
1170 | list_for_each_entry(path, &widget->codec->dapm_paths, list) { | 1289 | list_for_each_entry(path, &widget->dapm->card->paths, list) { |
1171 | if (path->kcontrol != kcontrol) | 1290 | if (path->kcontrol != kcontrol) |
1172 | continue; | 1291 | continue; |
1173 | 1292 | ||
@@ -1178,7 +1297,7 @@ static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget, | |||
1178 | } | 1297 | } |
1179 | 1298 | ||
1180 | if (found) | 1299 | if (found) |
1181 | dapm_power_widgets(widget->codec, SND_SOC_DAPM_STREAM_NOP); | 1300 | dapm_power_widgets(widget->dapm, SND_SOC_DAPM_STREAM_NOP); |
1182 | 1301 | ||
1183 | return 0; | 1302 | return 0; |
1184 | } | 1303 | } |
@@ -1194,7 +1313,9 @@ static ssize_t dapm_widget_show(struct device *dev, | |||
1194 | int count = 0; | 1313 | int count = 0; |
1195 | char *state = "not set"; | 1314 | char *state = "not set"; |
1196 | 1315 | ||
1197 | list_for_each_entry(w, &codec->dapm_widgets, list) { | 1316 | list_for_each_entry(w, &codec->card->widgets, list) { |
1317 | if (w->dapm != &codec->dapm) | ||
1318 | continue; | ||
1198 | 1319 | ||
1199 | /* only display widgets that burnm power */ | 1320 | /* only display widgets that burnm power */ |
1200 | switch (w->id) { | 1321 | switch (w->id) { |
@@ -1206,6 +1327,7 @@ static ssize_t dapm_widget_show(struct device *dev, | |||
1206 | case snd_soc_dapm_dac: | 1327 | case snd_soc_dapm_dac: |
1207 | case snd_soc_dapm_adc: | 1328 | case snd_soc_dapm_adc: |
1208 | case snd_soc_dapm_pga: | 1329 | case snd_soc_dapm_pga: |
1330 | case snd_soc_dapm_out_drv: | ||
1209 | case snd_soc_dapm_mixer: | 1331 | case snd_soc_dapm_mixer: |
1210 | case snd_soc_dapm_mixer_named_ctl: | 1332 | case snd_soc_dapm_mixer_named_ctl: |
1211 | case snd_soc_dapm_supply: | 1333 | case snd_soc_dapm_supply: |
@@ -1218,7 +1340,7 @@ static ssize_t dapm_widget_show(struct device *dev, | |||
1218 | } | 1340 | } |
1219 | } | 1341 | } |
1220 | 1342 | ||
1221 | switch (codec->bias_level) { | 1343 | switch (codec->dapm.bias_level) { |
1222 | case SND_SOC_BIAS_ON: | 1344 | case SND_SOC_BIAS_ON: |
1223 | state = "On"; | 1345 | state = "On"; |
1224 | break; | 1346 | break; |
@@ -1250,31 +1372,50 @@ static void snd_soc_dapm_sys_remove(struct device *dev) | |||
1250 | } | 1372 | } |
1251 | 1373 | ||
1252 | /* free all dapm widgets and resources */ | 1374 | /* free all dapm widgets and resources */ |
1253 | static void dapm_free_widgets(struct snd_soc_codec *codec) | 1375 | static void dapm_free_widgets(struct snd_soc_dapm_context *dapm) |
1254 | { | 1376 | { |
1255 | struct snd_soc_dapm_widget *w, *next_w; | 1377 | struct snd_soc_dapm_widget *w, *next_w; |
1256 | struct snd_soc_dapm_path *p, *next_p; | 1378 | struct snd_soc_dapm_path *p, *next_p; |
1257 | 1379 | ||
1258 | list_for_each_entry_safe(w, next_w, &codec->dapm_widgets, list) { | 1380 | list_for_each_entry_safe(w, next_w, &dapm->card->widgets, list) { |
1381 | if (w->dapm != dapm) | ||
1382 | continue; | ||
1259 | list_del(&w->list); | 1383 | list_del(&w->list); |
1384 | /* | ||
1385 | * remove source and sink paths associated to this widget. | ||
1386 | * While removing the path, remove reference to it from both | ||
1387 | * source and sink widgets so that path is removed only once. | ||
1388 | */ | ||
1389 | list_for_each_entry_safe(p, next_p, &w->sources, list_sink) { | ||
1390 | list_del(&p->list_sink); | ||
1391 | list_del(&p->list_source); | ||
1392 | list_del(&p->list); | ||
1393 | kfree(p->long_name); | ||
1394 | kfree(p); | ||
1395 | } | ||
1396 | list_for_each_entry_safe(p, next_p, &w->sinks, list_source) { | ||
1397 | list_del(&p->list_sink); | ||
1398 | list_del(&p->list_source); | ||
1399 | list_del(&p->list); | ||
1400 | kfree(p->long_name); | ||
1401 | kfree(p); | ||
1402 | } | ||
1403 | kfree(w->name); | ||
1260 | kfree(w); | 1404 | kfree(w); |
1261 | } | 1405 | } |
1262 | |||
1263 | list_for_each_entry_safe(p, next_p, &codec->dapm_paths, list) { | ||
1264 | list_del(&p->list); | ||
1265 | kfree(p->long_name); | ||
1266 | kfree(p); | ||
1267 | } | ||
1268 | } | 1406 | } |
1269 | 1407 | ||
1270 | static int snd_soc_dapm_set_pin(struct snd_soc_codec *codec, | 1408 | static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm, |
1271 | const char *pin, int status) | 1409 | const char *pin, int status) |
1272 | { | 1410 | { |
1273 | struct snd_soc_dapm_widget *w; | 1411 | struct snd_soc_dapm_widget *w; |
1274 | 1412 | ||
1275 | list_for_each_entry(w, &codec->dapm_widgets, list) { | 1413 | list_for_each_entry(w, &dapm->card->widgets, list) { |
1414 | if (w->dapm != dapm) | ||
1415 | continue; | ||
1276 | if (!strcmp(w->name, pin)) { | 1416 | if (!strcmp(w->name, pin)) { |
1277 | pr_debug("dapm: %s: pin %s\n", codec->name, pin); | 1417 | dev_dbg(w->dapm->dev, "dapm: pin %s = %d\n", |
1418 | pin, status); | ||
1278 | w->connected = status; | 1419 | w->connected = status; |
1279 | /* Allow disabling of forced pins */ | 1420 | /* Allow disabling of forced pins */ |
1280 | if (status == 0) | 1421 | if (status == 0) |
@@ -1283,46 +1424,72 @@ static int snd_soc_dapm_set_pin(struct snd_soc_codec *codec, | |||
1283 | } | 1424 | } |
1284 | } | 1425 | } |
1285 | 1426 | ||
1286 | pr_err("dapm: %s: configuring unknown pin %s\n", codec->name, pin); | 1427 | dev_err(dapm->dev, "dapm: unknown pin %s\n", pin); |
1287 | return -EINVAL; | 1428 | return -EINVAL; |
1288 | } | 1429 | } |
1289 | 1430 | ||
1290 | /** | 1431 | /** |
1291 | * snd_soc_dapm_sync - scan and power dapm paths | 1432 | * snd_soc_dapm_sync - scan and power dapm paths |
1292 | * @codec: audio codec | 1433 | * @dapm: DAPM context |
1293 | * | 1434 | * |
1294 | * Walks all dapm audio paths and powers widgets according to their | 1435 | * Walks all dapm audio paths and powers widgets according to their |
1295 | * stream or path usage. | 1436 | * stream or path usage. |
1296 | * | 1437 | * |
1297 | * Returns 0 for success. | 1438 | * Returns 0 for success. |
1298 | */ | 1439 | */ |
1299 | int snd_soc_dapm_sync(struct snd_soc_codec *codec) | 1440 | int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm) |
1300 | { | 1441 | { |
1301 | return dapm_power_widgets(codec, SND_SOC_DAPM_STREAM_NOP); | 1442 | return dapm_power_widgets(dapm, SND_SOC_DAPM_STREAM_NOP); |
1302 | } | 1443 | } |
1303 | EXPORT_SYMBOL_GPL(snd_soc_dapm_sync); | 1444 | EXPORT_SYMBOL_GPL(snd_soc_dapm_sync); |
1304 | 1445 | ||
1305 | static int snd_soc_dapm_add_route(struct snd_soc_codec *codec, | 1446 | static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm, |
1306 | const struct snd_soc_dapm_route *route) | 1447 | const struct snd_soc_dapm_route *route) |
1307 | { | 1448 | { |
1308 | struct snd_soc_dapm_path *path; | 1449 | struct snd_soc_dapm_path *path; |
1309 | struct snd_soc_dapm_widget *wsource = NULL, *wsink = NULL, *w; | 1450 | struct snd_soc_dapm_widget *wsource = NULL, *wsink = NULL, *w; |
1310 | const char *sink = route->sink; | 1451 | struct snd_soc_dapm_widget *wtsource = NULL, *wtsink = NULL; |
1452 | const char *sink; | ||
1311 | const char *control = route->control; | 1453 | const char *control = route->control; |
1312 | const char *source = route->source; | 1454 | const char *source; |
1455 | char prefixed_sink[80]; | ||
1456 | char prefixed_source[80]; | ||
1313 | int ret = 0; | 1457 | int ret = 0; |
1314 | 1458 | ||
1315 | /* find src and dest widgets */ | 1459 | if (dapm->codec->name_prefix) { |
1316 | list_for_each_entry(w, &codec->dapm_widgets, list) { | 1460 | snprintf(prefixed_sink, sizeof(prefixed_sink), "%s %s", |
1461 | dapm->codec->name_prefix, route->sink); | ||
1462 | sink = prefixed_sink; | ||
1463 | snprintf(prefixed_source, sizeof(prefixed_source), "%s %s", | ||
1464 | dapm->codec->name_prefix, route->source); | ||
1465 | source = prefixed_source; | ||
1466 | } else { | ||
1467 | sink = route->sink; | ||
1468 | source = route->source; | ||
1469 | } | ||
1317 | 1470 | ||
1471 | /* | ||
1472 | * find src and dest widgets over all widgets but favor a widget from | ||
1473 | * current DAPM context | ||
1474 | */ | ||
1475 | list_for_each_entry(w, &dapm->card->widgets, list) { | ||
1318 | if (!wsink && !(strcmp(w->name, sink))) { | 1476 | if (!wsink && !(strcmp(w->name, sink))) { |
1319 | wsink = w; | 1477 | wtsink = w; |
1478 | if (w->dapm == dapm) | ||
1479 | wsink = w; | ||
1320 | continue; | 1480 | continue; |
1321 | } | 1481 | } |
1322 | if (!wsource && !(strcmp(w->name, source))) { | 1482 | if (!wsource && !(strcmp(w->name, source))) { |
1323 | wsource = w; | 1483 | wtsource = w; |
1484 | if (w->dapm == dapm) | ||
1485 | wsource = w; | ||
1324 | } | 1486 | } |
1325 | } | 1487 | } |
1488 | /* use widget from another DAPM context if not found from this */ | ||
1489 | if (!wsink) | ||
1490 | wsink = wtsink; | ||
1491 | if (!wsource) | ||
1492 | wsource = wtsource; | ||
1326 | 1493 | ||
1327 | if (wsource == NULL || wsink == NULL) | 1494 | if (wsource == NULL || wsink == NULL) |
1328 | return -ENODEV; | 1495 | return -ENODEV; |
@@ -1356,7 +1523,7 @@ static int snd_soc_dapm_add_route(struct snd_soc_codec *codec, | |||
1356 | 1523 | ||
1357 | /* connect static paths */ | 1524 | /* connect static paths */ |
1358 | if (control == NULL) { | 1525 | if (control == NULL) { |
1359 | list_add(&path->list, &codec->dapm_paths); | 1526 | list_add(&path->list, &dapm->card->paths); |
1360 | list_add(&path->list_sink, &wsink->sources); | 1527 | list_add(&path->list_sink, &wsink->sources); |
1361 | list_add(&path->list_source, &wsource->sinks); | 1528 | list_add(&path->list_source, &wsource->sinks); |
1362 | path->connect = 1; | 1529 | path->connect = 1; |
@@ -1368,6 +1535,7 @@ static int snd_soc_dapm_add_route(struct snd_soc_codec *codec, | |||
1368 | case snd_soc_dapm_adc: | 1535 | case snd_soc_dapm_adc: |
1369 | case snd_soc_dapm_dac: | 1536 | case snd_soc_dapm_dac: |
1370 | case snd_soc_dapm_pga: | 1537 | case snd_soc_dapm_pga: |
1538 | case snd_soc_dapm_out_drv: | ||
1371 | case snd_soc_dapm_input: | 1539 | case snd_soc_dapm_input: |
1372 | case snd_soc_dapm_output: | 1540 | case snd_soc_dapm_output: |
1373 | case snd_soc_dapm_micbias: | 1541 | case snd_soc_dapm_micbias: |
@@ -1377,14 +1545,15 @@ static int snd_soc_dapm_add_route(struct snd_soc_codec *codec, | |||
1377 | case snd_soc_dapm_supply: | 1545 | case snd_soc_dapm_supply: |
1378 | case snd_soc_dapm_aif_in: | 1546 | case snd_soc_dapm_aif_in: |
1379 | case snd_soc_dapm_aif_out: | 1547 | case snd_soc_dapm_aif_out: |
1380 | list_add(&path->list, &codec->dapm_paths); | 1548 | list_add(&path->list, &dapm->card->paths); |
1381 | list_add(&path->list_sink, &wsink->sources); | 1549 | list_add(&path->list_sink, &wsink->sources); |
1382 | list_add(&path->list_source, &wsource->sinks); | 1550 | list_add(&path->list_source, &wsource->sinks); |
1383 | path->connect = 1; | 1551 | path->connect = 1; |
1384 | return 0; | 1552 | return 0; |
1385 | case snd_soc_dapm_mux: | 1553 | case snd_soc_dapm_mux: |
1554 | case snd_soc_dapm_virt_mux: | ||
1386 | case snd_soc_dapm_value_mux: | 1555 | case snd_soc_dapm_value_mux: |
1387 | ret = dapm_connect_mux(codec, wsource, wsink, path, control, | 1556 | ret = dapm_connect_mux(dapm, wsource, wsink, path, control, |
1388 | &wsink->kcontrols[0]); | 1557 | &wsink->kcontrols[0]); |
1389 | if (ret != 0) | 1558 | if (ret != 0) |
1390 | goto err; | 1559 | goto err; |
@@ -1392,7 +1561,7 @@ static int snd_soc_dapm_add_route(struct snd_soc_codec *codec, | |||
1392 | case snd_soc_dapm_switch: | 1561 | case snd_soc_dapm_switch: |
1393 | case snd_soc_dapm_mixer: | 1562 | case snd_soc_dapm_mixer: |
1394 | case snd_soc_dapm_mixer_named_ctl: | 1563 | case snd_soc_dapm_mixer_named_ctl: |
1395 | ret = dapm_connect_mixer(codec, wsource, wsink, path, control); | 1564 | ret = dapm_connect_mixer(dapm, wsource, wsink, path, control); |
1396 | if (ret != 0) | 1565 | if (ret != 0) |
1397 | goto err; | 1566 | goto err; |
1398 | break; | 1567 | break; |
@@ -1400,7 +1569,7 @@ static int snd_soc_dapm_add_route(struct snd_soc_codec *codec, | |||
1400 | case snd_soc_dapm_mic: | 1569 | case snd_soc_dapm_mic: |
1401 | case snd_soc_dapm_line: | 1570 | case snd_soc_dapm_line: |
1402 | case snd_soc_dapm_spk: | 1571 | case snd_soc_dapm_spk: |
1403 | list_add(&path->list, &codec->dapm_paths); | 1572 | list_add(&path->list, &dapm->card->paths); |
1404 | list_add(&path->list_sink, &wsink->sources); | 1573 | list_add(&path->list_sink, &wsink->sources); |
1405 | list_add(&path->list_source, &wsource->sinks); | 1574 | list_add(&path->list_source, &wsource->sinks); |
1406 | path->connect = 0; | 1575 | path->connect = 0; |
@@ -1409,15 +1578,15 @@ static int snd_soc_dapm_add_route(struct snd_soc_codec *codec, | |||
1409 | return 0; | 1578 | return 0; |
1410 | 1579 | ||
1411 | err: | 1580 | err: |
1412 | printk(KERN_WARNING "asoc: no dapm match for %s --> %s --> %s\n", source, | 1581 | dev_warn(dapm->dev, "asoc: no dapm match for %s --> %s --> %s\n", |
1413 | control, sink); | 1582 | source, control, sink); |
1414 | kfree(path); | 1583 | kfree(path); |
1415 | return ret; | 1584 | return ret; |
1416 | } | 1585 | } |
1417 | 1586 | ||
1418 | /** | 1587 | /** |
1419 | * snd_soc_dapm_add_routes - Add routes between DAPM widgets | 1588 | * snd_soc_dapm_add_routes - Add routes between DAPM widgets |
1420 | * @codec: codec | 1589 | * @dapm: DAPM context |
1421 | * @route: audio routes | 1590 | * @route: audio routes |
1422 | * @num: number of routes | 1591 | * @num: number of routes |
1423 | * | 1592 | * |
@@ -1428,17 +1597,16 @@ err: | |||
1428 | * Returns 0 for success else error. On error all resources can be freed | 1597 | * Returns 0 for success else error. On error all resources can be freed |
1429 | * with a call to snd_soc_card_free(). | 1598 | * with a call to snd_soc_card_free(). |
1430 | */ | 1599 | */ |
1431 | int snd_soc_dapm_add_routes(struct snd_soc_codec *codec, | 1600 | int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm, |
1432 | const struct snd_soc_dapm_route *route, int num) | 1601 | const struct snd_soc_dapm_route *route, int num) |
1433 | { | 1602 | { |
1434 | int i, ret; | 1603 | int i, ret; |
1435 | 1604 | ||
1436 | for (i = 0; i < num; i++) { | 1605 | for (i = 0; i < num; i++) { |
1437 | ret = snd_soc_dapm_add_route(codec, route); | 1606 | ret = snd_soc_dapm_add_route(dapm, route); |
1438 | if (ret < 0) { | 1607 | if (ret < 0) { |
1439 | printk(KERN_ERR "Failed to add route %s->%s\n", | 1608 | dev_err(dapm->dev, "Failed to add route %s->%s\n", |
1440 | route->source, | 1609 | route->source, route->sink); |
1441 | route->sink); | ||
1442 | return ret; | 1610 | return ret; |
1443 | } | 1611 | } |
1444 | route++; | 1612 | route++; |
@@ -1450,17 +1618,17 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_add_routes); | |||
1450 | 1618 | ||
1451 | /** | 1619 | /** |
1452 | * snd_soc_dapm_new_widgets - add new dapm widgets | 1620 | * snd_soc_dapm_new_widgets - add new dapm widgets |
1453 | * @codec: audio codec | 1621 | * @dapm: DAPM context |
1454 | * | 1622 | * |
1455 | * Checks the codec for any new dapm widgets and creates them if found. | 1623 | * Checks the codec for any new dapm widgets and creates them if found. |
1456 | * | 1624 | * |
1457 | * Returns 0 for success. | 1625 | * Returns 0 for success. |
1458 | */ | 1626 | */ |
1459 | int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec) | 1627 | int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm) |
1460 | { | 1628 | { |
1461 | struct snd_soc_dapm_widget *w; | 1629 | struct snd_soc_dapm_widget *w; |
1462 | 1630 | ||
1463 | list_for_each_entry(w, &codec->dapm_widgets, list) | 1631 | list_for_each_entry(w, &dapm->card->widgets, list) |
1464 | { | 1632 | { |
1465 | if (w->new) | 1633 | if (w->new) |
1466 | continue; | 1634 | continue; |
@@ -1470,12 +1638,13 @@ int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec) | |||
1470 | case snd_soc_dapm_mixer: | 1638 | case snd_soc_dapm_mixer: |
1471 | case snd_soc_dapm_mixer_named_ctl: | 1639 | case snd_soc_dapm_mixer_named_ctl: |
1472 | w->power_check = dapm_generic_check_power; | 1640 | w->power_check = dapm_generic_check_power; |
1473 | dapm_new_mixer(codec, w); | 1641 | dapm_new_mixer(dapm, w); |
1474 | break; | 1642 | break; |
1475 | case snd_soc_dapm_mux: | 1643 | case snd_soc_dapm_mux: |
1644 | case snd_soc_dapm_virt_mux: | ||
1476 | case snd_soc_dapm_value_mux: | 1645 | case snd_soc_dapm_value_mux: |
1477 | w->power_check = dapm_generic_check_power; | 1646 | w->power_check = dapm_generic_check_power; |
1478 | dapm_new_mux(codec, w); | 1647 | dapm_new_mux(dapm, w); |
1479 | break; | 1648 | break; |
1480 | case snd_soc_dapm_adc: | 1649 | case snd_soc_dapm_adc: |
1481 | case snd_soc_dapm_aif_out: | 1650 | case snd_soc_dapm_aif_out: |
@@ -1486,8 +1655,9 @@ int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec) | |||
1486 | w->power_check = dapm_dac_check_power; | 1655 | w->power_check = dapm_dac_check_power; |
1487 | break; | 1656 | break; |
1488 | case snd_soc_dapm_pga: | 1657 | case snd_soc_dapm_pga: |
1658 | case snd_soc_dapm_out_drv: | ||
1489 | w->power_check = dapm_generic_check_power; | 1659 | w->power_check = dapm_generic_check_power; |
1490 | dapm_new_pga(codec, w); | 1660 | dapm_new_pga(dapm, w); |
1491 | break; | 1661 | break; |
1492 | case snd_soc_dapm_input: | 1662 | case snd_soc_dapm_input: |
1493 | case snd_soc_dapm_output: | 1663 | case snd_soc_dapm_output: |
@@ -1508,7 +1678,7 @@ int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec) | |||
1508 | w->new = 1; | 1678 | w->new = 1; |
1509 | } | 1679 | } |
1510 | 1680 | ||
1511 | dapm_power_widgets(codec, SND_SOC_DAPM_STREAM_NOP); | 1681 | dapm_power_widgets(dapm, SND_SOC_DAPM_STREAM_NOP); |
1512 | return 0; | 1682 | return 0; |
1513 | } | 1683 | } |
1514 | EXPORT_SYMBOL_GPL(snd_soc_dapm_new_widgets); | 1684 | EXPORT_SYMBOL_GPL(snd_soc_dapm_new_widgets); |
@@ -1569,13 +1739,12 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, | |||
1569 | (struct soc_mixer_control *)kcontrol->private_value; | 1739 | (struct soc_mixer_control *)kcontrol->private_value; |
1570 | unsigned int reg = mc->reg; | 1740 | unsigned int reg = mc->reg; |
1571 | unsigned int shift = mc->shift; | 1741 | unsigned int shift = mc->shift; |
1572 | unsigned int rshift = mc->rshift; | ||
1573 | int max = mc->max; | 1742 | int max = mc->max; |
1574 | unsigned int mask = (1 << fls(max)) - 1; | 1743 | unsigned int mask = (1 << fls(max)) - 1; |
1575 | unsigned int invert = mc->invert; | 1744 | unsigned int invert = mc->invert; |
1576 | unsigned int val, val2, val_mask; | 1745 | unsigned int val, val_mask; |
1577 | int connect; | 1746 | int connect, change; |
1578 | int ret; | 1747 | struct snd_soc_dapm_update update; |
1579 | 1748 | ||
1580 | val = (ucontrol->value.integer.value[0] & mask); | 1749 | val = (ucontrol->value.integer.value[0] & mask); |
1581 | 1750 | ||
@@ -1583,18 +1752,12 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, | |||
1583 | val = max - val; | 1752 | val = max - val; |
1584 | val_mask = mask << shift; | 1753 | val_mask = mask << shift; |
1585 | val = val << shift; | 1754 | val = val << shift; |
1586 | if (shift != rshift) { | ||
1587 | val2 = (ucontrol->value.integer.value[1] & mask); | ||
1588 | if (invert) | ||
1589 | val2 = max - val2; | ||
1590 | val_mask |= mask << rshift; | ||
1591 | val |= val2 << rshift; | ||
1592 | } | ||
1593 | 1755 | ||
1594 | mutex_lock(&widget->codec->mutex); | 1756 | mutex_lock(&widget->codec->mutex); |
1595 | widget->value = val; | 1757 | widget->value = val; |
1596 | 1758 | ||
1597 | if (snd_soc_test_bits(widget->codec, reg, val_mask, val)) { | 1759 | change = snd_soc_test_bits(widget->codec, reg, val_mask, val); |
1760 | if (change) { | ||
1598 | if (val) | 1761 | if (val) |
1599 | /* new connection */ | 1762 | /* new connection */ |
1600 | connect = invert ? 0:1; | 1763 | connect = invert ? 0:1; |
@@ -1602,28 +1765,20 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, | |||
1602 | /* old connection must be powered down */ | 1765 | /* old connection must be powered down */ |
1603 | connect = invert ? 1:0; | 1766 | connect = invert ? 1:0; |
1604 | 1767 | ||
1768 | update.kcontrol = kcontrol; | ||
1769 | update.widget = widget; | ||
1770 | update.reg = reg; | ||
1771 | update.mask = mask; | ||
1772 | update.val = val; | ||
1773 | widget->dapm->update = &update; | ||
1774 | |||
1605 | dapm_mixer_update_power(widget, kcontrol, connect); | 1775 | dapm_mixer_update_power(widget, kcontrol, connect); |
1776 | |||
1777 | widget->dapm->update = NULL; | ||
1606 | } | 1778 | } |
1607 | 1779 | ||
1608 | if (widget->event) { | ||
1609 | if (widget->event_flags & SND_SOC_DAPM_PRE_REG) { | ||
1610 | ret = widget->event(widget, kcontrol, | ||
1611 | SND_SOC_DAPM_PRE_REG); | ||
1612 | if (ret < 0) { | ||
1613 | ret = 1; | ||
1614 | goto out; | ||
1615 | } | ||
1616 | } | ||
1617 | ret = snd_soc_update_bits(widget->codec, reg, val_mask, val); | ||
1618 | if (widget->event_flags & SND_SOC_DAPM_POST_REG) | ||
1619 | ret = widget->event(widget, kcontrol, | ||
1620 | SND_SOC_DAPM_POST_REG); | ||
1621 | } else | ||
1622 | ret = snd_soc_update_bits(widget->codec, reg, val_mask, val); | ||
1623 | |||
1624 | out: | ||
1625 | mutex_unlock(&widget->codec->mutex); | 1780 | mutex_unlock(&widget->codec->mutex); |
1626 | return ret; | 1781 | return 0; |
1627 | } | 1782 | } |
1628 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw); | 1783 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw); |
1629 | 1784 | ||
@@ -1671,7 +1826,7 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, | |||
1671 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | 1826 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
1672 | unsigned int val, mux, change; | 1827 | unsigned int val, mux, change; |
1673 | unsigned int mask, bitmask; | 1828 | unsigned int mask, bitmask; |
1674 | int ret = 0; | 1829 | struct snd_soc_dapm_update update; |
1675 | 1830 | ||
1676 | for (bitmask = 1; bitmask < e->max; bitmask <<= 1) | 1831 | for (bitmask = 1; bitmask < e->max; bitmask <<= 1) |
1677 | ; | 1832 | ; |
@@ -1690,24 +1845,20 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, | |||
1690 | mutex_lock(&widget->codec->mutex); | 1845 | mutex_lock(&widget->codec->mutex); |
1691 | widget->value = val; | 1846 | widget->value = val; |
1692 | change = snd_soc_test_bits(widget->codec, e->reg, mask, val); | 1847 | change = snd_soc_test_bits(widget->codec, e->reg, mask, val); |
1693 | dapm_mux_update_power(widget, kcontrol, change, mux, e); | ||
1694 | 1848 | ||
1695 | if (widget->event_flags & SND_SOC_DAPM_PRE_REG) { | 1849 | update.kcontrol = kcontrol; |
1696 | ret = widget->event(widget, | 1850 | update.widget = widget; |
1697 | kcontrol, SND_SOC_DAPM_PRE_REG); | 1851 | update.reg = e->reg; |
1698 | if (ret < 0) | 1852 | update.mask = mask; |
1699 | goto out; | 1853 | update.val = val; |
1700 | } | 1854 | widget->dapm->update = &update; |
1701 | 1855 | ||
1702 | ret = snd_soc_update_bits(widget->codec, e->reg, mask, val); | 1856 | dapm_mux_update_power(widget, kcontrol, change, mux, e); |
1703 | 1857 | ||
1704 | if (widget->event_flags & SND_SOC_DAPM_POST_REG) | 1858 | widget->dapm->update = NULL; |
1705 | ret = widget->event(widget, | ||
1706 | kcontrol, SND_SOC_DAPM_POST_REG); | ||
1707 | 1859 | ||
1708 | out: | ||
1709 | mutex_unlock(&widget->codec->mutex); | 1860 | mutex_unlock(&widget->codec->mutex); |
1710 | return ret; | 1861 | return change; |
1711 | } | 1862 | } |
1712 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double); | 1863 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double); |
1713 | 1864 | ||
@@ -1819,7 +1970,7 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol, | |||
1819 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | 1970 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
1820 | unsigned int val, mux, change; | 1971 | unsigned int val, mux, change; |
1821 | unsigned int mask; | 1972 | unsigned int mask; |
1822 | int ret = 0; | 1973 | struct snd_soc_dapm_update update; |
1823 | 1974 | ||
1824 | if (ucontrol->value.enumerated.item[0] > e->max - 1) | 1975 | if (ucontrol->value.enumerated.item[0] > e->max - 1) |
1825 | return -EINVAL; | 1976 | return -EINVAL; |
@@ -1836,24 +1987,20 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol, | |||
1836 | mutex_lock(&widget->codec->mutex); | 1987 | mutex_lock(&widget->codec->mutex); |
1837 | widget->value = val; | 1988 | widget->value = val; |
1838 | change = snd_soc_test_bits(widget->codec, e->reg, mask, val); | 1989 | change = snd_soc_test_bits(widget->codec, e->reg, mask, val); |
1839 | dapm_mux_update_power(widget, kcontrol, change, mux, e); | ||
1840 | 1990 | ||
1841 | if (widget->event_flags & SND_SOC_DAPM_PRE_REG) { | 1991 | update.kcontrol = kcontrol; |
1842 | ret = widget->event(widget, | 1992 | update.widget = widget; |
1843 | kcontrol, SND_SOC_DAPM_PRE_REG); | 1993 | update.reg = e->reg; |
1844 | if (ret < 0) | 1994 | update.mask = mask; |
1845 | goto out; | 1995 | update.val = val; |
1846 | } | 1996 | widget->dapm->update = &update; |
1847 | 1997 | ||
1848 | ret = snd_soc_update_bits(widget->codec, e->reg, mask, val); | 1998 | dapm_mux_update_power(widget, kcontrol, change, mux, e); |
1849 | 1999 | ||
1850 | if (widget->event_flags & SND_SOC_DAPM_POST_REG) | 2000 | widget->dapm->update = NULL; |
1851 | ret = widget->event(widget, | ||
1852 | kcontrol, SND_SOC_DAPM_POST_REG); | ||
1853 | 2001 | ||
1854 | out: | ||
1855 | mutex_unlock(&widget->codec->mutex); | 2002 | mutex_unlock(&widget->codec->mutex); |
1856 | return ret; | 2003 | return change; |
1857 | } | 2004 | } |
1858 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_value_enum_double); | 2005 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_value_enum_double); |
1859 | 2006 | ||
@@ -1892,7 +2039,7 @@ int snd_soc_dapm_get_pin_switch(struct snd_kcontrol *kcontrol, | |||
1892 | mutex_lock(&codec->mutex); | 2039 | mutex_lock(&codec->mutex); |
1893 | 2040 | ||
1894 | ucontrol->value.integer.value[0] = | 2041 | ucontrol->value.integer.value[0] = |
1895 | snd_soc_dapm_get_pin_status(codec, pin); | 2042 | snd_soc_dapm_get_pin_status(&codec->dapm, pin); |
1896 | 2043 | ||
1897 | mutex_unlock(&codec->mutex); | 2044 | mutex_unlock(&codec->mutex); |
1898 | 2045 | ||
@@ -1915,11 +2062,11 @@ int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol, | |||
1915 | mutex_lock(&codec->mutex); | 2062 | mutex_lock(&codec->mutex); |
1916 | 2063 | ||
1917 | if (ucontrol->value.integer.value[0]) | 2064 | if (ucontrol->value.integer.value[0]) |
1918 | snd_soc_dapm_enable_pin(codec, pin); | 2065 | snd_soc_dapm_enable_pin(&codec->dapm, pin); |
1919 | else | 2066 | else |
1920 | snd_soc_dapm_disable_pin(codec, pin); | 2067 | snd_soc_dapm_disable_pin(&codec->dapm, pin); |
1921 | 2068 | ||
1922 | snd_soc_dapm_sync(codec); | 2069 | snd_soc_dapm_sync(&codec->dapm); |
1923 | 2070 | ||
1924 | mutex_unlock(&codec->mutex); | 2071 | mutex_unlock(&codec->mutex); |
1925 | 2072 | ||
@@ -1929,26 +2076,43 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_put_pin_switch); | |||
1929 | 2076 | ||
1930 | /** | 2077 | /** |
1931 | * snd_soc_dapm_new_control - create new dapm control | 2078 | * snd_soc_dapm_new_control - create new dapm control |
1932 | * @codec: audio codec | 2079 | * @dapm: DAPM context |
1933 | * @widget: widget template | 2080 | * @widget: widget template |
1934 | * | 2081 | * |
1935 | * Creates a new dapm control based upon the template. | 2082 | * Creates a new dapm control based upon the template. |
1936 | * | 2083 | * |
1937 | * Returns 0 for success else error. | 2084 | * Returns 0 for success else error. |
1938 | */ | 2085 | */ |
1939 | int snd_soc_dapm_new_control(struct snd_soc_codec *codec, | 2086 | int snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, |
1940 | const struct snd_soc_dapm_widget *widget) | 2087 | const struct snd_soc_dapm_widget *widget) |
1941 | { | 2088 | { |
1942 | struct snd_soc_dapm_widget *w; | 2089 | struct snd_soc_dapm_widget *w; |
2090 | size_t name_len; | ||
1943 | 2091 | ||
1944 | if ((w = dapm_cnew_widget(widget)) == NULL) | 2092 | if ((w = dapm_cnew_widget(widget)) == NULL) |
1945 | return -ENOMEM; | 2093 | return -ENOMEM; |
1946 | 2094 | ||
1947 | w->codec = codec; | 2095 | name_len = strlen(widget->name) + 1; |
2096 | if (dapm->codec->name_prefix) | ||
2097 | name_len += 1 + strlen(dapm->codec->name_prefix); | ||
2098 | w->name = kmalloc(name_len, GFP_KERNEL); | ||
2099 | if (w->name == NULL) { | ||
2100 | kfree(w); | ||
2101 | return -ENOMEM; | ||
2102 | } | ||
2103 | if (dapm->codec->name_prefix) | ||
2104 | snprintf(w->name, name_len, "%s %s", | ||
2105 | dapm->codec->name_prefix, widget->name); | ||
2106 | else | ||
2107 | snprintf(w->name, name_len, "%s", widget->name); | ||
2108 | |||
2109 | dapm->n_widgets++; | ||
2110 | w->dapm = dapm; | ||
2111 | w->codec = dapm->codec; | ||
1948 | INIT_LIST_HEAD(&w->sources); | 2112 | INIT_LIST_HEAD(&w->sources); |
1949 | INIT_LIST_HEAD(&w->sinks); | 2113 | INIT_LIST_HEAD(&w->sinks); |
1950 | INIT_LIST_HEAD(&w->list); | 2114 | INIT_LIST_HEAD(&w->list); |
1951 | list_add(&w->list, &codec->dapm_widgets); | 2115 | list_add(&w->list, &dapm->card->widgets); |
1952 | 2116 | ||
1953 | /* machine layer set ups unconnected pins and insertions */ | 2117 | /* machine layer set ups unconnected pins and insertions */ |
1954 | w->connected = 1; | 2118 | w->connected = 1; |
@@ -1958,7 +2122,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_new_control); | |||
1958 | 2122 | ||
1959 | /** | 2123 | /** |
1960 | * snd_soc_dapm_new_controls - create new dapm controls | 2124 | * snd_soc_dapm_new_controls - create new dapm controls |
1961 | * @codec: audio codec | 2125 | * @dapm: DAPM context |
1962 | * @widget: widget array | 2126 | * @widget: widget array |
1963 | * @num: number of widgets | 2127 | * @num: number of widgets |
1964 | * | 2128 | * |
@@ -1966,18 +2130,18 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_new_control); | |||
1966 | * | 2130 | * |
1967 | * Returns 0 for success else error. | 2131 | * Returns 0 for success else error. |
1968 | */ | 2132 | */ |
1969 | int snd_soc_dapm_new_controls(struct snd_soc_codec *codec, | 2133 | int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm, |
1970 | const struct snd_soc_dapm_widget *widget, | 2134 | const struct snd_soc_dapm_widget *widget, |
1971 | int num) | 2135 | int num) |
1972 | { | 2136 | { |
1973 | int i, ret; | 2137 | int i, ret; |
1974 | 2138 | ||
1975 | for (i = 0; i < num; i++) { | 2139 | for (i = 0; i < num; i++) { |
1976 | ret = snd_soc_dapm_new_control(codec, widget); | 2140 | ret = snd_soc_dapm_new_control(dapm, widget); |
1977 | if (ret < 0) { | 2141 | if (ret < 0) { |
1978 | printk(KERN_ERR | 2142 | dev_err(dapm->dev, |
1979 | "ASoC: Failed to create DAPM control %s: %d\n", | 2143 | "ASoC: Failed to create DAPM control %s: %d\n", |
1980 | widget->name, ret); | 2144 | widget->name, ret); |
1981 | return ret; | 2145 | return ret; |
1982 | } | 2146 | } |
1983 | widget++; | 2147 | widget++; |
@@ -1986,34 +2150,17 @@ int snd_soc_dapm_new_controls(struct snd_soc_codec *codec, | |||
1986 | } | 2150 | } |
1987 | EXPORT_SYMBOL_GPL(snd_soc_dapm_new_controls); | 2151 | EXPORT_SYMBOL_GPL(snd_soc_dapm_new_controls); |
1988 | 2152 | ||
1989 | 2153 | static void soc_dapm_stream_event(struct snd_soc_dapm_context *dapm, | |
1990 | /** | ||
1991 | * snd_soc_dapm_stream_event - send a stream event to the dapm core | ||
1992 | * @codec: audio codec | ||
1993 | * @stream: stream name | ||
1994 | * @event: stream event | ||
1995 | * | ||
1996 | * Sends a stream event to the dapm core. The core then makes any | ||
1997 | * necessary widget power changes. | ||
1998 | * | ||
1999 | * Returns 0 for success else error. | ||
2000 | */ | ||
2001 | int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, | ||
2002 | const char *stream, int event) | 2154 | const char *stream, int event) |
2003 | { | 2155 | { |
2004 | struct snd_soc_codec *codec = rtd->codec; | ||
2005 | struct snd_soc_dapm_widget *w; | 2156 | struct snd_soc_dapm_widget *w; |
2006 | 2157 | ||
2007 | if (stream == NULL) | 2158 | list_for_each_entry(w, &dapm->card->widgets, list) |
2008 | return 0; | ||
2009 | |||
2010 | mutex_lock(&codec->mutex); | ||
2011 | list_for_each_entry(w, &codec->dapm_widgets, list) | ||
2012 | { | 2159 | { |
2013 | if (!w->sname) | 2160 | if (!w->sname || w->dapm != dapm) |
2014 | continue; | 2161 | continue; |
2015 | pr_debug("widget %s\n %s stream %s event %d\n", | 2162 | dev_dbg(w->dapm->dev, "widget %s\n %s stream %s event %d\n", |
2016 | w->name, w->sname, stream, event); | 2163 | w->name, w->sname, stream, event); |
2017 | if (strstr(w->sname, stream)) { | 2164 | if (strstr(w->sname, stream)) { |
2018 | switch(event) { | 2165 | switch(event) { |
2019 | case SND_SOC_DAPM_STREAM_START: | 2166 | case SND_SOC_DAPM_STREAM_START: |
@@ -2031,7 +2178,30 @@ int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, | |||
2031 | } | 2178 | } |
2032 | } | 2179 | } |
2033 | 2180 | ||
2034 | dapm_power_widgets(codec, event); | 2181 | dapm_power_widgets(dapm, event); |
2182 | } | ||
2183 | |||
2184 | /** | ||
2185 | * snd_soc_dapm_stream_event - send a stream event to the dapm core | ||
2186 | * @rtd: PCM runtime data | ||
2187 | * @stream: stream name | ||
2188 | * @event: stream event | ||
2189 | * | ||
2190 | * Sends a stream event to the dapm core. The core then makes any | ||
2191 | * necessary widget power changes. | ||
2192 | * | ||
2193 | * Returns 0 for success else error. | ||
2194 | */ | ||
2195 | int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, | ||
2196 | const char *stream, int event) | ||
2197 | { | ||
2198 | struct snd_soc_codec *codec = rtd->codec; | ||
2199 | |||
2200 | if (stream == NULL) | ||
2201 | return 0; | ||
2202 | |||
2203 | mutex_lock(&codec->mutex); | ||
2204 | soc_dapm_stream_event(&codec->dapm, stream, event); | ||
2035 | mutex_unlock(&codec->mutex); | 2205 | mutex_unlock(&codec->mutex); |
2036 | return 0; | 2206 | return 0; |
2037 | } | 2207 | } |
@@ -2039,7 +2209,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_stream_event); | |||
2039 | 2209 | ||
2040 | /** | 2210 | /** |
2041 | * snd_soc_dapm_enable_pin - enable pin. | 2211 | * snd_soc_dapm_enable_pin - enable pin. |
2042 | * @codec: SoC codec | 2212 | * @dapm: DAPM context |
2043 | * @pin: pin name | 2213 | * @pin: pin name |
2044 | * | 2214 | * |
2045 | * Enables input/output pin and its parents or children widgets iff there is | 2215 | * Enables input/output pin and its parents or children widgets iff there is |
@@ -2047,15 +2217,15 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_stream_event); | |||
2047 | * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to | 2217 | * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to |
2048 | * do any widget power switching. | 2218 | * do any widget power switching. |
2049 | */ | 2219 | */ |
2050 | int snd_soc_dapm_enable_pin(struct snd_soc_codec *codec, const char *pin) | 2220 | int snd_soc_dapm_enable_pin(struct snd_soc_dapm_context *dapm, const char *pin) |
2051 | { | 2221 | { |
2052 | return snd_soc_dapm_set_pin(codec, pin, 1); | 2222 | return snd_soc_dapm_set_pin(dapm, pin, 1); |
2053 | } | 2223 | } |
2054 | EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin); | 2224 | EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin); |
2055 | 2225 | ||
2056 | /** | 2226 | /** |
2057 | * snd_soc_dapm_force_enable_pin - force a pin to be enabled | 2227 | * snd_soc_dapm_force_enable_pin - force a pin to be enabled |
2058 | * @codec: SoC codec | 2228 | * @dapm: DAPM context |
2059 | * @pin: pin name | 2229 | * @pin: pin name |
2060 | * | 2230 | * |
2061 | * Enables input/output pin regardless of any other state. This is | 2231 | * Enables input/output pin regardless of any other state. This is |
@@ -2065,42 +2235,47 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin); | |||
2065 | * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to | 2235 | * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to |
2066 | * do any widget power switching. | 2236 | * do any widget power switching. |
2067 | */ | 2237 | */ |
2068 | int snd_soc_dapm_force_enable_pin(struct snd_soc_codec *codec, const char *pin) | 2238 | int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm, |
2239 | const char *pin) | ||
2069 | { | 2240 | { |
2070 | struct snd_soc_dapm_widget *w; | 2241 | struct snd_soc_dapm_widget *w; |
2071 | 2242 | ||
2072 | list_for_each_entry(w, &codec->dapm_widgets, list) { | 2243 | list_for_each_entry(w, &dapm->card->widgets, list) { |
2244 | if (w->dapm != dapm) | ||
2245 | continue; | ||
2073 | if (!strcmp(w->name, pin)) { | 2246 | if (!strcmp(w->name, pin)) { |
2074 | pr_debug("dapm: %s: pin %s\n", codec->name, pin); | 2247 | dev_dbg(w->dapm->dev, |
2248 | "dapm: force enable pin %s\n", pin); | ||
2075 | w->connected = 1; | 2249 | w->connected = 1; |
2076 | w->force = 1; | 2250 | w->force = 1; |
2077 | return 0; | 2251 | return 0; |
2078 | } | 2252 | } |
2079 | } | 2253 | } |
2080 | 2254 | ||
2081 | pr_err("dapm: %s: configuring unknown pin %s\n", codec->name, pin); | 2255 | dev_err(dapm->dev, "dapm: unknown pin %s\n", pin); |
2082 | return -EINVAL; | 2256 | return -EINVAL; |
2083 | } | 2257 | } |
2084 | EXPORT_SYMBOL_GPL(snd_soc_dapm_force_enable_pin); | 2258 | EXPORT_SYMBOL_GPL(snd_soc_dapm_force_enable_pin); |
2085 | 2259 | ||
2086 | /** | 2260 | /** |
2087 | * snd_soc_dapm_disable_pin - disable pin. | 2261 | * snd_soc_dapm_disable_pin - disable pin. |
2088 | * @codec: SoC codec | 2262 | * @dapm: DAPM context |
2089 | * @pin: pin name | 2263 | * @pin: pin name |
2090 | * | 2264 | * |
2091 | * Disables input/output pin and its parents or children widgets. | 2265 | * Disables input/output pin and its parents or children widgets. |
2092 | * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to | 2266 | * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to |
2093 | * do any widget power switching. | 2267 | * do any widget power switching. |
2094 | */ | 2268 | */ |
2095 | int snd_soc_dapm_disable_pin(struct snd_soc_codec *codec, const char *pin) | 2269 | int snd_soc_dapm_disable_pin(struct snd_soc_dapm_context *dapm, |
2270 | const char *pin) | ||
2096 | { | 2271 | { |
2097 | return snd_soc_dapm_set_pin(codec, pin, 0); | 2272 | return snd_soc_dapm_set_pin(dapm, pin, 0); |
2098 | } | 2273 | } |
2099 | EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin); | 2274 | EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin); |
2100 | 2275 | ||
2101 | /** | 2276 | /** |
2102 | * snd_soc_dapm_nc_pin - permanently disable pin. | 2277 | * snd_soc_dapm_nc_pin - permanently disable pin. |
2103 | * @codec: SoC codec | 2278 | * @dapm: DAPM context |
2104 | * @pin: pin name | 2279 | * @pin: pin name |
2105 | * | 2280 | * |
2106 | * Marks the specified pin as being not connected, disabling it along | 2281 | * Marks the specified pin as being not connected, disabling it along |
@@ -2112,26 +2287,29 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin); | |||
2112 | * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to | 2287 | * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to |
2113 | * do any widget power switching. | 2288 | * do any widget power switching. |
2114 | */ | 2289 | */ |
2115 | int snd_soc_dapm_nc_pin(struct snd_soc_codec *codec, const char *pin) | 2290 | int snd_soc_dapm_nc_pin(struct snd_soc_dapm_context *dapm, const char *pin) |
2116 | { | 2291 | { |
2117 | return snd_soc_dapm_set_pin(codec, pin, 0); | 2292 | return snd_soc_dapm_set_pin(dapm, pin, 0); |
2118 | } | 2293 | } |
2119 | EXPORT_SYMBOL_GPL(snd_soc_dapm_nc_pin); | 2294 | EXPORT_SYMBOL_GPL(snd_soc_dapm_nc_pin); |
2120 | 2295 | ||
2121 | /** | 2296 | /** |
2122 | * snd_soc_dapm_get_pin_status - get audio pin status | 2297 | * snd_soc_dapm_get_pin_status - get audio pin status |
2123 | * @codec: audio codec | 2298 | * @dapm: DAPM context |
2124 | * @pin: audio signal pin endpoint (or start point) | 2299 | * @pin: audio signal pin endpoint (or start point) |
2125 | * | 2300 | * |
2126 | * Get audio pin status - connected or disconnected. | 2301 | * Get audio pin status - connected or disconnected. |
2127 | * | 2302 | * |
2128 | * Returns 1 for connected otherwise 0. | 2303 | * Returns 1 for connected otherwise 0. |
2129 | */ | 2304 | */ |
2130 | int snd_soc_dapm_get_pin_status(struct snd_soc_codec *codec, const char *pin) | 2305 | int snd_soc_dapm_get_pin_status(struct snd_soc_dapm_context *dapm, |
2306 | const char *pin) | ||
2131 | { | 2307 | { |
2132 | struct snd_soc_dapm_widget *w; | 2308 | struct snd_soc_dapm_widget *w; |
2133 | 2309 | ||
2134 | list_for_each_entry(w, &codec->dapm_widgets, list) { | 2310 | list_for_each_entry(w, &dapm->card->widgets, list) { |
2311 | if (w->dapm != dapm) | ||
2312 | continue; | ||
2135 | if (!strcmp(w->name, pin)) | 2313 | if (!strcmp(w->name, pin)) |
2136 | return w->connected; | 2314 | return w->connected; |
2137 | } | 2315 | } |
@@ -2142,7 +2320,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_pin_status); | |||
2142 | 2320 | ||
2143 | /** | 2321 | /** |
2144 | * snd_soc_dapm_ignore_suspend - ignore suspend status for DAPM endpoint | 2322 | * snd_soc_dapm_ignore_suspend - ignore suspend status for DAPM endpoint |
2145 | * @codec: audio codec | 2323 | * @dapm: DAPM context |
2146 | * @pin: audio signal pin endpoint (or start point) | 2324 | * @pin: audio signal pin endpoint (or start point) |
2147 | * | 2325 | * |
2148 | * Mark the given endpoint or pin as ignoring suspend. When the | 2326 | * Mark the given endpoint or pin as ignoring suspend. When the |
@@ -2151,18 +2329,21 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_pin_status); | |||
2151 | * normal means at suspend time, it will not be turned on if it was not | 2329 | * normal means at suspend time, it will not be turned on if it was not |
2152 | * already enabled. | 2330 | * already enabled. |
2153 | */ | 2331 | */ |
2154 | int snd_soc_dapm_ignore_suspend(struct snd_soc_codec *codec, const char *pin) | 2332 | int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm, |
2333 | const char *pin) | ||
2155 | { | 2334 | { |
2156 | struct snd_soc_dapm_widget *w; | 2335 | struct snd_soc_dapm_widget *w; |
2157 | 2336 | ||
2158 | list_for_each_entry(w, &codec->dapm_widgets, list) { | 2337 | list_for_each_entry(w, &dapm->card->widgets, list) { |
2338 | if (w->dapm != dapm) | ||
2339 | continue; | ||
2159 | if (!strcmp(w->name, pin)) { | 2340 | if (!strcmp(w->name, pin)) { |
2160 | w->ignore_suspend = 1; | 2341 | w->ignore_suspend = 1; |
2161 | return 0; | 2342 | return 0; |
2162 | } | 2343 | } |
2163 | } | 2344 | } |
2164 | 2345 | ||
2165 | pr_err("Unknown DAPM pin: %s\n", pin); | 2346 | dev_err(dapm->dev, "dapm: unknown pin %s\n", pin); |
2166 | return -EINVAL; | 2347 | return -EINVAL; |
2167 | } | 2348 | } |
2168 | EXPORT_SYMBOL_GPL(snd_soc_dapm_ignore_suspend); | 2349 | EXPORT_SYMBOL_GPL(snd_soc_dapm_ignore_suspend); |
@@ -2173,20 +2354,23 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_ignore_suspend); | |||
2173 | * | 2354 | * |
2174 | * Free all dapm widgets and resources. | 2355 | * Free all dapm widgets and resources. |
2175 | */ | 2356 | */ |
2176 | void snd_soc_dapm_free(struct snd_soc_codec *codec) | 2357 | void snd_soc_dapm_free(struct snd_soc_dapm_context *dapm) |
2177 | { | 2358 | { |
2178 | snd_soc_dapm_sys_remove(codec->dev); | 2359 | snd_soc_dapm_sys_remove(dapm->dev); |
2179 | dapm_free_widgets(codec); | 2360 | dapm_free_widgets(dapm); |
2361 | list_del(&dapm->list); | ||
2180 | } | 2362 | } |
2181 | EXPORT_SYMBOL_GPL(snd_soc_dapm_free); | 2363 | EXPORT_SYMBOL_GPL(snd_soc_dapm_free); |
2182 | 2364 | ||
2183 | static void soc_dapm_shutdown_codec(struct snd_soc_codec *codec) | 2365 | static void soc_dapm_shutdown_codec(struct snd_soc_dapm_context *dapm) |
2184 | { | 2366 | { |
2185 | struct snd_soc_dapm_widget *w; | 2367 | struct snd_soc_dapm_widget *w; |
2186 | LIST_HEAD(down_list); | 2368 | LIST_HEAD(down_list); |
2187 | int powerdown = 0; | 2369 | int powerdown = 0; |
2188 | 2370 | ||
2189 | list_for_each_entry(w, &codec->dapm_widgets, list) { | 2371 | list_for_each_entry(w, &dapm->card->widgets, list) { |
2372 | if (w->dapm != dapm) | ||
2373 | continue; | ||
2190 | if (w->power) { | 2374 | if (w->power) { |
2191 | dapm_seq_insert(w, &down_list, dapm_down_seq); | 2375 | dapm_seq_insert(w, &down_list, dapm_down_seq); |
2192 | w->power = 0; | 2376 | w->power = 0; |
@@ -2198,9 +2382,9 @@ static void soc_dapm_shutdown_codec(struct snd_soc_codec *codec) | |||
2198 | * standby. | 2382 | * standby. |
2199 | */ | 2383 | */ |
2200 | if (powerdown) { | 2384 | if (powerdown) { |
2201 | snd_soc_dapm_set_bias_level(NULL, codec, SND_SOC_BIAS_PREPARE); | 2385 | snd_soc_dapm_set_bias_level(NULL, dapm, SND_SOC_BIAS_PREPARE); |
2202 | dapm_seq_run(codec, &down_list, 0, dapm_down_seq); | 2386 | dapm_seq_run(dapm, &down_list, 0, dapm_down_seq); |
2203 | snd_soc_dapm_set_bias_level(NULL, codec, SND_SOC_BIAS_STANDBY); | 2387 | snd_soc_dapm_set_bias_level(NULL, dapm, SND_SOC_BIAS_STANDBY); |
2204 | } | 2388 | } |
2205 | } | 2389 | } |
2206 | 2390 | ||
@@ -2211,10 +2395,10 @@ void snd_soc_dapm_shutdown(struct snd_soc_card *card) | |||
2211 | { | 2395 | { |
2212 | struct snd_soc_codec *codec; | 2396 | struct snd_soc_codec *codec; |
2213 | 2397 | ||
2214 | list_for_each_entry(codec, &card->codec_dev_list, list) | 2398 | list_for_each_entry(codec, &card->codec_dev_list, list) { |
2215 | soc_dapm_shutdown_codec(codec); | 2399 | soc_dapm_shutdown_codec(&codec->dapm); |
2216 | 2400 | snd_soc_dapm_set_bias_level(card, &codec->dapm, SND_SOC_BIAS_OFF); | |
2217 | snd_soc_dapm_set_bias_level(card, codec, SND_SOC_BIAS_OFF); | 2401 | } |
2218 | } | 2402 | } |
2219 | 2403 | ||
2220 | /* Module information */ | 2404 | /* Module information */ |