diff options
| author | Cliff Brake <cbrake@bec-systems.com> | 2007-01-31 13:41:09 +0000 |
|---|---|---|
| committer | Cliff Brake <cbrake@bec-systems.com> | 2007-01-31 13:41:09 +0000 |
| commit | a3990a712303e30e9d131f4c146f1cfde44255ed (patch) | |
| tree | ced2d3edc8c7fe37b3d9f9840dddbff71fcc54e2 | |
| parent | 7a2c81bf198b4bcd8f344a1ef72734d1d605bba9 (diff) | |
logicpd-pxa270 2.6.19.2: update kernel, contributed by Shane Volpe
24 files changed, 43282 insertions, 1 deletions
diff --git a/conf/machine/logicpd-pxa270.conf b/conf/machine/logicpd-pxa270.conf index dacee830b7..435014ac5c 100644 --- a/conf/machine/logicpd-pxa270.conf +++ b/conf/machine/logicpd-pxa270.conf @@ -3,7 +3,7 @@ #@DESCRIPTION: Machine configuration for LogicPD PXA270 Zoom Development Platform #OLDEST_KERNEL = "2.6.17-rc5" TARGET_ARCH = "arm" -PREFERRED_VERSION_logicpd-pxa270 = "2.6.17-rc5" +PREFERRED_VERSION_logicpd-pxa270 = "2.6.19.2" GUI_MACHINE_CLASS = "smallscreen" PREFERRED_PROVIDER_virtual/kernel = "${MACHINE}" diff --git a/packages/linux/logicpd-pxa270-2.6.19.2/.mtn2git_empty b/packages/linux/logicpd-pxa270-2.6.19.2/.mtn2git_empty new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/packages/linux/logicpd-pxa270-2.6.19.2/.mtn2git_empty diff --git a/packages/linux/logicpd-pxa270-2.6.19.2/asoc-v0.12.4.patch b/packages/linux/logicpd-pxa270-2.6.19.2/asoc-v0.12.4.patch new file mode 100644 index 0000000000..420f4aa2e2 --- /dev/null +++ b/packages/linux/logicpd-pxa270-2.6.19.2/asoc-v0.12.4.patch @@ -0,0 +1,31712 @@ +Index: linux-2.6-pxa-new/Documentation/sound/alsa/soc/DAI.txt +=================================================================== +--- /dev/null ++++ linux-2.6-pxa-new/Documentation/sound/alsa/soc/DAI.txt +@@ -0,0 +1,546 @@ ++ASoC currently supports the three main Digital Audio Interfaces (DAI) found on ++SoC controllers and portable audio CODECS today, namely AC97, I2S and PCM. ++ ++ ++AC97 ++==== ++ ++ AC97 is a five wire interface commonly found on many PC sound cards. It is ++now also popular in many portable devices. This DAI has a reset line and time ++multiplexes its data on its SDATA_OUT (playback) and SDATA_IN (capture) lines. ++The bit clock (BCLK) is always driven by the CODEC (usually 12.288MHz) and the ++frame (FRAME) (usually 48kHz) is always driven by the controller. Each AC97 ++frame is 21uS long and is divided into 13 time slots. ++ ++The AC97 specification can be found at :- ++http://www.intel.com/design/chipsets/audio/ac97_r23.pdf ++ ++ ++I2S ++=== ++ ++ I2S is a common 4 wire DAI used in HiFi, STB and portable devices. The Tx and ++Rx lines are used for audio transmision, whilst the bit clock (BCLK) and ++left/right clock (LRC) synchronise the link. I2S is flexible in that either the ++controller or CODEC can drive (master) the BCLK and LRC clock lines. Bit clock ++usually varies depending on the sample rate and the master system clock ++(SYSCLK). LRCLK is the same as the sample rate. A few devices support separate ++ADC and DAC LRCLK's, this allows for similtanious capture and playback at ++different sample rates. ++ ++I2S has several different operating modes:- ++ ++ o I2S - MSB is transmitted on the falling edge of the first BCLK after LRC ++ transition. ++ ++ o Left Justified - MSB is transmitted on transition of LRC. ++ ++ o Right Justified - MSB is transmitted sample size BCLK's before LRC ++ transition. ++ ++PCM ++=== ++ ++PCM is another 4 wire interface, very similar to I2S, that can support a more ++flexible protocol. It has bit clock (BCLK) and sync (SYNC) lines that are used ++to synchronise the link whilst the Tx and Rx lines are used to transmit and ++receive the audio data. Bit clock usually varies depending on sample rate ++whilst sync runs at the sample rate. PCM also supports Time Division ++Multiplexing (TDM) in that several devices can use the bus similtaniuosly (This ++is sometimes referred to as network mode). ++ ++Common PCM operating modes:- ++ ++ o Mode A - MSB is transmitted on falling edge of first BCLK after FRAME/SYNC. ++ ++ 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, ++ }, ++}; +Index: linux-2.6-pxa-new/Documentation/sound/alsa/soc/clocking.txt +=================================================================== +--- /dev/null ++++ linux-2.6-pxa-new/Documentation/sound/alsa/soc/clocking.txt +@@ -0,0 +1,314 @@ ++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 (LRC = Rate). ++ ++Bit Clock can be generated as follows:- ++ ++BCLK = MCLK / x ++ ++ or ++ ++BCLK = LRC * x ++ ++ or ++ ++BCLK = LRC * Channels * Word Size ++ ++This relationship depends on the codec or SoC CPU in particular. ASoC can quite ++easily match BCLK generated by division (SND_SOC_DAI_BFS_DIV) with BCLK by ++multiplication (SND_SOC_DAI_BFS_RATE) or BCLK generated by ++Rate * Channels * Word size (RCW or SND_SOC_DAI_BFS_RCW). ++ ++ ++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) { < |
