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