Difference between revisions of "DAPM"

From AlsaProject
Jump to: navigation, search
(copied from https://bugtrack.alsa-project.org/wiki/wikka.php?wakka=DAPM)
 
m (SND_SOC_DAPM_VMID(wname): sup? I meant sub of course!)
 
(One intermediate revision by one user not shown)
Line 1: Line 1:
 
'''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.
 
'''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 descisions based upon any audio stream (capture/playback) activity and audio mixer settings within the device.
+
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.
 
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.
Line 8: Line 8:
 
# ''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.
 
# ''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
 
# ''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 susbsystem signal paths. Automatically set when mixer and mux settings are changed by the user. e.g. alsamixer, amixer.
+
# ''Path domain'' – audio subsystem signal paths. Automatically set when mixer and mux settings are changed by the user. e.g. alsamixer, amixer.
 
# ''Stream domain'' – DAC's and ADC's. Enabled and disabled when stream playback/capture is started and stopped respectively. e.g. aplay, arecord.
 
# ''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 descisons 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).
+
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 =
 +
 
 +
All DAPM widgets are listed under <tt>include/sound/soc-dapm.h</tt>.
 +
 
 +
== CODEC Domain Widgets ==
 +
 
 +
=== SND_SOC_DAPM_VMID(wname) ===
 +
 
 +
This defines a V<sub>mid</sub> rail, otherwise called a V<sub>ref</sub> or common mode voltage.
 +
 
 +
{|
 +
! Parameter
 +
! Type
 +
! Description
 +
|-
 +
| <tt>wname</tt>
 +
| <tt>const char*</tt>
 +
| 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
 +
|-
 +
| <tt>wname</tt>
 +
| <tt>const char*</tt>
 +
| 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
 +
|-
 +
| <tt>wname</tt>
 +
| <tt>const char*</tt>
 +
| 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.
 +
 
 +
{|
 +
! Parameter
 +
! Type
 +
! Description
 +
|-
 +
| <tt>wname</tt>
 +
| <tt>const char*</tt>
 +
| Name to give to the widget.
 +
|-
 +
| <tt>wevent</tt>
 +
| see example below
 +
| Function to call in case of event changes, or <tt>NULL</tt>.
 +
|}
 +
 
 +
See the next section for details on the event handler.
 +
 
 +
=== SND_SOC_DAPM_HP(wname, wevent) ===
 +
TODO
 +
 
 +
=== SND_SOC_DAPM_SPK(wname, wevent) ===
 +
TODO
 +
 
 +
=== SND_SOC_DAPM_LINE(wname, wevent) ===
 +
TODO
 +
 
 +
== Path domain widgets ==
 +
 
 +
=== SND_SOC_DAPM_PGA(wname, wreg, wshift, winvert, wcontrols, wncontrols) ===
 +
==== SOC_PGA_ARRAY(wname, wreg, wshift, winvert, wcontrols) ====
 +
=== SND_SOC_DAPM_MIXER(wname, wreg, wshift, winvert, wcontrols, wncontrols) ===
 +
==== SND_SOC_DAPM_MIXER_NAMED_CTL(wname, wreg, wshift, winvert, wcontrols, wncontrols) ====
 +
=== SND_SOC_DAPM_MICBIAS(wname, wreg, wshift, winvert) ===
 +
=== 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 <tt>snd_soc_dai</tt> structure for your CODEC, with an optional channel prefix label (e.g. <tt>"Left Playback"</tt>).
 +
 
 +
There is a version of this, <tt>SND_SOC_DAPM_DAC_E</tt> that can also take an event handler pointer.
 +
 
 +
{|
 +
! Parameter
 +
! Type
 +
! Description
 +
|-
 +
| <tt>wname</tt>
 +
| <tt>const char*</tt>
 +
| Name to give to the widget.
 +
|-
 +
| <tt>stname</tt>
 +
| <tt>const char*</tt>
 +
| Name of an associated audio data stream (e.g. <tt>"Left Playback"</tt>)
 +
|-
 +
| <tt>wreg</tt>
 +
| <tt>unsigned int</tt>
 +
| Register to modify when turning the DAC on or off
 +
|-
 +
| <tt>wshift</tt>
 +
| <tt>unsigned int</tt>
 +
| Bit in register to modify when turning the DAC on or off
 +
|-
 +
| <tt>winvert</tt>
 +
| <tt>unsigned int</tt>
 +
| Is the control inverted?  If set to <tt>1</tt>, 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 <tt>snd_soc_dai</tt> structure for your CODEC, with an optional channel prefix label (e.g. <tt>"Left Playback"</tt>).
 +
 
 +
There is a version of this, <tt>SND_SOC_DAPM_ADC_E</tt> that can also take an event handler pointer.
 +
 
 +
{|
 +
! Parameter
 +
! Type
 +
! Description
 +
|-
 +
| <tt>wname</tt>
 +
| <tt>const char*</tt>
 +
| Name to give to the widget.
 +
|-
 +
| <tt>stname</tt>
 +
| <tt>const char*</tt>
 +
| Name of an associated audio data stream (e.g. <tt>"Left Capture"</tt>)
 +
|-
 +
| <tt>wreg</tt>
 +
| <tt>unsigned int</tt>
 +
| Register to modify when turning the ADC on or off
 +
|-
 +
| <tt>wshift</tt>
 +
| <tt>unsigned int</tt>
 +
| Bit in register to modify when turning the ADC on or off
 +
|-
 +
| <tt>winvert</tt>
 +
| <tt>unsigned int</tt>
 +
| Is the control inverted?  If set to <tt>1</tt>, 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.
 +
 
 +
{|
 +
! Parameter
 +
! Type
 +
! Description
 +
|-
 +
| <tt>xname</tt>
 +
| <tt>const char*</tt>
 +
| Name to give to the widget.
 +
|-
 +
| <tt>reg</tt>
 +
| <tt>unsigned int</tt>
 +
| Register associated with control
 +
|-
 +
| <tt>shift</tt>
 +
| <tt>unsigned int</tt>
 +
| Bit offset for control value
 +
|-
 +
| <tt>max</tt>
 +
| <tt>unsigned int</tt>
 +
| Maximum allowable value for control (the mask is derived from this)
 +
|-
 +
| <tt>invert</tt>
 +
| <tt>unsigned int</tt>
 +
| Is the control inverted?
 +
|}
 +
 
 +
=== SOC_DAPM_DOUBLE(xname, reg, shift_left, shift_right, max, invert, power) ===
 +
 
 +
Represents a pair of integer parameters, one associated with the left channel, and the other associated with the right channel.
 +
 
 +
{|
 +
! Parameter
 +
! Type
 +
! Description
 +
|-
 +
| <tt>xname</tt>
 +
| <tt>const char*</tt>
 +
| Name to give to the widget.
 +
|-
 +
| <tt>reg</tt>
 +
| <tt>unsigned int</tt>
 +
| Register associated with control
 +
|-
 +
| <tt>shift_left</tt>
 +
| <tt>unsigned int</tt>
 +
| Bit offset for left channel control value
 +
|-
 +
| <tt>shift_right</tt>
 +
| <tt>unsigned int</tt>
 +
| Bit offset for right channel control value
 +
|-
 +
| <tt>max</tt>
 +
| <tt>unsigned int</tt>
 +
| Maximum allowable value for control (the mask is derived from this)
 +
|-
 +
| <tt>invert</tt>
 +
| <tt>unsigned int</tt>
 +
| Is the control inverted?
 +
|-
 +
| <tt>power</tt>
 +
| ???
 +
| This doesn't appear to be used according to the macro definition
 +
|}
 +
 
 +
=== SOC_DAPM_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) ===
 +
=== SOC_DAPM_DOUBLE_TLV(xname, reg, shift_left, shift_right, max, invert, power, 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.
 +
 
 +
<source lang="c">
 +
static int corgi_amp_event(struct snd_soc_dapm_widget *w,
 +
struct snd_kcontrol *k, int event)
 +
{
 +
gpio_set_value(CORGI_GPIO_APM_ON, SND_SOC_DAPM_EVENT_ON(event));
 +
return 0;
 +
}
 +
</source>
 +
 
 +
The <tt>event</tt> argument tells the function whether you're powering up or down.  <tt>SND_SOC_DAPM_EVENT_ON</tt> 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.
 +
 
 +
This is registered with DAPM in the speaker handler:
 +
<source lang="c">
 +
/* corgi machine dapm widgets */
 +
static const struct snd_soc_dapm_widget wm8731_dapm_widgets[] = {
 +
SND_SOC_DAPM_HP("Headphone Jack", NULL),
 +
SND_SOC_DAPM_MIC("Mic Jack", corgi_mic_event),
 +
SND_SOC_DAPM_SPK("Ext Spk", corgi_amp_event),
 +
SND_SOC_DAPM_LINE("Line Jack", NULL),
 +
SND_SOC_DAPM_HP("Headset Jack", NULL),
 +
};
 +
</source>
 +
 
 +
= 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.
  
 
[[Category:Development]]
 
[[Category:Development]]
 
[[Category:MigratedFromDev]]
 
[[Category:MigratedFromDev]]

Latest revision as of 09:45, 11 June 2010

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:

  1. 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.
  2. 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
  3. Path domain – audio subsystem signal paths. Automatically set when mixer and mux settings are changed by the user. e.g. alsamixer, amixer.
  4. 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).

Contents

[edit] DAPM Widgets

All DAPM widgets are listed under include/sound/soc-dapm.h.

[edit] CODEC Domain Widgets

[edit] 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.

[edit] Platform Domain Widgets

[edit] 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.

[edit] 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.

[edit] 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.

Parameter Type Description
wname const char* Name to give to the widget.
wevent see example below Function to call in case of event changes, or NULL.

See the next section for details on the event handler.

[edit] SND_SOC_DAPM_HP(wname, wevent)

TODO

[edit] SND_SOC_DAPM_SPK(wname, wevent)

TODO

[edit] SND_SOC_DAPM_LINE(wname, wevent)

TODO

[edit] Path domain widgets

[edit] SND_SOC_DAPM_PGA(wname, wreg, wshift, winvert, wcontrols, wncontrols)

[edit] SOC_PGA_ARRAY(wname, wreg, wshift, winvert, wcontrols)

[edit] SND_SOC_DAPM_MIXER(wname, wreg, wshift, winvert, wcontrols, wncontrols)

[edit] SND_SOC_DAPM_MIXER_NAMED_CTL(wname, wreg, wshift, winvert, wcontrols, wncontrols)

[edit] SND_SOC_DAPM_MICBIAS(wname, wreg, wshift, winvert)

[edit] SND_SOC_DAPM_SWITCH(wname, wreg, wshift, winvert, wcontrols)

[edit] SND_SOC_DAPM_MUX(wname, wreg, wshift, winvert, wcontrols)

[edit] SND_SOC_DAPM_VALUE_MUX(wname, wreg, wshift, winvert, wcontrols)

[edit] Pre-DAPM and Post-DAPM event widgets

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

[edit] SND_SOC_DAPM_PRE(wname, wevent)

[edit] SND_SOC_DAPM_POST(wname, wevent)

[edit] Stream Domain Widgets

[edit] 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.

[edit] 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.

[edit] 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

[edit] 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

[edit] Generic widgets

[edit] SND_SOC_DAPM_REG(wid, wname, wreg, wshift, wmask, won_val, woff_val)

[edit] SND_SOC_DAPM_SUPPLY(wname, wreg, wshift, winvert, wevent, wflags)

[edit] 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.

[edit] 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.

Parameter Type Description
xname const char* Name to give to the widget.
reg unsigned int Register associated with control
shift unsigned int Bit offset for control value
max unsigned int Maximum allowable value for control (the mask is derived from this)
invert unsigned int Is the control inverted?

[edit] SOC_DAPM_DOUBLE(xname, reg, shift_left, shift_right, max, invert, power)

Represents a pair of integer parameters, one associated with the left channel, and the other associated with the right channel.

Parameter Type Description
xname const char* Name to give to the widget.
reg unsigned int Register associated with control
shift_left unsigned int Bit offset for left channel control value
shift_right unsigned int Bit offset for right channel control value
max unsigned int Maximum allowable value for control (the mask is derived from this)
invert unsigned int Is the control inverted?
power  ??? This doesn't appear to be used according to the macro definition

[edit] SOC_DAPM_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array)

[edit] SOC_DAPM_DOUBLE_TLV(xname, reg, shift_left, shift_right, max, invert, power, tlv_array)

[edit] SOC_DAPM_ENUM(xname, xenum)

[edit] SOC_DAPM_ENUM_VIRT(xname, xenum)

[edit] SOC_DAPM_VALUE_ENUM(xname, xenum)

[edit] SOC_DAPM_PIN_SWITCH(xname)

[edit] 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.

<source lang="c"> static int corgi_amp_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k, int event) { gpio_set_value(CORGI_GPIO_APM_ON, SND_SOC_DAPM_EVENT_ON(event)); return 0; } </source>

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.

This is registered with DAPM in the speaker handler: <source lang="c"> /* corgi machine dapm widgets */ static const struct snd_soc_dapm_widget wm8731_dapm_widgets[] = { SND_SOC_DAPM_HP("Headphone Jack", NULL), SND_SOC_DAPM_MIC("Mic Jack", corgi_mic_event), SND_SOC_DAPM_SPK("Ext Spk", corgi_amp_event), SND_SOC_DAPM_LINE("Line Jack", NULL), SND_SOC_DAPM_HP("Headset Jack", NULL), }; </source>

[edit] 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.

Custom Search
Personal tools
Namespaces

Variants
Actions
Navigation
wiki
Toolbox