DAPM

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 PM and as such, can easily co-exist with the other PM systems.

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 spans the whole machine. It covers power control within the entire audio subsystem, this includes internal codec power blocks and machine level power systems.

There are 4 power domains within DAPM:

Codec 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

Stream domain – DAC's and ADC's. Enabled and disabled when stream playback/capture is started and stopped respectively. e.g. aplay, arecord.

All DAPM power switching decisions are made automatically by consulting an audio routing map of the whole machine. This map is specific to each machine and consists of the interconnections between every audio component (including internal codec components).

DAPM Widgets

CODEC Domain Widgets

SND_SOC_DAPM_VMID(wname)

This defines a Vmid rail, otherwise called a Vref or common mode voltage.

Parameter

Type

Description

wname

const char*

Name to give to the widget.

Platform Domain Widgets

SND_SOC_DAPM_INPUT(wname)

This defines an audio signal input on the CODEC chip, such as a line level or microphone input. This is typically wired up to a MIC or LINE widget in the machine driver.

Parameter

Type

Description

wname

const char*

Name to give to the widget.

SND_SOC_DAPM_OUTPUT(wname)

This defines an audio signal output on the CODEC chip, such as a headphone driver or line level output driver. This is typically wired up to a line output jack (LINE), headphone output (HP), or internal speaker (SPK).

Parameter

Type

Description

wname

const char*

Name to give to the widget.

SND_SOC_DAPM_MIC(wname, wevent)

These widgets define physical microphone connection jacks. They are typically wired up via the signal routing to one of the INPUT pins on the CODEC. The constructor may be passed a pointer to an event handler function in case a microphone bias has to be connected up just before recording begins, for example.

SND_SOC_DAPM_SWITCH(wname, wreg, wshift, winvert, wcontrols)

SND_SOC_DAPM_MUX(wname, wreg, wshift, winvert, wcontrols)

SND_SOC_DAPM_VALUE_MUX(wname, wreg, wshift, winvert, wcontrols)

Pre-DAPM and Post-DAPM event widgets

These are generic widgets that are run immediately before, or after a DAPM run.

SND_SOC_DAPM_PRE(wname, wevent)

SND_SOC_DAPM_POST(wname, wevent)

Stream Domain Widgets

SND_SOC_DAPM_AIF_IN(wname, stname, wslot, wreg, wshift, winvert)

The audio interface input. This defines the connection to the host that receives the audio to be passed into the DAC(s).

TODO: further explanation.

SND_SOC_DAPM_AIF_OUT(wname, stname, wslot, wreg, wshift, winvert)

The audio interface output. This defines the connection to the host that transmits the audio received from the ADC(s).

TODO: further explanation.

SND_SOC_DAPM_DAC(wname, stname, wreg, wshift, winvert)

The DAC widget is used to control powering up and shutdown of the DAC on an as-needed basis. It is typically associated with a stream on the device, e.g. "Left Playback" or "Right Playback", and the register settings define a single register and bit position that, when flipped, will turn the DAC on or off.

The stream name _must_ match one of the names given in the snd_soc_dai structure for your CODEC, with an optional channel prefix label (e.g. "Left Playback").

There is a version of this, SND_SOC_DAPM_DAC_E that can also take an event handler pointer.

Parameter

Type

Description

wname

const char*

Name to give to the widget.

stname

const char*

Name of an associated audio data stream (e.g. "Left Playback")

wreg

unsigned int

Register to modify when turning the DAC on or off

wshift

unsigned int

Bit in register to modify when turning the DAC on or off

winvert

unsigned int

Is the control inverted? If set to 1, setting the bit turns the DAC off

SND_SOC_DAPM_ADC(wname, stname, wreg, wshift, winvert)

The ADC widget is used to control powering up and shutdown of the ADC on an as-needed basis. It is typically associated with a stream on the device, e.g. "Left Capture" or "Right Capture", and the register settings define a single register and bit position that, when flipped, will turn the ADC on or off.

The stream name _must_ match one of the names given in the snd_soc_dai structure for your CODEC, with an optional channel prefix label (e.g. "Left Playback").

There is a version of this, SND_SOC_DAPM_ADC_E that can also take an event handler pointer.

Parameter

Type

Description

wname

const char*

Name to give to the widget.

stname

const char*

Name of an associated audio data stream (e.g. "Left Capture")

wreg

unsigned int

Register to modify when turning the ADC on or off

wshift

unsigned int

Bit in register to modify when turning the ADC on or off

winvert

unsigned int

Is the control inverted? If set to 1, setting the bit turns the ADC off

Generic widgets

SND_SOC_DAPM_REG(wid, wname, wreg, wshift, wmask, won_val, woff_val)

SND_SOC_DAPM_SUPPLY(wname, wreg, wshift, winvert, wevent, wflags)

Control Types

For some widgets such as multiplexers, mixers and switches, they take either a single control, or an array of controls as an argument to their constructors. DAPM provides a variety of different controls to suit various requirements. These are extended versions of their standard ASoC cousins.

SOC_DAPM_SINGLE(xname, reg, shift, max, invert)

Represents a single integer parameter, such as the mute bit in a volume register. The parameter is not scaled.

SOC_DAPM_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array)

SOC_DAPM_ENUM(xname, xenum)

SOC_DAPM_ENUM_VIRT(xname, xenum)

SOC_DAPM_VALUE_ENUM(xname, xenum)

SOC_DAPM_PIN_SWITCH(xname)

Event Handlers

A number of these widgets can take a pointer to an event handler, and in some cases, flags that indicate when this event handler is triggered. An example of an event handler is to power up and down the speaker amplifier on the Corgi.

The event argument tells the function whether you're powering up or down. SND_SOC_DAPM_EVENT_ON is a macro, who's value is non-zero when the event is a power-up event. Thus, it can be fed straight to the GPIO handler as shown here.

When things don't work

DAPM relies heavily on a complete mapping of all widgets in the audio subsystem. If a DAC does not have a path from its output, to an output pin somewhere, it will not turn the DAC on. On some CODECs (such as the TLV320AIC3204) this means no clocks, and your audio interface bus will play dead.

When the audio map is registered with DAPM, the SOC DAPM core checks through, and builds up a runtime map of all the widgets. If it fails to find a widget, DAPM stops mapping out the audio system. If you're finding that DAPM isn't "seeing" a mapping, double check the names of all widgets for mistakes ... on complex CODECs with many routing options, it may take days to figure out that the reason a DAC isn't getting turned on for you, is because the name of a widget that connects an input pin to the ADC was mistyped, or something equally obscure.