Merge branch 'topic/asoc-next' into topic/asoc
[safe/jmp/linux-2.6] / sound / soc / soc-dapm.c
1 /*
2  * soc-dapm.c  --  ALSA SoC Dynamic Audio Power Management
3  *
4  * Copyright 2005 Wolfson Microelectronics PLC.
5  * Author: Liam Girdwood <lrg@slimlogic.co.uk>
6  *
7  *  This program is free software; you can redistribute  it and/or modify it
8  *  under  the terms of  the GNU General  Public License as published by the
9  *  Free Software Foundation;  either version 2 of the  License, or (at your
10  *  option) any later version.
11  *
12  *  Features:
13  *    o Changes power status of internal codec blocks depending on the
14  *      dynamic configuration of codec internal audio paths and active
15  *      DAC's/ADC's.
16  *    o Platform power domain - can support external components i.e. amps and
17  *      mic/meadphone insertion events.
18  *    o Automatic Mic Bias support
19  *    o Jack insertion power event initiation - e.g. hp insertion will enable
20  *      sinks, dacs, etc
21  *    o Delayed powerdown of audio susbsystem to reduce pops between a quick
22  *      device reopen.
23  *
24  *  Todo:
25  *    o DAPM power change sequencing - allow for configurable per
26  *      codec sequences.
27  *    o Support for analogue bias optimisation.
28  *    o Support for reduced codec oversampling rates.
29  *    o Support for reduced codec bias currents.
30  */
31
32 #include <linux/module.h>
33 #include <linux/moduleparam.h>
34 #include <linux/init.h>
35 #include <linux/delay.h>
36 #include <linux/pm.h>
37 #include <linux/bitops.h>
38 #include <linux/platform_device.h>
39 #include <linux/jiffies.h>
40 #include <linux/debugfs.h>
41 #include <sound/core.h>
42 #include <sound/pcm.h>
43 #include <sound/pcm_params.h>
44 #include <sound/soc-dapm.h>
45 #include <sound/initval.h>
46
47 /* debug */
48 #ifdef DEBUG
49 #define dump_dapm(codec, action) dbg_dump_dapm(codec, action)
50 #else
51 #define dump_dapm(codec, action)
52 #endif
53
54 /* dapm power sequences - make this per codec in the future */
55 static int dapm_up_seq[] = {
56         snd_soc_dapm_pre, snd_soc_dapm_micbias, snd_soc_dapm_mic,
57         snd_soc_dapm_mux, snd_soc_dapm_dac, snd_soc_dapm_mixer, snd_soc_dapm_pga,
58         snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk, snd_soc_dapm_post
59 };
60 static int dapm_down_seq[] = {
61         snd_soc_dapm_pre, snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk,
62         snd_soc_dapm_pga, snd_soc_dapm_mixer, snd_soc_dapm_dac, snd_soc_dapm_mic,
63         snd_soc_dapm_micbias, snd_soc_dapm_mux, snd_soc_dapm_post
64 };
65
66 static int dapm_status = 1;
67 module_param(dapm_status, int, 0);
68 MODULE_PARM_DESC(dapm_status, "enable DPM sysfs entries");
69
70 static struct dentry *asoc_debugfs;
71
72 static u32 pop_time;
73
74 static void pop_wait(void)
75 {
76         if (pop_time)
77                 schedule_timeout_uninterruptible(msecs_to_jiffies(pop_time));
78 }
79
80 static void pop_dbg(const char *fmt, ...)
81 {
82         va_list args;
83
84         va_start(args, fmt);
85
86         if (pop_time) {
87                 vprintk(fmt, args);
88                 pop_wait();
89         }
90
91         va_end(args);
92 }
93
94 /* create a new dapm widget */
95 static inline struct snd_soc_dapm_widget *dapm_cnew_widget(
96         const struct snd_soc_dapm_widget *_widget)
97 {
98         return kmemdup(_widget, sizeof(*_widget), GFP_KERNEL);
99 }
100
101 /* set up initial codec paths */
102 static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
103         struct snd_soc_dapm_path *p, int i)
104 {
105         switch (w->id) {
106         case snd_soc_dapm_switch:
107         case snd_soc_dapm_mixer: {
108                 int val;
109                 struct soc_mixer_control *mc = (struct soc_mixer_control *)
110                         w->kcontrols[i].private_value;
111                 unsigned int reg = mc->reg;
112                 unsigned int shift = mc->shift;
113                 int max = mc->max;
114                 unsigned int mask = (1 << fls(max)) - 1;
115                 unsigned int invert = mc->invert;
116
117                 val = snd_soc_read(w->codec, reg);
118                 val = (val >> shift) & mask;
119
120                 if ((invert && !val) || (!invert && val))
121                         p->connect = 1;
122                 else
123                         p->connect = 0;
124         }
125         break;
126         case snd_soc_dapm_mux: {
127                 struct soc_enum *e = (struct soc_enum *)w->kcontrols[i].private_value;
128                 int val, item, bitmask;
129
130                 for (bitmask = 1; bitmask < e->max; bitmask <<= 1)
131                 ;
132                 val = snd_soc_read(w->codec, e->reg);
133                 item = (val >> e->shift_l) & (bitmask - 1);
134
135                 p->connect = 0;
136                 for (i = 0; i < e->max; i++) {
137                         if (!(strcmp(p->name, e->texts[i])) && item == i)
138                                 p->connect = 1;
139                 }
140         }
141         break;
142         /* does not effect routing - always connected */
143         case snd_soc_dapm_pga:
144         case snd_soc_dapm_output:
145         case snd_soc_dapm_adc:
146         case snd_soc_dapm_input:
147         case snd_soc_dapm_dac:
148         case snd_soc_dapm_micbias:
149         case snd_soc_dapm_vmid:
150                 p->connect = 1;
151         break;
152         /* does effect routing - dynamically connected */
153         case snd_soc_dapm_hp:
154         case snd_soc_dapm_mic:
155         case snd_soc_dapm_spk:
156         case snd_soc_dapm_line:
157         case snd_soc_dapm_pre:
158         case snd_soc_dapm_post:
159                 p->connect = 0;
160         break;
161         }
162 }
163
164 /* connect mux widget to it's interconnecting audio paths */
165 static int dapm_connect_mux(struct snd_soc_codec *codec,
166         struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest,
167         struct snd_soc_dapm_path *path, const char *control_name,
168         const struct snd_kcontrol_new *kcontrol)
169 {
170         struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
171         int i;
172
173         for (i = 0; i < e->max; i++) {
174                 if (!(strcmp(control_name, e->texts[i]))) {
175                         list_add(&path->list, &codec->dapm_paths);
176                         list_add(&path->list_sink, &dest->sources);
177                         list_add(&path->list_source, &src->sinks);
178                         path->name = (char*)e->texts[i];
179                         dapm_set_path_status(dest, path, 0);
180                         return 0;
181                 }
182         }
183
184         return -ENODEV;
185 }
186
187 /* connect mixer widget to it's interconnecting audio paths */
188 static int dapm_connect_mixer(struct snd_soc_codec *codec,
189         struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest,
190         struct snd_soc_dapm_path *path, const char *control_name)
191 {
192         int i;
193
194         /* search for mixer kcontrol */
195         for (i = 0; i < dest->num_kcontrols; i++) {
196                 if (!strcmp(control_name, dest->kcontrols[i].name)) {
197                         list_add(&path->list, &codec->dapm_paths);
198                         list_add(&path->list_sink, &dest->sources);
199                         list_add(&path->list_source, &src->sinks);
200                         path->name = dest->kcontrols[i].name;
201                         dapm_set_path_status(dest, path, i);
202                         return 0;
203                 }
204         }
205         return -ENODEV;
206 }
207
208 /* update dapm codec register bits */
209 static int dapm_update_bits(struct snd_soc_dapm_widget *widget)
210 {
211         int change, power;
212         unsigned short old, new;
213         struct snd_soc_codec *codec = widget->codec;
214
215         /* check for valid widgets */
216         if (widget->reg < 0 || widget->id == snd_soc_dapm_input ||
217                 widget->id == snd_soc_dapm_output ||
218                 widget->id == snd_soc_dapm_hp ||
219                 widget->id == snd_soc_dapm_mic ||
220                 widget->id == snd_soc_dapm_line ||
221                 widget->id == snd_soc_dapm_spk)
222                 return 0;
223
224         power = widget->power;
225         if (widget->invert)
226                 power = (power ? 0:1);
227
228         old = snd_soc_read(codec, widget->reg);
229         new = (old & ~(0x1 << widget->shift)) | (power << widget->shift);
230
231         change = old != new;
232         if (change) {
233                 pop_dbg("pop test %s : %s in %d ms\n", widget->name,
234                         widget->power ? "on" : "off", pop_time);
235                 snd_soc_write(codec, widget->reg, new);
236                 pop_wait();
237         }
238         pr_debug("reg %x old %x new %x change %d\n", widget->reg,
239                  old, new, change);
240         return change;
241 }
242
243 /* ramps the volume up or down to minimise pops before or after a
244  * DAPM power event */
245 static int dapm_set_pga(struct snd_soc_dapm_widget *widget, int power)
246 {
247         const struct snd_kcontrol_new *k = widget->kcontrols;
248
249         if (widget->muted && !power)
250                 return 0;
251         if (!widget->muted && power)
252                 return 0;
253
254         if (widget->num_kcontrols && k) {
255                 struct soc_mixer_control *mc =
256                         (struct soc_mixer_control *)k->private_value;
257                 unsigned int reg = mc->reg;
258                 unsigned int shift = mc->shift;
259                 int max = mc->max;
260                 unsigned int mask = (1 << fls(max)) - 1;
261                 unsigned int invert = mc->invert;
262
263                 if (power) {
264                         int i;
265                         /* power up has happended, increase volume to last level */
266                         if (invert) {
267                                 for (i = max; i > widget->saved_value; i--)
268                                         snd_soc_update_bits(widget->codec, reg, mask, i);
269                         } else {
270                                 for (i = 0; i < widget->saved_value; i++)
271                                         snd_soc_update_bits(widget->codec, reg, mask, i);
272                         }
273                         widget->muted = 0;
274                 } else {
275                         /* power down is about to occur, decrease volume to mute */
276                         int val = snd_soc_read(widget->codec, reg);
277                         int i = widget->saved_value = (val >> shift) & mask;
278                         if (invert) {
279                                 for (; i < mask; i++)
280                                         snd_soc_update_bits(widget->codec, reg, mask, i);
281                         } else {
282                                 for (; i > 0; i--)
283                                         snd_soc_update_bits(widget->codec, reg, mask, i);
284                         }
285                         widget->muted = 1;
286                 }
287         }
288         return 0;
289 }
290
291 /* create new dapm mixer control */
292 static int dapm_new_mixer(struct snd_soc_codec *codec,
293         struct snd_soc_dapm_widget *w)
294 {
295         int i, ret = 0;
296         char name[32];
297         struct snd_soc_dapm_path *path;
298
299         /* add kcontrol */
300         for (i = 0; i < w->num_kcontrols; i++) {
301
302                 /* match name */
303                 list_for_each_entry(path, &w->sources, list_sink) {
304
305                         /* mixer/mux paths name must match control name */
306                         if (path->name != (char*)w->kcontrols[i].name)
307                                 continue;
308
309                         /* add dapm control with long name */
310                         snprintf(name, 32, "%s %s", w->name, w->kcontrols[i].name);
311                         path->long_name = kstrdup (name, GFP_KERNEL);
312                         if (path->long_name == NULL)
313                                 return -ENOMEM;
314
315                         path->kcontrol = snd_soc_cnew(&w->kcontrols[i], w,
316                                 path->long_name);
317                         ret = snd_ctl_add(codec->card, path->kcontrol);
318                         if (ret < 0) {
319                                 printk(KERN_ERR "asoc: failed to add dapm kcontrol %s\n",
320                                                 path->long_name);
321                                 kfree(path->long_name);
322                                 path->long_name = NULL;
323                                 return ret;
324                         }
325                 }
326         }
327         return ret;
328 }
329
330 /* create new dapm mux control */
331 static int dapm_new_mux(struct snd_soc_codec *codec,
332         struct snd_soc_dapm_widget *w)
333 {
334         struct snd_soc_dapm_path *path = NULL;
335         struct snd_kcontrol *kcontrol;
336         int ret = 0;
337
338         if (!w->num_kcontrols) {
339                 printk(KERN_ERR "asoc: mux %s has no controls\n", w->name);
340                 return -EINVAL;
341         }
342
343         kcontrol = snd_soc_cnew(&w->kcontrols[0], w, w->name);
344         ret = snd_ctl_add(codec->card, kcontrol);
345         if (ret < 0)
346                 goto err;
347
348         list_for_each_entry(path, &w->sources, list_sink)
349                 path->kcontrol = kcontrol;
350
351         return ret;
352
353 err:
354         printk(KERN_ERR "asoc: failed to add kcontrol %s\n", w->name);
355         return ret;
356 }
357
358 /* create new dapm volume control */
359 static int dapm_new_pga(struct snd_soc_codec *codec,
360         struct snd_soc_dapm_widget *w)
361 {
362         struct snd_kcontrol *kcontrol;
363         int ret = 0;
364
365         if (!w->num_kcontrols)
366                 return -EINVAL;
367
368         kcontrol = snd_soc_cnew(&w->kcontrols[0], w, w->name);
369         ret = snd_ctl_add(codec->card, kcontrol);
370         if (ret < 0) {
371                 printk(KERN_ERR "asoc: failed to add kcontrol %s\n", w->name);
372                 return ret;
373         }
374
375         return ret;
376 }
377
378 /* reset 'walked' bit for each dapm path */
379 static inline void dapm_clear_walk(struct snd_soc_codec *codec)
380 {
381         struct snd_soc_dapm_path *p;
382
383         list_for_each_entry(p, &codec->dapm_paths, list)
384                 p->walked = 0;
385 }
386
387 /*
388  * Recursively check for a completed path to an active or physically connected
389  * output widget. Returns number of complete paths.
390  */
391 static int is_connected_output_ep(struct snd_soc_dapm_widget *widget)
392 {
393         struct snd_soc_dapm_path *path;
394         int con = 0;
395
396         if (widget->id == snd_soc_dapm_adc && widget->active)
397                 return 1;
398
399         if (widget->connected) {
400                 /* connected pin ? */
401                 if (widget->id == snd_soc_dapm_output && !widget->ext)
402                         return 1;
403
404                 /* connected jack or spk ? */
405                 if (widget->id == snd_soc_dapm_hp || widget->id == snd_soc_dapm_spk ||
406                         widget->id == snd_soc_dapm_line)
407                         return 1;
408         }
409
410         list_for_each_entry(path, &widget->sinks, list_source) {
411                 if (path->walked)
412                         continue;
413
414                 if (path->sink && path->connect) {
415                         path->walked = 1;
416                         con += is_connected_output_ep(path->sink);
417                 }
418         }
419
420         return con;
421 }
422
423 /*
424  * Recursively check for a completed path to an active or physically connected
425  * input widget. Returns number of complete paths.
426  */
427 static int is_connected_input_ep(struct snd_soc_dapm_widget *widget)
428 {
429         struct snd_soc_dapm_path *path;
430         int con = 0;
431
432         /* active stream ? */
433         if (widget->id == snd_soc_dapm_dac && widget->active)
434                 return 1;
435
436         if (widget->connected) {
437                 /* connected pin ? */
438                 if (widget->id == snd_soc_dapm_input && !widget->ext)
439                         return 1;
440
441                 /* connected VMID/Bias for lower pops */
442                 if (widget->id == snd_soc_dapm_vmid)
443                         return 1;
444
445                 /* connected jack ? */
446                 if (widget->id == snd_soc_dapm_mic || widget->id == snd_soc_dapm_line)
447                         return 1;
448         }
449
450         list_for_each_entry(path, &widget->sources, list_sink) {
451                 if (path->walked)
452                         continue;
453
454                 if (path->source && path->connect) {
455                         path->walked = 1;
456                         con += is_connected_input_ep(path->source);
457                 }
458         }
459
460         return con;
461 }
462
463 /*
464  * Handler for generic register modifier widget.
465  */
466 int dapm_reg_event(struct snd_soc_dapm_widget *w,
467                    struct snd_kcontrol *kcontrol, int event)
468 {
469         unsigned int val;
470
471         if (SND_SOC_DAPM_EVENT_ON(event))
472                 val = w->on_val;
473         else
474                 val = w->off_val;
475
476         snd_soc_update_bits(w->codec, -(w->reg + 1),
477                             w->mask << w->shift, val << w->shift);
478
479         return 0;
480 }
481 EXPORT_SYMBOL_GPL(dapm_reg_event);
482
483 /*
484  * Scan each dapm widget for complete audio path.
485  * A complete path is a route that has valid endpoints i.e.:-
486  *
487  *  o DAC to output pin.
488  *  o Input Pin to ADC.
489  *  o Input pin to Output pin (bypass, sidetone)
490  *  o DAC to ADC (loopback).
491  */
492 static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
493 {
494         struct snd_soc_dapm_widget *w;
495         int in, out, i, c = 1, *seq = NULL, ret = 0, power_change, power;
496
497         /* do we have a sequenced stream event */
498         if (event == SND_SOC_DAPM_STREAM_START) {
499                 c = ARRAY_SIZE(dapm_up_seq);
500                 seq = dapm_up_seq;
501         } else if (event == SND_SOC_DAPM_STREAM_STOP) {
502                 c = ARRAY_SIZE(dapm_down_seq);
503                 seq = dapm_down_seq;
504         }
505
506         for(i = 0; i < c; i++) {
507                 list_for_each_entry(w, &codec->dapm_widgets, list) {
508
509                         /* is widget in stream order */
510                         if (seq && seq[i] && w->id != seq[i])
511                                 continue;
512
513                         /* vmid - no action */
514                         if (w->id == snd_soc_dapm_vmid)
515                                 continue;
516
517                         /* active ADC */
518                         if (w->id == snd_soc_dapm_adc && w->active) {
519                                 in = is_connected_input_ep(w);
520                                 dapm_clear_walk(w->codec);
521                                 w->power = (in != 0) ? 1 : 0;
522                                 dapm_update_bits(w);
523                                 continue;
524                         }
525
526                         /* active DAC */
527                         if (w->id == snd_soc_dapm_dac && w->active) {
528                                 out = is_connected_output_ep(w);
529                                 dapm_clear_walk(w->codec);
530                                 w->power = (out != 0) ? 1 : 0;
531                                 dapm_update_bits(w);
532                                 continue;
533                         }
534
535                         /* pre and post event widgets */
536                         if (w->id == snd_soc_dapm_pre) {
537                                 if (!w->event)
538                                         continue;
539
540                                 if (event == SND_SOC_DAPM_STREAM_START) {
541                                         ret = w->event(w,
542                                                 NULL, SND_SOC_DAPM_PRE_PMU);
543                                         if (ret < 0)
544                                                 return ret;
545                                 } else if (event == SND_SOC_DAPM_STREAM_STOP) {
546                                         ret = w->event(w,
547                                                 NULL, SND_SOC_DAPM_PRE_PMD);
548                                         if (ret < 0)
549                                                 return ret;
550                                 }
551                                 continue;
552                         }
553                         if (w->id == snd_soc_dapm_post) {
554                                 if (!w->event)
555                                         continue;
556
557                                 if (event == SND_SOC_DAPM_STREAM_START) {
558                                         ret = w->event(w,
559                                                 NULL, SND_SOC_DAPM_POST_PMU);
560                                         if (ret < 0)
561                                                 return ret;
562                                 } else if (event == SND_SOC_DAPM_STREAM_STOP) {
563                                         ret = w->event(w,
564                                                 NULL, SND_SOC_DAPM_POST_PMD);
565                                         if (ret < 0)
566                                                 return ret;
567                                 }
568                                 continue;
569                         }
570
571                         /* all other widgets */
572                         in = is_connected_input_ep(w);
573                         dapm_clear_walk(w->codec);
574                         out = is_connected_output_ep(w);
575                         dapm_clear_walk(w->codec);
576                         power = (out != 0 && in != 0) ? 1 : 0;
577                         power_change = (w->power == power) ? 0: 1;
578                         w->power = power;
579
580                         if (!power_change)
581                                 continue;
582
583                         /* call any power change event handlers */
584                         if (w->event)
585                                 pr_debug("power %s event for %s flags %x\n",
586                                          w->power ? "on" : "off",
587                                          w->name, w->event_flags);
588
589                         /* power up pre event */
590                         if (power && w->event &&
591                             (w->event_flags & SND_SOC_DAPM_PRE_PMU)) {
592                                 ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMU);
593                                 if (ret < 0)
594                                         return ret;
595                         }
596
597                         /* power down pre event */
598                         if (!power && w->event &&
599                             (w->event_flags & SND_SOC_DAPM_PRE_PMD)) {
600                                 ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMD);
601                                 if (ret < 0)
602                                         return ret;
603                         }
604
605                         /* Lower PGA volume to reduce pops */
606                         if (w->id == snd_soc_dapm_pga && !power)
607                                 dapm_set_pga(w, power);
608
609                         dapm_update_bits(w);
610
611                         /* Raise PGA volume to reduce pops */
612                         if (w->id == snd_soc_dapm_pga && power)
613                                 dapm_set_pga(w, power);
614
615                         /* power up post event */
616                         if (power && w->event &&
617                             (w->event_flags & SND_SOC_DAPM_POST_PMU)) {
618                                 ret = w->event(w,
619                                                NULL, SND_SOC_DAPM_POST_PMU);
620                                 if (ret < 0)
621                                         return ret;
622                         }
623
624                         /* power down post event */
625                         if (!power && w->event &&
626                             (w->event_flags & SND_SOC_DAPM_POST_PMD)) {
627                                 ret = w->event(w, NULL, SND_SOC_DAPM_POST_PMD);
628                                 if (ret < 0)
629                                         return ret;
630                         }
631                 }
632         }
633
634         return ret;
635 }
636
637 #ifdef DEBUG
638 static void dbg_dump_dapm(struct snd_soc_codec* codec, const char *action)
639 {
640         struct snd_soc_dapm_widget *w;
641         struct snd_soc_dapm_path *p = NULL;
642         int in, out;
643
644         printk("DAPM %s %s\n", codec->name, action);
645
646         list_for_each_entry(w, &codec->dapm_widgets, list) {
647
648                 /* only display widgets that effect routing */
649                 switch (w->id) {
650                 case snd_soc_dapm_pre:
651                 case snd_soc_dapm_post:
652                 case snd_soc_dapm_vmid:
653                         continue;
654                 case snd_soc_dapm_mux:
655                 case snd_soc_dapm_output:
656                 case snd_soc_dapm_input:
657                 case snd_soc_dapm_switch:
658                 case snd_soc_dapm_hp:
659                 case snd_soc_dapm_mic:
660                 case snd_soc_dapm_spk:
661                 case snd_soc_dapm_line:
662                 case snd_soc_dapm_micbias:
663                 case snd_soc_dapm_dac:
664                 case snd_soc_dapm_adc:
665                 case snd_soc_dapm_pga:
666                 case snd_soc_dapm_mixer:
667                         if (w->name) {
668                                 in = is_connected_input_ep(w);
669                                 dapm_clear_walk(w->codec);
670                                 out = is_connected_output_ep(w);
671                                 dapm_clear_walk(w->codec);
672                                 printk("%s: %s  in %d out %d\n", w->name,
673                                         w->power ? "On":"Off",in, out);
674
675                                 list_for_each_entry(p, &w->sources, list_sink) {
676                                         if (p->connect)
677                                                 printk(" in  %s %s\n", p->name ? p->name : "static",
678                                                         p->source->name);
679                                 }
680                                 list_for_each_entry(p, &w->sinks, list_source) {
681                                         if (p->connect)
682                                                 printk(" out %s %s\n", p->name ? p->name : "static",
683                                                         p->sink->name);
684                                 }
685                         }
686                 break;
687                 }
688         }
689 }
690 #endif
691
692 /* test and update the power status of a mux widget */
693 static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
694                                  struct snd_kcontrol *kcontrol, int mask,
695                                  int mux, int val, struct soc_enum *e)
696 {
697         struct snd_soc_dapm_path *path;
698         int found = 0;
699
700         if (widget->id != snd_soc_dapm_mux)
701                 return -ENODEV;
702
703         if (!snd_soc_test_bits(widget->codec, e->reg, mask, val))
704                 return 0;
705
706         /* find dapm widget path assoc with kcontrol */
707         list_for_each_entry(path, &widget->codec->dapm_paths, list) {
708                 if (path->kcontrol != kcontrol)
709                         continue;
710
711                 if (!path->name || !e->texts[mux])
712                         continue;
713
714                 found = 1;
715                 /* we now need to match the string in the enum to the path */
716                 if (!(strcmp(path->name, e->texts[mux])))
717                         path->connect = 1; /* new connection */
718                 else
719                         path->connect = 0; /* old connection must be powered down */
720         }
721
722         if (found) {
723                 dapm_power_widgets(widget->codec, SND_SOC_DAPM_STREAM_NOP);
724                 dump_dapm(widget->codec, "mux power update");
725         }
726
727         return 0;
728 }
729
730 /* test and update the power status of a mixer or switch widget */
731 static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
732                                    struct snd_kcontrol *kcontrol, int reg,
733                                    int val_mask, int val, int invert)
734 {
735         struct snd_soc_dapm_path *path;
736         int found = 0;
737
738         if (widget->id != snd_soc_dapm_mixer &&
739             widget->id != snd_soc_dapm_switch)
740                 return -ENODEV;
741
742         if (!snd_soc_test_bits(widget->codec, reg, val_mask, val))
743                 return 0;
744
745         /* find dapm widget path assoc with kcontrol */
746         list_for_each_entry(path, &widget->codec->dapm_paths, list) {
747                 if (path->kcontrol != kcontrol)
748                         continue;
749
750                 /* found, now check type */
751                 found = 1;
752                 if (val)
753                         /* new connection */
754                         path->connect = invert ? 0:1;
755                 else
756                         /* old connection must be powered down */
757                         path->connect = invert ? 1:0;
758                 break;
759         }
760
761         if (found) {
762                 dapm_power_widgets(widget->codec, SND_SOC_DAPM_STREAM_NOP);
763                 dump_dapm(widget->codec, "mixer power update");
764         }
765
766         return 0;
767 }
768
769 /* show dapm widget status in sys fs */
770 static ssize_t dapm_widget_show(struct device *dev,
771         struct device_attribute *attr, char *buf)
772 {
773         struct snd_soc_device *devdata = dev_get_drvdata(dev);
774         struct snd_soc_codec *codec = devdata->codec;
775         struct snd_soc_dapm_widget *w;
776         int count = 0;
777         char *state = "not set";
778
779         list_for_each_entry(w, &codec->dapm_widgets, list) {
780
781                 /* only display widgets that burnm power */
782                 switch (w->id) {
783                 case snd_soc_dapm_hp:
784                 case snd_soc_dapm_mic:
785                 case snd_soc_dapm_spk:
786                 case snd_soc_dapm_line:
787                 case snd_soc_dapm_micbias:
788                 case snd_soc_dapm_dac:
789                 case snd_soc_dapm_adc:
790                 case snd_soc_dapm_pga:
791                 case snd_soc_dapm_mixer:
792                         if (w->name)
793                                 count += sprintf(buf + count, "%s: %s\n",
794                                         w->name, w->power ? "On":"Off");
795                 break;
796                 default:
797                 break;
798                 }
799         }
800
801         switch (codec->bias_level) {
802         case SND_SOC_BIAS_ON:
803                 state = "On";
804                 break;
805         case SND_SOC_BIAS_PREPARE:
806                 state = "Prepare";
807                 break;
808         case SND_SOC_BIAS_STANDBY:
809                 state = "Standby";
810                 break;
811         case SND_SOC_BIAS_OFF:
812                 state = "Off";
813                 break;
814         }
815         count += sprintf(buf + count, "PM State: %s\n", state);
816
817         return count;
818 }
819
820 static DEVICE_ATTR(dapm_widget, 0444, dapm_widget_show, NULL);
821
822 int snd_soc_dapm_sys_add(struct device *dev)
823 {
824         int ret = 0;
825
826         if (!dapm_status)
827                 return 0;
828
829         ret = device_create_file(dev, &dev_attr_dapm_widget);
830         if (ret != 0)
831                 return ret;
832
833         asoc_debugfs = debugfs_create_dir("asoc", NULL);
834         if (!IS_ERR(asoc_debugfs) && asoc_debugfs)
835                 debugfs_create_u32("dapm_pop_time", 0744, asoc_debugfs,
836                                    &pop_time);
837         else
838                 asoc_debugfs = NULL;
839
840         return 0;
841 }
842
843 static void snd_soc_dapm_sys_remove(struct device *dev)
844 {
845         if (dapm_status) {
846                 device_remove_file(dev, &dev_attr_dapm_widget);
847         }
848
849         if (asoc_debugfs)
850                 debugfs_remove_recursive(asoc_debugfs);
851 }
852
853 /* free all dapm widgets and resources */
854 static void dapm_free_widgets(struct snd_soc_codec *codec)
855 {
856         struct snd_soc_dapm_widget *w, *next_w;
857         struct snd_soc_dapm_path *p, *next_p;
858
859         list_for_each_entry_safe(w, next_w, &codec->dapm_widgets, list) {
860                 list_del(&w->list);
861                 kfree(w);
862         }
863
864         list_for_each_entry_safe(p, next_p, &codec->dapm_paths, list) {
865                 list_del(&p->list);
866                 kfree(p->long_name);
867                 kfree(p);
868         }
869 }
870
871 static int snd_soc_dapm_set_pin(struct snd_soc_codec *codec,
872         char *pin, int status)
873 {
874         struct snd_soc_dapm_widget *w;
875
876         list_for_each_entry(w, &codec->dapm_widgets, list) {
877                 if (!strcmp(w->name, pin)) {
878                         pr_debug("dapm: %s: pin %s\n", codec->name, pin);
879                         w->connected = status;
880                         return 0;
881                 }
882         }
883
884         pr_err("dapm: %s: configuring unknown pin %s\n", codec->name, pin);
885         return -EINVAL;
886 }
887
888 /**
889  * snd_soc_dapm_sync - scan and power dapm paths
890  * @codec: audio codec
891  *
892  * Walks all dapm audio paths and powers widgets according to their
893  * stream or path usage.
894  *
895  * Returns 0 for success.
896  */
897 int snd_soc_dapm_sync(struct snd_soc_codec *codec)
898 {
899         int ret = dapm_power_widgets(codec, SND_SOC_DAPM_STREAM_NOP);
900         dump_dapm(codec, "sync");
901         return ret;
902 }
903 EXPORT_SYMBOL_GPL(snd_soc_dapm_sync);
904
905 static int snd_soc_dapm_add_route(struct snd_soc_codec *codec,
906         const char *sink, const char *control, const char *source)
907 {
908         struct snd_soc_dapm_path *path;
909         struct snd_soc_dapm_widget *wsource = NULL, *wsink = NULL, *w;
910         int ret = 0;
911
912         /* find src and dest widgets */
913         list_for_each_entry(w, &codec->dapm_widgets, list) {
914
915                 if (!wsink && !(strcmp(w->name, sink))) {
916                         wsink = w;
917                         continue;
918                 }
919                 if (!wsource && !(strcmp(w->name, source))) {
920                         wsource = w;
921                 }
922         }
923
924         if (wsource == NULL || wsink == NULL)
925                 return -ENODEV;
926
927         path = kzalloc(sizeof(struct snd_soc_dapm_path), GFP_KERNEL);
928         if (!path)
929                 return -ENOMEM;
930
931         path->source = wsource;
932         path->sink = wsink;
933         INIT_LIST_HEAD(&path->list);
934         INIT_LIST_HEAD(&path->list_source);
935         INIT_LIST_HEAD(&path->list_sink);
936
937         /* check for external widgets */
938         if (wsink->id == snd_soc_dapm_input) {
939                 if (wsource->id == snd_soc_dapm_micbias ||
940                         wsource->id == snd_soc_dapm_mic ||
941                         wsink->id == snd_soc_dapm_line ||
942                         wsink->id == snd_soc_dapm_output)
943                         wsink->ext = 1;
944         }
945         if (wsource->id == snd_soc_dapm_output) {
946                 if (wsink->id == snd_soc_dapm_spk ||
947                         wsink->id == snd_soc_dapm_hp ||
948                         wsink->id == snd_soc_dapm_line ||
949                         wsink->id == snd_soc_dapm_input)
950                         wsource->ext = 1;
951         }
952
953         /* connect static paths */
954         if (control == NULL) {
955                 list_add(&path->list, &codec->dapm_paths);
956                 list_add(&path->list_sink, &wsink->sources);
957                 list_add(&path->list_source, &wsource->sinks);
958                 path->connect = 1;
959                 return 0;
960         }
961
962         /* connect dynamic paths */
963         switch(wsink->id) {
964         case snd_soc_dapm_adc:
965         case snd_soc_dapm_dac:
966         case snd_soc_dapm_pga:
967         case snd_soc_dapm_input:
968         case snd_soc_dapm_output:
969         case snd_soc_dapm_micbias:
970         case snd_soc_dapm_vmid:
971         case snd_soc_dapm_pre:
972         case snd_soc_dapm_post:
973                 list_add(&path->list, &codec->dapm_paths);
974                 list_add(&path->list_sink, &wsink->sources);
975                 list_add(&path->list_source, &wsource->sinks);
976                 path->connect = 1;
977                 return 0;
978         case snd_soc_dapm_mux:
979                 ret = dapm_connect_mux(codec, wsource, wsink, path, control,
980                         &wsink->kcontrols[0]);
981                 if (ret != 0)
982                         goto err;
983                 break;
984         case snd_soc_dapm_switch:
985         case snd_soc_dapm_mixer:
986                 ret = dapm_connect_mixer(codec, wsource, wsink, path, control);
987                 if (ret != 0)
988                         goto err;
989                 break;
990         case snd_soc_dapm_hp:
991         case snd_soc_dapm_mic:
992         case snd_soc_dapm_line:
993         case snd_soc_dapm_spk:
994                 list_add(&path->list, &codec->dapm_paths);
995                 list_add(&path->list_sink, &wsink->sources);
996                 list_add(&path->list_source, &wsource->sinks);
997                 path->connect = 0;
998                 return 0;
999         }
1000         return 0;
1001
1002 err:
1003         printk(KERN_WARNING "asoc: no dapm match for %s --> %s --> %s\n", source,
1004                 control, sink);
1005         kfree(path);
1006         return ret;
1007 }
1008
1009 /**
1010  * snd_soc_dapm_add_routes - Add routes between DAPM widgets
1011  * @codec: codec
1012  * @route: audio routes
1013  * @num: number of routes
1014  *
1015  * Connects 2 dapm widgets together via a named audio path. The sink is
1016  * the widget receiving the audio signal, whilst the source is the sender
1017  * of the audio signal.
1018  *
1019  * Returns 0 for success else error. On error all resources can be freed
1020  * with a call to snd_soc_card_free().
1021  */
1022 int snd_soc_dapm_add_routes(struct snd_soc_codec *codec,
1023                             const struct snd_soc_dapm_route *route, int num)
1024 {
1025         int i, ret;
1026
1027         for (i = 0; i < num; i++) {
1028                 ret = snd_soc_dapm_add_route(codec, route->sink,
1029                                              route->control, route->source);
1030                 if (ret < 0) {
1031                         printk(KERN_ERR "Failed to add route %s->%s\n",
1032                                route->source,
1033                                route->sink);
1034                         return ret;
1035                 }
1036                 route++;
1037         }
1038
1039         return 0;
1040 }
1041 EXPORT_SYMBOL_GPL(snd_soc_dapm_add_routes);
1042
1043 /**
1044  * snd_soc_dapm_new_widgets - add new dapm widgets
1045  * @codec: audio codec
1046  *
1047  * Checks the codec for any new dapm widgets and creates them if found.
1048  *
1049  * Returns 0 for success.
1050  */
1051 int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec)
1052 {
1053         struct snd_soc_dapm_widget *w;
1054
1055         list_for_each_entry(w, &codec->dapm_widgets, list)
1056         {
1057                 if (w->new)
1058                         continue;
1059
1060                 switch(w->id) {
1061                 case snd_soc_dapm_switch:
1062                 case snd_soc_dapm_mixer:
1063                         dapm_new_mixer(codec, w);
1064                         break;
1065                 case snd_soc_dapm_mux:
1066                         dapm_new_mux(codec, w);
1067                         break;
1068                 case snd_soc_dapm_adc:
1069                 case snd_soc_dapm_dac:
1070                 case snd_soc_dapm_pga:
1071                         dapm_new_pga(codec, w);
1072                         break;
1073                 case snd_soc_dapm_input:
1074                 case snd_soc_dapm_output:
1075                 case snd_soc_dapm_micbias:
1076                 case snd_soc_dapm_spk:
1077                 case snd_soc_dapm_hp:
1078                 case snd_soc_dapm_mic:
1079                 case snd_soc_dapm_line:
1080                 case snd_soc_dapm_vmid:
1081                 case snd_soc_dapm_pre:
1082                 case snd_soc_dapm_post:
1083                         break;
1084                 }
1085                 w->new = 1;
1086         }
1087
1088         dapm_power_widgets(codec, SND_SOC_DAPM_STREAM_NOP);
1089         return 0;
1090 }
1091 EXPORT_SYMBOL_GPL(snd_soc_dapm_new_widgets);
1092
1093 /**
1094  * snd_soc_dapm_get_volsw - dapm mixer get callback
1095  * @kcontrol: mixer control
1096  * @uinfo: control element information
1097  *
1098  * Callback to get the value of a dapm mixer control.
1099  *
1100  * Returns 0 for success.
1101  */
1102 int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol,
1103         struct snd_ctl_elem_value *ucontrol)
1104 {
1105         struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
1106         struct soc_mixer_control *mc =
1107                 (struct soc_mixer_control *)kcontrol->private_value;
1108         unsigned int reg = mc->reg;
1109         unsigned int shift = mc->shift;
1110         unsigned int rshift = mc->rshift;
1111         int max = mc->max;
1112         unsigned int invert = mc->invert;
1113         unsigned int mask = (1 << fls(max)) - 1;
1114
1115         /* return the saved value if we are powered down */
1116         if (widget->id == snd_soc_dapm_pga && !widget->power) {
1117                 ucontrol->value.integer.value[0] = widget->saved_value;
1118                 return 0;
1119         }
1120
1121         ucontrol->value.integer.value[0] =
1122                 (snd_soc_read(widget->codec, reg) >> shift) & mask;
1123         if (shift != rshift)
1124                 ucontrol->value.integer.value[1] =
1125                         (snd_soc_read(widget->codec, reg) >> rshift) & mask;
1126         if (invert) {
1127                 ucontrol->value.integer.value[0] =
1128                         max - ucontrol->value.integer.value[0];
1129                 if (shift != rshift)
1130                         ucontrol->value.integer.value[1] =
1131                                 max - ucontrol->value.integer.value[1];
1132         }
1133
1134         return 0;
1135 }
1136 EXPORT_SYMBOL_GPL(snd_soc_dapm_get_volsw);
1137
1138 /**
1139  * snd_soc_dapm_put_volsw - dapm mixer set callback
1140  * @kcontrol: mixer control
1141  * @uinfo: control element information
1142  *
1143  * Callback to set the value of a dapm mixer control.
1144  *
1145  * Returns 0 for success.
1146  */
1147 int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
1148         struct snd_ctl_elem_value *ucontrol)
1149 {
1150         struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
1151         struct soc_mixer_control *mc =
1152                 (struct soc_mixer_control *)kcontrol->private_value;
1153         unsigned int reg = mc->reg;
1154         unsigned int shift = mc->shift;
1155         unsigned int rshift = mc->rshift;
1156         int max = mc->max;
1157         unsigned int mask = (1 << fls(max)) - 1;
1158         unsigned int invert = mc->invert;
1159         unsigned short val, val2, val_mask;
1160         int ret;
1161
1162         val = (ucontrol->value.integer.value[0] & mask);
1163
1164         if (invert)
1165                 val = max - val;
1166         val_mask = mask << shift;
1167         val = val << shift;
1168         if (shift != rshift) {
1169                 val2 = (ucontrol->value.integer.value[1] & mask);
1170                 if (invert)
1171                         val2 = max - val2;
1172                 val_mask |= mask << rshift;
1173                 val |= val2 << rshift;
1174         }
1175
1176         mutex_lock(&widget->codec->mutex);
1177         widget->value = val;
1178
1179         /* save volume value if the widget is powered down */
1180         if (widget->id == snd_soc_dapm_pga && !widget->power) {
1181                 widget->saved_value = val;
1182                 mutex_unlock(&widget->codec->mutex);
1183                 return 1;
1184         }
1185
1186         dapm_mixer_update_power(widget, kcontrol, reg, val_mask, val, invert);
1187         if (widget->event) {
1188                 if (widget->event_flags & SND_SOC_DAPM_PRE_REG) {
1189                         ret = widget->event(widget, kcontrol,
1190                                                 SND_SOC_DAPM_PRE_REG);
1191                         if (ret < 0) {
1192                                 ret = 1;
1193                                 goto out;
1194                         }
1195                 }
1196                 ret = snd_soc_update_bits(widget->codec, reg, val_mask, val);
1197                 if (widget->event_flags & SND_SOC_DAPM_POST_REG)
1198                         ret = widget->event(widget, kcontrol,
1199                                                 SND_SOC_DAPM_POST_REG);
1200         } else
1201                 ret = snd_soc_update_bits(widget->codec, reg, val_mask, val);
1202
1203 out:
1204         mutex_unlock(&widget->codec->mutex);
1205         return ret;
1206 }
1207 EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw);
1208
1209 /**
1210  * snd_soc_dapm_get_enum_double - dapm enumerated double mixer get callback
1211  * @kcontrol: mixer control
1212  * @uinfo: control element information
1213  *
1214  * Callback to get the value of a dapm enumerated double mixer control.
1215  *
1216  * Returns 0 for success.
1217  */
1218 int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol,
1219         struct snd_ctl_elem_value *ucontrol)
1220 {
1221         struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
1222         struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1223         unsigned short val, bitmask;
1224
1225         for (bitmask = 1; bitmask < e->max; bitmask <<= 1)
1226                 ;
1227         val = snd_soc_read(widget->codec, e->reg);
1228         ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & (bitmask - 1);
1229         if (e->shift_l != e->shift_r)
1230                 ucontrol->value.enumerated.item[1] =
1231                         (val >> e->shift_r) & (bitmask - 1);
1232
1233         return 0;
1234 }
1235 EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_double);
1236
1237 /**
1238  * snd_soc_dapm_put_enum_double - dapm enumerated double mixer set callback
1239  * @kcontrol: mixer control
1240  * @uinfo: control element information
1241  *
1242  * Callback to set the value of a dapm enumerated double mixer control.
1243  *
1244  * Returns 0 for success.
1245  */
1246 int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
1247         struct snd_ctl_elem_value *ucontrol)
1248 {
1249         struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
1250         struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1251         unsigned short val, mux;
1252         unsigned short mask, bitmask;
1253         int ret = 0;
1254
1255         for (bitmask = 1; bitmask < e->max; bitmask <<= 1)
1256                 ;
1257         if (ucontrol->value.enumerated.item[0] > e->max - 1)
1258                 return -EINVAL;
1259         mux = ucontrol->value.enumerated.item[0];
1260         val = mux << e->shift_l;
1261         mask = (bitmask - 1) << e->shift_l;
1262         if (e->shift_l != e->shift_r) {
1263                 if (ucontrol->value.enumerated.item[1] > e->max - 1)
1264                         return -EINVAL;
1265                 val |= ucontrol->value.enumerated.item[1] << e->shift_r;
1266                 mask |= (bitmask - 1) << e->shift_r;
1267         }
1268
1269         mutex_lock(&widget->codec->mutex);
1270         widget->value = val;
1271         dapm_mux_update_power(widget, kcontrol, mask, mux, val, e);
1272         if (widget->event) {
1273                 if (widget->event_flags & SND_SOC_DAPM_PRE_REG) {
1274                         ret = widget->event(widget,
1275                                 kcontrol, SND_SOC_DAPM_PRE_REG);
1276                         if (ret < 0)
1277                                 goto out;
1278                 }
1279                 ret = snd_soc_update_bits(widget->codec, e->reg, mask, val);
1280                 if (widget->event_flags & SND_SOC_DAPM_POST_REG)
1281                         ret = widget->event(widget,
1282                                 kcontrol, SND_SOC_DAPM_POST_REG);
1283         } else
1284                 ret = snd_soc_update_bits(widget->codec, e->reg, mask, val);
1285
1286 out:
1287         mutex_unlock(&widget->codec->mutex);
1288         return ret;
1289 }
1290 EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double);
1291
1292 /**
1293  * snd_soc_dapm_new_control - create new dapm control
1294  * @codec: audio codec
1295  * @widget: widget template
1296  *
1297  * Creates a new dapm control based upon the template.
1298  *
1299  * Returns 0 for success else error.
1300  */
1301 int snd_soc_dapm_new_control(struct snd_soc_codec *codec,
1302         const struct snd_soc_dapm_widget *widget)
1303 {
1304         struct snd_soc_dapm_widget *w;
1305
1306         if ((w = dapm_cnew_widget(widget)) == NULL)
1307                 return -ENOMEM;
1308
1309         w->codec = codec;
1310         INIT_LIST_HEAD(&w->sources);
1311         INIT_LIST_HEAD(&w->sinks);
1312         INIT_LIST_HEAD(&w->list);
1313         list_add(&w->list, &codec->dapm_widgets);
1314
1315         /* machine layer set ups unconnected pins and insertions */
1316         w->connected = 1;
1317         return 0;
1318 }
1319 EXPORT_SYMBOL_GPL(snd_soc_dapm_new_control);
1320
1321 /**
1322  * snd_soc_dapm_new_controls - create new dapm controls
1323  * @codec: audio codec
1324  * @widget: widget array
1325  * @num: number of widgets
1326  *
1327  * Creates new DAPM controls based upon the templates.
1328  *
1329  * Returns 0 for success else error.
1330  */
1331 int snd_soc_dapm_new_controls(struct snd_soc_codec *codec,
1332         const struct snd_soc_dapm_widget *widget,
1333         int num)
1334 {
1335         int i, ret;
1336
1337         for (i = 0; i < num; i++) {
1338                 ret = snd_soc_dapm_new_control(codec, widget);
1339                 if (ret < 0)
1340                         return ret;
1341                 widget++;
1342         }
1343         return 0;
1344 }
1345 EXPORT_SYMBOL_GPL(snd_soc_dapm_new_controls);
1346
1347
1348 /**
1349  * snd_soc_dapm_stream_event - send a stream event to the dapm core
1350  * @codec: audio codec
1351  * @stream: stream name
1352  * @event: stream event
1353  *
1354  * Sends a stream event to the dapm core. The core then makes any
1355  * necessary widget power changes.
1356  *
1357  * Returns 0 for success else error.
1358  */
1359 int snd_soc_dapm_stream_event(struct snd_soc_codec *codec,
1360         char *stream, int event)
1361 {
1362         struct snd_soc_dapm_widget *w;
1363
1364         if (stream == NULL)
1365                 return 0;
1366
1367         mutex_lock(&codec->mutex);
1368         list_for_each_entry(w, &codec->dapm_widgets, list)
1369         {
1370                 if (!w->sname)
1371                         continue;
1372                 pr_debug("widget %s\n %s stream %s event %d\n",
1373                          w->name, w->sname, stream, event);
1374                 if (strstr(w->sname, stream)) {
1375                         switch(event) {
1376                         case SND_SOC_DAPM_STREAM_START:
1377                                 w->active = 1;
1378                                 break;
1379                         case SND_SOC_DAPM_STREAM_STOP:
1380                                 w->active = 0;
1381                                 break;
1382                         case SND_SOC_DAPM_STREAM_SUSPEND:
1383                                 if (w->active)
1384                                         w->suspend = 1;
1385                                 w->active = 0;
1386                                 break;
1387                         case SND_SOC_DAPM_STREAM_RESUME:
1388                                 if (w->suspend) {
1389                                         w->active = 1;
1390                                         w->suspend = 0;
1391                                 }
1392                                 break;
1393                         case SND_SOC_DAPM_STREAM_PAUSE_PUSH:
1394                                 break;
1395                         case SND_SOC_DAPM_STREAM_PAUSE_RELEASE:
1396                                 break;
1397                         }
1398                 }
1399         }
1400         mutex_unlock(&codec->mutex);
1401
1402         dapm_power_widgets(codec, event);
1403         dump_dapm(codec, __func__);
1404         return 0;
1405 }
1406 EXPORT_SYMBOL_GPL(snd_soc_dapm_stream_event);
1407
1408 /**
1409  * snd_soc_dapm_set_bias_level - set the bias level for the system
1410  * @socdev: audio device
1411  * @level: level to configure
1412  *
1413  * Configure the bias (power) levels for the SoC audio device.
1414  *
1415  * Returns 0 for success else error.
1416  */
1417 int snd_soc_dapm_set_bias_level(struct snd_soc_device *socdev,
1418                                 enum snd_soc_bias_level level)
1419 {
1420         struct snd_soc_codec *codec = socdev->codec;
1421         struct snd_soc_machine *machine = socdev->machine;
1422         int ret = 0;
1423
1424         if (machine->set_bias_level)
1425                 ret = machine->set_bias_level(machine, level);
1426         if (ret == 0 && codec->set_bias_level)
1427                 ret = codec->set_bias_level(codec, level);
1428
1429         return ret;
1430 }
1431
1432 /**
1433  * snd_soc_dapm_enable_pin - enable pin.
1434  * @snd_soc_codec: SoC codec
1435  * @pin: pin name
1436  *
1437  * Enables input/output pin and it's parents or children widgets iff there is
1438  * a valid audio route and active audio stream.
1439  * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
1440  * do any widget power switching.
1441  */
1442 int snd_soc_dapm_enable_pin(struct snd_soc_codec *codec, char *pin)
1443 {
1444         return snd_soc_dapm_set_pin(codec, pin, 1);
1445 }
1446 EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin);
1447
1448 /**
1449  * snd_soc_dapm_disable_pin - disable pin.
1450  * @codec: SoC codec
1451  * @pin: pin name
1452  *
1453  * Disables input/output pin and it's parents or children widgets.
1454  * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
1455  * do any widget power switching.
1456  */
1457 int snd_soc_dapm_disable_pin(struct snd_soc_codec *codec, char *pin)
1458 {
1459         return snd_soc_dapm_set_pin(codec, pin, 0);
1460 }
1461 EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin);
1462
1463 /**
1464  * snd_soc_dapm_nc_pin - permanently disable pin.
1465  * @codec: SoC codec
1466  * @pin: pin name
1467  *
1468  * Marks the specified pin as being not connected, disabling it along
1469  * any parent or child widgets.  At present this is identical to
1470  * snd_soc_dapm_disable_pin() but in future it will be extended to do
1471  * additional things such as disabling controls which only affect
1472  * paths through the pin.
1473  *
1474  * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
1475  * do any widget power switching.
1476  */
1477 int snd_soc_dapm_nc_pin(struct snd_soc_codec *codec, char *pin)
1478 {
1479         return snd_soc_dapm_set_pin(codec, pin, 0);
1480 }
1481 EXPORT_SYMBOL_GPL(snd_soc_dapm_nc_pin);
1482
1483 /**
1484  * snd_soc_dapm_get_pin_status - get audio pin status
1485  * @codec: audio codec
1486  * @pin: audio signal pin endpoint (or start point)
1487  *
1488  * Get audio pin status - connected or disconnected.
1489  *
1490  * Returns 1 for connected otherwise 0.
1491  */
1492 int snd_soc_dapm_get_pin_status(struct snd_soc_codec *codec, char *pin)
1493 {
1494         struct snd_soc_dapm_widget *w;
1495
1496         list_for_each_entry(w, &codec->dapm_widgets, list) {
1497                 if (!strcmp(w->name, pin))
1498                         return w->connected;
1499         }
1500
1501         return 0;
1502 }
1503 EXPORT_SYMBOL_GPL(snd_soc_dapm_get_pin_status);
1504
1505 /**
1506  * snd_soc_dapm_free - free dapm resources
1507  * @socdev: SoC device
1508  *
1509  * Free all dapm widgets and resources.
1510  */
1511 void snd_soc_dapm_free(struct snd_soc_device *socdev)
1512 {
1513         struct snd_soc_codec *codec = socdev->codec;
1514
1515         snd_soc_dapm_sys_remove(socdev->dev);
1516         dapm_free_widgets(codec);
1517 }
1518 EXPORT_SYMBOL_GPL(snd_soc_dapm_free);
1519
1520 /* Module information */
1521 MODULE_AUTHOR("Liam Girdwood, lrg@slimlogic.co.uk");
1522 MODULE_DESCRIPTION("Dynamic Audio Power Management core for ALSA SoC");
1523 MODULE_LICENSE("GPL");