← Documents Documentation/sound/soc/dapm.rst GitHub 원문 ↗

Linux 6.18.37 · Sound / ASoC

휴대용 장치를 위한 Dynamic Audio Power Management

ASoC DAPM이 sound card 전체 routing graph의 widget·route를 바탕으로 codec bias, machine, path, stream 전원을 자동 관리하는 원리를 설명합니다. Widget 유형, 정적·동적 등록, codec·machine interconnection, endpoint, custom event와 power sequence flag를 원문 코드 좌표와 함께 정리합니다.

Source pathDocumentation/sound/soc/dapm.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.

1. 요약·해설

원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.

요약·해설

dapm.rst:1-422

ASoC DAPM이 sound card 전체 routing graph의 widget·route를 바탕으로 codec bias, machine, path, stream 전원을 자동 관리하는 원리를 설명합니다. Widget 유형, 정적·동적 등록, codec·machine interconnection, endpoint, custom event와 power sequence flag를 원문 코드 좌표와 함께 정리합니다.

2. 영어 원문 전체

번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.

원문 전체 펼치기
1 ===================================================
2 Dynamic Audio Power Management for Portable Devices
3 ===================================================
4
5 Description
6 ===========
7
8 Dynamic Audio Power Management (DAPM) is designed to allow portable
9 Linux devices to use the minimum amount of power within the audio
10 subsystem at all times. It is independent of other kernel power
11 management frameworks and, as such, can easily co-exist with them.
12
13 DAPM is also completely transparent to all user space applications as
14 all power switching is done within the ASoC core. No code changes or
15 recompiling are required for user space applications. DAPM makes power
16 switching decisions based upon any audio stream (capture/playback)
17 activity and audio mixer settings within the device.
18
19 DAPM is based on two basic elements, called widgets and routes:
20
21 * a **widget** is every part of the audio hardware that can be enabled by
22 software when in use and disabled to save power when not in use
23 * a **route** is an interconnection between widgets that exists when sound
24 can flow from one widget to the other
25
26 All DAPM power switching decisions are made automatically by consulting an
27 audio routing graph. This graph is specific to each sound card and spans
28 the whole sound card, so some DAPM routes connect two widgets belonging to
29 different components (e.g. the LINE OUT pin of a CODEC and the input pin of
30 an amplifier).
31
32 The graph for the STM32MP1-DK1 sound card is shown in picture:
33
34 .. kernel-figure:: dapm-graph.svg
35 :alt: Example DAPM graph
36 :align: center
37
38 You can also generate compatible graph for your sound card using
39 `tools/sound/dapm-graph` utility.
40
41 DAPM power domains
42 ==================
43
44 There are 4 power domains within DAPM:
45
46 Codec bias domain
47 VREF, VMID (core codec and audio power)
48
49 Usually controlled at codec probe/remove and suspend/resume, although
50 can be set at stream time if power is not needed for sidetone, etc.
51
52 Platform/Machine domain
53 physically connected inputs and outputs
54
55 Is platform/machine and user action specific, is configured by the
56 machine driver and responds to asynchronous events e.g when HP
57 are inserted
58
59 Path domain
60 audio subsystem signal paths
61
62 Automatically set when mixer and mux settings are changed by the user.
63 e.g. alsamixer, amixer.
64
65 Stream domain
66 DACs and ADCs.
67
68 Enabled and disabled when stream playback/capture is started and
69 stopped respectively. e.g. aplay, arecord.
70
71
72 DAPM Widgets
73 ============
74
75 Audio DAPM widgets fall into a number of types:
76
77 Mixer
78 Mixes several analog signals into a single analog signal.
79 Mux
80 An analog switch that outputs only one of many inputs.
81 PGA
82 A programmable gain amplifier or attenuation widget.
83 ADC
84 Analog to Digital Converter
85 DAC
86 Digital to Analog Converter
87 Switch
88 An analog switch
89 Input
90 A codec input pin
91 Output
92 A codec output pin
93 Headphone
94 Headphone (and optional Jack)
95 Mic
96 Mic (and optional Jack)
97 Line
98 Line Input/Output (and optional Jack)
99 Speaker
100 Speaker
101 Supply
102 Power or clock supply widget used by other widgets.
103 Regulator
104 External regulator that supplies power to audio components.
105 Clock
106 External clock that supplies clock to audio components.
107 AIF IN
108 Audio Interface Input (with TDM slot mask).
109 AIF OUT
110 Audio Interface Output (with TDM slot mask).
111 Siggen
112 Signal Generator.
113 DAI IN
114 Digital Audio Interface Input.
115 DAI OUT
116 Digital Audio Interface Output.
117 DAI Link
118 DAI Link between two DAI structures
119 Pre
120 Special PRE widget (exec before all others)
121 Post
122 Special POST widget (exec after all others)
123 Buffer
124 Inter widget audio data buffer within a DSP.
125 Scheduler
126 DSP internal scheduler that schedules component/pipeline processing
127 work.
128 Effect
129 Widget that performs an audio processing effect.
130 SRC
131 Sample Rate Converter within DSP or CODEC
132 ASRC
133 Asynchronous Sample Rate Converter within DSP or CODEC
134 Encoder
135 Widget that encodes audio data from one format (usually PCM) to another
136 usually more compressed format.
137 Decoder
138 Widget that decodes audio data from a compressed format to an
139 uncompressed format like PCM.
140
141
142 (Widgets are defined in include/sound/soc-dapm.h)
143
144 Widgets can be added to the sound card by any of the component driver types.
145 There are convenience macros defined in soc-dapm.h that can be used to quickly
146 build a list of widgets of the codecs and machines DAPM widgets.
147
148 Most widgets have a name, register, shift and invert. Some widgets have extra
149 parameters for stream name and kcontrols.
150
151
152 Stream Domain Widgets
153 ---------------------
154
155 Stream Widgets relate to the stream power domain and only consist of ADCs
156 (analog to digital converters), DACs (digital to analog converters),
157 AIF IN and AIF OUT.
158
159 Stream widgets have the following format:
160 ::
161
162 SND_SOC_DAPM_DAC(name, stream name, reg, shift, invert),
163 SND_SOC_DAPM_AIF_IN(name, stream, slot, reg, shift, invert)
164
165 NOTE: the stream name must match the corresponding stream name in your codec
166 snd_soc_dai_driver.
167
168 e.g. stream widgets for HiFi playback and capture
169 ::
170
171 SND_SOC_DAPM_DAC("HiFi DAC", "HiFi Playback", REG, 3, 1),
172 SND_SOC_DAPM_ADC("HiFi ADC", "HiFi Capture", REG, 2, 1),
173
174 e.g. stream widgets for AIF
175 ::
176
177 SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
178 SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0),
179
180
181 Path Domain Widgets
182 -------------------
183
184 Path domain widgets have a ability to control or affect the audio signal or
185 audio paths within the audio subsystem. They have the following form:
186 ::
187
188 SND_SOC_DAPM_PGA(name, reg, shift, invert, controls, num_controls)
189
190 Any widget kcontrols can be set using the controls and num_controls members.
191
192 e.g. Mixer widget (the kcontrols are declared first)
193 ::
194
195 /* Output Mixer */
196 static const snd_kcontrol_new_t wm8731_output_mixer_controls[] = {
197 SOC_DAPM_SINGLE("Line Bypass Switch", WM8731_APANA, 3, 1, 0),
198 SOC_DAPM_SINGLE("Mic Sidetone Switch", WM8731_APANA, 5, 1, 0),
199 SOC_DAPM_SINGLE("HiFi Playback Switch", WM8731_APANA, 4, 1, 0),
200 };
201
202 SND_SOC_DAPM_MIXER("Output Mixer", WM8731_PWR, 4, 1, wm8731_output_mixer_controls,
203 ARRAY_SIZE(wm8731_output_mixer_controls)),
204
205 If you don't want the mixer elements prefixed with the name of the mixer widget,
206 you can use SND_SOC_DAPM_MIXER_NAMED_CTL instead. the parameters are the same
207 as for SND_SOC_DAPM_MIXER.
208
209
210 Machine domain Widgets
211 ----------------------
212
213 Machine widgets are different from codec widgets in that they don't have a
214 codec register bit associated with them. A machine widget is assigned to each
215 machine audio component (non codec or DSP) that can be independently
216 powered. e.g.
217
218 * Speaker Amp
219 * Microphone Bias
220 * Jack connectors
221
222 A machine widget can have an optional call back.
223
224 e.g. Jack connector widget for an external Mic that enables Mic Bias
225 when the Mic is inserted::
226
227 static int spitz_mic_bias(struct snd_soc_dapm_widget* w, int event)
228 {
229 gpio_set_value(SPITZ_GPIO_MIC_BIAS, SND_SOC_DAPM_EVENT_ON(event));
230 return 0;
231 }
232
233 SND_SOC_DAPM_MIC("Mic Jack", spitz_mic_bias),
234
235
236 Codec (BIAS) Domain
237 -------------------
238
239 The codec bias power domain has no widgets and is handled by the codec DAPM
240 event handler. This handler is called when the codec powerstate is changed wrt
241 to any stream event or by kernel PM events.
242
243
244 Virtual Widgets
245 ---------------
246
247 Sometimes widgets exist in the codec or machine audio graph that don't have any
248 corresponding soft power control. In this case it is necessary to create
249 a virtual widget - a widget with no control bits e.g.
250 ::
251
252 SND_SOC_DAPM_MIXER("AC97 Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
253
254 This can be used to merge two signal paths together in software.
255
256 Registering DAPM controls
257 =========================
258
259 In many cases the DAPM widgets are implemented statically in a ``static
260 const struct snd_soc_dapm_widget`` array in a codec driver, and simply
261 declared via the ``dapm_widgets`` and ``num_dapm_widgets`` fields of the
262 ``struct snd_soc_component_driver``.
263
264 Similarly, routes connecting them are implemented statically in a ``static
265 const struct snd_soc_dapm_route`` array and declared via the
266 ``dapm_routes`` and ``num_dapm_routes`` fields of the same struct.
267
268 With the above declared, the driver registration will take care of
269 populating them::
270
271 static const struct snd_soc_dapm_widget wm2000_dapm_widgets[] = {
272 SND_SOC_DAPM_OUTPUT("SPKN"),
273 SND_SOC_DAPM_OUTPUT("SPKP"),
274 ...
275 };
276
277 /* Target, Path, Source */
278 static const struct snd_soc_dapm_route wm2000_audio_map[] = {
279 { "SPKN", NULL, "ANC Engine" },
280 { "SPKP", NULL, "ANC Engine" },
281 ...
282 };
283
284 static const struct snd_soc_component_driver soc_component_dev_wm2000 = {
285 ...
286 .dapm_widgets = wm2000_dapm_widgets,
287 .num_dapm_widgets = ARRAY_SIZE(wm2000_dapm_widgets),
288 .dapm_routes = wm2000_audio_map,
289 .num_dapm_routes = ARRAY_SIZE(wm2000_audio_map),
290 ...
291 };
292
293 In more complex cases the list of DAPM widgets and/or routes can be only
294 known at probe time. This happens for example when a driver supports
295 different models having a different set of features. In those cases
296 separate widgets and routes arrays implementing the case-specific features
297 can be registered programmatically by calling snd_soc_dapm_new_controls()
298 and snd_soc_dapm_add_routes().
299
300
301 Codec/DSP Widget Interconnections
302 =================================
303
304 Widgets are connected to each other within the codec, platform and machine by
305 audio paths (called interconnections). Each interconnection must be defined in
306 order to create a graph of all audio paths between widgets.
307
308 This is easiest with a diagram of the codec or DSP (and schematic of the machine
309 audio system), as it requires joining widgets together via their audio signal
310 paths.
311
312 For example the WM8731 output mixer (wm8731.c) has 3 inputs (sources):
313
314 1. Line Bypass Input
315 2. DAC (HiFi playback)
316 3. Mic Sidetone Input
317
318 Each input in this example has a kcontrol associated with it (defined in
319 the example above) and is connected to the output mixer via its kcontrol
320 name. We can now connect the destination widget (wrt audio signal) with its
321 source widgets. ::
322
323 /* output mixer */
324 {"Output Mixer", "Line Bypass Switch", "Line Input"},
325 {"Output Mixer", "HiFi Playback Switch", "DAC"},
326 {"Output Mixer", "Mic Sidetone Switch", "Mic Bias"},
327
328 So we have:
329
330 * Destination Widget <=== Path Name <=== Source Widget, or
331 * Sink, Path, Source, or
332 * ``Output Mixer`` is connected to the ``DAC`` via the ``HiFi Playback Switch``.
333
334 When there is no path name connecting widgets (e.g. a direct connection) we
335 pass NULL for the path name.
336
337 Interconnections are created with a call to::
338
339 snd_soc_dapm_connect_input(codec, sink, path, source);
340
341 Finally, snd_soc_dapm_new_widgets() must be called after all widgets and
342 interconnections have been registered with the core. This causes the core to
343 scan the codec and machine so that the internal DAPM state matches the
344 physical state of the machine.
345
346
347 Machine Widget Interconnections
348 -------------------------------
349 Machine widget interconnections are created in the same way as codec ones and
350 directly connect the codec pins to machine level widgets.
351
352 e.g. connects the speaker out codec pins to the internal speaker.
353 ::
354
355 /* ext speaker connected to codec pins LOUT2, ROUT2 */
356 {"Ext Spk", NULL , "ROUT2"},
357 {"Ext Spk", NULL , "LOUT2"},
358
359 This allows the DAPM to power on and off pins that are connected (and in use)
360 and pins that are NC respectively.
361
362
363 Endpoint Widgets
364 ================
365 An endpoint is a start or end point (widget) of an audio signal within the
366 machine and includes the codec. e.g.
367
368 * Headphone Jack
369 * Internal Speaker
370 * Internal Mic
371 * Mic Jack
372 * Codec Pins
373
374 Endpoints are added to the DAPM graph so that their usage can be determined in
375 order to save power. e.g. NC codecs pins will be switched OFF, unconnected
376 jacks can also be switched OFF.
377
378
379 DAPM Widget Events
380 ==================
381
382 Widgets needing to implement a more complex behaviour than what DAPM can do
383 can set a custom "event handler" by setting a function pointer. An example
384 is a power supply needing to enable a GPIO::
385
386 static int sof_es8316_speaker_power_event(struct snd_soc_dapm_widget *w,
387 struct snd_kcontrol *kcontrol, int event)
388 {
389 if (SND_SOC_DAPM_EVENT_ON(event))
390 gpiod_set_value_cansleep(gpio_pa, true);
391 else
392 gpiod_set_value_cansleep(gpio_pa, false);
393
394 return 0;
395 }
396
397 static const struct snd_soc_dapm_widget st_widgets[] = {
398 ...
399 SND_SOC_DAPM_SUPPLY("Speaker Power", SND_SOC_NOPM, 0, 0,
400 sof_es8316_speaker_power_event,
401 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
402 };
403
404 See soc-dapm.h for all other widgets that support events.
405
406
407 Event types
408 -----------
409
410 The following event types are supported by event widgets::
411
412 /* dapm event types */
413 #define SND_SOC_DAPM_PRE_PMU 0x1 /* before widget power up */
414 #define SND_SOC_DAPM_POST_PMU 0x2 /* after widget power up */
415 #define SND_SOC_DAPM_PRE_PMD 0x4 /* before widget power down */
416 #define SND_SOC_DAPM_POST_PMD 0x8 /* after widget power down */
417 #define SND_SOC_DAPM_PRE_REG 0x10 /* before audio path setup */
418 #define SND_SOC_DAPM_POST_REG 0x20 /* after audio path setup */
419 #define SND_SOC_DAPM_WILL_PMU 0x40 /* called at start of sequence */
420 #define SND_SOC_DAPM_WILL_PMD 0x80 /* called at start of sequence */
421 #define SND_SOC_DAPM_PRE_POST_PMD (SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD)
422 #define SND_SOC_DAPM_PRE_POST_PMU (SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU)
423

3. 한국어 전문 번역

영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.

DAPM의 목적과 routing graph

1-41

Dynamic Audio Power Management(DAPM)는 휴대용 Linux 장치의 오디오 서브시스템이 항상 가능한 최소 전력을 사용하도록 설계됐다. 다른 kernel power management framework와 독립적이므로 함께 사용할 수 있다.

모든 power switching은 ASoC core 안에서 수행되므로 DAPM은 user space application에 완전히 투명하다. Application 코드 변경이나 재컴파일은 필요 없다. DAPM은 capture·playback stream activity와 장치의 audio mixer 설정을 바탕으로 전원 전환을 결정한다.

DAPM의 두 기본 요소는 widget과 route다. Widget은 사용 중 소프트웨어로 켜고 미사용 시 절전을 위해 끌 수 있는 모든 audio hardware 부분이다. Route는 sound가 한 widget에서 다른 widget으로 흐를 수 있을 때 존재하는 widget 사이의 연결이다.

DAPM은 sound card 전체에 걸친 audio routing graph를 조회해 전원 결정을 자동으로 내린다. 따라서 route는 서로 다른 component의 widget도 연결할 수 있다. 예를 들어 CODEC의 LINE OUT pin과 amplifier input pin을 잇는다.

원문의 `dapm-graph.svg`는 STM32MP1-DK1 sound card graph 예제다. `tools/sound/dapm-graph` utility로 각 sound card에 호환되는 graph를 만들 수 있다.

DAPM 기본 요소
요소정의전원 관리 의미
WidgetSoftware로 enable·disable 가능한 audio hardware 부분사용 경로에 있는 widget만 켬
RouteSound가 흐를 수 있는 widget 간 연결활성 path 계산에 사용

Routing graph를 구성하는 두 단위다.

Sound card 전역 DAPM graph
Capture / playback activityASoC core
Mixer settingsASoC core
CODEC LINE OUT widgetCross-component routeAmplifier input widgetSpeaker endpoint
ASoC coreRouting graph scanRequired widgets ONUnused widgets OFF

Component 경계를 넘어 실제 audio signal path 전체를 연결한다.

===================================================
Dynamic Audio Power Management for Portable Devices
===================================================

Description
===========

Dynamic Audio Power Management (DAPM) is designed to allow portable
Linux devices to use the minimum amount of power within the audio
subsystem at all times. It is independent of other kernel power
management frameworks and, as such, can easily co-exist with them.

DAPM is also completely transparent to all user space applications as
all power switching is done within the ASoC core. No code changes or
recompiling are required for user space applications. DAPM makes power
switching decisions based upon any audio stream (capture/playback)
activity and audio mixer settings within the device.

DAPM is based on two basic elements, called widgets and routes:

 * a **widget** is every part of the audio hardware that can be enabled by
   software when in use and disabled to save power when not in use
 * a **route** is an interconnection between widgets that exists when sound
   can flow from one widget to the other

All DAPM power switching decisions are made automatically by consulting an
audio routing graph. This graph is specific to each sound card and spans
the whole sound card, so some DAPM routes connect two widgets belonging to
different components (e.g. the LINE OUT pin of a CODEC and the input pin of
an amplifier).

The graph for the STM32MP1-DK1 sound card is shown in picture:

.. kernel-figure:: dapm-graph.svg
    :alt:   Example DAPM graph
    :align: center

You can also generate compatible graph for your sound card using
`tools/sound/dapm-graph` utility.

DAPM power domains

네 가지 DAPM power domain

42-72

Codec bias domain은 core codec 및 audio power인 VREF와 VMID를 다룬다. 보통 codec probe·remove와 suspend·resume에서 제어하지만 sidetone 등에 전원이 필요하지 않으면 stream 시점에 설정할 수도 있다.

Platform/Machine domain은 물리적으로 연결된 input과 output을 다룬다. Platform·machine 및 사용자 동작에 종속되며 machine driver가 구성한다. Headphone 삽입 같은 비동기 event에도 반응한다.

Path domain은 audio subsystem signal path를 다룬다. 사용자가 alsamixer나 amixer에서 mixer·mux 설정을 바꾸면 자동으로 설정된다. Stream domain은 DAC와 ADC를 다루며 aplay·arecord의 playback·capture 시작과 정지에 따라 각각 enable·disable된다.

DAPM power domain
Domain대상주요 전환 원인
Codec biasVREF, VMID, core codec·audio powerProbe/remove, suspend/resume, 필요 시 stream
Platform/Machine물리적 input·outputMachine 설정, jack 삽입 같은 비동기 event
PathAudio signal pathsMixer·mux control 변경
StreamDAC, ADCPlayback·capture 시작 및 정지

각 domain의 대상과 전환 원인을 비교한다.

Domain별 전원 결정 입력
Kernel PMCodec bias domain
Machine event / user actionPlatform/Machine domain
Mixer / mux settingsPath domain
aplay / arecord streamStream domain

각 domain은 서로 다른 상태 변화에 반응한다.

==================

There are 4 power domains within DAPM:

Codec bias domain
      VREF, VMID (core codec and audio power)

      Usually controlled at codec probe/remove and suspend/resume, although
      can be set at stream time if power is not needed for sidetone, etc.

Platform/Machine domain
      physically connected inputs and outputs

      Is platform/machine and user action specific, is configured by the
      machine driver and responds to asynchronous events e.g when HP
      are inserted

Path domain
      audio subsystem signal paths

      Automatically set when mixer and mux settings are changed by the user.
      e.g. alsamixer, amixer.

Stream domain
      DACs and ADCs.

      Enabled and disabled when stream playback/capture is started and
      stopped respectively. e.g. aplay, arecord.


DAPM Widgets

DAPM widget 종류와 공통 필드

73-151

Audio DAPM widget은 analog mixing과 선택, converter, physical pin·endpoint, power·clock supply, audio interface, DSP processing 등 여러 유형으로 나뉜다. 정의는 `include/sound/soc-dapm.h`에 있다.

어떤 component driver 유형도 sound card에 widget을 추가할 수 있다. `soc-dapm.h`의 편의 macro로 codec과 machine의 DAPM widget list를 빠르게 만들 수 있다. 대부분의 widget은 name, register, shift, invert를 가지며 일부는 stream name과 kcontrol 같은 추가 parameter도 갖는다.

Signal·converter widget
Widget역할
Mixer여러 analog signal을 하나로 혼합
Mux여러 input 중 하나만 출력하는 analog switch
PGAProgrammable gain·attenuation
ADCAnalog to Digital Converter
DACDigital to Analog Converter
SwitchAnalog switch
SiggenSignal Generator
SRCDSP·CODEC 내부 Sample Rate Converter
ASRCDSP·CODEC 내부 Asynchronous SRC

기본 analog·digital signal path를 구성하는 widget이다.

Pin·endpoint widget
Widget역할
Input / OutputCodec input·output pin
HeadphoneHeadphone 및 선택적 Jack
MicMicrophone 및 선택적 Jack
LineLine input/output 및 선택적 Jack
SpeakerSpeaker

Codec pin과 machine의 실제 입출력 요소다.

Supply·interface widget
Widget역할
Supply다른 widget이 쓰는 power 또는 clock supply
RegulatorAudio component용 external regulator
ClockAudio component용 external clock
AIF IN / AIF OUTTDM slot mask를 가진 Audio Interface input·output
DAI IN / DAI OUTDigital Audio Interface input·output
DAI Link두 DAI structure 사이의 link

전원·clock 공급과 digital audio interface를 나타낸다.

DSP·sequence widget
Widget역할
Pre / Post다른 widget 전·후에 실행되는 특수 widget
BufferDSP 내부 widget 사이 audio data buffer
SchedulerComponent·pipeline 처리 작업을 schedule
EffectAudio processing effect
EncoderPCM 등을 보통 더 압축된 format으로 encode
DecoderCompressed format을 PCM 같은 uncompressed format으로 decode

DSP 처리와 DAPM 실행 순서를 표현한다.

============

Audio DAPM widgets fall into a number of types:

Mixer
	Mixes several analog signals into a single analog signal.
Mux
	An analog switch that outputs only one of many inputs.
PGA
	A programmable gain amplifier or attenuation widget.
ADC
	Analog to Digital Converter
DAC
	Digital to Analog Converter
Switch
	An analog switch
Input
	A codec input pin
Output
	A codec output pin
Headphone
	Headphone (and optional Jack)
Mic
	Mic (and optional Jack)
Line
	Line Input/Output (and optional Jack)
Speaker
	Speaker
Supply
	Power or clock supply widget used by other widgets.
Regulator
	External regulator that supplies power to audio components.
Clock
	External clock that supplies clock to audio components.
AIF IN
	Audio Interface Input (with TDM slot mask).
AIF OUT
	Audio Interface Output (with TDM slot mask).
Siggen
	Signal Generator.
DAI IN
	Digital Audio Interface Input.
DAI OUT
	Digital Audio Interface Output.
DAI Link
	DAI Link between two DAI structures
Pre
	Special PRE widget (exec before all others)
Post
	Special POST widget (exec after all others)
Buffer
	Inter widget audio data buffer within a DSP.
Scheduler
	DSP internal scheduler that schedules component/pipeline processing
	work.
Effect
	Widget that performs an audio processing effect.
SRC
	Sample Rate Converter within DSP or CODEC
ASRC
	Asynchronous Sample Rate Converter within DSP or CODEC
Encoder
	Widget that encodes audio data from one format (usually PCM) to another
	usually more compressed format.
Decoder
	Widget that decodes audio data from a compressed format to an
	uncompressed format like PCM.


(Widgets are defined in include/sound/soc-dapm.h)

Widgets can be added to the sound card by any of the component driver types.
There are convenience macros defined in soc-dapm.h that can be used to quickly
build a list of widgets of the codecs and machines DAPM widgets.

Most widgets have a name, register, shift and invert. Some widgets have extra
parameters for stream name and kcontrols.

Stream domain widget

152-180

Stream widget은 stream power domain에 속하며 ADC, DAC, AIF IN, AIF OUT만 포함한다. `SND_SOC_DAPM_DAC()`와 `SND_SOC_DAPM_AIF_IN()` 같은 macro로 name, stream name, register, shift, invert와 AIF slot을 지정한다.

Stream name은 codec의 `snd_soc_dai_driver`에 있는 대응 stream name과 반드시 일치해야 한다. HiFi 예제는 `HiFi Playback` DAC와 `HiFi Capture` ADC를 만들고, AIF 예제는 `AIF1 Playback`의 `AIF1RX`와 `AIF1 Capture`의 `AIF1TX`를 `SND_SOC_NOPM` register로 만든다.

Stream widget macro
WidgetStreamMacro·비고
HiFi DACHiFi PlaybackSND_SOC_DAPM_DAC, REG bit 3
HiFi ADCHiFi CaptureSND_SOC_DAPM_ADC, REG bit 2
AIF1RXAIF1 PlaybackSND_SOC_DAPM_AIF_IN, slot 0, SND_SOC_NOPM
AIF1TXAIF1 CaptureSND_SOC_DAPM_AIF_OUT, slot 0, SND_SOC_NOPM

원문 예제의 widget과 stream name 연결이다.

Stream name 연결
snd_soc_dai_driver Playback streamMatching stream nameDAC / AIF IN widgetPlayback path power
snd_soc_dai_driver Capture streamMatching stream nameADC / AIF OUT widgetCapture path power

DAI stream activity가 같은 이름의 DAPM stream widget을 구동한다.

Stream Domain Widgets
---------------------

Stream Widgets relate to the stream power domain and only consist of ADCs
(analog to digital converters), DACs (digital to analog converters),
AIF IN and AIF OUT.

Stream widgets have the following format:
::

  SND_SOC_DAPM_DAC(name, stream name, reg, shift, invert),
  SND_SOC_DAPM_AIF_IN(name, stream, slot, reg, shift, invert)

NOTE: the stream name must match the corresponding stream name in your codec
snd_soc_dai_driver.

e.g. stream widgets for HiFi playback and capture
::

  SND_SOC_DAPM_DAC("HiFi DAC", "HiFi Playback", REG, 3, 1),
  SND_SOC_DAPM_ADC("HiFi ADC", "HiFi Capture", REG, 2, 1),

e.g. stream widgets for AIF
::

  SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
  SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0),

Path domain widget과 mixer control

181-209

Path domain widget은 audio subsystem 안에서 audio signal 또는 audio path를 제어하거나 변경한다. `SND_SOC_DAPM_PGA(name, reg, shift, invert, controls, num_controls)` 형식을 사용하며, widget kcontrol은 `controls`와 `num_controls` member로 지정한다.

WM8731 Output Mixer 예제는 `SOC_DAPM_SINGLE`로 `Line Bypass Switch`, `Mic Sidetone Switch`, `HiFi Playback Switch`를 먼저 선언하고, `SND_SOC_DAPM_MIXER`에 control array와 `ARRAY_SIZE()`를 전달한다.

Mixer element 이름 앞에 mixer widget 이름을 붙이고 싶지 않다면 같은 parameter를 받는 `SND_SOC_DAPM_MIXER_NAMED_CTL`을 사용할 수 있다.

WM8731 Output Mixer control
ControlRegister bitSignal source
Line Bypass SwitchWM8731_APANA bit 3Line bypass
Mic Sidetone SwitchWM8731_APANA bit 5Mic sidetone
HiFi Playback SwitchWM8731_APANA bit 4HiFi playback

각 path switch가 사용하는 WM8731_APANA bit다.

Mixer widget 구성
SOC_DAPM_SINGLE controlswm8731_output_mixer_controls[]SND_SOC_DAPM_MIXEROutput Mixer widget

Kcontrol을 먼저 정의하고 widget에 control array를 연결한다.

Path Domain Widgets
-------------------

Path domain widgets have a ability to control or affect the audio signal or
audio paths within the audio subsystem. They have the following form:
::

  SND_SOC_DAPM_PGA(name, reg, shift, invert, controls, num_controls)

Any widget kcontrols can be set using the controls and num_controls members.

e.g. Mixer widget (the kcontrols are declared first)
::

  /* Output Mixer */
  static const snd_kcontrol_new_t wm8731_output_mixer_controls[] = {
  SOC_DAPM_SINGLE("Line Bypass Switch", WM8731_APANA, 3, 1, 0),
  SOC_DAPM_SINGLE("Mic Sidetone Switch", WM8731_APANA, 5, 1, 0),
  SOC_DAPM_SINGLE("HiFi Playback Switch", WM8731_APANA, 4, 1, 0),
  };

  SND_SOC_DAPM_MIXER("Output Mixer", WM8731_PWR, 4, 1, wm8731_output_mixer_controls,
	ARRAY_SIZE(wm8731_output_mixer_controls)),

If you don't want the mixer elements prefixed with the name of the mixer widget,
you can use SND_SOC_DAPM_MIXER_NAMED_CTL instead. the parameters are the same
as for SND_SOC_DAPM_MIXER.

Machine domain widget

210-235

Machine widget은 codec register bit가 없다는 점에서 codec widget과 다르다. Codec이나 DSP가 아니면서 독립적으로 전원을 켤 수 있는 speaker amplifier, microphone bias, jack connector 같은 각 machine audio component에 machine widget을 배정한다.

Machine widget에는 선택적 callback을 둘 수 있다. 외부 microphone용 `Mic Jack` 예제는 mic 삽입 시 `spitz_mic_bias()`를 호출하고, `SND_SOC_DAPM_EVENT_ON(event)` 결과를 `SPITZ_GPIO_MIC_BIAS` GPIO 값으로 설정한다.

Machine widget 예
Component전원 제어 예
Speaker AmpAmplifier enable GPIO 또는 regulator
Microphone BiasBias supply GPIO
Jack connector삽입 event에 따른 optional callback

Register bit 밖의 board-level audio component다.

External Mic 삽입
Mic insertedMic Jack DAPM eventspitz_mic_bias()SPITZ_GPIO_MIC_BIAS ON

Jack event가 board-level microphone bias를 제어한다.

Machine domain Widgets
----------------------

Machine widgets are different from codec widgets in that they don't have a
codec register bit associated with them. A machine widget is assigned to each
machine audio component (non codec or DSP) that can be independently
powered. e.g.

* Speaker Amp
* Microphone Bias
* Jack connectors

A machine widget can have an optional call back.

e.g. Jack connector widget for an external Mic that enables Mic Bias
when the Mic is inserted::

  static int spitz_mic_bias(struct snd_soc_dapm_widget* w, int event)
  {
	gpio_set_value(SPITZ_GPIO_MIC_BIAS, SND_SOC_DAPM_EVENT_ON(event));
	return 0;
  }

  SND_SOC_DAPM_MIC("Mic Jack", spitz_mic_bias),

Codec bias domain과 virtual widget

236-256

Codec bias power domain에는 widget이 없고 codec DAPM event handler가 처리한다. 이 handler는 stream event 또는 kernel PM event로 codec power state가 바뀔 때 호출된다.

Codec 또는 machine audio graph에 실제 soft power control이 없는 요소가 존재할 수 있다. 이때 control bit가 없는 virtual widget을 만들어야 한다. 예제 `AC97 Mixer`는 register로 `SND_SOC_NOPM`을 사용하고 control 없이 두 signal path를 software에서 합친다.

Virtual widget 특성
항목설정
NameAC97 Mixer
RegisterSND_SOC_NOPM
ControlsNULL, 0
용도두 signal path의 software merge

실제 register power bit가 없는 graph node를 표현한다.

Codec (BIAS) Domain
-------------------

The codec bias power domain has no widgets and is handled by the codec DAPM
event handler. This handler is called when the codec powerstate is changed wrt
to any stream event or by kernel PM events.


Virtual Widgets
---------------

Sometimes widgets exist in the codec or machine audio graph that don't have any
corresponding soft power control. In this case it is necessary to create
a virtual widget - a widget with no control bits e.g.
::

  SND_SOC_DAPM_MIXER("AC97 Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),

This can be used to merge two signal paths together in software.

Registering DAPM controls

DAPM widget과 route 등록

257-300

많은 driver는 DAPM widget을 `static const struct snd_soc_dapm_widget` array로 구현하고 `struct snd_soc_component_driver`의 `dapm_widgets`, `num_dapm_widgets` field로 선언한다.

Route도 `static const struct snd_soc_dapm_route` array로 구현한 뒤 같은 component driver의 `dapm_routes`, `num_dapm_routes` field에 선언한다. 이렇게 하면 driver 등록 과정이 widget과 route를 자동으로 채운다.

WM2000 예제는 `SPKN`, `SPKP` output widget을 선언하고 두 output을 `ANC Engine` source에 직접 연결한다. Route tuple의 순서는 `Target, Path, Source`다.

지원 model에 따라 기능 집합이 달라지는 경우처럼 widget이나 route 목록을 probe 시점에만 알 수 있다면, case-specific array를 `snd_soc_dapm_new_controls()`와 `snd_soc_dapm_add_routes()`로 동적 등록한다.

정적 DAPM 등록 field
Field
dapm_widgetswm2000_dapm_widgets
num_dapm_widgetsARRAY_SIZE(wm2000_dapm_widgets)
dapm_routeswm2000_audio_map
num_dapm_routesARRAY_SIZE(wm2000_audio_map)

Component driver가 array와 개수를 함께 받는다.

정적·동적 등록
방식시점API·field
정적Compile timesnd_soc_component_driver field
동적 widgetProbe timesnd_soc_dapm_new_controls()
동적 routeProbe timesnd_soc_dapm_add_routes()

Widget·route 목록을 알 수 있는 시점에 따라 방식을 선택한다.

=========================

In many cases the DAPM widgets are implemented statically in a ``static
const struct snd_soc_dapm_widget`` array in a codec driver, and simply
declared via the ``dapm_widgets`` and ``num_dapm_widgets`` fields of the
``struct snd_soc_component_driver``.

Similarly, routes connecting them are implemented statically in a ``static
const struct snd_soc_dapm_route`` array and declared via the
``dapm_routes`` and ``num_dapm_routes`` fields of the same struct.

With the above declared, the driver registration will take care of
populating them::

  static const struct snd_soc_dapm_widget wm2000_dapm_widgets[] = {
  	SND_SOC_DAPM_OUTPUT("SPKN"),
  	SND_SOC_DAPM_OUTPUT("SPKP"),
  	...
  };

  /* Target, Path, Source */
  static const struct snd_soc_dapm_route wm2000_audio_map[] = {
  	{ "SPKN", NULL, "ANC Engine" },
  	{ "SPKP", NULL, "ANC Engine" },
	...
  };

  static const struct snd_soc_component_driver soc_component_dev_wm2000 = {
	...
  	.dapm_widgets		= wm2000_dapm_widgets,
  	.num_dapm_widgets	= ARRAY_SIZE(wm2000_dapm_widgets),
  	.dapm_routes            = wm2000_audio_map,
  	.num_dapm_routes        = ARRAY_SIZE(wm2000_audio_map),
	...
  };

In more complex cases the list of DAPM widgets and/or routes can be only
known at probe time. This happens for example when a driver supports
different models having a different set of features. In those cases
separate widgets and routes arrays implementing the case-specific features
can be registered programmatically by calling snd_soc_dapm_new_controls()
and snd_soc_dapm_add_routes().

Codec·DSP widget interconnection

301-346

Codec, platform, machine 안의 widget은 interconnection이라고 부르는 audio path로 서로 연결된다. 모든 widget 사이의 audio path graph를 만들려면 각 interconnection을 정의해야 한다. Codec·DSP block diagram과 machine audio schematic을 이용해 signal path대로 widget을 연결하는 것이 가장 쉽다.

WM8731 Output Mixer에는 Line Bypass Input, DAC(HiFi playback), Mic Sidetone Input 세 source가 있다. 각 input은 앞서 정의한 kcontrol 이름을 통해 output mixer에 연결된다.

Route는 `Destination Widget <=== Path Name <=== Source Widget`, 즉 `Sink, Path, Source` 순서다. 따라서 `Output Mixer`는 `HiFi Playback Switch`를 통해 `DAC`에 연결된다. 직접 연결처럼 path name이 없으면 `NULL`을 전달한다.

원문은 interconnection 생성 호출로 `snd_soc_dapm_connect_input(codec, sink, path, source)`를 제시한다. 모든 widget과 interconnection을 core에 등록한 뒤 `snd_soc_dapm_new_widgets()`를 호출해야 한다. Core가 codec과 machine을 scan해 내부 DAPM 상태를 machine의 물리 상태와 맞춘다.

WM8731 Output Mixer route
DestinationPathSource
Output MixerLine Bypass SwitchLine Input
Output MixerHiFi Playback SwitchDAC
Output MixerMic Sidetone SwitchMic Bias

Destination, path control, source의 순서를 보존한다.

Interconnection 등록 순서
Define widgetsDefine Sink·Path·Source routesRegister with ASoC coresnd_soc_dapm_new_widgets()Scan codec + machineState synchronized

Graph를 정의한 뒤 새 widget scan으로 논리 상태를 물리 상태에 맞춘다.

Codec/DSP Widget Interconnections
=================================

Widgets are connected to each other within the codec, platform and machine by
audio paths (called interconnections). Each interconnection must be defined in
order to create a graph of all audio paths between widgets.

This is easiest with a diagram of the codec or DSP (and schematic of the machine
audio system), as it requires joining widgets together via their audio signal
paths.

For example the WM8731 output mixer (wm8731.c) has 3 inputs (sources):

1. Line Bypass Input
2. DAC (HiFi playback)
3. Mic Sidetone Input

Each input in this example has a kcontrol associated with it (defined in
the example above) and is connected to the output mixer via its kcontrol
name. We can now connect the destination widget (wrt audio signal) with its
source widgets.  ::

	/* output mixer */
	{"Output Mixer", "Line Bypass Switch", "Line Input"},
	{"Output Mixer", "HiFi Playback Switch", "DAC"},
	{"Output Mixer", "Mic Sidetone Switch", "Mic Bias"},

So we have:

* Destination Widget  <=== Path Name <=== Source Widget, or
* Sink, Path, Source, or
* ``Output Mixer`` is connected to the ``DAC`` via the ``HiFi Playback Switch``.

When there is no path name connecting widgets (e.g. a direct connection) we
pass NULL for the path name.

Interconnections are created with a call to::

  snd_soc_dapm_connect_input(codec, sink, path, source);

Finally, snd_soc_dapm_new_widgets() must be called after all widgets and
interconnections have been registered with the core. This causes the core to
scan the codec and machine so that the internal DAPM state matches the
physical state of the machine.

Machine widget interconnection

347-362

Machine widget interconnection도 codec과 같은 방식으로 만들며 codec pin을 machine-level widget에 직접 연결한다.

예제는 codec output pin `ROUT2`, `LOUT2`를 내부 speaker인 `Ext Spk`에 path name `NULL`로 연결한다. 그러면 DAPM은 연결되어 사용 중인 pin은 켜고 NC인 pin은 끌 수 있다.

External speaker route
DestinationPathSource
Ext SpkNULLROUT2
Ext SpkNULLLOUT2

두 codec output pin이 하나의 machine speaker endpoint로 연결된다.

Codec pin에서 machine speaker로
ROUT2Direct routeExt Spk
LOUT2Direct routeExt Spk

직접 route이므로 path control 이름은 없다.

Machine Widget Interconnections
-------------------------------
Machine widget interconnections are created in the same way as codec ones and
directly connect the codec pins to machine level widgets.

e.g. connects the speaker out codec pins to the internal speaker.
::

	/* ext speaker connected to codec pins LOUT2, ROUT2  */
	{"Ext Spk", NULL , "ROUT2"},
	{"Ext Spk", NULL , "LOUT2"},

This allows the DAPM to power on and off pins that are connected (and in use)
and pins that are NC respectively.

Endpoint widget

363-379

Endpoint는 codec을 포함한 machine 안에서 audio signal의 시작점 또는 끝점인 widget이다. Headphone Jack, Internal Speaker, Internal Mic, Mic Jack, Codec Pin이 여기에 포함된다.

Endpoint를 DAPM graph에 넣으면 사용 여부를 판단해 전력을 절약할 수 있다. 연결되지 않은 codec pin과 jack은 끌 수 있다.

DAPM endpoint
Endpoint대표 방향
Headphone JackPlayback sink
Internal SpeakerPlayback sink
Internal MicCapture source
Mic JackCapture source
Codec PinsMachine graph 연결점

Audio signal path의 실제 시작·종료 지점이다.

Endpoint Widgets
================
An endpoint is a start or end point (widget) of an audio signal within the
machine and includes the codec. e.g.

* Headphone Jack
* Internal Speaker
* Internal Mic
* Mic Jack
* Codec Pins

Endpoints are added to the DAPM graph so that their usage can be determined in
order to save power. e.g. NC codecs pins will be switched OFF, unconnected
jacks can also be switched OFF.


DAPM Widget Events

Custom DAPM widget event

380-407

DAPM 기본 기능보다 복잡한 동작이 필요한 widget은 function pointer로 custom event handler를 설정할 수 있다. 예를 들어 power supply가 GPIO를 enable해야 할 수 있다.

`sof_es8316_speaker_power_event()`는 `SND_SOC_DAPM_EVENT_ON(event)`가 참이면 `gpio_pa`를 true로, 아니면 false로 설정한다. `gpiod_set_value_cansleep()`을 사용하므로 sleep 가능한 GPIO context를 처리한다.

`Speaker Power` supply widget은 register power bit가 없는 `SND_SOC_NOPM`을 사용하고, `SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU` event에서 callback을 실행한다. Event를 지원하는 다른 widget은 `soc-dapm.h`에서 확인한다.

Speaker Power event
Event conditionGPIO 동작
SND_SOC_DAPM_EVENT_ON(event)gpiod_set_value_cansleep(gpio_pa, true)
그 외gpiod_set_value_cansleep(gpio_pa, false)

Power sequence 전후의 GPIO amplifier 제어다.

Supply widget custom event
POST_PMUsof_es8316_speaker_power_event()gpio_pa trueSpeaker amplifier ON
PRE_PMDsof_es8316_speaker_power_event()gpio_pa falseSpeaker amplifier OFF

DAPM power sequence가 board-level GPIO를 제어한다.

==================

Widgets needing to implement a more complex behaviour than what DAPM can do
can set a custom "event handler" by setting a function pointer. An example
is a power supply needing to enable a GPIO::

  static int sof_es8316_speaker_power_event(struct snd_soc_dapm_widget *w,
  					  struct snd_kcontrol *kcontrol, int event)
  {
  	if (SND_SOC_DAPM_EVENT_ON(event))
  		gpiod_set_value_cansleep(gpio_pa, true);
  	else
  		gpiod_set_value_cansleep(gpio_pa, false);

  	return 0;
  }

  static const struct snd_soc_dapm_widget st_widgets[] = {
  	...
  	SND_SOC_DAPM_SUPPLY("Speaker Power", SND_SOC_NOPM, 0, 0,
  			    sof_es8316_speaker_power_event,
  			    SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
  };

See soc-dapm.h for all other widgets that support events.


Event types

DAPM event type

408-422

Event widget은 power up·down 전후, audio path register 설정 전후, sequence 시작 시점을 나타내는 bit flag를 지원한다.

`PRE_PMU`와 `POST_PMU`는 widget power up 전·후, `PRE_PMD`와 `POST_PMD`는 power down 전·후다. `PRE_REG`와 `POST_REG`는 audio path 설정 전·후이며, `WILL_PMU`와 `WILL_PMD`는 각 sequence 시작 시 호출된다. `PRE_POST_PMD`와 `PRE_POST_PMU`는 전·후 flag를 묶은 조합이다.

DAPM event flag
상수호출 시점
SND_SOC_DAPM_PRE_PMU0x1Widget power up 전
SND_SOC_DAPM_POST_PMU0x2Widget power up 후
SND_SOC_DAPM_PRE_PMD0x4Widget power down 전
SND_SOC_DAPM_POST_PMD0x8Widget power down 후
SND_SOC_DAPM_PRE_REG0x10Audio path 설정 전
SND_SOC_DAPM_POST_REG0x20Audio path 설정 후
SND_SOC_DAPM_WILL_PMU0x40Power-up sequence 시작
SND_SOC_DAPM_WILL_PMD0x80Power-down sequence 시작
SND_SOC_DAPM_PRE_POST_PMDPRE_PMD | POST_PMDPower down 전·후
SND_SOC_DAPM_PRE_POST_PMUPRE_PMU | POST_PMUPower up 전·후

원문 상수와 호출 시점을 모두 보존한다.

Widget power event 순서
WILL_PMUPRE_PMUWidget power ONPOST_PMU
WILL_PMDPRE_PMDWidget power OFFPOST_PMD

Power-up과 power-down sequence에서 callback이 실행되는 위치다.

-----------

The following event types are supported by event widgets::

  /* dapm event types */
  #define SND_SOC_DAPM_PRE_PMU		0x1	/* before widget power up */
  #define SND_SOC_DAPM_POST_PMU		0x2	/* after  widget power up */
  #define SND_SOC_DAPM_PRE_PMD		0x4	/* before widget power down */
  #define SND_SOC_DAPM_POST_PMD		0x8	/* after  widget power down */
  #define SND_SOC_DAPM_PRE_REG		0x10	/* before audio path setup */
  #define SND_SOC_DAPM_POST_REG		0x20	/* after  audio path setup */
  #define SND_SOC_DAPM_WILL_PMU		0x40	/* called at start of sequence */
  #define SND_SOC_DAPM_WILL_PMD		0x80	/* called at start of sequence */
  #define SND_SOC_DAPM_PRE_POST_PMD	(SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD)
  #define SND_SOC_DAPM_PRE_POST_PMU	(SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU)