[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: Liam Girdwood <lg@opensource.wolfsonmicro.com> Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Jaroslav Kysela <perex@suse.cz>
This commit is contained in:
parent
c6d6eeeacc
commit
10b98527c3
5 changed files with 48 additions and 837 deletions
|
@ -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
|
||||||
|
|
||||||
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
|
||||||
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/
|
||||||
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:-
|
||||||
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:-
|
||||||
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.
|
||||||
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.
|
||||||
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:-
|
||||||
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 = {
|
||||||
.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 = {
|
||||||
.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
|
||||||
=====================
|
=====================
|
||||||
|
|
||||||
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
|
||||||
|
|
Loading…
Reference in a new issue