2 * soc-dapm.c -- ALSA SoC Dynamic Audio Power Management
4 * Copyright 2005 Wolfson Microelectronics PLC.
5 * Author: Liam Girdwood
6 * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
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.
14 * o Changes power status of internal codec blocks depending on the
15 * dynamic configuration of codec internal audio paths and active
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
22 * o Delayed powerdown of audio susbsystem to reduce pops between a quick
26 * o DAPM power change sequencing - allow for configurable per
28 * o Support for analogue bias optimisation.
29 * o Support for reduced codec oversampling rates.
30 * o Support for reduced codec bias currents.
33 #include <linux/module.h>
34 #include <linux/moduleparam.h>
35 #include <linux/init.h>
36 #include <linux/delay.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>
50 #define dump_dapm(codec, action) dbg_dump_dapm(codec, action)
51 #define dbg(format, arg...) printk(format, ## arg)
53 #define dump_dapm(codec, action)
54 #define dbg(format, arg...)
59 #define POP_TIME 500 /* 500 msecs - change if pop debug is too fast */
60 #define pop_wait(time) schedule_timeout_uninterruptible(msecs_to_jiffies(time))
61 #define pop_dbg(format, arg...) printk(format, ## arg); pop_wait(POP_TIME)
63 #define pop_dbg(format, arg...)
64 #define pop_wait(time)
67 /* dapm power sequences - make this per codec in the future */
68 static int dapm_up_seq
[] = {
69 snd_soc_dapm_pre
, snd_soc_dapm_micbias
, snd_soc_dapm_mic
,
70 snd_soc_dapm_mux
, snd_soc_dapm_dac
, snd_soc_dapm_mixer
, snd_soc_dapm_pga
,
71 snd_soc_dapm_adc
, snd_soc_dapm_hp
, snd_soc_dapm_spk
, snd_soc_dapm_post
73 static int dapm_down_seq
[] = {
74 snd_soc_dapm_pre
, snd_soc_dapm_adc
, snd_soc_dapm_hp
, snd_soc_dapm_spk
,
75 snd_soc_dapm_pga
, snd_soc_dapm_mixer
, snd_soc_dapm_dac
, snd_soc_dapm_mic
,
76 snd_soc_dapm_micbias
, snd_soc_dapm_mux
, snd_soc_dapm_post
79 static int dapm_status
= 1;
80 module_param(dapm_status
, int, 0);
81 MODULE_PARM_DESC(dapm_status
, "enable DPM sysfs entries");
83 /* create a new dapm widget */
84 static inline struct snd_soc_dapm_widget
*dapm_cnew_widget(
85 const struct snd_soc_dapm_widget
*_widget
)
87 return kmemdup(_widget
, sizeof(*_widget
), GFP_KERNEL
);
90 /* set up initial codec paths */
91 static void dapm_set_path_status(struct snd_soc_dapm_widget
*w
,
92 struct snd_soc_dapm_path
*p
, int i
)
95 case snd_soc_dapm_switch
:
96 case snd_soc_dapm_mixer
: {
98 int reg
= w
->kcontrols
[i
].private_value
& 0xff;
99 int shift
= (w
->kcontrols
[i
].private_value
>> 8) & 0x0f;
100 int mask
= (w
->kcontrols
[i
].private_value
>> 16) & 0xff;
101 int invert
= (w
->kcontrols
[i
].private_value
>> 24) & 0x01;
103 val
= snd_soc_read(w
->codec
, reg
);
104 val
= (val
>> shift
) & mask
;
106 if ((invert
&& !val
) || (!invert
&& val
))
112 case snd_soc_dapm_mux
: {
113 struct soc_enum
*e
= (struct soc_enum
*)w
->kcontrols
[i
].private_value
;
114 int val
, item
, bitmask
;
116 for (bitmask
= 1; bitmask
< e
->mask
; bitmask
<<= 1)
118 val
= snd_soc_read(w
->codec
, e
->reg
);
119 item
= (val
>> e
->shift_l
) & (bitmask
- 1);
122 for (i
= 0; i
< e
->mask
; i
++) {
123 if (!(strcmp(p
->name
, e
->texts
[i
])) && item
== i
)
128 /* does not effect routing - always connected */
129 case snd_soc_dapm_pga
:
130 case snd_soc_dapm_output
:
131 case snd_soc_dapm_adc
:
132 case snd_soc_dapm_input
:
133 case snd_soc_dapm_dac
:
134 case snd_soc_dapm_micbias
:
135 case snd_soc_dapm_vmid
:
138 /* does effect routing - dynamically connected */
139 case snd_soc_dapm_hp
:
140 case snd_soc_dapm_mic
:
141 case snd_soc_dapm_spk
:
142 case snd_soc_dapm_line
:
143 case snd_soc_dapm_pre
:
144 case snd_soc_dapm_post
:
150 /* connect mux widget to it's interconnecting audio paths */
151 static int dapm_connect_mux(struct snd_soc_codec
*codec
,
152 struct snd_soc_dapm_widget
*src
, struct snd_soc_dapm_widget
*dest
,
153 struct snd_soc_dapm_path
*path
, const char *control_name
,
154 const struct snd_kcontrol_new
*kcontrol
)
156 struct soc_enum
*e
= (struct soc_enum
*)kcontrol
->private_value
;
159 for (i
= 0; i
< e
->mask
; i
++) {
160 if (!(strcmp(control_name
, e
->texts
[i
]))) {
161 list_add(&path
->list
, &codec
->dapm_paths
);
162 list_add(&path
->list_sink
, &dest
->sources
);
163 list_add(&path
->list_source
, &src
->sinks
);
164 path
->name
= (char*)e
->texts
[i
];
165 dapm_set_path_status(dest
, path
, 0);
173 /* connect mixer widget to it's interconnecting audio paths */
174 static int dapm_connect_mixer(struct snd_soc_codec
*codec
,
175 struct snd_soc_dapm_widget
*src
, struct snd_soc_dapm_widget
*dest
,
176 struct snd_soc_dapm_path
*path
, const char *control_name
)
180 /* search for mixer kcontrol */
181 for (i
= 0; i
< dest
->num_kcontrols
; i
++) {
182 if (!strcmp(control_name
, dest
->kcontrols
[i
].name
)) {
183 list_add(&path
->list
, &codec
->dapm_paths
);
184 list_add(&path
->list_sink
, &dest
->sources
);
185 list_add(&path
->list_source
, &src
->sinks
);
186 path
->name
= dest
->kcontrols
[i
].name
;
187 dapm_set_path_status(dest
, path
, i
);
194 /* update dapm codec register bits */
195 static int dapm_update_bits(struct snd_soc_dapm_widget
*widget
)
198 unsigned short old
, new;
199 struct snd_soc_codec
*codec
= widget
->codec
;
201 /* check for valid widgets */
202 if (widget
->reg
< 0 || widget
->id
== snd_soc_dapm_input
||
203 widget
->id
== snd_soc_dapm_output
||
204 widget
->id
== snd_soc_dapm_hp
||
205 widget
->id
== snd_soc_dapm_mic
||
206 widget
->id
== snd_soc_dapm_line
||
207 widget
->id
== snd_soc_dapm_spk
)
210 power
= widget
->power
;
212 power
= (power
? 0:1);
214 old
= snd_soc_read(codec
, widget
->reg
);
215 new = (old
& ~(0x1 << widget
->shift
)) | (power
<< widget
->shift
);
219 pop_dbg("pop test %s : %s in %d ms\n", widget
->name
,
220 widget
->power
? "on" : "off", POP_TIME
);
221 snd_soc_write(codec
, widget
->reg
, new);
224 dbg("reg %x old %x new %x change %d\n", widget
->reg
, old
, new, change
);
228 /* ramps the volume up or down to minimise pops before or after a
229 * DAPM power event */
230 static int dapm_set_pga(struct snd_soc_dapm_widget
*widget
, int power
)
232 const struct snd_kcontrol_new
*k
= widget
->kcontrols
;
234 if (widget
->muted
&& !power
)
236 if (!widget
->muted
&& power
)
239 if (widget
->num_kcontrols
&& k
) {
240 int reg
= k
->private_value
& 0xff;
241 int shift
= (k
->private_value
>> 8) & 0x0f;
242 int mask
= (k
->private_value
>> 16) & 0xff;
243 int invert
= (k
->private_value
>> 24) & 0x01;
247 /* power up has happended, increase volume to last level */
249 for (i
= mask
; i
> widget
->saved_value
; i
--)
250 snd_soc_update_bits(widget
->codec
, reg
, mask
, i
);
252 for (i
= 0; i
< widget
->saved_value
; i
++)
253 snd_soc_update_bits(widget
->codec
, reg
, mask
, i
);
257 /* power down is about to occur, decrease volume to mute */
258 int val
= snd_soc_read(widget
->codec
, reg
);
259 int i
= widget
->saved_value
= (val
>> shift
) & mask
;
261 for (; i
< mask
; i
++)
262 snd_soc_update_bits(widget
->codec
, reg
, mask
, i
);
265 snd_soc_update_bits(widget
->codec
, reg
, mask
, i
);
273 /* create new dapm mixer control */
274 static int dapm_new_mixer(struct snd_soc_codec
*codec
,
275 struct snd_soc_dapm_widget
*w
)
279 struct snd_soc_dapm_path
*path
;
282 for (i
= 0; i
< w
->num_kcontrols
; i
++) {
285 list_for_each_entry(path
, &w
->sources
, list_sink
) {
287 /* mixer/mux paths name must match control name */
288 if (path
->name
!= (char*)w
->kcontrols
[i
].name
)
291 /* add dapm control with long name */
292 snprintf(name
, 32, "%s %s", w
->name
, w
->kcontrols
[i
].name
);
293 path
->long_name
= kstrdup (name
, GFP_KERNEL
);
294 if (path
->long_name
== NULL
)
297 path
->kcontrol
= snd_soc_cnew(&w
->kcontrols
[i
], w
,
299 ret
= snd_ctl_add(codec
->card
, path
->kcontrol
);
301 printk(KERN_ERR
"asoc: failed to add dapm kcontrol %s\n",
303 kfree(path
->long_name
);
304 path
->long_name
= NULL
;
312 /* create new dapm mux control */
313 static int dapm_new_mux(struct snd_soc_codec
*codec
,
314 struct snd_soc_dapm_widget
*w
)
316 struct snd_soc_dapm_path
*path
= NULL
;
317 struct snd_kcontrol
*kcontrol
;
320 if (!w
->num_kcontrols
) {
321 printk(KERN_ERR
"asoc: mux %s has no controls\n", w
->name
);
325 kcontrol
= snd_soc_cnew(&w
->kcontrols
[0], w
, w
->name
);
326 ret
= snd_ctl_add(codec
->card
, kcontrol
);
330 list_for_each_entry(path
, &w
->sources
, list_sink
)
331 path
->kcontrol
= kcontrol
;
336 printk(KERN_ERR
"asoc: failed to add kcontrol %s\n", w
->name
);
340 /* create new dapm volume control */
341 static int dapm_new_pga(struct snd_soc_codec
*codec
,
342 struct snd_soc_dapm_widget
*w
)
344 struct snd_kcontrol
*kcontrol
;
347 if (!w
->num_kcontrols
)
350 kcontrol
= snd_soc_cnew(&w
->kcontrols
[0], w
, w
->name
);
351 ret
= snd_ctl_add(codec
->card
, kcontrol
);
353 printk(KERN_ERR
"asoc: failed to add kcontrol %s\n", w
->name
);
360 /* reset 'walked' bit for each dapm path */
361 static inline void dapm_clear_walk(struct snd_soc_codec
*codec
)
363 struct snd_soc_dapm_path
*p
;
365 list_for_each_entry(p
, &codec
->dapm_paths
, list
)
370 * Recursively check for a completed path to an active or physically connected
371 * output widget. Returns number of complete paths.
373 static int is_connected_output_ep(struct snd_soc_dapm_widget
*widget
)
375 struct snd_soc_dapm_path
*path
;
378 if (widget
->id
== snd_soc_dapm_adc
&& widget
->active
)
381 if (widget
->connected
) {
382 /* connected pin ? */
383 if (widget
->id
== snd_soc_dapm_output
&& !widget
->ext
)
386 /* connected jack or spk ? */
387 if (widget
->id
== snd_soc_dapm_hp
|| widget
->id
== snd_soc_dapm_spk
||
388 widget
->id
== snd_soc_dapm_line
)
392 list_for_each_entry(path
, &widget
->sinks
, list_source
) {
396 if (path
->sink
&& path
->connect
) {
398 con
+= is_connected_output_ep(path
->sink
);
406 * Recursively check for a completed path to an active or physically connected
407 * input widget. Returns number of complete paths.
409 static int is_connected_input_ep(struct snd_soc_dapm_widget
*widget
)
411 struct snd_soc_dapm_path
*path
;
414 /* active stream ? */
415 if (widget
->id
== snd_soc_dapm_dac
&& widget
->active
)
418 if (widget
->connected
) {
419 /* connected pin ? */
420 if (widget
->id
== snd_soc_dapm_input
&& !widget
->ext
)
423 /* connected VMID/Bias for lower pops */
424 if (widget
->id
== snd_soc_dapm_vmid
)
427 /* connected jack ? */
428 if (widget
->id
== snd_soc_dapm_mic
|| widget
->id
== snd_soc_dapm_line
)
432 list_for_each_entry(path
, &widget
->sources
, list_sink
) {
436 if (path
->source
&& path
->connect
) {
438 con
+= is_connected_input_ep(path
->source
);
446 * Scan each dapm widget for complete audio path.
447 * A complete path is a route that has valid endpoints i.e.:-
449 * o DAC to output pin.
450 * o Input Pin to ADC.
451 * o Input pin to Output pin (bypass, sidetone)
452 * o DAC to ADC (loopback).
454 static int dapm_power_widgets(struct snd_soc_codec
*codec
, int event
)
456 struct snd_soc_dapm_widget
*w
;
457 int in
, out
, i
, c
= 1, *seq
= NULL
, ret
= 0, power_change
, power
;
459 /* do we have a sequenced stream event */
460 if (event
== SND_SOC_DAPM_STREAM_START
) {
461 c
= ARRAY_SIZE(dapm_up_seq
);
463 } else if (event
== SND_SOC_DAPM_STREAM_STOP
) {
464 c
= ARRAY_SIZE(dapm_down_seq
);
468 for(i
= 0; i
< c
; i
++) {
469 list_for_each_entry(w
, &codec
->dapm_widgets
, list
) {
471 /* is widget in stream order */
472 if (seq
&& seq
[i
] && w
->id
!= seq
[i
])
475 /* vmid - no action */
476 if (w
->id
== snd_soc_dapm_vmid
)
480 if (w
->id
== snd_soc_dapm_adc
&& w
->active
) {
481 in
= is_connected_input_ep(w
);
482 dapm_clear_walk(w
->codec
);
483 w
->power
= (in
!= 0) ? 1 : 0;
489 if (w
->id
== snd_soc_dapm_dac
&& w
->active
) {
490 out
= is_connected_output_ep(w
);
491 dapm_clear_walk(w
->codec
);
492 w
->power
= (out
!= 0) ? 1 : 0;
497 /* programmable gain/attenuation */
498 if (w
->id
== snd_soc_dapm_pga
) {
500 in
= is_connected_input_ep(w
);
501 dapm_clear_walk(w
->codec
);
502 out
= is_connected_output_ep(w
);
503 dapm_clear_walk(w
->codec
);
504 w
->power
= on
= (out
!= 0 && in
!= 0) ? 1 : 0;
507 dapm_set_pga(w
, on
); /* lower volume to reduce pops */
510 dapm_set_pga(w
, on
); /* restore volume from zero */
515 /* pre and post event widgets */
516 if (w
->id
== snd_soc_dapm_pre
) {
520 if (event
== SND_SOC_DAPM_STREAM_START
) {
522 NULL
, SND_SOC_DAPM_PRE_PMU
);
525 } else if (event
== SND_SOC_DAPM_STREAM_STOP
) {
527 NULL
, SND_SOC_DAPM_PRE_PMD
);
533 if (w
->id
== snd_soc_dapm_post
) {
537 if (event
== SND_SOC_DAPM_STREAM_START
) {
539 NULL
, SND_SOC_DAPM_POST_PMU
);
542 } else if (event
== SND_SOC_DAPM_STREAM_STOP
) {
544 NULL
, SND_SOC_DAPM_POST_PMD
);
551 /* all other widgets */
552 in
= is_connected_input_ep(w
);
553 dapm_clear_walk(w
->codec
);
554 out
= is_connected_output_ep(w
);
555 dapm_clear_walk(w
->codec
);
556 power
= (out
!= 0 && in
!= 0) ? 1 : 0;
557 power_change
= (w
->power
== power
) ? 0: 1;
560 /* call any power change event handlers */
563 dbg("power %s event for %s flags %x\n",
564 w
->power
? "on" : "off", w
->name
, w
->event_flags
);
567 if (w
->event_flags
& SND_SOC_DAPM_PRE_PMU
) {
569 NULL
, SND_SOC_DAPM_PRE_PMU
);
574 if (w
->event_flags
& SND_SOC_DAPM_POST_PMU
){
576 NULL
, SND_SOC_DAPM_POST_PMU
);
581 /* power down event */
582 if (w
->event_flags
& SND_SOC_DAPM_PRE_PMD
) {
584 NULL
, SND_SOC_DAPM_PRE_PMD
);
589 if (w
->event_flags
& SND_SOC_DAPM_POST_PMD
) {
591 NULL
, SND_SOC_DAPM_POST_PMD
);
597 /* no event handler */
607 static void dbg_dump_dapm(struct snd_soc_codec
* codec
, const char *action
)
609 struct snd_soc_dapm_widget
*w
;
610 struct snd_soc_dapm_path
*p
= NULL
;
613 printk("DAPM %s %s\n", codec
->name
, action
);
615 list_for_each_entry(w
, &codec
->dapm_widgets
, list
) {
617 /* only display widgets that effect routing */
619 case snd_soc_dapm_pre
:
620 case snd_soc_dapm_post
:
621 case snd_soc_dapm_vmid
:
623 case snd_soc_dapm_mux
:
624 case snd_soc_dapm_output
:
625 case snd_soc_dapm_input
:
626 case snd_soc_dapm_switch
:
627 case snd_soc_dapm_hp
:
628 case snd_soc_dapm_mic
:
629 case snd_soc_dapm_spk
:
630 case snd_soc_dapm_line
:
631 case snd_soc_dapm_micbias
:
632 case snd_soc_dapm_dac
:
633 case snd_soc_dapm_adc
:
634 case snd_soc_dapm_pga
:
635 case snd_soc_dapm_mixer
:
637 in
= is_connected_input_ep(w
);
638 dapm_clear_walk(w
->codec
);
639 out
= is_connected_output_ep(w
);
640 dapm_clear_walk(w
->codec
);
641 printk("%s: %s in %d out %d\n", w
->name
,
642 w
->power
? "On":"Off",in
, out
);
644 list_for_each_entry(p
, &w
->sources
, list_sink
) {
646 printk(" in %s %s\n", p
->name
? p
->name
: "static",
649 list_for_each_entry(p
, &w
->sinks
, list_source
) {
651 printk(" out %s %s\n", p
->name
? p
->name
: "static",
661 /* test and update the power status of a mux widget */
662 static int dapm_mux_update_power(struct snd_soc_dapm_widget
*widget
,
663 struct snd_kcontrol
*kcontrol
, int mask
,
664 int val
, struct soc_enum
* e
)
666 struct snd_soc_dapm_path
*path
;
669 if (widget
->id
!= snd_soc_dapm_mux
)
672 if (!snd_soc_test_bits(widget
->codec
, e
->reg
, mask
, val
))
675 /* find dapm widget path assoc with kcontrol */
676 list_for_each_entry(path
, &widget
->codec
->dapm_paths
, list
) {
677 if (path
->kcontrol
!= kcontrol
)
680 if (!path
->name
|| ! e
->texts
[val
])
684 /* we now need to match the string in the enum to the path */
685 if (!(strcmp(path
->name
, e
->texts
[val
])))
686 path
->connect
= 1; /* new connection */
688 path
->connect
= 0; /* old connection must be powered down */
692 dapm_power_widgets(widget
->codec
, SND_SOC_DAPM_STREAM_NOP
);
697 /* test and update the power status of a mixer or switch widget */
698 static int dapm_mixer_update_power(struct snd_soc_dapm_widget
*widget
,
699 struct snd_kcontrol
*kcontrol
, int reg
,
700 int val_mask
, int val
, int invert
)
702 struct snd_soc_dapm_path
*path
;
705 if (widget
->id
!= snd_soc_dapm_mixer
&&
706 widget
->id
!= snd_soc_dapm_switch
)
709 if (!snd_soc_test_bits(widget
->codec
, reg
, val_mask
, val
))
712 /* find dapm widget path assoc with kcontrol */
713 list_for_each_entry(path
, &widget
->codec
->dapm_paths
, list
) {
714 if (path
->kcontrol
!= kcontrol
)
717 /* found, now check type */
721 path
->connect
= invert
? 0:1;
723 /* old connection must be powered down */
724 path
->connect
= invert
? 1:0;
729 dapm_power_widgets(widget
->codec
, SND_SOC_DAPM_STREAM_NOP
);
734 /* show dapm widget status in sys fs */
735 static ssize_t
dapm_widget_show(struct device
*dev
,
736 struct device_attribute
*attr
, char *buf
)
738 struct snd_soc_device
*devdata
= dev_get_drvdata(dev
);
739 struct snd_soc_codec
*codec
= devdata
->codec
;
740 struct snd_soc_dapm_widget
*w
;
742 char *state
= "not set";
744 list_for_each_entry(w
, &codec
->dapm_widgets
, list
) {
746 /* only display widgets that burnm power */
748 case snd_soc_dapm_hp
:
749 case snd_soc_dapm_mic
:
750 case snd_soc_dapm_spk
:
751 case snd_soc_dapm_line
:
752 case snd_soc_dapm_micbias
:
753 case snd_soc_dapm_dac
:
754 case snd_soc_dapm_adc
:
755 case snd_soc_dapm_pga
:
756 case snd_soc_dapm_mixer
:
758 count
+= sprintf(buf
+ count
, "%s: %s\n",
759 w
->name
, w
->power
? "On":"Off");
766 switch(codec
->dapm_state
){
767 case SNDRV_CTL_POWER_D0
:
770 case SNDRV_CTL_POWER_D1
:
773 case SNDRV_CTL_POWER_D2
:
776 case SNDRV_CTL_POWER_D3hot
:
779 case SNDRV_CTL_POWER_D3cold
:
783 count
+= sprintf(buf
+ count
, "PM State: %s\n", state
);
788 static DEVICE_ATTR(dapm_widget
, 0444, dapm_widget_show
, NULL
);
790 int snd_soc_dapm_sys_add(struct device
*dev
)
795 ret
= device_create_file(dev
, &dev_attr_dapm_widget
);
800 static void snd_soc_dapm_sys_remove(struct device
*dev
)
803 device_remove_file(dev
, &dev_attr_dapm_widget
);
806 /* free all dapm widgets and resources */
807 static void dapm_free_widgets(struct snd_soc_codec
*codec
)
809 struct snd_soc_dapm_widget
*w
, *next_w
;
810 struct snd_soc_dapm_path
*p
, *next_p
;
812 list_for_each_entry_safe(w
, next_w
, &codec
->dapm_widgets
, list
) {
817 list_for_each_entry_safe(p
, next_p
, &codec
->dapm_paths
, list
) {
825 * snd_soc_dapm_sync_endpoints - scan and power dapm paths
826 * @codec: audio codec
828 * Walks all dapm audio paths and powers widgets according to their
829 * stream or path usage.
831 * Returns 0 for success.
833 int snd_soc_dapm_sync_endpoints(struct snd_soc_codec
*codec
)
835 return dapm_power_widgets(codec
, SND_SOC_DAPM_STREAM_NOP
);
837 EXPORT_SYMBOL_GPL(snd_soc_dapm_sync_endpoints
);
839 static int snd_soc_dapm_add_route(struct snd_soc_codec
*codec
,
840 const char *sink
, const char *control
, const char *source
)
842 struct snd_soc_dapm_path
*path
;
843 struct snd_soc_dapm_widget
*wsource
= NULL
, *wsink
= NULL
, *w
;
846 /* find src and dest widgets */
847 list_for_each_entry(w
, &codec
->dapm_widgets
, list
) {
849 if (!wsink
&& !(strcmp(w
->name
, sink
))) {
853 if (!wsource
&& !(strcmp(w
->name
, source
))) {
858 if (wsource
== NULL
|| wsink
== NULL
)
861 path
= kzalloc(sizeof(struct snd_soc_dapm_path
), GFP_KERNEL
);
865 path
->source
= wsource
;
867 INIT_LIST_HEAD(&path
->list
);
868 INIT_LIST_HEAD(&path
->list_source
);
869 INIT_LIST_HEAD(&path
->list_sink
);
871 /* check for external widgets */
872 if (wsink
->id
== snd_soc_dapm_input
) {
873 if (wsource
->id
== snd_soc_dapm_micbias
||
874 wsource
->id
== snd_soc_dapm_mic
||
875 wsink
->id
== snd_soc_dapm_line
||
876 wsink
->id
== snd_soc_dapm_output
)
879 if (wsource
->id
== snd_soc_dapm_output
) {
880 if (wsink
->id
== snd_soc_dapm_spk
||
881 wsink
->id
== snd_soc_dapm_hp
||
882 wsink
->id
== snd_soc_dapm_line
||
883 wsink
->id
== snd_soc_dapm_input
)
887 /* connect static paths */
888 if (control
== NULL
) {
889 list_add(&path
->list
, &codec
->dapm_paths
);
890 list_add(&path
->list_sink
, &wsink
->sources
);
891 list_add(&path
->list_source
, &wsource
->sinks
);
896 /* connect dynamic paths */
898 case snd_soc_dapm_adc
:
899 case snd_soc_dapm_dac
:
900 case snd_soc_dapm_pga
:
901 case snd_soc_dapm_input
:
902 case snd_soc_dapm_output
:
903 case snd_soc_dapm_micbias
:
904 case snd_soc_dapm_vmid
:
905 case snd_soc_dapm_pre
:
906 case snd_soc_dapm_post
:
907 list_add(&path
->list
, &codec
->dapm_paths
);
908 list_add(&path
->list_sink
, &wsink
->sources
);
909 list_add(&path
->list_source
, &wsource
->sinks
);
912 case snd_soc_dapm_mux
:
913 ret
= dapm_connect_mux(codec
, wsource
, wsink
, path
, control
,
914 &wsink
->kcontrols
[0]);
918 case snd_soc_dapm_switch
:
919 case snd_soc_dapm_mixer
:
920 ret
= dapm_connect_mixer(codec
, wsource
, wsink
, path
, control
);
924 case snd_soc_dapm_hp
:
925 case snd_soc_dapm_mic
:
926 case snd_soc_dapm_line
:
927 case snd_soc_dapm_spk
:
928 list_add(&path
->list
, &codec
->dapm_paths
);
929 list_add(&path
->list_sink
, &wsink
->sources
);
930 list_add(&path
->list_source
, &wsource
->sinks
);
937 printk(KERN_WARNING
"asoc: no dapm match for %s --> %s --> %s\n", source
,
944 * snd_soc_dapm_connect_input - connect dapm widgets
945 * @codec: audio codec
946 * @sink: name of target widget
947 * @control: mixer control name
948 * @source: name of source name
950 * Connects 2 dapm widgets together via a named audio path. The sink is
951 * the widget receiving the audio signal, whilst the source is the sender
952 * of the audio signal.
954 * This function has been deprecated in favour of snd_soc_dapm_add_routes().
956 * Returns 0 for success else error.
958 int snd_soc_dapm_connect_input(struct snd_soc_codec
*codec
, const char *sink
,
959 const char *control
, const char *source
)
961 return snd_soc_dapm_add_route(codec
, sink
, control
, source
);
963 EXPORT_SYMBOL_GPL(snd_soc_dapm_connect_input
);
966 * snd_soc_dapm_add_routes - Add routes between DAPM widgets
968 * @route: audio routes
969 * @num: number of routes
971 * Connects 2 dapm widgets together via a named audio path. The sink is
972 * the widget receiving the audio signal, whilst the source is the sender
973 * of the audio signal.
975 * Returns 0 for success else error. On error all resources can be freed
976 * with a call to snd_soc_card_free().
978 int snd_soc_dapm_add_routes(struct snd_soc_codec
*codec
,
979 const struct snd_soc_dapm_route
*route
, int num
)
983 for (i
= 0; i
< num
; i
++) {
984 ret
= snd_soc_dapm_add_route(codec
, route
->sink
,
985 route
->control
, route
->source
);
987 printk(KERN_ERR
"Failed to add route %s->%s\n",
997 EXPORT_SYMBOL_GPL(snd_soc_dapm_add_routes
);
1000 * snd_soc_dapm_new_widgets - add new dapm widgets
1001 * @codec: audio codec
1003 * Checks the codec for any new dapm widgets and creates them if found.
1005 * Returns 0 for success.
1007 int snd_soc_dapm_new_widgets(struct snd_soc_codec
*codec
)
1009 struct snd_soc_dapm_widget
*w
;
1011 list_for_each_entry(w
, &codec
->dapm_widgets
, list
)
1017 case snd_soc_dapm_switch
:
1018 case snd_soc_dapm_mixer
:
1019 dapm_new_mixer(codec
, w
);
1021 case snd_soc_dapm_mux
:
1022 dapm_new_mux(codec
, w
);
1024 case snd_soc_dapm_adc
:
1025 case snd_soc_dapm_dac
:
1026 case snd_soc_dapm_pga
:
1027 dapm_new_pga(codec
, w
);
1029 case snd_soc_dapm_input
:
1030 case snd_soc_dapm_output
:
1031 case snd_soc_dapm_micbias
:
1032 case snd_soc_dapm_spk
:
1033 case snd_soc_dapm_hp
:
1034 case snd_soc_dapm_mic
:
1035 case snd_soc_dapm_line
:
1036 case snd_soc_dapm_vmid
:
1037 case snd_soc_dapm_pre
:
1038 case snd_soc_dapm_post
:
1044 dapm_power_widgets(codec
, SND_SOC_DAPM_STREAM_NOP
);
1047 EXPORT_SYMBOL_GPL(snd_soc_dapm_new_widgets
);
1050 * snd_soc_dapm_get_volsw - dapm mixer get callback
1051 * @kcontrol: mixer control
1052 * @uinfo: control element information
1054 * Callback to get the value of a dapm mixer control.
1056 * Returns 0 for success.
1058 int snd_soc_dapm_get_volsw(struct snd_kcontrol
*kcontrol
,
1059 struct snd_ctl_elem_value
*ucontrol
)
1061 struct snd_soc_dapm_widget
*widget
= snd_kcontrol_chip(kcontrol
);
1062 int reg
= kcontrol
->private_value
& 0xff;
1063 int shift
= (kcontrol
->private_value
>> 8) & 0x0f;
1064 int rshift
= (kcontrol
->private_value
>> 12) & 0x0f;
1065 int max
= (kcontrol
->private_value
>> 16) & 0xff;
1066 int invert
= (kcontrol
->private_value
>> 24) & 0x01;
1067 int mask
= (1 << fls(max
)) - 1;
1069 /* return the saved value if we are powered down */
1070 if (widget
->id
== snd_soc_dapm_pga
&& !widget
->power
) {
1071 ucontrol
->value
.integer
.value
[0] = widget
->saved_value
;
1075 ucontrol
->value
.integer
.value
[0] =
1076 (snd_soc_read(widget
->codec
, reg
) >> shift
) & mask
;
1077 if (shift
!= rshift
)
1078 ucontrol
->value
.integer
.value
[1] =
1079 (snd_soc_read(widget
->codec
, reg
) >> rshift
) & mask
;
1081 ucontrol
->value
.integer
.value
[0] =
1082 max
- ucontrol
->value
.integer
.value
[0];
1083 if (shift
!= rshift
)
1084 ucontrol
->value
.integer
.value
[1] =
1085 max
- ucontrol
->value
.integer
.value
[1];
1090 EXPORT_SYMBOL_GPL(snd_soc_dapm_get_volsw
);
1093 * snd_soc_dapm_put_volsw - dapm mixer set callback
1094 * @kcontrol: mixer control
1095 * @uinfo: control element information
1097 * Callback to set the value of a dapm mixer control.
1099 * Returns 0 for success.
1101 int snd_soc_dapm_put_volsw(struct snd_kcontrol
*kcontrol
,
1102 struct snd_ctl_elem_value
*ucontrol
)
1104 struct snd_soc_dapm_widget
*widget
= snd_kcontrol_chip(kcontrol
);
1105 int reg
= kcontrol
->private_value
& 0xff;
1106 int shift
= (kcontrol
->private_value
>> 8) & 0x0f;
1107 int rshift
= (kcontrol
->private_value
>> 12) & 0x0f;
1108 int max
= (kcontrol
->private_value
>> 16) & 0xff;
1109 int mask
= (1 << fls(max
)) - 1;
1110 int invert
= (kcontrol
->private_value
>> 24) & 0x01;
1111 unsigned short val
, val2
, val_mask
;
1114 val
= (ucontrol
->value
.integer
.value
[0] & mask
);
1118 val_mask
= mask
<< shift
;
1120 if (shift
!= rshift
) {
1121 val2
= (ucontrol
->value
.integer
.value
[1] & mask
);
1124 val_mask
|= mask
<< rshift
;
1125 val
|= val2
<< rshift
;
1128 mutex_lock(&widget
->codec
->mutex
);
1129 widget
->value
= val
;
1131 /* save volume value if the widget is powered down */
1132 if (widget
->id
== snd_soc_dapm_pga
&& !widget
->power
) {
1133 widget
->saved_value
= val
;
1134 mutex_unlock(&widget
->codec
->mutex
);
1138 dapm_mixer_update_power(widget
, kcontrol
, reg
, val_mask
, val
, invert
);
1139 if (widget
->event
) {
1140 if (widget
->event_flags
& SND_SOC_DAPM_PRE_REG
) {
1141 ret
= widget
->event(widget
, kcontrol
,
1142 SND_SOC_DAPM_PRE_REG
);
1148 ret
= snd_soc_update_bits(widget
->codec
, reg
, val_mask
, val
);
1149 if (widget
->event_flags
& SND_SOC_DAPM_POST_REG
)
1150 ret
= widget
->event(widget
, kcontrol
,
1151 SND_SOC_DAPM_POST_REG
);
1153 ret
= snd_soc_update_bits(widget
->codec
, reg
, val_mask
, val
);
1156 mutex_unlock(&widget
->codec
->mutex
);
1159 EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw
);
1162 * snd_soc_dapm_get_enum_double - dapm enumerated double mixer get callback
1163 * @kcontrol: mixer control
1164 * @uinfo: control element information
1166 * Callback to get the value of a dapm enumerated double mixer control.
1168 * Returns 0 for success.
1170 int snd_soc_dapm_get_enum_double(struct snd_kcontrol
*kcontrol
,
1171 struct snd_ctl_elem_value
*ucontrol
)
1173 struct snd_soc_dapm_widget
*widget
= snd_kcontrol_chip(kcontrol
);
1174 struct soc_enum
*e
= (struct soc_enum
*)kcontrol
->private_value
;
1175 unsigned short val
, bitmask
;
1177 for (bitmask
= 1; bitmask
< e
->mask
; bitmask
<<= 1)
1179 val
= snd_soc_read(widget
->codec
, e
->reg
);
1180 ucontrol
->value
.enumerated
.item
[0] = (val
>> e
->shift_l
) & (bitmask
- 1);
1181 if (e
->shift_l
!= e
->shift_r
)
1182 ucontrol
->value
.enumerated
.item
[1] =
1183 (val
>> e
->shift_r
) & (bitmask
- 1);
1187 EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_double
);
1190 * snd_soc_dapm_put_enum_double - dapm enumerated double mixer set callback
1191 * @kcontrol: mixer control
1192 * @uinfo: control element information
1194 * Callback to set the value of a dapm enumerated double mixer control.
1196 * Returns 0 for success.
1198 int snd_soc_dapm_put_enum_double(struct snd_kcontrol
*kcontrol
,
1199 struct snd_ctl_elem_value
*ucontrol
)
1201 struct snd_soc_dapm_widget
*widget
= snd_kcontrol_chip(kcontrol
);
1202 struct soc_enum
*e
= (struct soc_enum
*)kcontrol
->private_value
;
1203 unsigned short val
, mux
;
1204 unsigned short mask
, bitmask
;
1207 for (bitmask
= 1; bitmask
< e
->mask
; bitmask
<<= 1)
1209 if (ucontrol
->value
.enumerated
.item
[0] > e
->mask
- 1)
1211 mux
= ucontrol
->value
.enumerated
.item
[0];
1212 val
= mux
<< e
->shift_l
;
1213 mask
= (bitmask
- 1) << e
->shift_l
;
1214 if (e
->shift_l
!= e
->shift_r
) {
1215 if (ucontrol
->value
.enumerated
.item
[1] > e
->mask
- 1)
1217 val
|= ucontrol
->value
.enumerated
.item
[1] << e
->shift_r
;
1218 mask
|= (bitmask
- 1) << e
->shift_r
;
1221 mutex_lock(&widget
->codec
->mutex
);
1222 widget
->value
= val
;
1223 dapm_mux_update_power(widget
, kcontrol
, mask
, mux
, e
);
1224 if (widget
->event
) {
1225 if (widget
->event_flags
& SND_SOC_DAPM_PRE_REG
) {
1226 ret
= widget
->event(widget
,
1227 kcontrol
, SND_SOC_DAPM_PRE_REG
);
1231 ret
= snd_soc_update_bits(widget
->codec
, e
->reg
, mask
, val
);
1232 if (widget
->event_flags
& SND_SOC_DAPM_POST_REG
)
1233 ret
= widget
->event(widget
,
1234 kcontrol
, SND_SOC_DAPM_POST_REG
);
1236 ret
= snd_soc_update_bits(widget
->codec
, e
->reg
, mask
, val
);
1239 mutex_unlock(&widget
->codec
->mutex
);
1242 EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double
);
1245 * snd_soc_dapm_new_control - create new dapm control
1246 * @codec: audio codec
1247 * @widget: widget template
1249 * Creates a new dapm control based upon the template.
1251 * Returns 0 for success else error.
1253 int snd_soc_dapm_new_control(struct snd_soc_codec
*codec
,
1254 const struct snd_soc_dapm_widget
*widget
)
1256 struct snd_soc_dapm_widget
*w
;
1258 if ((w
= dapm_cnew_widget(widget
)) == NULL
)
1262 INIT_LIST_HEAD(&w
->sources
);
1263 INIT_LIST_HEAD(&w
->sinks
);
1264 INIT_LIST_HEAD(&w
->list
);
1265 list_add(&w
->list
, &codec
->dapm_widgets
);
1267 /* machine layer set ups unconnected pins and insertions */
1271 EXPORT_SYMBOL_GPL(snd_soc_dapm_new_control
);
1274 * snd_soc_dapm_new_controls - create new dapm controls
1275 * @codec: audio codec
1276 * @widget: widget array
1277 * @num: number of widgets
1279 * Creates new DAPM controls based upon the templates.
1281 * Returns 0 for success else error.
1283 int snd_soc_dapm_new_controls(struct snd_soc_codec
*codec
,
1284 const struct snd_soc_dapm_widget
*widget
,
1289 for (i
= 0; i
< num
; i
++) {
1290 ret
= snd_soc_dapm_new_control(codec
, widget
);
1297 EXPORT_SYMBOL_GPL(snd_soc_dapm_new_controls
);
1301 * snd_soc_dapm_stream_event - send a stream event to the dapm core
1302 * @codec: audio codec
1303 * @stream: stream name
1304 * @event: stream event
1306 * Sends a stream event to the dapm core. The core then makes any
1307 * necessary widget power changes.
1309 * Returns 0 for success else error.
1311 int snd_soc_dapm_stream_event(struct snd_soc_codec
*codec
,
1312 char *stream
, int event
)
1314 struct snd_soc_dapm_widget
*w
;
1319 mutex_lock(&codec
->mutex
);
1320 list_for_each_entry(w
, &codec
->dapm_widgets
, list
)
1324 dbg("widget %s\n %s stream %s event %d\n", w
->name
, w
->sname
,
1326 if (strstr(w
->sname
, stream
)) {
1328 case SND_SOC_DAPM_STREAM_START
:
1331 case SND_SOC_DAPM_STREAM_STOP
:
1334 case SND_SOC_DAPM_STREAM_SUSPEND
:
1339 case SND_SOC_DAPM_STREAM_RESUME
:
1345 case SND_SOC_DAPM_STREAM_PAUSE_PUSH
:
1347 case SND_SOC_DAPM_STREAM_PAUSE_RELEASE
:
1352 mutex_unlock(&codec
->mutex
);
1354 dapm_power_widgets(codec
, event
);
1355 dump_dapm(codec
, __func__
);
1358 EXPORT_SYMBOL_GPL(snd_soc_dapm_stream_event
);
1361 * snd_soc_dapm_device_event - send a device event to the dapm core
1362 * @socdev: audio device
1363 * @event: device event
1365 * Sends a device event to the dapm core. The core then makes any
1366 * necessary machine or codec power changes..
1368 * Returns 0 for success else error.
1370 int snd_soc_dapm_device_event(struct snd_soc_device
*socdev
, int event
)
1372 struct snd_soc_codec
*codec
= socdev
->codec
;
1373 struct snd_soc_machine
*machine
= socdev
->machine
;
1375 if (machine
->dapm_event
)
1376 machine
->dapm_event(machine
, event
);
1377 if (codec
->dapm_event
)
1378 codec
->dapm_event(codec
, event
);
1381 EXPORT_SYMBOL_GPL(snd_soc_dapm_device_event
);
1384 * snd_soc_dapm_set_endpoint - set audio endpoint status
1385 * @codec: audio codec
1386 * @endpoint: audio signal endpoint (or start point)
1387 * @status: point status
1389 * Set audio endpoint status - connected or disconnected.
1391 * Returns 0 for success else error.
1393 int snd_soc_dapm_set_endpoint(struct snd_soc_codec
*codec
,
1394 char *endpoint
, int status
)
1396 struct snd_soc_dapm_widget
*w
;
1398 list_for_each_entry(w
, &codec
->dapm_widgets
, list
) {
1399 if (!strcmp(w
->name
, endpoint
)) {
1400 w
->connected
= status
;
1407 EXPORT_SYMBOL_GPL(snd_soc_dapm_set_endpoint
);
1410 * snd_soc_dapm_get_endpoint_status - get audio endpoint status
1411 * @codec: audio codec
1412 * @endpoint: audio signal endpoint (or start point)
1414 * Get audio endpoint status - connected or disconnected.
1418 int snd_soc_dapm_get_endpoint_status(struct snd_soc_codec
*codec
,
1421 struct snd_soc_dapm_widget
*w
;
1423 list_for_each_entry(w
, &codec
->dapm_widgets
, list
) {
1424 if (!strcmp(w
->name
, endpoint
))
1425 return w
->connected
;
1430 EXPORT_SYMBOL_GPL(snd_soc_dapm_get_endpoint_status
);
1433 * snd_soc_dapm_free - free dapm resources
1434 * @socdev: SoC device
1436 * Free all dapm widgets and resources.
1438 void snd_soc_dapm_free(struct snd_soc_device
*socdev
)
1440 struct snd_soc_codec
*codec
= socdev
->codec
;
1442 snd_soc_dapm_sys_remove(socdev
->dev
);
1443 dapm_free_widgets(codec
);
1445 EXPORT_SYMBOL_GPL(snd_soc_dapm_free
);
1447 /* Module information */
1448 MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com");
1449 MODULE_DESCRIPTION("Dynamic Audio Power Management core for ALSA SoC");
1450 MODULE_LICENSE("GPL");