mirror of https://gitee.com/openkylin/linux.git
Merge branch 'topic/restize-docs' into for-next
This commit is contained in:
commit
7f084afa52
|
@ -7,6 +7,7 @@ Linux Sound Subsystem Documentation
|
|||
|
||||
kernel-api/index
|
||||
designs/index
|
||||
soc/index
|
||||
alsa-configuration
|
||||
hd-audio/index
|
||||
cards/index
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
==============
|
||||
Audio Clocking
|
||||
==============
|
||||
|
||||
|
@ -30,15 +31,9 @@ runs at exactly the sample rate (LRC = Rate).
|
|||
|
||||
Bit Clock can be generated as follows:-
|
||||
|
||||
BCLK = MCLK / x
|
||||
|
||||
or
|
||||
|
||||
BCLK = LRC * x
|
||||
|
||||
or
|
||||
|
||||
BCLK = LRC * Channels * Word Size
|
||||
- BCLK = MCLK / x, or
|
||||
- BCLK = LRC * x, or
|
||||
- BCLK = LRC * Channels * Word Size
|
||||
|
||||
This relationship depends on the codec or SoC CPU in particular. In general
|
||||
it is best to configure BCLK to the lowest possible speed (depending on your
|
|
@ -0,0 +1,108 @@
|
|||
==============================================
|
||||
Creating codec to codec dai link for ALSA dapm
|
||||
==============================================
|
||||
|
||||
Mostly the flow of audio is always from CPU to codec so your system
|
||||
will look as below:
|
||||
::
|
||||
|
||||
--------- ---------
|
||||
| | dai | |
|
||||
CPU -------> codec
|
||||
| | | |
|
||||
--------- ---------
|
||||
|
||||
In case your system looks as below:
|
||||
::
|
||||
|
||||
---------
|
||||
| |
|
||||
codec-2
|
||||
| |
|
||||
---------
|
||||
|
|
||||
dai-2
|
||||
|
|
||||
---------- ---------
|
||||
| | dai-1 | |
|
||||
CPU -------> codec-1
|
||||
| | | |
|
||||
---------- ---------
|
||||
|
|
||||
dai-3
|
||||
|
|
||||
---------
|
||||
| |
|
||||
codec-3
|
||||
| |
|
||||
---------
|
||||
|
||||
Suppose codec-2 is a bluetooth chip and codec-3 is connected to
|
||||
a speaker and you have a below scenario:
|
||||
codec-2 will receive the audio data and the user wants to play that
|
||||
audio through codec-3 without involving the CPU.This
|
||||
aforementioned case is the ideal case when codec to codec
|
||||
connection should be used.
|
||||
|
||||
Your dai_link should appear as below in your machine
|
||||
file:
|
||||
::
|
||||
|
||||
/*
|
||||
* this pcm stream only supports 24 bit, 2 channel and
|
||||
* 48k sampling rate.
|
||||
*/
|
||||
static const struct snd_soc_pcm_stream dsp_codec_params = {
|
||||
.formats = SNDRV_PCM_FMTBIT_S24_LE,
|
||||
.rate_min = 48000,
|
||||
.rate_max = 48000,
|
||||
.channels_min = 2,
|
||||
.channels_max = 2,
|
||||
};
|
||||
|
||||
{
|
||||
.name = "CPU-DSP",
|
||||
.stream_name = "CPU-DSP",
|
||||
.cpu_dai_name = "samsung-i2s.0",
|
||||
.codec_name = "codec-2,
|
||||
.codec_dai_name = "codec-2-dai_name",
|
||||
.platform_name = "samsung-i2s.0",
|
||||
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
|
||||
| SND_SOC_DAIFMT_CBM_CFM,
|
||||
.ignore_suspend = 1,
|
||||
.params = &dsp_codec_params,
|
||||
},
|
||||
{
|
||||
.name = "DSP-CODEC",
|
||||
.stream_name = "DSP-CODEC",
|
||||
.cpu_dai_name = "wm0010-sdi2",
|
||||
.codec_name = "codec-3,
|
||||
.codec_dai_name = "codec-3-dai_name",
|
||||
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
|
||||
| SND_SOC_DAIFMT_CBM_CFM,
|
||||
.ignore_suspend = 1,
|
||||
.params = &dsp_codec_params,
|
||||
},
|
||||
|
||||
Above code snippet is motivated from sound/soc/samsung/speyside.c.
|
||||
|
||||
Note the "params" callback which lets the dapm know that this
|
||||
dai_link is a codec to codec connection.
|
||||
|
||||
In dapm core a route is created between cpu_dai playback widget
|
||||
and codec_dai capture widget for playback path and vice-versa is
|
||||
true for capture path. In order for this aforementioned route to get
|
||||
triggered, DAPM needs to find a valid endpoint which could be either
|
||||
a sink or source widget corresponding to playback and capture path
|
||||
respectively.
|
||||
|
||||
In order to trigger this dai_link widget, a thin codec driver for
|
||||
the speaker amp can be created as demonstrated in wm8727.c file, it
|
||||
sets appropriate constraints for the device even if it needs no control.
|
||||
|
||||
Make sure to name your corresponding cpu and codec playback and capture
|
||||
dai names ending with "Playback" and "Capture" respectively as dapm core
|
||||
will link and power those dais based on the name.
|
||||
|
||||
Note that in current device tree there is no way to mark a dai_link
|
||||
as codec to codec. However, it may change in future.
|
|
@ -1,3 +1,4 @@
|
|||
=======================
|
||||
ASoC Codec Class Driver
|
||||
=======================
|
||||
|
||||
|
@ -9,16 +10,16 @@ machine drivers respectively.
|
|||
|
||||
Each codec class driver *must* provide the following features:-
|
||||
|
||||
1) Codec DAI and PCM configuration
|
||||
2) Codec control IO - using RegMap API
|
||||
3) Mixers and audio controls
|
||||
4) Codec audio operations
|
||||
5) DAPM description.
|
||||
6) DAPM event handler.
|
||||
1. Codec DAI and PCM configuration
|
||||
2. Codec control IO - using RegMap API
|
||||
3. Mixers and audio controls
|
||||
4. Codec audio operations
|
||||
5. DAPM description.
|
||||
6. DAPM event handler.
|
||||
|
||||
Optionally, codec drivers can also provide:-
|
||||
|
||||
7) DAC Digital mute control.
|
||||
7. DAC Digital mute control.
|
||||
|
||||
Its probably best to use this guide in conjunction with the existing codec
|
||||
driver code in sound/soc/codecs/
|
||||
|
@ -26,24 +27,25 @@ driver code in sound/soc/codecs/
|
|||
ASoC Codec driver breakdown
|
||||
===========================
|
||||
|
||||
1 - Codec DAI and PCM configuration
|
||||
-----------------------------------
|
||||
Codec DAI and PCM configuration
|
||||
-------------------------------
|
||||
Each codec driver must have a struct snd_soc_dai_driver to define its DAI and
|
||||
PCM capabilities and operations. This struct is exported so that it can be
|
||||
registered with the core by your machine driver.
|
||||
|
||||
e.g.
|
||||
::
|
||||
|
||||
static struct snd_soc_dai_ops wm8731_dai_ops = {
|
||||
static struct snd_soc_dai_ops wm8731_dai_ops = {
|
||||
.prepare = wm8731_pcm_prepare,
|
||||
.hw_params = wm8731_hw_params,
|
||||
.shutdown = wm8731_shutdown,
|
||||
.digital_mute = wm8731_mute,
|
||||
.set_sysclk = wm8731_set_dai_sysclk,
|
||||
.set_fmt = wm8731_set_dai_fmt,
|
||||
};
|
||||
|
||||
struct snd_soc_dai_driver wm8731_dai = {
|
||||
};
|
||||
|
||||
struct snd_soc_dai_driver wm8731_dai = {
|
||||
.name = "wm8731-hifi",
|
||||
.playback = {
|
||||
.stream_name = "Playback",
|
||||
|
@ -59,25 +61,27 @@ struct snd_soc_dai_driver wm8731_dai = {
|
|||
.formats = WM8731_FORMATS,},
|
||||
.ops = &wm8731_dai_ops,
|
||||
.symmetric_rates = 1,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
2 - Codec control IO
|
||||
--------------------
|
||||
Codec control IO
|
||||
----------------
|
||||
The codec can usually be controlled via an I2C or SPI style interface
|
||||
(AC97 combines control with data in the DAI). The codec driver should use the
|
||||
Regmap API for all codec IO. Please see include/linux/regmap.h and existing
|
||||
codec drivers for example regmap usage.
|
||||
|
||||
|
||||
3 - Mixers and audio controls
|
||||
-----------------------------
|
||||
Mixers and audio controls
|
||||
-------------------------
|
||||
All the codec mixers and audio controls can be defined using the convenience
|
||||
macros defined in soc.h.
|
||||
::
|
||||
|
||||
#define SOC_SINGLE(xname, reg, shift, mask, invert)
|
||||
|
||||
Defines a single control as follows:-
|
||||
::
|
||||
|
||||
xname = Control name e.g. "Playback Volume"
|
||||
reg = codec register
|
||||
|
@ -86,18 +90,22 @@ Defines a single control as follows:-
|
|||
invert = the control is inverted
|
||||
|
||||
Other macros include:-
|
||||
::
|
||||
|
||||
#define SOC_DOUBLE(xname, reg, shift_left, shift_right, mask, invert)
|
||||
|
||||
A stereo control
|
||||
::
|
||||
|
||||
#define SOC_DOUBLE_R(xname, reg_left, reg_right, shift, mask, invert)
|
||||
|
||||
A stereo control spanning 2 registers
|
||||
::
|
||||
|
||||
#define SOC_ENUM_SINGLE(xreg, xshift, xmask, xtexts)
|
||||
|
||||
Defines an single enumerated control as follows:-
|
||||
::
|
||||
|
||||
xreg = register
|
||||
xshift = control bit(s) offset in register
|
||||
|
@ -109,25 +117,26 @@ Defines an single enumerated control as follows:-
|
|||
Defines a stereo enumerated control
|
||||
|
||||
|
||||
4 - Codec Audio Operations
|
||||
--------------------------
|
||||
Codec Audio Operations
|
||||
----------------------
|
||||
The codec driver also supports the following ALSA PCM operations:-
|
||||
::
|
||||
|
||||
/* SoC audio ops */
|
||||
struct snd_soc_ops {
|
||||
/* SoC audio ops */
|
||||
struct snd_soc_ops {
|
||||
int (*startup)(struct snd_pcm_substream *);
|
||||
void (*shutdown)(struct snd_pcm_substream *);
|
||||
int (*hw_params)(struct snd_pcm_substream *, struct snd_pcm_hw_params *);
|
||||
int (*hw_free)(struct snd_pcm_substream *);
|
||||
int (*prepare)(struct snd_pcm_substream *);
|
||||
};
|
||||
};
|
||||
|
||||
Please refer to the ALSA driver PCM documentation for details.
|
||||
http://www.alsa-project.org/~iwai/writing-an-alsa-driver/
|
||||
|
||||
|
||||
5 - DAPM description.
|
||||
---------------------
|
||||
DAPM description
|
||||
----------------
|
||||
The Dynamic Audio Power Management description describes the codec power
|
||||
components and their relationships and registers to the ASoC core.
|
||||
Please read dapm.txt for details of building the description.
|
||||
|
@ -135,13 +144,14 @@ Please read dapm.txt for details of building the description.
|
|||
Please also see the examples in other codec drivers.
|
||||
|
||||
|
||||
6 - DAPM event handler
|
||||
----------------------
|
||||
DAPM event handler
|
||||
------------------
|
||||
This function is a callback that handles codec domain PM calls and system
|
||||
domain PM calls (e.g. suspend and resume). It is used to put the codec
|
||||
to sleep when not in use.
|
||||
|
||||
Power states:-
|
||||
::
|
||||
|
||||
SNDRV_CTL_POWER_D0: /* full On */
|
||||
/* vref/mid, clk and osc on, active */
|
||||
|
@ -155,8 +165,8 @@ Power states:-
|
|||
SNDRV_CTL_POWER_D3cold: /* Everything Off, without power */
|
||||
|
||||
|
||||
7 - Codec DAC digital mute control
|
||||
----------------------------------
|
||||
Codec DAC digital mute control
|
||||
------------------------------
|
||||
Most codecs have a digital mute before the DACs that can be used to
|
||||
minimise any system noise. The mute stops any digital data from
|
||||
entering the DAC.
|
||||
|
@ -165,9 +175,10 @@ A callback can be created that is called by the core for each codec DAI
|
|||
when the mute is applied or freed.
|
||||
|
||||
i.e.
|
||||
::
|
||||
|
||||
static int wm8974_mute(struct snd_soc_dai *dai, int mute)
|
||||
{
|
||||
static int wm8974_mute(struct snd_soc_dai *dai, int mute)
|
||||
{
|
||||
struct snd_soc_codec *codec = dai->codec;
|
||||
u16 mute_reg = snd_soc_read(codec, WM8974_DAC) & 0xffbf;
|
||||
|
||||
|
@ -176,4 +187,4 @@ static int wm8974_mute(struct snd_soc_dai *dai, int mute)
|
|||
else
|
||||
snd_soc_write(codec, WM8974_DAC, mute_reg);
|
||||
return 0;
|
||||
}
|
||||
}
|
|
@ -1,3 +1,7 @@
|
|||
==================================
|
||||
ASoC Digital Audio Interface (DAI)
|
||||
==================================
|
||||
|
||||
ASoC currently supports the three main Digital Audio Interfaces (DAI) found on
|
||||
SoC controllers and portable audio CODECs today, namely AC97, I2S and PCM.
|
||||
|
||||
|
@ -5,21 +9,21 @@ SoC controllers and portable audio CODECs today, namely AC97, I2S and PCM.
|
|||
AC97
|
||||
====
|
||||
|
||||
AC97 is a five wire interface commonly found on many PC sound cards. It is
|
||||
AC97 is a five wire interface commonly found on many PC sound cards. It is
|
||||
now also popular in many portable devices. This DAI has a reset line and time
|
||||
multiplexes its data on its SDATA_OUT (playback) and SDATA_IN (capture) lines.
|
||||
The bit clock (BCLK) is always driven by the CODEC (usually 12.288MHz) and the
|
||||
frame (FRAME) (usually 48kHz) is always driven by the controller. Each AC97
|
||||
frame is 21uS long and is divided into 13 time slots.
|
||||
|
||||
The AC97 specification can be found at :-
|
||||
The AC97 specification can be found at :
|
||||
http://www.intel.com/p/en_US/business/design
|
||||
|
||||
|
||||
I2S
|
||||
===
|
||||
|
||||
I2S is a common 4 wire DAI used in HiFi, STB and portable devices. The Tx and
|
||||
I2S is a common 4 wire DAI used in HiFi, STB and portable devices. The Tx and
|
||||
Rx lines are used for audio transmission, whilst the bit clock (BCLK) and
|
||||
left/right clock (LRC) synchronise the link. I2S is flexible in that either the
|
||||
controller or CODEC can drive (master) the BCLK and LRC clock lines. Bit clock
|
||||
|
@ -30,13 +34,15 @@ different sample rates.
|
|||
|
||||
I2S has several different operating modes:-
|
||||
|
||||
o I2S - MSB is transmitted on the falling edge of the first BCLK after LRC
|
||||
transition.
|
||||
I2S
|
||||
MSB is transmitted on the falling edge of the first BCLK after LRC
|
||||
transition.
|
||||
|
||||
o Left Justified - MSB is transmitted on transition of LRC.
|
||||
Left Justified
|
||||
MSB is transmitted on transition of LRC.
|
||||
|
||||
o Right Justified - MSB is transmitted sample size BCLKs before LRC
|
||||
transition.
|
||||
Right Justified
|
||||
MSB is transmitted sample size BCLKs before LRC transition.
|
||||
|
||||
PCM
|
||||
===
|
||||
|
@ -51,6 +57,8 @@ is sometimes referred to as network mode).
|
|||
|
||||
Common PCM operating modes:-
|
||||
|
||||
o Mode A - MSB is transmitted on falling edge of first BCLK after FRAME/SYNC.
|
||||
Mode A
|
||||
MSB is transmitted on falling edge of first BCLK after FRAME/SYNC.
|
||||
|
||||
o Mode B - MSB is transmitted on rising edge of FRAME/SYNC.
|
||||
Mode B
|
||||
MSB is transmitted on rising edge of FRAME/SYNC.
|
|
@ -1,8 +1,9 @@
|
|||
===================================================
|
||||
Dynamic Audio Power Management for Portable Devices
|
||||
===================================================
|
||||
|
||||
1. Description
|
||||
==============
|
||||
Description
|
||||
===========
|
||||
|
||||
Dynamic Audio Power Management (DAPM) is designed to allow portable
|
||||
Linux devices to use the minimum amount of power within the audio
|
||||
|
@ -21,20 +22,28 @@ level power systems.
|
|||
|
||||
There are 4 power domains within DAPM
|
||||
|
||||
1. Codec bias domain - VREF, VMID (core codec and audio power)
|
||||
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.
|
||||
|
||||
2. Platform/Machine domain - physically connected inputs and outputs
|
||||
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
|
||||
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 - DACs and ADCs.
|
||||
Stream domain
|
||||
DACs and ADCs.
|
||||
|
||||
Enabled and disabled when stream playback/capture is started and
|
||||
stopped respectively. e.g. aplay, arecord.
|
||||
|
||||
|
@ -45,34 +54,57 @@ internal codec components). All audio components that effect power are called
|
|||
widgets hereafter.
|
||||
|
||||
|
||||
2. DAPM Widgets
|
||||
===============
|
||||
DAPM Widgets
|
||||
============
|
||||
|
||||
Audio DAPM widgets fall into a number of types:-
|
||||
|
||||
o Mixer - Mixes several analog signals into a single analog signal.
|
||||
o Mux - An analog switch that outputs only one of many inputs.
|
||||
o PGA - A programmable gain amplifier or attenuation widget.
|
||||
o ADC - Analog to Digital Converter
|
||||
o DAC - Digital to Analog Converter
|
||||
o Switch - An analog switch
|
||||
o Input - A codec input pin
|
||||
o Output - A codec output pin
|
||||
o Headphone - Headphone (and optional Jack)
|
||||
o Mic - Mic (and optional Jack)
|
||||
o Line - Line Input/Output (and optional Jack)
|
||||
o Speaker - Speaker
|
||||
o Supply - Power or clock supply widget used by other widgets.
|
||||
o Regulator - External regulator that supplies power to audio components.
|
||||
o Clock - External clock that supplies clock to audio components.
|
||||
o AIF IN - Audio Interface Input (with TDM slot mask).
|
||||
o AIF OUT - Audio Interface Output (with TDM slot mask).
|
||||
o Siggen - Signal Generator.
|
||||
o DAI IN - Digital Audio Interface Input.
|
||||
o DAI OUT - Digital Audio Interface Output.
|
||||
o DAI Link - DAI Link between two DAI structures */
|
||||
o Pre - Special PRE widget (exec before all others)
|
||||
o Post - Special POST widget (exec after all others)
|
||||
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)
|
||||
|
||||
(Widgets are defined in include/sound/soc-dapm.h)
|
||||
|
||||
|
@ -84,52 +116,57 @@ Most widgets have a name, register, shift and invert. Some widgets have extra
|
|||
parameters for stream name and kcontrols.
|
||||
|
||||
|
||||
2.1 Stream Domain Widgets
|
||||
-------------------------
|
||||
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)
|
||||
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_codec_dai.
|
||||
|
||||
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),
|
||||
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),
|
||||
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),
|
||||
|
||||
|
||||
2.2 Path Domain Widgets
|
||||
-----------------------
|
||||
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)
|
||||
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),
|
||||
};
|
||||
/* 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,
|
||||
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,
|
||||
|
@ -137,48 +174,49 @@ you can use SND_SOC_DAPM_MIXER_NAMED_CTL instead. the parameters are the same
|
|||
as for SND_SOC_DAPM_MIXER.
|
||||
|
||||
|
||||
2.3 Machine domain Widgets
|
||||
--------------------------
|
||||
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.
|
||||
|
||||
o Speaker Amp
|
||||
o Microphone Bias
|
||||
o Jack connectors
|
||||
* 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:-
|
||||
when the Mic is inserted:-::
|
||||
|
||||
static int spitz_mic_bias(struct snd_soc_dapm_widget* w, int event)
|
||||
{
|
||||
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),
|
||||
SND_SOC_DAPM_MIC("Mic Jack", spitz_mic_bias),
|
||||
|
||||
|
||||
2.4 Codec (BIAS) Domain
|
||||
-----------------------
|
||||
Codec (BIAS) Domain
|
||||
-------------------
|
||||
|
||||
The codec bias power domain has no widgets and is handled by the codecs DAPM
|
||||
event handler. This handler is called when the codec powerstate is changed wrt
|
||||
to any stream event or by kernel PM events.
|
||||
|
||||
|
||||
2.5 Virtual Widgets
|
||||
-------------------
|
||||
Virtual Widgets
|
||||
---------------
|
||||
|
||||
Sometimes widgets exist in the codec or machine audio map 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_DAPM_NOPM, 0, 0, NULL, 0),
|
||||
SND_SOC_DAPM_MIXER("AC97 Mixer", SND_SOC_DAPM_NOPM, 0, 0, NULL, 0),
|
||||
|
||||
This can be used to merge to signal paths together in software.
|
||||
|
||||
|
@ -186,8 +224,8 @@ After all the widgets have been defined, they can then be added to the DAPM
|
|||
subsystem individually with a call to snd_soc_dapm_new_control().
|
||||
|
||||
|
||||
3. Codec/DSP Widget Interconnections
|
||||
====================================
|
||||
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
|
||||
|
@ -201,13 +239,14 @@ e.g., from the WM8731 output mixer (wm8731.c)
|
|||
|
||||
The WM8731 output mixer has 3 inputs (sources)
|
||||
|
||||
1. Line Bypass Input
|
||||
2. DAC (HiFi playback)
|
||||
3. Mic Sidetone Input
|
||||
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 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"},
|
||||
|
@ -216,22 +255,17 @@ connect the destination widget (wrt audio signal) with its source widgets.
|
|||
|
||||
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".
|
||||
* 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);
|
||||
snd_soc_dapm_connect_input(codec, sink, path, source);
|
||||
|
||||
Finally, snd_soc_dapm_new_widgets(codec) must be called after all widgets and
|
||||
interconnections have been registered with the core. This causes the core to
|
||||
|
@ -239,12 +273,13 @@ scan the codec and machine so that the internal DAPM state matches the
|
|||
physical state of the machine.
|
||||
|
||||
|
||||
3.1 Machine Widget Interconnections
|
||||
-----------------------------------
|
||||
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"},
|
||||
|
@ -254,52 +289,54 @@ This allows the DAPM to power on and off pins that are connected (and in use)
|
|||
and pins that are NC respectively.
|
||||
|
||||
|
||||
4 Endpoint Widgets
|
||||
===================
|
||||
Endpoint Widgets
|
||||
================
|
||||
An endpoint is a start or end point (widget) of an audio signal within the
|
||||
machine and includes the codec. e.g.
|
||||
|
||||
o Headphone Jack
|
||||
o Internal Speaker
|
||||
o Internal Mic
|
||||
o Mic Jack
|
||||
o Codec Pins
|
||||
* 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.
|
||||
|
||||
|
||||
5 DAPM Widget Events
|
||||
====================
|
||||
DAPM Widget Events
|
||||
==================
|
||||
|
||||
Some widgets can register their interest with the DAPM core in PM events.
|
||||
e.g. A Speaker with an amplifier registers a widget so the amplifier can be
|
||||
powered only when the spk is in use.
|
||||
::
|
||||
|
||||
/* turn speaker amplifier on/off depending on use */
|
||||
static int corgi_amp_event(struct snd_soc_dapm_widget *w, int event)
|
||||
{
|
||||
/* turn speaker amplifier on/off depending on use */
|
||||
static int corgi_amp_event(struct snd_soc_dapm_widget *w, int event)
|
||||
{
|
||||
gpio_set_value(CORGI_GPIO_APM_ON, SND_SOC_DAPM_EVENT_ON(event));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* corgi machine dapm widgets */
|
||||
static const struct snd_soc_dapm_widget wm8731_dapm_widgets =
|
||||
/* corgi machine dapm widgets */
|
||||
static const struct snd_soc_dapm_widget wm8731_dapm_widgets =
|
||||
SND_SOC_DAPM_SPK("Ext Spk", corgi_amp_event);
|
||||
|
||||
Please see soc-dapm.h for all other widgets that support events.
|
||||
|
||||
|
||||
5.1 Event types
|
||||
---------------
|
||||
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 */
|
||||
/* 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 */
|
|
@ -1,8 +1,9 @@
|
|||
===========
|
||||
Dynamic PCM
|
||||
===========
|
||||
|
||||
1. Description
|
||||
==============
|
||||
Description
|
||||
===========
|
||||
|
||||
Dynamic PCM allows an ALSA PCM device to digitally route its PCM audio to
|
||||
various digital endpoints during the PCM stream runtime. e.g. PCM0 can route
|
||||
|
@ -23,22 +24,23 @@ Phone Audio System with SoC based DSP
|
|||
|
||||
Consider the following phone audio subsystem. This will be used in this
|
||||
document for all examples :-
|
||||
::
|
||||
|
||||
| Front End PCMs | SoC DSP | Back End DAIs | Audio devices |
|
||||
|
||||
*************
|
||||
PCM0 <------------> * * <----DAI0-----> Codec Headset
|
||||
* *
|
||||
PCM1 <------------> * * <----DAI1-----> Codec Speakers
|
||||
* DSP *
|
||||
PCM2 <------------> * * <----DAI2-----> MODEM
|
||||
* *
|
||||
PCM3 <------------> * * <----DAI3-----> BT
|
||||
* *
|
||||
* * <----DAI4-----> DMIC
|
||||
* *
|
||||
* * <----DAI5-----> FM
|
||||
*************
|
||||
| Front End PCMs | SoC DSP | Back End DAIs | Audio devices |
|
||||
|
||||
*************
|
||||
PCM0 <------------> * * <----DAI0-----> Codec Headset
|
||||
* *
|
||||
PCM1 <------------> * * <----DAI1-----> Codec Speakers
|
||||
* DSP *
|
||||
PCM2 <------------> * * <----DAI2-----> MODEM
|
||||
* *
|
||||
PCM3 <------------> * * <----DAI3-----> BT
|
||||
* *
|
||||
* * <----DAI4-----> DMIC
|
||||
* *
|
||||
* * <----DAI5-----> FM
|
||||
*************
|
||||
|
||||
This diagram shows a simple smart phone audio subsystem. It supports Bluetooth,
|
||||
FM digital radio, Speakers, Headset Jack, digital microphones and cellular
|
||||
|
@ -55,50 +57,52 @@ Audio is being played to the Headset. After a while the user removes the headset
|
|||
and audio continues playing on the speakers.
|
||||
|
||||
Playback on PCM0 to Headset would look like :-
|
||||
::
|
||||
|
||||
*************
|
||||
PCM0 <============> * * <====DAI0=====> Codec Headset
|
||||
* *
|
||||
PCM1 <------------> * * <----DAI1-----> Codec Speakers
|
||||
* DSP *
|
||||
PCM2 <------------> * * <----DAI2-----> MODEM
|
||||
* *
|
||||
PCM3 <------------> * * <----DAI3-----> BT
|
||||
* *
|
||||
* * <----DAI4-----> DMIC
|
||||
* *
|
||||
* * <----DAI5-----> FM
|
||||
*************
|
||||
*************
|
||||
PCM0 <============> * * <====DAI0=====> Codec Headset
|
||||
* *
|
||||
PCM1 <------------> * * <----DAI1-----> Codec Speakers
|
||||
* DSP *
|
||||
PCM2 <------------> * * <----DAI2-----> MODEM
|
||||
* *
|
||||
PCM3 <------------> * * <----DAI3-----> BT
|
||||
* *
|
||||
* * <----DAI4-----> DMIC
|
||||
* *
|
||||
* * <----DAI5-----> FM
|
||||
*************
|
||||
|
||||
The headset is removed from the jack by user so the speakers must now be used :-
|
||||
::
|
||||
|
||||
*************
|
||||
PCM0 <============> * * <----DAI0-----> Codec Headset
|
||||
* *
|
||||
PCM1 <------------> * * <====DAI1=====> Codec Speakers
|
||||
* DSP *
|
||||
PCM2 <------------> * * <----DAI2-----> MODEM
|
||||
* *
|
||||
PCM3 <------------> * * <----DAI3-----> BT
|
||||
* *
|
||||
* * <----DAI4-----> DMIC
|
||||
* *
|
||||
* * <----DAI5-----> FM
|
||||
*************
|
||||
*************
|
||||
PCM0 <============> * * <----DAI0-----> Codec Headset
|
||||
* *
|
||||
PCM1 <------------> * * <====DAI1=====> Codec Speakers
|
||||
* DSP *
|
||||
PCM2 <------------> * * <----DAI2-----> MODEM
|
||||
* *
|
||||
PCM3 <------------> * * <----DAI3-----> BT
|
||||
* *
|
||||
* * <----DAI4-----> DMIC
|
||||
* *
|
||||
* * <----DAI5-----> FM
|
||||
*************
|
||||
|
||||
The audio driver processes this as follows :-
|
||||
|
||||
1) Machine driver receives Jack removal event.
|
||||
1. Machine driver receives Jack removal event.
|
||||
|
||||
2) Machine driver OR audio HAL disables the Headset path.
|
||||
2. Machine driver OR audio HAL disables the Headset path.
|
||||
|
||||
3) DPCM runs the PCM trigger(stop), hw_free(), shutdown() operations on DAI0
|
||||
for headset since the path is now disabled.
|
||||
3. DPCM runs the PCM trigger(stop), hw_free(), shutdown() operations on DAI0
|
||||
for headset since the path is now disabled.
|
||||
|
||||
4) Machine driver or audio HAL enables the speaker path.
|
||||
4. Machine driver or audio HAL enables the speaker path.
|
||||
|
||||
5) DPCM runs the PCM ops for startup(), hw_params(), prepapre() and
|
||||
trigger(start) for DAI1 Speakers since the path is enabled.
|
||||
5. DPCM runs the PCM ops for startup(), hw_params(), prepapre() and
|
||||
trigger(start) for DAI1 Speakers since the path is enabled.
|
||||
|
||||
In this example, the machine driver or userspace audio HAL can alter the routing
|
||||
and then DPCM will take care of managing the DAI PCM operations to either bring
|
||||
|
@ -112,36 +116,38 @@ DPCM machine driver
|
|||
The DPCM enabled ASoC machine driver is similar to normal machine drivers
|
||||
except that we also have to :-
|
||||
|
||||
1) Define the FE and BE DAI links.
|
||||
1. Define the FE and BE DAI links.
|
||||
|
||||
2) Define any FE/BE PCM operations.
|
||||
2. Define any FE/BE PCM operations.
|
||||
|
||||
3) Define widget graph connections.
|
||||
3. Define widget graph connections.
|
||||
|
||||
|
||||
1 FE and BE DAI links
|
||||
---------------------
|
||||
FE and BE DAI links
|
||||
-------------------
|
||||
::
|
||||
|
||||
| Front End PCMs | SoC DSP | Back End DAIs | Audio devices |
|
||||
|
||||
*************
|
||||
PCM0 <------------> * * <----DAI0-----> Codec Headset
|
||||
* *
|
||||
PCM1 <------------> * * <----DAI1-----> Codec Speakers
|
||||
* DSP *
|
||||
PCM2 <------------> * * <----DAI2-----> MODEM
|
||||
* *
|
||||
PCM3 <------------> * * <----DAI3-----> BT
|
||||
* *
|
||||
* * <----DAI4-----> DMIC
|
||||
* *
|
||||
* * <----DAI5-----> FM
|
||||
*************
|
||||
| Front End PCMs | SoC DSP | Back End DAIs | Audio devices |
|
||||
|
||||
*************
|
||||
PCM0 <------------> * * <----DAI0-----> Codec Headset
|
||||
* *
|
||||
PCM1 <------------> * * <----DAI1-----> Codec Speakers
|
||||
* DSP *
|
||||
PCM2 <------------> * * <----DAI2-----> MODEM
|
||||
* *
|
||||
PCM3 <------------> * * <----DAI3-----> BT
|
||||
* *
|
||||
* * <----DAI4-----> DMIC
|
||||
* *
|
||||
* * <----DAI5-----> FM
|
||||
*************
|
||||
|
||||
For the example above we have to define 4 FE DAI links and 6 BE DAI links. The
|
||||
FE DAI links are defined as follows :-
|
||||
::
|
||||
|
||||
static struct snd_soc_dai_link machine_dais[] = {
|
||||
static struct snd_soc_dai_link machine_dais[] = {
|
||||
{
|
||||
.name = "PCM0 System",
|
||||
.stream_name = "System Playback",
|
||||
|
@ -154,11 +160,11 @@ static struct snd_soc_dai_link machine_dais[] = {
|
|||
.dpcm_playback = 1,
|
||||
},
|
||||
.....< other FE and BE DAI links here >
|
||||
};
|
||||
};
|
||||
|
||||
This FE DAI link is pretty similar to a regular DAI link except that we also
|
||||
set the DAI link to a DPCM FE with the "dynamic = 1". The supported FE stream
|
||||
directions should also be set with the "dpcm_playback" and "dpcm_capture"
|
||||
set the DAI link to a DPCM FE with the ``dynamic = 1``. The supported FE stream
|
||||
directions should also be set with the ``dpcm_playback`` and ``dpcm_capture``
|
||||
flags. There is also an option to specify the ordering of the trigger call for
|
||||
each FE. This allows the ASoC core to trigger the DSP before or after the other
|
||||
components (as some DSPs have strong requirements for the ordering DAI/DSP
|
||||
|
@ -168,8 +174,9 @@ The FE DAI above sets the codec and code DAIs to dummy devices since the BE is
|
|||
dynamic and will change depending on runtime config.
|
||||
|
||||
The BE DAIs are configured as follows :-
|
||||
::
|
||||
|
||||
static struct snd_soc_dai_link machine_dais[] = {
|
||||
static struct snd_soc_dai_link machine_dais[] = {
|
||||
.....< FE DAI links here >
|
||||
{
|
||||
.name = "Codec Headset",
|
||||
|
@ -186,29 +193,30 @@ static struct snd_soc_dai_link machine_dais[] = {
|
|||
.dpcm_capture = 1,
|
||||
},
|
||||
.....< other BE DAI links here >
|
||||
};
|
||||
};
|
||||
|
||||
This BE DAI link connects DAI0 to the codec (in this case RT5460 AIF1). It sets
|
||||
the "no_pcm" flag to mark it has a BE and sets flags for supported stream
|
||||
directions using "dpcm_playback" and "dpcm_capture" above.
|
||||
the ``no_pcm`` flag to mark it has a BE and sets flags for supported stream
|
||||
directions using ``dpcm_playback`` and ``dpcm_capture`` above.
|
||||
|
||||
The BE has also flags set for ignoring suspend and PM down time. This allows
|
||||
the BE to work in a hostless mode where the host CPU is not transferring data
|
||||
like a BT phone call :-
|
||||
::
|
||||
|
||||
*************
|
||||
PCM0 <------------> * * <----DAI0-----> Codec Headset
|
||||
* *
|
||||
PCM1 <------------> * * <----DAI1-----> Codec Speakers
|
||||
* DSP *
|
||||
PCM2 <------------> * * <====DAI2=====> MODEM
|
||||
* *
|
||||
PCM3 <------------> * * <====DAI3=====> BT
|
||||
* *
|
||||
* * <----DAI4-----> DMIC
|
||||
* *
|
||||
* * <----DAI5-----> FM
|
||||
*************
|
||||
*************
|
||||
PCM0 <------------> * * <----DAI0-----> Codec Headset
|
||||
* *
|
||||
PCM1 <------------> * * <----DAI1-----> Codec Speakers
|
||||
* DSP *
|
||||
PCM2 <------------> * * <====DAI2=====> MODEM
|
||||
* *
|
||||
PCM3 <------------> * * <====DAI3=====> BT
|
||||
* *
|
||||
* * <----DAI4-----> DMIC
|
||||
* *
|
||||
* * <----DAI5-----> FM
|
||||
*************
|
||||
|
||||
This allows the host CPU to sleep whilst the DSP, MODEM DAI and the BT DAI are
|
||||
still in operation.
|
||||
|
@ -220,10 +228,10 @@ Likewise a BE DAI can also set a dummy cpu DAI if the CPU DAI is managed by the
|
|||
DSP firmware.
|
||||
|
||||
|
||||
2 FE/BE PCM operations
|
||||
----------------------
|
||||
FE/BE PCM operations
|
||||
--------------------
|
||||
|
||||
The BE above also exports some PCM operations and a "fixup" callback. The fixup
|
||||
The BE above also exports some PCM operations and a ``fixup`` callback. The fixup
|
||||
callback is used by the machine driver to (re)configure the DAI based upon the
|
||||
FE hw params. i.e. the DSP may perform SRC or ASRC from the FE to BE.
|
||||
|
||||
|
@ -231,10 +239,11 @@ e.g. DSP converts all FE hw params to run at fixed rate of 48k, 16bit, stereo fo
|
|||
DAI0. This means all FE hw_params have to be fixed in the machine driver for
|
||||
DAI0 so that the DAI is running at desired configuration regardless of the FE
|
||||
configuration.
|
||||
::
|
||||
|
||||
static int dai0_fixup(struct snd_soc_pcm_runtime *rtd,
|
||||
static int dai0_fixup(struct snd_soc_pcm_runtime *rtd,
|
||||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
{
|
||||
struct snd_interval *rate = hw_param_interval(params,
|
||||
SNDRV_PCM_HW_PARAM_RATE);
|
||||
struct snd_interval *channels = hw_param_interval(params,
|
||||
|
@ -249,21 +258,22 @@ static int dai0_fixup(struct snd_soc_pcm_runtime *rtd,
|
|||
SNDRV_PCM_HW_PARAM_FIRST_MASK],
|
||||
SNDRV_PCM_FORMAT_S16_LE);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
The other PCM operation are the same as for regular DAI links. Use as necessary.
|
||||
|
||||
|
||||
3 Widget graph connections
|
||||
--------------------------
|
||||
Widget graph connections
|
||||
------------------------
|
||||
|
||||
The BE DAI links will normally be connected to the graph at initialisation time
|
||||
by the ASoC DAPM core. However, if the BE codec or BE DAI is a dummy then this
|
||||
has to be set explicitly in the driver :-
|
||||
::
|
||||
|
||||
/* BE for codec Headset - DAI0 is dummy and managed by DSP FW */
|
||||
{"DAI0 CODEC IN", NULL, "AIF1 Capture"},
|
||||
{"AIF1 Playback", NULL, "DAI0 CODEC OUT"},
|
||||
/* BE for codec Headset - DAI0 is dummy and managed by DSP FW */
|
||||
{"DAI0 CODEC IN", NULL, "AIF1 Capture"},
|
||||
{"AIF1 Playback", NULL, "DAI0 CODEC OUT"},
|
||||
|
||||
|
||||
Writing a DPCM DSP driver
|
||||
|
@ -273,24 +283,25 @@ The DPCM DSP driver looks much like a standard platform class ASoC driver
|
|||
combined with elements from a codec class driver. A DSP platform driver must
|
||||
implement :-
|
||||
|
||||
1) Front End PCM DAIs - i.e. struct snd_soc_dai_driver.
|
||||
1. Front End PCM DAIs - i.e. struct snd_soc_dai_driver.
|
||||
|
||||
2) DAPM graph showing DSP audio routing from FE DAIs to BEs.
|
||||
2. DAPM graph showing DSP audio routing from FE DAIs to BEs.
|
||||
|
||||
3) DAPM widgets from DSP graph.
|
||||
3. DAPM widgets from DSP graph.
|
||||
|
||||
4) Mixers for gains, routing, etc.
|
||||
4. Mixers for gains, routing, etc.
|
||||
|
||||
5) DMA configuration.
|
||||
5. DMA configuration.
|
||||
|
||||
6) BE AIF widgets.
|
||||
6. BE AIF widgets.
|
||||
|
||||
Items 6 is important for routing the audio outside of the DSP. AIF need to be
|
||||
defined for each BE and each stream direction. e.g for BE DAI0 above we would
|
||||
have :-
|
||||
::
|
||||
|
||||
SND_SOC_DAPM_AIF_IN("DAI0 RX", NULL, 0, SND_SOC_NOPM, 0, 0),
|
||||
SND_SOC_DAPM_AIF_OUT("DAI0 TX", NULL, 0, SND_SOC_NOPM, 0, 0),
|
||||
SND_SOC_DAPM_AIF_IN("DAI0 RX", NULL, 0, SND_SOC_NOPM, 0, 0),
|
||||
SND_SOC_DAPM_AIF_OUT("DAI0 TX", NULL, 0, SND_SOC_NOPM, 0, 0),
|
||||
|
||||
The BE AIF are used to connect the DSP graph to the graphs for the other
|
||||
component drivers (e.g. codec graph).
|
||||
|
@ -301,33 +312,33 @@ Hostless PCM streams
|
|||
|
||||
A hostless PCM stream is a stream that is not routed through the host CPU. An
|
||||
example of this would be a phone call from handset to modem.
|
||||
::
|
||||
|
||||
|
||||
*************
|
||||
PCM0 <------------> * * <----DAI0-----> Codec Headset
|
||||
* *
|
||||
PCM1 <------------> * * <====DAI1=====> Codec Speakers/Mic
|
||||
* DSP *
|
||||
PCM2 <------------> * * <====DAI2=====> MODEM
|
||||
* *
|
||||
PCM3 <------------> * * <----DAI3-----> BT
|
||||
* *
|
||||
* * <----DAI4-----> DMIC
|
||||
* *
|
||||
* * <----DAI5-----> FM
|
||||
*************
|
||||
*************
|
||||
PCM0 <------------> * * <----DAI0-----> Codec Headset
|
||||
* *
|
||||
PCM1 <------------> * * <====DAI1=====> Codec Speakers/Mic
|
||||
* DSP *
|
||||
PCM2 <------------> * * <====DAI2=====> MODEM
|
||||
* *
|
||||
PCM3 <------------> * * <----DAI3-----> BT
|
||||
* *
|
||||
* * <----DAI4-----> DMIC
|
||||
* *
|
||||
* * <----DAI5-----> FM
|
||||
*************
|
||||
|
||||
In this case the PCM data is routed via the DSP. The host CPU in this use case
|
||||
is only used for control and can sleep during the runtime of the stream.
|
||||
|
||||
The host can control the hostless link either by :-
|
||||
|
||||
1) Configuring the link as a CODEC <-> CODEC style link. In this case the link
|
||||
1. Configuring the link as a CODEC <-> CODEC style link. In this case the link
|
||||
is enabled or disabled by the state of the DAPM graph. This usually means
|
||||
there is a mixer control that can be used to connect or disconnect the path
|
||||
between both DAIs.
|
||||
|
||||
2) Hostless FE. This FE has a virtual connection to the BE DAI links on the DAPM
|
||||
2. Hostless FE. This FE has a virtual connection to the BE DAI links on the DAPM
|
||||
graph. Control is then carried out by the FE as regular PCM operations.
|
||||
This method gives more control over the DAI links, but requires much more
|
||||
userspace code to control the link. Its recommended to use CODEC<->CODEC
|
||||
|
@ -339,16 +350,17 @@ CODEC <-> CODEC link
|
|||
|
||||
This DAI link is enabled when DAPM detects a valid path within the DAPM graph.
|
||||
The machine driver sets some additional parameters to the DAI link i.e.
|
||||
::
|
||||
|
||||
static const struct snd_soc_pcm_stream dai_params = {
|
||||
static const struct snd_soc_pcm_stream dai_params = {
|
||||
.formats = SNDRV_PCM_FMTBIT_S32_LE,
|
||||
.rate_min = 8000,
|
||||
.rate_max = 8000,
|
||||
.channels_min = 2,
|
||||
.channels_max = 2,
|
||||
};
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_link dais[] = {
|
||||
static struct snd_soc_dai_link dais[] = {
|
||||
< ... more DAI links above ... >
|
||||
{
|
||||
.name = "MODEM",
|
|
@ -0,0 +1,20 @@
|
|||
==============
|
||||
ALSA SoC Layer
|
||||
==============
|
||||
|
||||
The documentation is spilt into the following sections:-
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
overview
|
||||
codec
|
||||
dai
|
||||
dapm
|
||||
platform
|
||||
machine
|
||||
pops-clicks
|
||||
clocking
|
||||
jack
|
||||
dpcm
|
||||
codec-to-codec
|
|
@ -1,3 +1,4 @@
|
|||
===================
|
||||
ASoC jack detection
|
||||
===================
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
===================
|
||||
ASoC Machine Driver
|
||||
===================
|
||||
|
||||
|
@ -9,9 +10,10 @@ interrupts, clocking, jacks and voltage regulators.
|
|||
The machine driver can contain codec and platform specific code. It registers
|
||||
the audio subsystem with the kernel as a platform device and is represented by
|
||||
the following struct:-
|
||||
::
|
||||
|
||||
/* SoC machine */
|
||||
struct snd_soc_card {
|
||||
/* SoC machine */
|
||||
struct snd_soc_card {
|
||||
char *name;
|
||||
|
||||
...
|
||||
|
@ -33,7 +35,7 @@ struct snd_soc_card {
|
|||
int num_links;
|
||||
|
||||
...
|
||||
};
|
||||
};
|
||||
|
||||
probe()/remove()
|
||||
----------------
|
||||
|
@ -55,9 +57,10 @@ initialisation e.g. the machine audio map can be connected to the codec audio
|
|||
map, unconnected codec pins can be set as such.
|
||||
|
||||
struct snd_soc_dai_link is used to set up each DAI in your machine. e.g.
|
||||
::
|
||||
|
||||
/* corgi digital audio interface glue - connects codec <--> CPU */
|
||||
static struct snd_soc_dai_link corgi_dai = {
|
||||
/* corgi digital audio interface glue - connects codec <--> CPU */
|
||||
static struct snd_soc_dai_link corgi_dai = {
|
||||
.name = "WM8731",
|
||||
.stream_name = "WM8731",
|
||||
.cpu_dai_name = "pxa-is2-dai",
|
||||
|
@ -66,16 +69,17 @@ static struct snd_soc_dai_link corgi_dai = {
|
|||
.codec_name = "wm8713-codec.0-001a",
|
||||
.init = corgi_wm8731_init,
|
||||
.ops = &corgi_ops,
|
||||
};
|
||||
};
|
||||
|
||||
struct snd_soc_card then sets up the machine with its DAIs. e.g.
|
||||
::
|
||||
|
||||
/* corgi audio machine driver */
|
||||
static struct snd_soc_card snd_soc_corgi = {
|
||||
/* corgi audio machine driver */
|
||||
static struct snd_soc_card snd_soc_corgi = {
|
||||
.name = "Corgi",
|
||||
.dai_link = &corgi_dai,
|
||||
.num_links = 1,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
Machine Power Map
|
|
@ -1,5 +1,6 @@
|
|||
ALSA SoC Layer
|
||||
==============
|
||||
=======================
|
||||
ALSA SoC Layer Overview
|
||||
=======================
|
||||
|
||||
The overall project goal of the ALSA System on Chip (ASoC) layer is to
|
||||
provide better ALSA support for embedded system-on-chip processors (e.g.
|
||||
|
@ -66,30 +67,3 @@ multiple re-usable component drivers :-
|
|||
describes and binds the other component drivers together to form an ALSA
|
||||
"sound card device". It handles any machine specific controls and
|
||||
machine level audio events (e.g. turning on an amp at start of playback).
|
||||
|
||||
|
||||
Documentation
|
||||
=============
|
||||
|
||||
The documentation is spilt into the following sections:-
|
||||
|
||||
overview.txt: This file.
|
||||
|
||||
codec.txt: Codec driver internals.
|
||||
|
||||
DAI.txt: Description of Digital Audio Interface standards and how to configure
|
||||
a DAI within your codec and CPU DAI drivers.
|
||||
|
||||
dapm.txt: Dynamic Audio Power Management
|
||||
|
||||
platform.txt: Platform audio DMA and DAI.
|
||||
|
||||
machine.txt: Machine driver internals.
|
||||
|
||||
pop_clicks.txt: How to minimise audio artifacts.
|
||||
|
||||
clocking.txt: ASoC clocking for best power performance.
|
||||
|
||||
jack.txt: ASoC jack detection.
|
||||
|
||||
DPCM.txt: Dynamic PCM - Describes DPCM with DSP examples.
|
|
@ -1,3 +1,4 @@
|
|||
====================
|
||||
ASoC Platform Driver
|
||||
====================
|
||||
|
||||
|
@ -9,21 +10,23 @@ Audio DMA
|
|||
=========
|
||||
|
||||
The platform DMA driver optionally supports the following ALSA operations:-
|
||||
::
|
||||
|
||||
/* SoC audio ops */
|
||||
struct snd_soc_ops {
|
||||
/* SoC audio ops */
|
||||
struct snd_soc_ops {
|
||||
int (*startup)(struct snd_pcm_substream *);
|
||||
void (*shutdown)(struct snd_pcm_substream *);
|
||||
int (*hw_params)(struct snd_pcm_substream *, struct snd_pcm_hw_params *);
|
||||
int (*hw_free)(struct snd_pcm_substream *);
|
||||
int (*prepare)(struct snd_pcm_substream *);
|
||||
int (*trigger)(struct snd_pcm_substream *, int);
|
||||
};
|
||||
};
|
||||
|
||||
The platform driver exports its DMA functionality via struct
|
||||
snd_soc_platform_driver:-
|
||||
::
|
||||
|
||||
struct snd_soc_platform_driver {
|
||||
struct snd_soc_platform_driver {
|
||||
char *name;
|
||||
|
||||
int (*probe)(struct platform_device *pdev);
|
||||
|
@ -44,7 +47,7 @@ struct snd_soc_platform_driver {
|
|||
|
||||
/* platform stream ops */
|
||||
struct snd_pcm_ops *pcm_ops;
|
||||
};
|
||||
};
|
||||
|
||||
Please refer to the ALSA driver documentation for details of audio DMA.
|
||||
http://www.alsa-project.org/~iwai/writing-an-alsa-driver/
|
||||
|
@ -57,11 +60,11 @@ SoC DAI Drivers
|
|||
|
||||
Each SoC DAI driver must provide the following features:-
|
||||
|
||||
1) Digital audio interface (DAI) description
|
||||
2) Digital audio interface configuration
|
||||
3) PCM's description
|
||||
4) SYSCLK configuration
|
||||
5) Suspend and resume (optional)
|
||||
1. Digital audio interface (DAI) description
|
||||
2. Digital audio interface configuration
|
||||
3. PCM's description
|
||||
4. SYSCLK configuration
|
||||
5. Suspend and resume (optional)
|
||||
|
||||
Please see codec.txt for a description of items 1 - 4.
|
||||
|
||||
|
@ -71,9 +74,9 @@ SoC DSP Drivers
|
|||
|
||||
Each SoC DSP driver usually supplies the following features :-
|
||||
|
||||
1) DAPM graph
|
||||
2) Mixer controls
|
||||
3) DMA IO to/from DSP buffers (if applicable)
|
||||
4) Definition of DSP front end (FE) PCM devices.
|
||||
1. DAPM graph
|
||||
2. Mixer controls
|
||||
3. DMA IO to/from DSP buffers (if applicable)
|
||||
4. Definition of DSP front end (FE) PCM devices.
|
||||
|
||||
Please see DPCM.txt for a description of item 4.
|
|
@ -1,3 +1,4 @@
|
|||
=====================
|
||||
Audio Pops and Clicks
|
||||
=====================
|
||||
|
||||
|
@ -20,10 +21,11 @@ currently, however future audio codec hardware will have better pop and click
|
|||
suppression. Pops can be reduced within playback by powering the audio
|
||||
components in a specific order. This order is different for startup and
|
||||
shutdown and follows some basic rules:-
|
||||
::
|
||||
|
||||
Startup Order :- DAC --> Mixers --> Output PGA --> Digital Unmute
|
||||
|
||||
Shutdown Order :- Digital Mute --> Output PGA --> Mixers --> DAC
|
||||
Startup Order :- DAC --> Mixers --> Output PGA --> Digital Unmute
|
||||
|
||||
Shutdown Order :- Digital Mute --> Output PGA --> Mixers --> DAC
|
||||
|
||||
This assumes that the codec PCM output path from the DAC is via a mixer and then
|
||||
a PGA (programmable gain amplifier) before being output to the speakers.
|
||||
|
@ -36,10 +38,11 @@ Capture artifacts are somewhat easier to get rid as we can delay activating the
|
|||
ADC until all the pops have occurred. This follows similar power rules to
|
||||
playback in that components are powered in a sequence depending upon stream
|
||||
startup or shutdown.
|
||||
::
|
||||
|
||||
Startup Order - Input PGA --> Mixers --> ADC
|
||||
|
||||
Shutdown Order - ADC --> Mixers --> Input PGA
|
||||
Startup Order - Input PGA --> Mixers --> ADC
|
||||
|
||||
Shutdown Order - ADC --> Mixers --> Input PGA
|
||||
|
||||
|
||||
Zipper Noise
|
Loading…
Reference in New Issue