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