Commit eb1a6af3 authored by Liam Girdwood's avatar Liam Girdwood Committed by Jaroslav Kysela

[ALSA] ASoC: documentation & maintainer

This patch adds documentation describing the ASoC architecture and a
maintainer entry for ASoC.
The documentation includes the following files:-
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.
Signed-off-by: default avatarLiam Girdwood <liam.girdwood@wolfsonmicro.com>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
Signed-off-by: default avatarJaroslav Kysela <perex@suse.cz>
parent a3288176
This diff is collapsed.
Audio Clocking
==============
This text describes the audio clocking terms in ASoC and digital audio in
general. Note: Audio clocking can be complex !
Master Clock
------------
Every audio subsystem is driven by a master clock (sometimes refered to as MCLK
or SYSCLK). This audio master clock can be derived from a number of sources
(e.g. crystal, PLL, CPU clock) and is responsible for producing the correct
audio playback and capture sample rates.
Some master clocks (e.g. PLL's and CPU based clocks) are configuarble in that
their speed can be altered by software (depending on the system use and to save
power). Other master clocks are fixed at at set frequency (i.e. crystals).
DAI Clocks
----------
The Digital Audio Interface is usually driven by a Bit Clock (often referred to
as BCLK). This clock is used to drive the digital audio data across the link
between the codec and CPU.
The DAI also has a frame clock to signal the start of each audio frame. This
clock is sometimes referred to as LRC (left right clock) or FRAME. This clock
runs at exactly the sample rate.
Bit Clock is usually always a ratio of MCLK or a multiple of LRC. i.e.
BCLK = MCLK / x
or
BCLK = LRC * x
This relationship depends on the codec or SoC CPU in particular. ASoC can quite
easily match a codec that generates BCLK by division (FSBD) with a CPU that
generates BCLK by multiplication (FSB).
ASoC Clocking
-------------
The ASoC core determines the clocking for each particular configuration at
runtime. This is to allow for dynamic audio clocking wereby the audio clock is
variable and depends on the system state or device usage scenario. i.e. a voice
call requires slower clocks (and hence less power) than MP3 playback.
ASoC will call the config_sysclock() function for the target machine during the
audio parameters configuration. The function is responsible for then clocking
the machine audio subsytem and returning the audio clock speed to the core.
This function should also call the codec and cpu DAI clock_config() functions
to configure their respective internal clocking if required.
ASoC Clocking Control Flow
--------------------------
The ASoC core will call the machine drivers config_sysclock() when most of the
DAI capabilities are known. The machine driver is then responsible for calling
the codec and/or CPU DAI drivers with the selected capabilities and the current
MCLK. Note that the machine driver is also resonsible for setting the MCLK (and
enabling it).
(1) Match Codec and CPU DAI capabilities. At this point we have
matched the majority of the DAI fields and now need to make sure this
mode is currently clockable.
(2) machine->config_sysclk() is now called with the matched DAI FS, sample
rate and BCLK master. This function then gets/sets the current audio
clock (depening on usage) and calls the codec and CPUI DAI drivers with
the FS, rate, BCLK master and MCLK.
(3) Codec/CPU DAI config_sysclock(). This function checks that the FS, rate,
BCLK master and MCLK are acceptable for the codec or CPU DAI. It also
sets the DAI internal state to work with said clocks.
The config_sysclk() functions for CPU, codec and machine should return the MCLK
on success and 0 on failure.
Examples (b = BCLK, l = LRC)
============================
Example 1
---------
Simple codec that only runs at 48k @ 256FS in master mode.
CPU only runs as slave DAI, however it generates a variable MCLK.
-------- ---------
| | <----mclk--- | |
| Codec |b -----------> | CPU |
| |l -----------> | |
| | | |
-------- ---------
The codec driver has the following config_sysclock()
static unsigned int config_sysclk(struct snd_soc_codec_dai *dai,
struct snd_soc_clock_info *info, unsigned int clk)
{
/* make sure clock is 256 * rate */
if(info->rate << 8 == clk) {
dai->mclk = clk;
return clk;
}
return 0;
}
The CPU I2S DAI driver has the following config_sysclk()
static unsigned int config_sysclk(struct snd_soc_codec_dai *dai,
struct snd_soc_clock_info *info, unsigned int clk)
{
/* can we support this clk */
if(set_audio_clk(clk) < 0)
return -EINVAL;
dai->mclk = clk;
return dai->clk;
}
The machine driver config_sysclk() in this example is as follows:-
unsigned int machine_config_sysclk(struct snd_soc_pcm_runtime *rtd,
struct snd_soc_clock_info *info)
{
int clk = info->rate * info->fs;
/* check that CPU can deliver clock */
if(rtd->cpu_dai->config_sysclk(rtd->cpu_dai, info, clk) < 0)
return -EINVAL;
/* can codec work with this clock */
return rtd->codec_dai->config_sysclk(rtd->codec_dai, info, clk);
}
Example 2
---------
Codec that can master at 8k and 48k at various FS (and hence supports a fixed
set of input MCLK's) and can also be slave at various FS .
The CPU can master at 8k and 48k @256 FS and can be slave at any FS.
MCLK is a 12.288MHz crystal on this machine.
-------- ---------
| | <---xtal---> | |
| Codec |b <----------> | CPU |
| |l <----------> | |
| | | |
-------- ---------
The codec driver has the following config_sysclock()
/* supported input clocks */
const static int hifi_clks[] = {11289600, 12000000, 12288000,
16934400, 18432000};
static unsigned int config_hsysclk(struct snd_soc_codec_dai *dai,
struct snd_soc_clock_info *info, unsigned int clk)
{
int i;
/* is clk supported */
for(i = 0; i < ARRAY_SIZE(hifi_clks); i++) {
if(clk == hifi_clks[i]) {
dai->mclk = clk;
return clk;
}
}
/* this clk is not supported */
return 0;
}
The CPU I2S DAI driver has the following config_sysclk()
static unsigned int config_sysclk(struct snd_soc_codec_dai *dai,
struct snd_soc_clock_info *info, unsigned int clk)
{
/* are we master or slave */
if (info->bclk_master &
(SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_CBM_CFS)) {
/* we can only master @ 256FS */
if(info->rate << 8 == clk) {
dai->mclk = clk;
return dai->mclk;
}
} else {
/* slave we can run at any FS */
dai->mclk = clk;
return dai->mclk;
}
/* not supported */
return dai->clk;
}
The machine driver config_sysclk() in this example is as follows:-
unsigned int machine_config_sysclk(struct snd_soc_pcm_runtime *rtd,
struct snd_soc_clock_info *info)
{
int clk = 12288000; /* 12.288MHz */
/* who's driving the link */
if (info->bclk_master &
(SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_CBM_CFS)) {
/* codec master */
/* check that CPU can work with clock */
if(rtd->cpu_dai->config_sysclk(rtd->cpu_dai, info, clk) < 0)
return -EINVAL;
/* can codec work with this clock */
return rtd->codec_dai->config_sysclk(rtd->codec_dai, info, clk);
} else {
/* cpu master */
/* check that codec can work with clock */
if(rtd->codec_dai->config_sysclk(rtd->codec_dai, info, clk) < 0)
return -EINVAL;
/* can CPU work with this clock */
return rtd->cpu_dai->config_sysclk(rtd->cpu_dai, info, clk);
}
}
Example 3
---------
Codec that masters at 8k ... 48k @256 FS. Codec can also be slave and
doesn't care about FS. The codec has an internal PLL and dividers to generate
the necessary internal clocks (for 256FS).
CPU can only be slave and doesn't care about FS.
MCLK is a non controllable 13MHz clock from the CPU.
-------- ---------
| | <----mclk--- | |
| Codec |b <----------> | CPU |
| |l <----------> | |
| | | |
-------- ---------
The codec driver has the following config_sysclock()
/* valid PCM clock dividers * 2 */
static int pcm_divs[] = {2, 6, 11, 4, 8, 12, 16};
static unsigned int config_vsysclk(struct snd_soc_codec_dai *dai,
struct snd_soc_clock_info *info, unsigned int clk)
{
int i, j, best_clk = info->fs * info->rate;
/* can we run at this clk without the PLL ? */
for (i = 0; i < ARRAY_SIZE(pcm_divs); i++) {
if ((best_clk >> 1) * pcm_divs[i] == clk) {
dai->pll_in = 0;
dai->clk_div = pcm_divs[i];
dai->mclk = best_clk;
return dai->mclk;
}
}
/* now check for PLL support */
for (i = 0; i < ARRAY_SIZE(pll_div); i++) {
if (pll_div[i].pll_in == clk) {
for (j = 0; j < ARRAY_SIZE(pcm_divs); j++) {
if (pll_div[i].pll_out == pcm_divs[j] * (best_clk >> 1)) {
dai->pll_in = clk;
dai->pll_out = pll_div[i].pll_out;
dai->clk_div = pcm_divs[j];
dai->mclk = best_clk;
return dai->mclk;
}
}
}
}
/* this clk is not supported */
return 0;
}
The CPU I2S DAI driver has the does not need a config_sysclk() as it can slave
at any FS.
unsigned int config_sysclk(struct snd_soc_pcm_runtime *rtd,
struct snd_soc_clock_info *info)
{
/* codec has pll that generates mclk from 13MHz xtal */
return rtd->codec_dai->config_sysclk(rtd->codec_dai, info, 13000000);
}
ASoC Codec Driver
=================
The codec driver is generic and hardware independent code that configures the
codec to provide audio capture and playback. It should contain no code that is
specific to the target platform or machine. All platform and machine specific
code should be added to the platform and machine drivers respectively.
Each codec driver must provide the following features:-
1) Digital audio interface (DAI) description
2) Digital audio interface configuration
3) PCM's description
4) Codec control IO - using I2C, 3 Wire(SPI) or both API's
5) Mixers and audio controls
6) Sysclk configuration
7) Codec audio operations
Optionally, codec drivers can also provide:-
8) DAPM description.
9) DAPM event handler.
10) DAC Digital mute control.
It's probably best to use this guide in conjuction with the existing codec
driver code in sound/soc/codecs/
ASoC Codec driver breakdown
===========================
1 - Digital Audio Interface (DAI) description
---------------------------------------------
The DAI is a digital audio data transfer link between the codec and host SoC
CPU. It typically has data transfer capabilities in both directions
(playback and capture) and can run at a variety of different speeds.
Supported interfaces currently include AC97, I2S and generic PCM style links.
Please read DAI.txt for implementation information.
2 - Digital Audio Interface (DAI) configuration
-----------------------------------------------
DAI configuration is handled by the codec_pcm_prepare function and is
responsible for configuring and starting the DAI on the codec. This can be
called multiple times and is atomic. It can access the runtime parameters.
This usually consists of a large function with numerous switch statements to
set up each configuration option. These options are set by the core at runtime.
3 - Codec PCM's
---------------
Each codec must have it's PCM's defined. This defines the number of channels,
stream names, callbacks and codec name. It is also used to register the DAI
with the ASoC core. The PCM structure also associates the DAI capabilities with
the ALSA PCM.
e.g.
static struct snd_soc_pcm_codec wm8731_pcm_client = {
.name = "WM8731",
.playback = {
.stream_name = "Playback",
.channels_min = 1,
.channels_max = 2,
},
.capture = {
.stream_name = "Capture",
.channels_min = 1,
.channels_max = 2,
},
.config_sysclk = wm8731_config_sysclk,
.ops = {
.prepare = wm8731_pcm_prepare,
},
.caps = {
.num_modes = ARRAY_SIZE(wm8731_hwfmt),
.modes = &wm8731_hwfmt[0],
},
};
4 - Codec control IO
--------------------
The codec can ususally be controlled via an I2C or SPI style interface (AC97
combines control with data in the DAI). The codec drivers will have to provide
functions to read and write the codec registers along with supplying a register
cache:-
/* IO control data and register cache */
void *control_data; /* codec control (i2c/3wire) data */
void *reg_cache;
Codec read/write should do any data formatting and call the hardware read write
below to perform the IO. These functions are called by the core and alsa when
performing DAPM or changing the mixer:-
unsigned int (*read)(struct snd_soc_codec *, unsigned int);
int (*write)(struct snd_soc_codec *, unsigned int, unsigned int);
Codec hardware IO functions - usually points to either the I2C, SPI or AC97
read/write:-
hw_write_t hw_write;
hw_read_t hw_read;
5 - 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
shift = control bit(s) offset in register
mask = control bit size(s) e.g. mask of 7 = 3 bits
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
xmask = control bit(s) size
xtexts = pointer to array of strings that describe each setting
#define SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, xtexts)
Defines a stereo enumerated control
6 - System clock configuration.
-------------------------------
The system clock that drives the audio subsystem can change depending on sample
rate and the system power state. i.e.
o Higher sample rates sometimes need a higher system clock.
o Low system power states can sometimes limit the available clocks.
This function is a callback that the machine driver can call to set and
determine if the clock and sample rate combination is supported by the codec at
the present time (and system state).
NOTE: If the codec has a PLL then it has a lot more flexability wrt clock and
sample rate combinations.
Your config_sysclock function should return the MCLK if it's a valid
combination for your codec else 0;
Please read clocking.txt now.
7 - Codec Audio Operations
--------------------------
The codec driver also supports the following alsa operations:-
/* SoC audio ops */
struct snd_soc_ops {
int (*startup)(snd_pcm_substream_t *);
void (*shutdown)(snd_pcm_substream_t *);
int (*hw_params)(snd_pcm_substream_t *, snd_pcm_hw_params_t *);
int (*hw_free)(snd_pcm_substream_t *);
int (*prepare)(snd_pcm_substream_t *);
};
Please refer to the alsa driver PCM documentation for details.
http://www.alsa-project.org/~iwai/writing-an-alsa-driver/c436.htm
8 - DAPM description.
---------------------
The Dynamic Audio Power Management description describes the codec's power
components, their relationships and registers to the ASoC core. Please read
dapm.txt for details of building the description.
Please also see the examples in other codec drivers.
9 - 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's 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 */
SNDRV_CTL_POWER_D1: /* partial On */
SNDRV_CTL_POWER_D2: /* partial On */
SNDRV_CTL_POWER_D3hot: /* Off, with power */
/* everything off except vref/vmid, inactive */
SNDRV_CTL_POWER_D3cold: /* Everything Off, without power */
10 - Codec DAC digital mute control.
------------------------------------
Most codecs have a digital mute before the DAC's that can be used to minimise
any system noise. The mute stops any digital data from entering the DAC.
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_codec *codec,
struct snd_soc_codec_dai *dai, int mute)
{
u16 mute_reg = wm8974_read_reg_cache(codec, WM8974_DAC) & 0xffbf;
if(mute)
wm8974_write(codec, WM8974_DAC, mute_reg | 0x40);
else
wm8974_write(codec, WM8974_DAC, mute_reg);
return 0;
}
This diff is collapsed.
ASoC Machine Driver
===================
The ASoC machine (or board) driver is the code that glues together the platform
and codec drivers.
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_machine {
char *name;
int (*probe)(struct platform_device *pdev);
int (*remove)(struct platform_device *pdev);
/* the pre and post PM functions are used to do any PM work before and
* after the codec and DAI's do any PM work. */
int (*suspend_pre)(struct platform_device *pdev, pm_message_t state);
int (*suspend_post)(struct platform_device *pdev, pm_message_t state);
int (*resume_pre)(struct platform_device *pdev);
int (*resume_post)(struct platform_device *pdev);
/* machine stream operations */
struct snd_soc_ops *ops;
/* CPU <--> Codec DAI links */
struct snd_soc_dai_link *dai_link;
int num_links;
};
probe()/remove()
----------------
probe/remove are optional. Do any machine specific probe here.
suspend()/resume()
------------------
The machine driver has pre and post versions of suspend and resume to take care
of any machine audio tasks that have to be done before or after the codec, DAI's
and DMA is suspended and resumed. Optional.
Machine operations
------------------
The machine specific audio operations can be set here. Again this is optional.
Machine DAI Configuration
-------------------------
The machine DAI configuration glues all the codec and CPU DAI's together. It can
also be used to set up the DAI system clock and for any machine related DAI
initialisation e.g. the machine audio map can be connected to the codec audio
map, unconnnected codec pins can be set as such. Please see corgi.c, spitz.c
for examples.
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 = {
.name = "WM8731",
.stream_name = "WM8731",
.cpu_dai = &pxa_i2s_dai,
.codec_dai = &wm8731_dai,
.init = corgi_wm8731_init,
.config_sysclk = corgi_config_sysclk,
};
struct snd_soc_machine then sets up the machine with it's DAI's. e.g.
/* corgi audio machine driver */
static struct snd_soc_machine snd_soc_machine_corgi = {
.name = "Corgi",
.dai_link = &corgi_dai,
.num_links = 1,
.ops = &corgi_ops,
};
Machine Audio Subsystem
-----------------------
The machine soc device glues the platform, machine and codec driver together.
Private data can also be set here. e.g.
/* corgi audio private data */
static struct wm8731_setup_data corgi_wm8731_setup = {
.i2c_address = 0x1b,
};
/* corgi audio subsystem */
static struct snd_soc_device corgi_snd_devdata = {
.machine = &snd_soc_machine_corgi,
.platform = &pxa2xx_soc_platform,
.codec_dev = &soc_codec_dev_wm8731,
.codec_data = &corgi_wm8731_setup,
};
Machine Power Map
-----------------
The machine driver can optionally extend the codec power map and to become an
audio power map of the audio subsystem. This allows for automatic power up/down
of speaker/HP amplifiers, etc. Codec pins can be connected to the machines jack
sockets in the machine init function. See soc/pxa/spitz.c and dapm.txt for
details.
Machine Controls
----------------
Machine specific audio mixer controls can be added in the dai init function.
\ No newline at end of file
ALSA SoC Layer
==============
The overall project goal of the ALSA System on Chip (ASoC) layer is to provide
better ALSA support for embedded system on chip procesors (e.g. pxa2xx, au1x00,
iMX, etc) and portable audio codecs. Currently there is some support in the
kernel for SoC audio, however it has some limitations:-
* Currently, codec drivers are often tightly coupled to the underlying SoC
cpu. This is not ideal and leads to code duplication i.e. Linux now has 4
different wm8731 drivers for 4 different SoC platforms.
* There is no standard method to signal user initiated audio events.
e.g. Headphone/Mic insertion, Headphone/Mic detection after an insertion
event. These are quite common events on portable devices and ofter require
machine specific code to re route audio, enable amps etc after such an event.
* Current drivers tend to power up the entire codec when playing
(or recording) audio. This is fine for a PC, but tends to waste a lot of
power on portable devices. There is also no support for saving power via
changing codec oversampling rates, bias currents, etc.
ASoC Design
===========
The ASoC layer is designed to address these issues and provide the following
features :-
* Codec independence. Allows reuse of codec drivers on other platforms
and machines.
* Easy I2S/PCM audio interface setup between codec and SoC. Each SoC interface
and codec registers it's audio interface capabilities with the core and are
subsequently matched and configured when the application hw params are known.
* Dynamic Audio Power Management (DAPM). DAPM automatically sets the codec to
it's minimum power state at all times. This includes powering up/down
internal power blocks depending on the internal codec audio routing and any
active streams.
* Pop and click reduction. Pops and clicks can be reduced by powering the
codec up/down in the correct sequence (including using digital mute). ASoC
signals the codec when to change power states.
* Machine specific controls: Allow machines to add controls to the sound card
e.g. volume control for speaker amp.
To achieve all this, ASoC basically splits an embedded audio system into 3
components :-
* Codec driver: The codec driver is platform independent and contains audio
controls, audio interface capabilities, codec dapm definition and codec IO
functions.
* Platform driver: The platform driver contains the audio dma engine and audio
interface drivers (e.g. I2S, AC97, PCM) for that platform.
* Machine driver: The machine driver handles any machine specific controls and
audio events. i.e. turing 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.
\ No newline at end of file
ASoC Platform Driver
====================
An ASoC platform driver can be divided into audio DMA and SoC DAI configuration
and control. The platform drivers only target the SoC CPU and must have no board
specific code.
Audio DMA
=========
The platform DMA driver optionally supports the following alsa operations:-
/* SoC audio ops */
struct snd_soc_ops {
int (*startup)(snd_pcm_substream_t *);
void (*shutdown)(snd_pcm_substream_t *);
int (*hw_params)(snd_pcm_substream_t *, snd_pcm_hw_params_t *);
int (*hw_free)(snd_pcm_substream_t *);
int (*prepare)(snd_pcm_substream_t *);
int (*trigger)(snd_pcm_substream_t *, int);
};
The platform driver exports it's DMA functionailty via struct snd_soc_platform:-
struct snd_soc_platform {
char *name;
int (*probe)(struct platform_device *pdev);
int (*remove)(struct platform_device *pdev);
int (*suspend)(struct platform_device *pdev, struct snd_soc_cpu_dai *cpu_dai);
int (*resume)(struct platform_device *pdev, struct snd_soc_cpu_dai *cpu_dai);
/* pcm creation and destruction */
int (*pcm_new)(snd_card_t *, struct snd_soc_codec_dai *, snd_pcm_t *);
void (*pcm_free)(snd_pcm_t *);
/* platform stream ops */
snd_pcm_ops_t *pcm_ops;
};
Please refer to the alsa driver documentation for details of audio DMA.
http://www.alsa-project.org/~iwai/writing-an-alsa-driver/c436.htm
An example DMA driver is soc/pxa/pxa2xx-pcm.c
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)
Please see codec.txt for a description of items 1 - 4.
Audio Pops and Clicks
=====================
Pops and clicks are unwanted audio artifacts caused by the powering up and down
of components within the audio subsystem. This is noticable on PC's when an audio
module is either loaded or unloaded (at module load time the sound card is
powered up and causes a popping noise on the speakers).
Pops and clicks can be more frequent on portable systems with DAPM. This is because
the components within the subsystem are being dynamically powered depending on
the audio usage and this can subsequently cause a small pop or click every time a
component power state is changed.
Minimising Playback Pops and Clicks
===================================
Playback pops in portable audio subsystems cannot be completely eliminated atm,
however future audio codec hardware will have better pop and click supression.
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
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.
Minimising Capture Pops and Clicks
==================================
Capture artifacts are somewhat easier to get rid as we can delay activating the
ADC until all the pops have occured. 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
Zipper Noise
============
An unwanted zipper noise can occur within the audio playback or capture stream
when a volume control is changed near its maximum gain value. The zipper noise
is heard when the gain increase or decrease changes the mean audio signal
amplitude too quickly. It can be minimised by enabling the zero cross setting
for each volume control. The ZC forces the gain change to occur when the signal
crosses the zero amplitude line.
......@@ -3037,6 +3037,12 @@ M: perex@suse.cz
L: alsa-devel@alsa-project.org
S: Maintained
SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT
P: Liam Girdwood
M: liam.girdwood@wolfsonmicro.com
L: alsa-devel@alsa-project.org
S: Supported
SPI SUBSYSTEM
P: David Brownell
M: dbrownell@users.sourceforge.net
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment