1 |
3 |
xianfeng |
Dynamic Audio Power Management for Portable Devices
|
2 |
|
|
===================================================
|
3 |
|
|
|
4 |
|
|
1. Description
|
5 |
|
|
==============
|
6 |
|
|
|
7 |
|
|
Dynamic Audio Power Management (DAPM) is designed to allow portable Linux devices
|
8 |
|
|
to use the minimum amount of power within the audio subsystem at all times. It
|
9 |
|
|
is independent of other kernel PM and as such, can easily co-exist with the
|
10 |
|
|
other PM systems.
|
11 |
|
|
|
12 |
|
|
DAPM is also completely transparent to all user space applications as all power
|
13 |
|
|
switching is done within the ASoC core. No code changes or recompiling are
|
14 |
|
|
required for user space applications. DAPM makes power switching decisions based
|
15 |
|
|
upon any audio stream (capture/playback) activity and audio mixer settings
|
16 |
|
|
within the device.
|
17 |
|
|
|
18 |
|
|
DAPM spans the whole machine. It covers power control within the entire audio
|
19 |
|
|
subsystem, this includes internal codec power blocks and machine level power
|
20 |
|
|
systems.
|
21 |
|
|
|
22 |
|
|
There are 4 power domains within DAPM
|
23 |
|
|
|
24 |
|
|
1. Codec domain - VREF, VMID (core codec and audio power)
|
25 |
|
|
Usually controlled at codec probe/remove and suspend/resume, although
|
26 |
|
|
can be set at stream time if power is not needed for sidetone, etc.
|
27 |
|
|
|
28 |
|
|
2. Platform/Machine domain - physically connected inputs and outputs
|
29 |
|
|
Is platform/machine and user action specific, is configured by the
|
30 |
|
|
machine driver and responds to asynchronous events e.g when HP
|
31 |
|
|
are inserted
|
32 |
|
|
|
33 |
|
|
3. Path domain - audio susbsystem signal paths
|
34 |
|
|
Automatically set when mixer and mux settings are changed by the user.
|
35 |
|
|
e.g. alsamixer, amixer.
|
36 |
|
|
|
37 |
|
|
4. Stream domain - DAC's and ADC's.
|
38 |
|
|
Enabled and disabled when stream playback/capture is started and
|
39 |
|
|
stopped respectively. e.g. aplay, arecord.
|
40 |
|
|
|
41 |
|
|
All DAPM power switching decisions are made automatically by consulting an audio
|
42 |
|
|
routing map of the whole machine. This map is specific to each machine and
|
43 |
|
|
consists of the interconnections between every audio component (including
|
44 |
|
|
internal codec components). All audio components that effect power are called
|
45 |
|
|
widgets hereafter.
|
46 |
|
|
|
47 |
|
|
|
48 |
|
|
2. DAPM Widgets
|
49 |
|
|
===============
|
50 |
|
|
|
51 |
|
|
Audio DAPM widgets fall into a number of types:-
|
52 |
|
|
|
53 |
|
|
o Mixer - Mixes several analog signals into a single analog signal.
|
54 |
|
|
o Mux - An analog switch that outputs only 1 of it's inputs.
|
55 |
|
|
o PGA - A programmable gain amplifier or attenuation widget.
|
56 |
|
|
o ADC - Analog to Digital Converter
|
57 |
|
|
o DAC - Digital to Analog Converter
|
58 |
|
|
o Switch - An analog switch
|
59 |
|
|
o Input - A codec input pin
|
60 |
|
|
o Output - A codec output pin
|
61 |
|
|
o Headphone - Headphone (and optional Jack)
|
62 |
|
|
o Mic - Mic (and optional Jack)
|
63 |
|
|
o Line - Line Input/Output (and optional Jack)
|
64 |
|
|
o Speaker - Speaker
|
65 |
|
|
o Pre - Special PRE widget (exec before all others)
|
66 |
|
|
o Post - Special POST widget (exec after all others)
|
67 |
|
|
|
68 |
|
|
(Widgets are defined in include/sound/soc-dapm.h)
|
69 |
|
|
|
70 |
|
|
Widgets are usually added in the codec driver and the machine driver. There are
|
71 |
|
|
convience macros defined in soc-dapm.h that can be used to quickly build a
|
72 |
|
|
list of widgets of the codecs and machines DAPM widgets.
|
73 |
|
|
|
74 |
|
|
Most widgets have a name, register, shift and invert. Some widgets have extra
|
75 |
|
|
parameters for stream name and kcontrols.
|
76 |
|
|
|
77 |
|
|
|
78 |
|
|
2.1 Stream Domain Widgets
|
79 |
|
|
-------------------------
|
80 |
|
|
|
81 |
|
|
Stream Widgets relate to the stream power domain and only consist of ADC's
|
82 |
|
|
(analog to digital converters) and DAC's (digital to analog converters).
|
83 |
|
|
|
84 |
|
|
Stream widgets have the following format:-
|
85 |
|
|
|
86 |
|
|
SND_SOC_DAPM_DAC(name, stream name, reg, shift, invert),
|
87 |
|
|
|
88 |
|
|
NOTE: the stream name must match the corresponding stream name in your codecs
|
89 |
|
|
snd_soc_codec_dai.
|
90 |
|
|
|
91 |
|
|
e.g. stream widgets for HiFi playback and capture
|
92 |
|
|
|
93 |
|
|
SND_SOC_DAPM_DAC("HiFi DAC", "HiFi Playback", REG, 3, 1),
|
94 |
|
|
SND_SOC_DAPM_ADC("HiFi ADC", "HiFi Capture", REG, 2, 1),
|
95 |
|
|
|
96 |
|
|
|
97 |
|
|
2.2 Path Domain Widgets
|
98 |
|
|
-----------------------
|
99 |
|
|
|
100 |
|
|
Path domain widgets have a ability to control or effect the audio signal or
|
101 |
|
|
audio paths within the audio subsystem. They have the following form:-
|
102 |
|
|
|
103 |
|
|
SND_SOC_DAPM_PGA(name, reg, shift, invert, controls, num_controls)
|
104 |
|
|
|
105 |
|
|
Any widget kcontrols can be set using the controls and num_controls members.
|
106 |
|
|
|
107 |
|
|
e.g. Mixer widget (the kcontrols are declared first)
|
108 |
|
|
|
109 |
|
|
/* Output Mixer */
|
110 |
|
|
static const snd_kcontrol_new_t wm8731_output_mixer_controls[] = {
|
111 |
|
|
SOC_DAPM_SINGLE("Line Bypass Switch", WM8731_APANA, 3, 1, 0),
|
112 |
|
|
SOC_DAPM_SINGLE("Mic Sidetone Switch", WM8731_APANA, 5, 1, 0),
|
113 |
|
|
SOC_DAPM_SINGLE("HiFi Playback Switch", WM8731_APANA, 4, 1, 0),
|
114 |
|
|
};
|
115 |
|
|
|
116 |
|
|
SND_SOC_DAPM_MIXER("Output Mixer", WM8731_PWR, 4, 1, wm8731_output_mixer_controls,
|
117 |
|
|
ARRAY_SIZE(wm8731_output_mixer_controls)),
|
118 |
|
|
|
119 |
|
|
|
120 |
|
|
2.3 Platform/Machine domain Widgets
|
121 |
|
|
-----------------------------------
|
122 |
|
|
|
123 |
|
|
Machine widgets are different from codec widgets in that they don't have a
|
124 |
|
|
codec register bit associated with them. A machine widget is assigned to each
|
125 |
|
|
machine audio component (non codec) that can be independently powered. e.g.
|
126 |
|
|
|
127 |
|
|
o Speaker Amp
|
128 |
|
|
o Microphone Bias
|
129 |
|
|
o Jack connectors
|
130 |
|
|
|
131 |
|
|
A machine widget can have an optional call back.
|
132 |
|
|
|
133 |
|
|
e.g. Jack connector widget for an external Mic that enables Mic Bias
|
134 |
|
|
when the Mic is inserted:-
|
135 |
|
|
|
136 |
|
|
static int spitz_mic_bias(struct snd_soc_dapm_widget* w, int event)
|
137 |
|
|
{
|
138 |
|
|
if(SND_SOC_DAPM_EVENT_ON(event))
|
139 |
|
|
set_scoop_gpio(&spitzscoop2_device.dev, SPITZ_SCP2_MIC_BIAS);
|
140 |
|
|
else
|
141 |
|
|
reset_scoop_gpio(&spitzscoop2_device.dev, SPITZ_SCP2_MIC_BIAS);
|
142 |
|
|
|
143 |
|
|
return 0;
|
144 |
|
|
}
|
145 |
|
|
|
146 |
|
|
SND_SOC_DAPM_MIC("Mic Jack", spitz_mic_bias),
|
147 |
|
|
|
148 |
|
|
|
149 |
|
|
2.4 Codec Domain
|
150 |
|
|
----------------
|
151 |
|
|
|
152 |
|
|
The Codec power domain has no widgets and is handled by the codecs DAPM event
|
153 |
|
|
handler. This handler is called when the codec powerstate is changed wrt to any
|
154 |
|
|
stream event or by kernel PM events.
|
155 |
|
|
|
156 |
|
|
|
157 |
|
|
2.5 Virtual Widgets
|
158 |
|
|
-------------------
|
159 |
|
|
|
160 |
|
|
Sometimes widgets exist in the codec or machine audio map that don't have any
|
161 |
|
|
corresponding register bit for power control. In this case it's necessary to
|
162 |
|
|
create a virtual widget - a widget with no control bits e.g.
|
163 |
|
|
|
164 |
|
|
SND_SOC_DAPM_MIXER("AC97 Mixer", SND_SOC_DAPM_NOPM, 0, 0, NULL, 0),
|
165 |
|
|
|
166 |
|
|
This can be used to merge to signal paths together in software.
|
167 |
|
|
|
168 |
|
|
After all the widgets have been defined, they can then be added to the DAPM
|
169 |
|
|
subsystem individually with a call to snd_soc_dapm_new_control().
|
170 |
|
|
|
171 |
|
|
|
172 |
|
|
3. Codec Widget Interconnections
|
173 |
|
|
================================
|
174 |
|
|
|
175 |
|
|
Widgets are connected to each other within the codec and machine by audio
|
176 |
|
|
paths (called interconnections). Each interconnection must be defined in order
|
177 |
|
|
to create a map of all audio paths between widgets.
|
178 |
|
|
This is easiest with a diagram of the codec (and schematic of the machine audio
|
179 |
|
|
system), as it requires joining widgets together via their audio signal paths.
|
180 |
|
|
|
181 |
|
|
i.e. from the WM8731 codec's output mixer (wm8731.c)
|
182 |
|
|
|
183 |
|
|
The WM8731 output mixer has 3 inputs (sources)
|
184 |
|
|
|
185 |
|
|
1. Line Bypass Input
|
186 |
|
|
2. DAC (HiFi playback)
|
187 |
|
|
3. Mic Sidetone Input
|
188 |
|
|
|
189 |
|
|
Each input in this example has a kcontrol associated with it (defined in example
|
190 |
|
|
above) and is connected to the output mixer via it's kcontrol name. We can now
|
191 |
|
|
connect the destination widget (wrt audio signal) with it's source widgets.
|
192 |
|
|
|
193 |
|
|
/* output mixer */
|
194 |
|
|
{"Output Mixer", "Line Bypass Switch", "Line Input"},
|
195 |
|
|
{"Output Mixer", "HiFi Playback Switch", "DAC"},
|
196 |
|
|
{"Output Mixer", "Mic Sidetone Switch", "Mic Bias"},
|
197 |
|
|
|
198 |
|
|
So we have :-
|
199 |
|
|
|
200 |
|
|
Destination Widget <=== Path Name <=== Source Widget
|
201 |
|
|
|
202 |
|
|
Or:-
|
203 |
|
|
|
204 |
|
|
Sink, Path, Source
|
205 |
|
|
|
206 |
|
|
Or :-
|
207 |
|
|
|
208 |
|
|
"Output Mixer" is connected to the "DAC" via the "HiFi Playback Switch".
|
209 |
|
|
|
210 |
|
|
When there is no path name connecting widgets (e.g. a direct connection) we
|
211 |
|
|
pass NULL for the path name.
|
212 |
|
|
|
213 |
|
|
Interconnections are created with a call to:-
|
214 |
|
|
|
215 |
|
|
snd_soc_dapm_connect_input(codec, sink, path, source);
|
216 |
|
|
|
217 |
|
|
Finally, snd_soc_dapm_new_widgets(codec) must be called after all widgets and
|
218 |
|
|
interconnections have been registered with the core. This causes the core to
|
219 |
|
|
scan the codec and machine so that the internal DAPM state matches the
|
220 |
|
|
physical state of the machine.
|
221 |
|
|
|
222 |
|
|
|
223 |
|
|
3.1 Machine Widget Interconnections
|
224 |
|
|
-----------------------------------
|
225 |
|
|
Machine widget interconnections are created in the same way as codec ones and
|
226 |
|
|
directly connect the codec pins to machine level widgets.
|
227 |
|
|
|
228 |
|
|
e.g. connects the speaker out codec pins to the internal speaker.
|
229 |
|
|
|
230 |
|
|
/* ext speaker connected to codec pins LOUT2, ROUT2 */
|
231 |
|
|
{"Ext Spk", NULL , "ROUT2"},
|
232 |
|
|
{"Ext Spk", NULL , "LOUT2"},
|
233 |
|
|
|
234 |
|
|
This allows the DAPM to power on and off pins that are connected (and in use)
|
235 |
|
|
and pins that are NC respectively.
|
236 |
|
|
|
237 |
|
|
|
238 |
|
|
4 Endpoint Widgets
|
239 |
|
|
===================
|
240 |
|
|
An endpoint is a start or end point (widget) of an audio signal within the
|
241 |
|
|
machine and includes the codec. e.g.
|
242 |
|
|
|
243 |
|
|
o Headphone Jack
|
244 |
|
|
o Internal Speaker
|
245 |
|
|
o Internal Mic
|
246 |
|
|
o Mic Jack
|
247 |
|
|
o Codec Pins
|
248 |
|
|
|
249 |
|
|
When a codec pin is NC it can be marked as not used with a call to
|
250 |
|
|
|
251 |
|
|
snd_soc_dapm_set_endpoint(codec, "Widget Name", 0);
|
252 |
|
|
|
253 |
|
|
The last argument is 0 for inactive and 1 for active. This way the pin and its
|
254 |
|
|
input widget will never be powered up and consume power.
|
255 |
|
|
|
256 |
|
|
This also applies to machine widgets. e.g. if a headphone is connected to a
|
257 |
|
|
jack then the jack can be marked active. If the headphone is removed, then
|
258 |
|
|
the headphone jack can be marked inactive.
|
259 |
|
|
|
260 |
|
|
|
261 |
|
|
5 DAPM Widget Events
|
262 |
|
|
====================
|
263 |
|
|
|
264 |
|
|
Some widgets can register their interest with the DAPM core in PM events.
|
265 |
|
|
e.g. A Speaker with an amplifier registers a widget so the amplifier can be
|
266 |
|
|
powered only when the spk is in use.
|
267 |
|
|
|
268 |
|
|
/* turn speaker amplifier on/off depending on use */
|
269 |
|
|
static int corgi_amp_event(struct snd_soc_dapm_widget *w, int event)
|
270 |
|
|
{
|
271 |
|
|
if (SND_SOC_DAPM_EVENT_ON(event))
|
272 |
|
|
set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_APM_ON);
|
273 |
|
|
else
|
274 |
|
|
reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_APM_ON);
|
275 |
|
|
|
276 |
|
|
return 0;
|
277 |
|
|
}
|
278 |
|
|
|
279 |
|
|
/* corgi machine dapm widgets */
|
280 |
|
|
static const struct snd_soc_dapm_widget wm8731_dapm_widgets =
|
281 |
|
|
SND_SOC_DAPM_SPK("Ext Spk", corgi_amp_event);
|
282 |
|
|
|
283 |
|
|
Please see soc-dapm.h for all other widgets that support events.
|
284 |
|
|
|
285 |
|
|
|
286 |
|
|
5.1 Event types
|
287 |
|
|
---------------
|
288 |
|
|
|
289 |
|
|
The following event types are supported by event widgets.
|
290 |
|
|
|
291 |
|
|
/* dapm event types */
|
292 |
|
|
#define SND_SOC_DAPM_PRE_PMU 0x1 /* before widget power up */
|
293 |
|
|
#define SND_SOC_DAPM_POST_PMU 0x2 /* after widget power up */
|
294 |
|
|
#define SND_SOC_DAPM_PRE_PMD 0x4 /* before widget power down */
|
295 |
|
|
#define SND_SOC_DAPM_POST_PMD 0x8 /* after widget power down */
|
296 |
|
|
#define SND_SOC_DAPM_PRE_REG 0x10 /* before audio path setup */
|
297 |
|
|
#define SND_SOC_DAPM_POST_REG 0x20 /* after audio path setup */
|