[ALSA] ASoC documentation updates
[powerpc.git] / Documentation / sound / alsa / soc / clocking.txt
index 1f55fd8..e93960d 100644 (file)
@@ -40,275 +40,12 @@ BCLK = LRC * x
 
 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).
+This relationship depends on the codec or SoC CPU in particular. In general
+it's best to configure BCLK to the lowest possible speed (depending on your
+rate, number of channels and wordsize) to save on power.
 
+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);
-       }