Commit 10b98527 authored by Liam Girdwood's avatar Liam Girdwood Committed by Jaroslav Kysela

[ALSA] ASoC documentation updates

This patch updates the documentation for ASoC to reflect the recent
changes in API between 0.12.x and 0.13.x
Changes:-
 o Removed all reference to old API's.
 o Removed references and examples of automatic DAI config and matching.
 o Fixed 80 char line length on some files.
Signed-off-by: default avatarLiam Girdwood <lg@opensource.wolfsonmicro.com>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
Signed-off-by: default avatarJaroslav Kysela <perex@suse.cz>
parent c6d6eeea
...@@ -54,493 +54,3 @@ Common PCM operating modes:- ...@@ -54,493 +54,3 @@ Common PCM operating modes:-
o Mode A - MSB is transmitted on falling edge of first BCLK after FRAME/SYNC. o 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. o Mode B - MSB is transmitted on rising edge of FRAME/SYNC.
ASoC DAI Configuration
======================
Every CODEC DAI and SoC DAI must have their capabilities defined in order to
be configured together at runtime when the audio and clocking parameters are
known. This is achieved by creating an array of struct snd_soc_hw_mode in the
the CODEC and SoC interface drivers. Each element in the array describes a DAI
mode and each mode is usually based upon the DAI system clock to sample rate
ratio (FS).
i.e. 48k sample rate @ 256 FS = sytem clock of 12.288 MHz
48000 * 256 = 12288000
The CPU and Codec DAI modes are then ANDed together at runtime to determine the
rutime DAI configuration for both the Codec and CPU.
When creating a new codec or SoC DAI it's probably best to start of with a few
sample rates first and then test your interface.
struct snd_soc_dai_mode is defined (in soc.h) as:-
/* SoC DAI mode */
struct snd_soc_dai_mode {
u16 fmt; /* SND_SOC_DAIFMT_* */
u16 tdm; /* SND_SOC_HWTDM_* */
u64 pcmfmt; /* SNDRV_PCM_FMTBIT_* */
u16 pcmrate; /* SND_SOC_HWRATE_* */
u16 pcmdir:2; /* SND_SOC_HWDIR_* */
u16 flags:8; /* hw flags */
u16 fs; /* mclk to rate divider */
u64 bfs; /* mclk to bclk dividers */
unsigned long priv; /* private mode data */
};
fmt:
----
This field defines the DAI mode hardware format (e.g. I2S settings) and
supports the following settings:-
1) hardware DAI formats
#define SND_SOC_DAIFMT_I2S (1 << 0) /* I2S mode */
#define SND_SOC_DAIFMT_RIGHT_J (1 << 1) /* Right justified mode */
#define SND_SOC_DAIFMT_LEFT_J (1 << 2) /* Left Justified mode */
#define SND_SOC_DAIFMT_DSP_A (1 << 3) /* L data msb after FRM */
#define SND_SOC_DAIFMT_DSP_B (1 << 4) /* L data msb during FRM */
#define SND_SOC_DAIFMT_AC97 (1 << 5) /* AC97 */
2) hw DAI signal inversions
#define SND_SOC_DAIFMT_NB_NF (1 << 8) /* normal bit clock + frame */
#define SND_SOC_DAIFMT_NB_IF (1 << 9) /* normal bclk + inv frm */
#define SND_SOC_DAIFMT_IB_NF (1 << 10) /* invert bclk + nor frm */
#define SND_SOC_DAIFMT_IB_IF (1 << 11) /* invert bclk + frm */
3) hw clock masters
This is wrt the codec, the inverse is true for the interface
i.e. if the codec is clk and frm master then the interface is
clk and frame slave.
#define SND_SOC_DAIFMT_CBM_CFM (1 << 12) /* codec clk & frm master */
#define SND_SOC_DAIFMT_CBS_CFM (1 << 13) /* codec clk slave & frm master */
#define SND_SOC_DAIFMT_CBM_CFS (1 << 14) /* codec clk master & frame slave */
#define SND_SOC_DAIFMT_CBS_CFS (1 << 15) /* codec clk & frm slave */
At least one option from each section must be selected. Multiple selections are
also supported e.g.
.fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_RIGHT_J | \
SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_NB_IF | SND_SOC_DAIFMT_IB_NF | \
SND_SOC_DAIFMT_IB_IF
tdm:
------
This field defines the Time Division Multiplexing left and right word
positions for the DAI mode if applicable. Set to SND_SOC_DAITDM_LRDW(0,0) for
no TDM.
pcmfmt:
---------
The hardware PCM format. This describes the PCM formats supported by the DAI
mode e.g.
.pcmfmt = SNDRV_PCM_FORMAT_S16_LE | SNDRV_PCM_FORMAT_S20_3LE | \
SNDRV_PCM_FORMAT_S24_3LE
pcmrate:
----------
The PCM sample rates supported by the DAI mode. e.g.
.pcmrate = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \
SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000
pcmdir:
---------
The stream directions supported by this mode. e.g. playback and capture
flags:
--------
The DAI hardware flags supported by the mode.
/* use bfs mclk divider mode (BCLK = MCLK / x) */
#define SND_SOC_DAI_BFS_DIV 0x1
/* use bfs rate mulitplier (BCLK = RATE * x)*/
#define SND_SOC_DAI_BFS_RATE 0x2
/* use bfs rcw multiplier (BCLK = RATE * CHN * WORD SIZE) */
#define SND_SOC_DAI_BFS_RCW 0x4
/* capture and playback can use different clocks */
#define SND_SOC_DAI_ASYNC 0x8
NOTE: Bitclock division and mulitiplication modes can be safely matched by the
core logic.
fs:
-----
The FS supported by this DAI mode FS is the ratio between the system clock and
the sample rate. See above
bfs:
------
BFS is the ratio of BCLK to MCLK or the ratio of BCLK to sample rate (this
depends on the codec or CPU DAI).
The BFS supported by the DAI mode. This can either be the ratio between the
bitclock (BCLK) and the sample rate OR the ratio between the system clock and
the sample rate. Depends on the flags above.
priv:
-----
private codec mode data.
Examples
========
Note that Codec DAI and CPU DAI examples are interchangeable in these examples
as long as the bus master is reversed. i.e.
SND_SOC_DAIFMT_CBM_CFM would become SND_SOC_DAIFMT_CBS_CFS
and vice versa.
This applies to all SND_SOC_DAIFMT_CB*_CF*.
Example 1
---------
Simple codec that only runs at 8k & 48k @ 256FS in master mode, can generate a
BCLK of either MCLK/2 or MCLK/4.
/* codec master */
{
.fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM,
.pcmfmt = SNDRV_PCM_FORMAT_S16_LE,
.pcmrate = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_48000,
.pcmdir = SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE,
.flags = SND_SOC_DAI_BFS_DIV,
.fs = 256,
.bfs = SND_SOC_FSBD(2) | SND_SOC_FSBD(4),
}
Example 2
---------
Simple codec that only runs at 8k & 48k @ 256FS in master mode, can generate a
BCLK of either Rate * 32 or Rate * 64.
/* codec master */
{
.fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM,
.pcmfmt = SNDRV_PCM_FORMAT_S16_LE,
.pcmrate = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_48000,
.pcmdir = SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE,
.flags = SND_SOC_DAI_BFS_RATE,
.fs = 256,
.bfs = 32,
},
{
.fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM,
.pcmfmt = SNDRV_PCM_FORMAT_S16_LE,
.pcmrate = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_48000,
.pcmdir = SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE,
.flags = SND_SOC_DAI_BFS_RATE,
.fs = 256,
.bfs = 64,
},
Example 3
---------
Codec that runs at 8k & 48k @ 256FS in master mode, can generate a BCLK that
is a multiple of Rate * channels * word size. (RCW) i.e.
BCLK = 8000 * 2 * 16 (8k, stereo, 16bit)
= 256kHz
This codecs supports a RCW multiple of 1,2
{
.fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM,
.pcmfmt = SNDRV_PCM_FORMAT_S16_LE,
.pcmrate = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_48000,
.pcmdir = SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE,
.flags = SND_SOC_DAI_BFS_RCW,
.fs = 256,
.bfs = SND_SOC_FSBW(1) | SND_SOC_FSBW(2),
}
Example 4
---------
Codec that only runs at 8k & 48k @ 256FS in master mode, can generate a
BCLK of either Rate * 32 or Rate * 64. Codec can also run in slave mode as long
as BCLK is rate * 32 or rate * 64.
/* codec master */
{
.fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM,
.pcmfmt = SNDRV_PCM_FORMAT_S16_LE,
.pcmrate = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_48000,
.pcmdir = SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE,
.flags = SND_SOC_DAI_BFS_RATE,
.fs = 256,
.bfs = 32,
},
{
.fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM,
.pcmfmt = SNDRV_PCM_FORMAT_S16_LE,
.pcmrate = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_48000,
.pcmdir = SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE,
.flags = SND_SOC_DAI_BFS_RATE,
.fs = 256,
.bfs = 64,
},
/* codec slave */
{
.fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS,
.pcmfmt = SNDRV_PCM_FORMAT_S16_LE,
.pcmdir = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_48000,
.pcmdir = SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE,
.flags = SND_SOC_DAI_BFS_RATE,
.fs = SND_SOC_FS_ALL,
.bfs = 32,
},
{
.fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS,
.pcmfmt = SNDRV_PCM_FORMAT_S16_LE,
.pcmdir = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_48000,
.pcmdir = SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE,
.flags = SND_SOC_DAI_BFS_RATE,
.fs = SND_SOC_FS_ALL,
.bfs = 64,
},
Example 5
---------
Codec that only runs at 8k, 16k, 32k, 48k, 96k @ 128FS, 192FS & 256FS in master
mode and can generate a BCLK of MCLK / (1,2,4,8,16). Codec can also run in slave
mode as and does not care about FS or BCLK (as long as there is enough bandwidth).
#define CODEC_FSB \
(SND_SOC_FSBD(1) | SND_SOC_FSBD(2) | SND_SOC_FSBD(4) | \
SND_SOC_FSBD(8) | SND_SOC_FSBD(16))
#define CODEC_RATES \
(SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_32000 |\
SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000)
/* codec master @ 128, 192 & 256 FS */
{
.fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM,
.pcmfmt = SNDRV_PCM_FORMAT_S16_LE,
.pcmrate = CODEC_RATES,
.pcmdir = SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE,
.flags = SND_SOC_DAI_BFS_DIV,
.fs = 128,
.bfs = CODEC_FSB,
},
{
.fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM,
.pcmfmt = SNDRV_PCM_FORMAT_S16_LE,
.pcmrate = CODEC_RATES,
.pcmdir = SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE,
.flags = SND_SOC_DAI_BFS_DIV,
.fs = 192,
.bfs = CODEC_FSB
},
{
.fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM,
.pcmfmt = SNDRV_PCM_FORMAT_S16_LE,
.pcmrate = CODEC_RATES,
.pcmdir = SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE,
.flags = SND_SOC_DAI_BFS_DIV,
.fs = 256,
.bfs = CODEC_FSB,
},
/* codec slave */
{
.fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS,
.pcmfmt = SNDRV_PCM_FORMAT_S16_LE,
.pcmrate = CODEC_RATES,
.pcmdir = SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE,
.fs = SND_SOC_FS_ALL,
.bfs = SND_SOC_FSB_ALL,
},
Example 6
---------
Codec that only runs at 8k, 44.1k, 48k @ different FS in master mode (for use
with a fixed MCLK) and can generate a BCLK of MCLK / (1,2,4,8,16).
Codec can also run in slave mode as and does not care about FS or BCLK (as long
as there is enough bandwidth). Codec can support 16, 24 and 32 bit PCM sample
sizes.
#define CODEC_FSB \
(SND_SOC_FSBD(1) | SND_SOC_FSBD(2) | SND_SOC_FSBD(4) | \
SND_SOC_FSBD(8) | SND_SOC_FSBD(16))
#define CODEC_PCM_FORMATS \
(SNDRV_PCM_FORMAT_S16_LE | SNDRV_PCM_FORMAT_S20_3LE | \
SNDRV_PCM_FORMAT_S24_3LE | SNDRV_PCM_FORMAT_S24_LE | SNDRV_PCM_FORMAT_S32_LE)
/* codec master */
{
.fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM,
.pcmfmt = SNDRV_PCM_FORMAT_S16_LE,
.pcmrate = SNDRV_PCM_RATE_8000,
.pcmdir = SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE,
.flags = SND_SOC_DAI_BFS_DIV,
.fs = 1536,
.bfs = CODEC_FSB,
},
{
.fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM,
.pcmfmt = SNDRV_PCM_FORMAT_S16_LE,
.pcmrate = SNDRV_PCM_RATE_44100,
.pcmdir = SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE,
.flags = SND_SOC_DAI_BFS_DIV,
.fs = 272,
.bfs = CODEC_FSB,
},
{
.fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM,
.pcmfmt = SNDRV_PCM_FORMAT_S16_LE,
.pcmrate = SNDRV_PCM_RATE_48000,
.pcmdir = SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE,
.flags = SND_SOC_DAI_BFS_DIV,
.fs = 256,
.bfs = CODEC_FSB,
},
/* codec slave */
{
.fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS,
.pcmfmt = SNDRV_PCM_FORMAT_S16_LE,
.pcmrate = CODEC_RATES,
.pcmdir = SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE,
.fs = SND_SOC_FS_ALL,
.bfs = SND_SOC_FSB_ALL,
},
Example 7
---------
AC97 Codec that does not support VRA (i.e only runs at 48k).
#define AC97_DIR \
(SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE)
#define AC97_PCM_FORMATS \
(SNDRV_PCM_FORMAT_S16_LE | SNDRV_PCM_FORMAT_S18_3LE | \
SNDRV_PCM_FORMAT_S20_3LE)
/* AC97 with no VRA */
{
.pcmfmt = AC97_PCM_FORMATS,
.pcmrate = SNDRV_PCM_RATE_48000,
}
Example 8
---------
CPU DAI that supports 8k - 48k @ 256FS and BCLK = MCLK / 4 in master mode.
Slave mode (CPU DAI is FRAME master) supports 8k - 96k at any FS as long as
BCLK = 64 * rate. (Intel XScale I2S controller).
#define PXA_I2S_DAIFMT \
(SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_NB_NF)
#define PXA_I2S_DIR \
(SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE)
#define PXA_I2S_RATES \
(SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \
SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
/* priv is divider */
static struct snd_soc_dai_mode pxa2xx_i2s_modes[] = {
/* pxa2xx I2S frame and clock master modes */
{
.fmt = PXA_I2S_DAIFMT | SND_SOC_DAIFMT_CBS_CFS,
.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
.pcmrate = SNDRV_PCM_RATE_8000,
.pcmdir = PXA_I2S_DIR,
.flags = SND_SOC_DAI_BFS_DIV,
.fs = 256,
.bfs = SND_SOC_FSBD(4),
.priv = 0x48,
},
{
.fmt = PXA_I2S_DAIFMT | SND_SOC_DAIFMT_CBS_CFS,
.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
.pcmrate = SNDRV_PCM_RATE_11025,
.pcmdir = PXA_I2S_DIR,
.flags = SND_SOC_DAI_BFS_DIV,
.fs = 256,
.bfs = SND_SOC_FSBD(4),
.priv = 0x34,
},
{
.fmt = PXA_I2S_DAIFMT | SND_SOC_DAIFMT_CBS_CFS,
.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
.pcmrate = SNDRV_PCM_RATE_16000,
.pcmdir = PXA_I2S_DIR,
.flags = SND_SOC_DAI_BFS_DIV,
.fs = 256,
.bfs = SND_SOC_FSBD(4),
.priv = 0x24,
},
{
.fmt = PXA_I2S_DAIFMT | SND_SOC_DAIFMT_CBS_CFS,
.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
.pcmrate = SNDRV_PCM_RATE_22050,
.pcmdir = PXA_I2S_DIR,
.flags = SND_SOC_DAI_BFS_DIV,
.fs = 256,
.bfs = SND_SOC_FSBD(4),
.priv = 0x1a,
},
{
.fmt = PXA_I2S_DAIFMT | SND_SOC_DAIFMT_CBS_CFS,
.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
.pcmrate = SNDRV_PCM_RATE_44100,
.pcmdir = PXA_I2S_DIR,
.flags = SND_SOC_DAI_BFS_DIV,
.fs = 256,
.bfs = SND_SOC_FSBD(4),
.priv = 0xd,
},
{
.fmt = PXA_I2S_DAIFMT | SND_SOC_DAIFMT_CBS_CFS,
.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
.pcmrate = SNDRV_PCM_RATE_48000,
.pcmdir = PXA_I2S_DIR,
.flags = SND_SOC_DAI_BFS_DIV,
.fs = 256,
.bfs = SND_SOC_FSBD(4),
.priv = 0xc,
},
/* pxa2xx I2S frame master and clock slave mode */
{
.fmt = PXA_I2S_DAIFMT | SND_SOC_DAIFMT_CBM_CFS,
.pcmfmt = SNDRV_PCM_FMTBIT_S16_LE,
.pcmrate = PXA_I2S_RATES,
.pcmdir = PXA_I2S_DIR,
.fs = SND_SOC_FS_ALL,
.flags = SND_SOC_DAI_BFS_RATE,
.bfs = 64,
.priv = 0x48,
},
};
...@@ -40,275 +40,12 @@ BCLK = LRC * x ...@@ -40,275 +40,12 @@ BCLK = LRC * x
BCLK = LRC * Channels * Word Size BCLK = LRC * Channels * Word Size
This relationship depends on the codec or SoC CPU in particular. ASoC can quite This relationship depends on the codec or SoC CPU in particular. In general
easily match BCLK generated by division (SND_SOC_DAI_BFS_DIV) with BCLK by it's best to configure BCLK to the lowest possible speed (depending on your
multiplication (SND_SOC_DAI_BFS_RATE) or BCLK generated by rate, number of channels and wordsize) to save on power.
Rate * Channels * Word size (RCW or SND_SOC_DAI_BFS_RCW).
It's also desireable to use the codec (if possible) to drive (or master) the
audio clocks as it's usually gives more accurate sample rates than the CPU.
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);
}
...@@ -6,21 +6,18 @@ codec to provide audio capture and playback. It should contain no code that is ...@@ -6,21 +6,18 @@ 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 specific to the target platform or machine. All platform and machine specific
code should be added to the platform and machine drivers respectively. code should be added to the platform and machine drivers respectively.
Each codec driver must provide the following features:- Each codec driver *must* provide the following features:-
1) Digital audio interface (DAI) description 1) Codec DAI and PCM configuration
2) Digital audio interface configuration 2) Codec control IO - using I2C, 3 Wire(SPI) or both API's
3) PCM's description 3) Mixers and audio controls
4) Codec control IO - using I2C, 3 Wire(SPI) or both API's 4) Codec audio operations
5) Mixers and audio controls
6) Sysclk configuration
7) Codec audio operations
Optionally, codec drivers can also provide:- Optionally, codec drivers can also provide:-
8) DAPM description. 5) DAPM description.
9) DAPM event handler. 6) DAPM event handler.
10) DAC Digital mute control. 7) DAC Digital mute control.
It's probably best to use this guide in conjuction with the existing codec It's probably best to use this guide in conjuction with the existing codec
driver code in sound/soc/codecs/ driver code in sound/soc/codecs/
...@@ -28,58 +25,47 @@ driver code in sound/soc/codecs/ ...@@ -28,58 +25,47 @@ driver code in sound/soc/codecs/
ASoC Codec driver breakdown ASoC Codec driver breakdown
=========================== ===========================
1 - Digital Audio Interface (DAI) description 1 - Codec DAI and PCM configuration
--------------------------------------------- -----------------------------------
The DAI is a digital audio data transfer link between the codec and host SoC Each codec driver must have a struct snd_soc_codec_dai to define it's DAI and
CPU. It typically has data transfer capabilities in both directions PCM's capablities and operations. This struct is exported so that it can be
(playback and capture) and can run at a variety of different speeds. registered with the core by your machine driver.
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. e.g.
static struct snd_soc_pcm_codec wm8731_pcm_client = { struct snd_soc_codec_dai wm8731_dai = {
.name = "WM8731", .name = "WM8731",
/* playback capabilities */
.playback = { .playback = {
.stream_name = "Playback", .stream_name = "Playback",
.channels_min = 1, .channels_min = 1,
.channels_max = 2, .channels_max = 2,
}, .rates = WM8731_RATES,
.formats = WM8731_FORMATS,},
/* capture capabilities */
.capture = { .capture = {
.stream_name = "Capture", .stream_name = "Capture",
.channels_min = 1, .channels_min = 1,
.channels_max = 2, .channels_max = 2,
}, .rates = WM8731_RATES,
.config_sysclk = wm8731_config_sysclk, .formats = WM8731_FORMATS,},
/* pcm operations - see section 4 below */
.ops = { .ops = {
.prepare = wm8731_pcm_prepare, .prepare = wm8731_pcm_prepare,
.hw_params = wm8731_hw_params,
.shutdown = wm8731_shutdown,
}, },
.caps = { /* DAI operations - see DAI.txt */
.num_modes = ARRAY_SIZE(wm8731_hwfmt), .dai_ops = {
.modes = &wm8731_hwfmt[0], .digital_mute = wm8731_mute,
}, .set_sysclk = wm8731_set_dai_sysclk,
.set_fmt = wm8731_set_dai_fmt,
}
}; };
EXPORT_SYMBOL_GPL(wm8731_dai);
4 - Codec control IO 2 - Codec control IO
-------------------- --------------------
The codec can ususally be controlled via an I2C or SPI style interface (AC97 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 combines control with data in the DAI). The codec drivers will have to provide
...@@ -104,7 +90,7 @@ read/write:- ...@@ -104,7 +90,7 @@ read/write:-
hw_read_t hw_read; hw_read_t hw_read;
5 - Mixers and audio controls 3 - Mixers and audio controls
----------------------------- -----------------------------
All the codec mixers and audio controls can be defined using the convenience All the codec mixers and audio controls can be defined using the convenience
macros defined in soc.h. macros defined in soc.h.
...@@ -143,28 +129,7 @@ Defines an single enumerated control as follows:- ...@@ -143,28 +129,7 @@ Defines an single enumerated control as follows:-
Defines a stereo enumerated control Defines a stereo enumerated control
6 - System clock configuration. 4 - Codec Audio Operations
-------------------------------
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:- The codec driver also supports the following alsa operations:-
...@@ -181,7 +146,7 @@ Please refer to the alsa driver PCM documentation for details. ...@@ -181,7 +146,7 @@ Please refer to the alsa driver PCM documentation for details.
http://www.alsa-project.org/~iwai/writing-an-alsa-driver/c436.htm http://www.alsa-project.org/~iwai/writing-an-alsa-driver/c436.htm
8 - DAPM description. 5 - DAPM description.
--------------------- ---------------------
The Dynamic Audio Power Management description describes the codec's power The Dynamic Audio Power Management description describes the codec's power
components, their relationships and registers to the ASoC core. Please read components, their relationships and registers to the ASoC core. Please read
...@@ -190,7 +155,7 @@ dapm.txt for details of building the description. ...@@ -190,7 +155,7 @@ dapm.txt for details of building the description.
Please also see the examples in other codec drivers. Please also see the examples in other codec drivers.
9 - DAPM event handler 6 - DAPM event handler
---------------------- ----------------------
This function is a callback that handles codec domain PM calls and system 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 domain PM calls (e.g. suspend and resume). It's used to put the codec to sleep
...@@ -210,7 +175,7 @@ Power states:- ...@@ -210,7 +175,7 @@ Power states:-
SNDRV_CTL_POWER_D3cold: /* Everything Off, without power */ SNDRV_CTL_POWER_D3cold: /* Everything Off, without power */
10 - Codec DAC digital mute control. 7 - Codec DAC digital mute control.
------------------------------------ ------------------------------------
Most codecs have a digital mute before the DAC's that can be used to minimise 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. any system noise. The mute stops any digital data from entering the DAC.
......
...@@ -64,7 +64,7 @@ static struct snd_soc_dai_link corgi_dai = { ...@@ -64,7 +64,7 @@ static struct snd_soc_dai_link corgi_dai = {
.cpu_dai = &pxa_i2s_dai, .cpu_dai = &pxa_i2s_dai,
.codec_dai = &wm8731_dai, .codec_dai = &wm8731_dai,
.init = corgi_wm8731_init, .init = corgi_wm8731_init,
.config_sysclk = corgi_config_sysclk, .ops = &corgi_ops,
}; };
struct snd_soc_machine then sets up the machine with it's DAI's. e.g. struct snd_soc_machine then sets up the machine with it's DAI's. e.g.
...@@ -74,7 +74,6 @@ static struct snd_soc_machine snd_soc_machine_corgi = { ...@@ -74,7 +74,6 @@ static struct snd_soc_machine snd_soc_machine_corgi = {
.name = "Corgi", .name = "Corgi",
.dai_link = &corgi_dai, .dai_link = &corgi_dai,
.num_links = 1, .num_links = 1,
.ops = &corgi_ops,
}; };
......
...@@ -2,14 +2,14 @@ Audio Pops and Clicks ...@@ -2,14 +2,14 @@ Audio Pops and Clicks
===================== =====================
Pops and clicks are unwanted audio artifacts caused by the powering up and down 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 of components within the audio subsystem. This is noticable on PC's when an
module is either loaded or unloaded (at module load time the sound card is 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). 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 Pops and clicks can be more frequent on portable systems with DAPM. This is
the components within the subsystem are being dynamically powered depending on because the components within the subsystem are being dynamically powered
the audio usage and this can subsequently cause a small pop or click every time a depending on the audio usage and this can subsequently cause a small pop or
component power state is changed. click every time a component power state is changed.
Minimising Playback Pops and Clicks Minimising Playback Pops and Clicks
......
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