123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309 |
- Audio Clocking
- ==============
- This text describes the audio clocking terms in ASoC and digital audio in
- general. Note: Audio clocking can be complex !
- Master Clock
- ------------
- Every audio subsystem is driven by a master clock (sometimes refered to as MCLK
- or SYSCLK). This audio master clock can be derived from a number of sources
- (e.g. crystal, PLL, CPU clock) and is responsible for producing the correct
- audio playback and capture sample rates.
- Some master clocks (e.g. PLL's and CPU based clocks) are configuarble in that
- their speed can be altered by software (depending on the system use and to save
- power). Other master clocks are fixed at at set frequency (i.e. crystals).
- DAI Clocks
- ----------
- The Digital Audio Interface is usually driven by a Bit Clock (often referred to
- as BCLK). This clock is used to drive the digital audio data across the link
- between the codec and CPU.
- The DAI also has a frame clock to signal the start of each audio frame. This
- clock is sometimes referred to as LRC (left right clock) or FRAME. This clock
- runs at exactly the sample rate.
- Bit Clock is usually always a ratio of MCLK or a multiple of LRC. i.e.
- BCLK = MCLK / x
- or
- BCLK = LRC * x
- This relationship depends on the codec or SoC CPU in particular. ASoC can quite
- easily match a codec that generates BCLK by division (FSBD) with a CPU that
- generates BCLK by multiplication (FSB).
- ASoC Clocking
- -------------
- The ASoC core determines the clocking for each particular configuration at
- runtime. This is to allow for dynamic audio clocking wereby the audio clock is
- variable and depends on the system state or device usage scenario. i.e. a voice
- call requires slower clocks (and hence less power) than MP3 playback.
- ASoC will call the config_sysclock() function for the target machine during the
- audio parameters configuration. The function is responsible for then clocking
- the machine audio subsytem and returning the audio clock speed to the core.
- This function should also call the codec and cpu DAI clock_config() functions
- to configure their respective internal clocking if required.
- ASoC Clocking Control Flow
- --------------------------
- The ASoC core will call the machine drivers config_sysclock() when most of the
- DAI capabilities are known. The machine driver is then responsible for calling
- the codec and/or CPU DAI drivers with the selected capabilities and the current
- MCLK. Note that the machine driver is also resonsible for setting the MCLK (and
- enabling it).
- (1) Match Codec and CPU DAI capabilities. At this point we have
- matched the majority of the DAI fields and now need to make sure this
- mode is currently clockable.
- (2) machine->config_sysclk() is now called with the matched DAI FS, sample
- rate and BCLK master. This function then gets/sets the current audio
- clock (depening on usage) and calls the codec and CPUI DAI drivers with
- the FS, rate, BCLK master and MCLK.
- (3) Codec/CPU DAI config_sysclock(). This function checks that the FS, rate,
- BCLK master and MCLK are acceptable for the codec or CPU DAI. It also
- sets the DAI internal state to work with said clocks.
- The config_sysclk() functions for CPU, codec and machine should return the MCLK
- on success and 0 on failure.
- Examples (b = BCLK, l = LRC)
- ============================
- Example 1
- ---------
- Simple codec that only runs at 48k @ 256FS in master mode.
- CPU only runs as slave DAI, however it generates a variable MCLK.
- -------- ---------
- | | <----mclk--- | |
- | Codec |b -----------> | CPU |
- | |l -----------> | |
- | | | |
- -------- ---------
- The codec driver has the following config_sysclock()
- static unsigned int config_sysclk(struct snd_soc_codec_dai *dai,
- struct snd_soc_clock_info *info, unsigned int clk)
- {
- /* make sure clock is 256 * rate */
- if(info->rate << 8 == clk) {
- dai->mclk = clk;
- return clk;
- }
- return 0;
- }
- The CPU I2S DAI driver has the following config_sysclk()
- static unsigned int config_sysclk(struct snd_soc_codec_dai *dai,
- struct snd_soc_clock_info *info, unsigned int clk)
- {
- /* can we support this clk */
- if(set_audio_clk(clk) < 0)
- return -EINVAL;
- dai->mclk = clk;
- return dai->clk;
- }
- The machine driver config_sysclk() in this example is as follows:-
- unsigned int machine_config_sysclk(struct snd_soc_pcm_runtime *rtd,
- struct snd_soc_clock_info *info)
- {
- int clk = info->rate * info->fs;
- /* check that CPU can deliver clock */
- if(rtd->cpu_dai->config_sysclk(rtd->cpu_dai, info, clk) < 0)
- return -EINVAL;
- /* can codec work with this clock */
- return rtd->codec_dai->config_sysclk(rtd->codec_dai, info, clk);
- }
- Example 2
- ---------
- Codec that can master at 8k and 48k at various FS (and hence supports a fixed
- set of input MCLK's) and can also be slave at various FS .
- The CPU can master at 8k and 48k @256 FS and can be slave at any FS.
- MCLK is a 12.288MHz crystal on this machine.
- -------- ---------
- | | <---xtal---> | |
- | Codec |b <----------> | CPU |
- | |l <----------> | |
- | | | |
- -------- ---------
- The codec driver has the following config_sysclock()
- /* supported input clocks */
- const static int hifi_clks[] = {11289600, 12000000, 12288000,
- 16934400, 18432000};
- static unsigned int config_hsysclk(struct snd_soc_codec_dai *dai,
- struct snd_soc_clock_info *info, unsigned int clk)
- {
- int i;
- /* is clk supported */
- for(i = 0; i < ARRAY_SIZE(hifi_clks); i++) {
- if(clk == hifi_clks[i]) {
- dai->mclk = clk;
- return clk;
- }
- }
- /* this clk is not supported */
- return 0;
- }
- The CPU I2S DAI driver has the following config_sysclk()
- static unsigned int config_sysclk(struct snd_soc_codec_dai *dai,
- struct snd_soc_clock_info *info, unsigned int clk)
- {
- /* are we master or slave */
- if (info->bclk_master &
- (SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_CBM_CFS)) {
- /* we can only master @ 256FS */
- if(info->rate << 8 == clk) {
- dai->mclk = clk;
- return dai->mclk;
- }
- } else {
- /* slave we can run at any FS */
- dai->mclk = clk;
- return dai->mclk;
- }
- /* not supported */
- return dai->clk;
- }
- The machine driver config_sysclk() in this example is as follows:-
- unsigned int machine_config_sysclk(struct snd_soc_pcm_runtime *rtd,
- struct snd_soc_clock_info *info)
- {
- int clk = 12288000; /* 12.288MHz */
- /* who's driving the link */
- if (info->bclk_master &
- (SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_CBM_CFS)) {
- /* codec master */
- /* check that CPU can work with clock */
- if(rtd->cpu_dai->config_sysclk(rtd->cpu_dai, info, clk) < 0)
- return -EINVAL;
- /* can codec work with this clock */
- return rtd->codec_dai->config_sysclk(rtd->codec_dai, info, clk);
- } else {
- /* cpu master */
- /* check that codec can work with clock */
- if(rtd->codec_dai->config_sysclk(rtd->codec_dai, info, clk) < 0)
- return -EINVAL;
- /* can CPU work with this clock */
- return rtd->cpu_dai->config_sysclk(rtd->cpu_dai, info, clk);
- }
- }
- Example 3
- ---------
- Codec that masters at 8k ... 48k @256 FS. Codec can also be slave and
- doesn't care about FS. The codec has an internal PLL and dividers to generate
- the necessary internal clocks (for 256FS).
- CPU can only be slave and doesn't care about FS.
- MCLK is a non controllable 13MHz clock from the CPU.
- -------- ---------
- | | <----mclk--- | |
- | Codec |b <----------> | CPU |
- | |l <----------> | |
- | | | |
- -------- ---------
- The codec driver has the following config_sysclock()
- /* valid PCM clock dividers * 2 */
- static int pcm_divs[] = {2, 6, 11, 4, 8, 12, 16};
- static unsigned int config_vsysclk(struct snd_soc_codec_dai *dai,
- struct snd_soc_clock_info *info, unsigned int clk)
- {
- int i, j, best_clk = info->fs * info->rate;
- /* can we run at this clk without the PLL ? */
- for (i = 0; i < ARRAY_SIZE(pcm_divs); i++) {
- if ((best_clk >> 1) * pcm_divs[i] == clk) {
- dai->pll_in = 0;
- dai->clk_div = pcm_divs[i];
- dai->mclk = best_clk;
- return dai->mclk;
- }
- }
- /* now check for PLL support */
- for (i = 0; i < ARRAY_SIZE(pll_div); i++) {
- if (pll_div[i].pll_in == clk) {
- for (j = 0; j < ARRAY_SIZE(pcm_divs); j++) {
- if (pll_div[i].pll_out == pcm_divs[j] * (best_clk >> 1)) {
- dai->pll_in = clk;
- dai->pll_out = pll_div[i].pll_out;
- dai->clk_div = pcm_divs[j];
- dai->mclk = best_clk;
- return dai->mclk;
- }
- }
- }
- }
- /* this clk is not supported */
- return 0;
- }
- The CPU I2S DAI driver has the does not need a config_sysclk() as it can slave
- at any FS.
- unsigned int config_sysclk(struct snd_soc_pcm_runtime *rtd,
- struct snd_soc_clock_info *info)
- {
- /* codec has pll that generates mclk from 13MHz xtal */
- return rtd->codec_dai->config_sysclk(rtd->codec_dai, info, 13000000);
- }
|