요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
===================================================
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
==================
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
============
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 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 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 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
-------------------
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
=========================
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 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 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 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
==================
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
-----------
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)
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
DAPM의 목적과 routing graph
1-41Dynamic 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를 만들 수 있다.
Routing graph를 구성하는 두 단위다.
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-72Codec 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된다.
각 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-151Audio 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도 갖는다.
기본 analog·digital signal path를 구성하는 widget이다.
Codec pin과 machine의 실제 입출력 요소다.
전원·clock 공급과 digital audio interface를 나타낸다.
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-180Stream 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로 만든다.
원문 예제의 widget과 stream name 연결이다.
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-209Path 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`을 사용할 수 있다.
각 path switch가 사용하는 WM8731_APANA bit다.
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-235Machine 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 값으로 설정한다.
Register bit 밖의 board-level audio component다.
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-256Codec 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에서 합친다.
실제 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()`로 동적 등록한다.
Component driver가 array와 개수를 함께 받는다.
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-346Codec, 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의 물리 상태와 맞춘다.
Destination, path control, source의 순서를 보존한다.
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-362Machine widget interconnection도 codec과 같은 방식으로 만들며 codec pin을 machine-level widget에 직접 연결한다.
예제는 codec output pin `ROUT2`, `LOUT2`를 내부 speaker인 `Ext Spk`에 path name `NULL`로 연결한다. 그러면 DAPM은 연결되어 사용 중인 pin은 켜고 NC인 pin은 끌 수 있다.
두 codec output pin이 하나의 machine speaker endpoint로 연결된다.
직접 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-379Endpoint는 codec을 포함한 machine 안에서 audio signal의 시작점 또는 끝점인 widget이다. Headphone Jack, Internal Speaker, Internal Mic, Mic Jack, Codec Pin이 여기에 포함된다.
Endpoint를 DAPM graph에 넣으면 사용 여부를 판단해 전력을 절약할 수 있다. 연결되지 않은 codec pin과 jack은 끌 수 있다.
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-407DAPM 기본 기능보다 복잡한 동작이 필요한 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`에서 확인한다.
Power sequence 전후의 GPIO amplifier 제어다.
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-422Event 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를 묶은 조합이다.
원문 상수와 호출 시점을 모두 보존한다.
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)
요약·해설
dapm.rst:1-422ASoC DAPM이 sound card 전체 routing graph의 widget·route를 바탕으로 codec bias, machine, path, stream 전원을 자동 관리하는 원리를 설명합니다. Widget 유형, 정적·동적 등록, codec·machine interconnection, endpoint, custom event와 power sequence flag를 원문 코드 좌표와 함께 정리합니다.