diff options
Diffstat (limited to 'Documentation/sound/alsa/soc/clocking.txt')
-rw-r--r-- | Documentation/sound/alsa/soc/clocking.txt | 309 |
1 files changed, 309 insertions, 0 deletions
diff --git a/Documentation/sound/alsa/soc/clocking.txt b/Documentation/sound/alsa/soc/clocking.txt new file mode 100644 index 000000000000..88a16c9e1979 --- /dev/null +++ b/Documentation/sound/alsa/soc/clocking.txt | |||
@@ -0,0 +1,309 @@ | |||
1 | Audio Clocking | ||
2 | ============== | ||
3 | |||
4 | This text describes the audio clocking terms in ASoC and digital audio in | ||
5 | general. Note: Audio clocking can be complex ! | ||
6 | |||
7 | |||
8 | Master Clock | ||
9 | ------------ | ||
10 | |||
11 | Every audio subsystem is driven by a master clock (sometimes refered to as MCLK | ||
12 | or SYSCLK). This audio master clock can be derived from a number of sources | ||
13 | (e.g. crystal, PLL, CPU clock) and is responsible for producing the correct | ||
14 | audio playback and capture sample rates. | ||
15 | |||
16 | Some master clocks (e.g. PLL's and CPU based clocks) are configuarble in that | ||
17 | their speed can be altered by software (depending on the system use and to save | ||
18 | power). Other master clocks are fixed at at set frequency (i.e. crystals). | ||
19 | |||
20 | |||
21 | DAI Clocks | ||
22 | ---------- | ||
23 | The Digital Audio Interface is usually driven by a Bit Clock (often referred to | ||
24 | as BCLK). This clock is used to drive the digital audio data across the link | ||
25 | between the codec and CPU. | ||
26 | |||
27 | The DAI also has a frame clock to signal the start of each audio frame. This | ||
28 | clock is sometimes referred to as LRC (left right clock) or FRAME. This clock | ||
29 | runs at exactly the sample rate. | ||
30 | |||
31 | Bit Clock is usually always a ratio of MCLK or a multiple of LRC. i.e. | ||
32 | |||
33 | BCLK = MCLK / x | ||
34 | |||
35 | or | ||
36 | |||
37 | BCLK = LRC * x | ||
38 | |||
39 | This relationship depends on the codec or SoC CPU in particular. ASoC can quite | ||
40 | easily match a codec that generates BCLK by division (FSBD) with a CPU that | ||
41 | generates BCLK by multiplication (FSB). | ||
42 | |||
43 | |||
44 | ASoC Clocking | ||
45 | ------------- | ||
46 | |||
47 | The ASoC core determines the clocking for each particular configuration at | ||
48 | runtime. This is to allow for dynamic audio clocking wereby the audio clock is | ||
49 | variable and depends on the system state or device usage scenario. i.e. a voice | ||
50 | call requires slower clocks (and hence less power) than MP3 playback. | ||
51 | |||
52 | ASoC will call the config_sysclock() function for the target machine during the | ||
53 | audio parameters configuration. The function is responsible for then clocking | ||
54 | the machine audio subsytem and returning the audio clock speed to the core. | ||
55 | This function should also call the codec and cpu DAI clock_config() functions | ||
56 | to configure their respective internal clocking if required. | ||
57 | |||
58 | |||
59 | ASoC Clocking Control Flow | ||
60 | -------------------------- | ||
61 | |||
62 | The ASoC core will call the machine drivers config_sysclock() when most of the | ||
63 | DAI capabilities are known. The machine driver is then responsible for calling | ||
64 | the codec and/or CPU DAI drivers with the selected capabilities and the current | ||
65 | MCLK. Note that the machine driver is also resonsible for setting the MCLK (and | ||
66 | enabling it). | ||
67 | |||
68 | (1) Match Codec and CPU DAI capabilities. At this point we have | ||
69 | matched the majority of the DAI fields and now need to make sure this | ||
70 | mode is currently clockable. | ||
71 | |||
72 | (2) machine->config_sysclk() is now called with the matched DAI FS, sample | ||
73 | rate and BCLK master. This function then gets/sets the current audio | ||
74 | clock (depening on usage) and calls the codec and CPUI DAI drivers with | ||
75 | the FS, rate, BCLK master and MCLK. | ||
76 | |||
77 | (3) Codec/CPU DAI config_sysclock(). This function checks that the FS, rate, | ||
78 | BCLK master and MCLK are acceptable for the codec or CPU DAI. It also | ||
79 | sets the DAI internal state to work with said clocks. | ||
80 | |||
81 | The config_sysclk() functions for CPU, codec and machine should return the MCLK | ||
82 | on success and 0 on failure. | ||
83 | |||
84 | |||
85 | Examples (b = BCLK, l = LRC) | ||
86 | ============================ | ||
87 | |||
88 | Example 1 | ||
89 | --------- | ||
90 | |||
91 | Simple codec that only runs at 48k @ 256FS in master mode. | ||
92 | |||
93 | CPU only runs as slave DAI, however it generates a variable MCLK. | ||
94 | |||
95 | -------- --------- | ||
96 | | | <----mclk--- | | | ||
97 | | Codec |b -----------> | CPU | | ||
98 | | |l -----------> | | | ||
99 | | | | | | ||
100 | -------- --------- | ||
101 | |||
102 | The codec driver has the following config_sysclock() | ||
103 | |||
104 | static unsigned int config_sysclk(struct snd_soc_codec_dai *dai, | ||
105 | struct snd_soc_clock_info *info, unsigned int clk) | ||
106 | { | ||
107 | /* make sure clock is 256 * rate */ | ||
108 | if(info->rate << 8 == clk) { | ||
109 | dai->mclk = clk; | ||
110 | return clk; | ||
111 | } | ||
112 | |||
113 | return 0; | ||
114 | } | ||
115 | |||
116 | The CPU I2S DAI driver has the following config_sysclk() | ||
117 | |||
118 | static unsigned int config_sysclk(struct snd_soc_codec_dai *dai, | ||
119 | struct snd_soc_clock_info *info, unsigned int clk) | ||
120 | { | ||
121 | /* can we support this clk */ | ||
122 | if(set_audio_clk(clk) < 0) | ||
123 | return -EINVAL; | ||
124 | |||
125 | dai->mclk = clk; | ||
126 | return dai->clk; | ||
127 | } | ||
128 | |||
129 | The machine driver config_sysclk() in this example is as follows:- | ||
130 | |||
131 | unsigned int machine_config_sysclk(struct snd_soc_pcm_runtime *rtd, | ||
132 | struct snd_soc_clock_info *info) | ||
133 | { | ||
134 | int clk = info->rate * info->fs; | ||
135 | |||
136 | /* check that CPU can deliver clock */ | ||
137 | if(rtd->cpu_dai->config_sysclk(rtd->cpu_dai, info, clk) < 0) | ||
138 | return -EINVAL; | ||
139 | |||
140 | /* can codec work with this clock */ | ||
141 | return rtd->codec_dai->config_sysclk(rtd->codec_dai, info, clk); | ||
142 | } | ||
143 | |||
144 | |||
145 | Example 2 | ||
146 | --------- | ||
147 | |||
148 | Codec that can master at 8k and 48k at various FS (and hence supports a fixed | ||
149 | set of input MCLK's) and can also be slave at various FS . | ||
150 | |||
151 | The CPU can master at 8k and 48k @256 FS and can be slave at any FS. | ||
152 | |||
153 | MCLK is a 12.288MHz crystal on this machine. | ||
154 | |||
155 | -------- --------- | ||
156 | | | <---xtal---> | | | ||
157 | | Codec |b <----------> | CPU | | ||
158 | | |l <----------> | | | ||
159 | | | | | | ||
160 | -------- --------- | ||
161 | |||
162 | |||
163 | The codec driver has the following config_sysclock() | ||
164 | |||
165 | /* supported input clocks */ | ||
166 | const static int hifi_clks[] = {11289600, 12000000, 12288000, | ||
167 | 16934400, 18432000}; | ||
168 | |||
169 | static unsigned int config_hsysclk(struct snd_soc_codec_dai *dai, | ||
170 | struct snd_soc_clock_info *info, unsigned int clk) | ||
171 | { | ||
172 | int i; | ||
173 | |||
174 | /* is clk supported */ | ||
175 | for(i = 0; i < ARRAY_SIZE(hifi_clks); i++) { | ||
176 | if(clk == hifi_clks[i]) { | ||
177 | dai->mclk = clk; | ||
178 | return clk; | ||
179 | } | ||
180 | } | ||
181 | |||
182 | /* this clk is not supported */ | ||
183 | return 0; | ||
184 | } | ||
185 | |||
186 | The CPU I2S DAI driver has the following config_sysclk() | ||
187 | |||
188 | static unsigned int config_sysclk(struct snd_soc_codec_dai *dai, | ||
189 | struct snd_soc_clock_info *info, unsigned int clk) | ||
190 | { | ||
191 | /* are we master or slave */ | ||
192 | if (info->bclk_master & | ||
193 | (SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_CBM_CFS)) { | ||
194 | |||
195 | /* we can only master @ 256FS */ | ||
196 | if(info->rate << 8 == clk) { | ||
197 | dai->mclk = clk; | ||
198 | return dai->mclk; | ||
199 | } | ||
200 | } else { | ||
201 | /* slave we can run at any FS */ | ||
202 | dai->mclk = clk; | ||
203 | return dai->mclk; | ||
204 | } | ||
205 | |||
206 | /* not supported */ | ||
207 | return dai->clk; | ||
208 | } | ||
209 | |||
210 | The machine driver config_sysclk() in this example is as follows:- | ||
211 | |||
212 | unsigned int machine_config_sysclk(struct snd_soc_pcm_runtime *rtd, | ||
213 | struct snd_soc_clock_info *info) | ||
214 | { | ||
215 | int clk = 12288000; /* 12.288MHz */ | ||
216 | |||
217 | /* who's driving the link */ | ||
218 | if (info->bclk_master & | ||
219 | (SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_CBM_CFS)) { | ||
220 | /* codec master */ | ||
221 | |||
222 | /* check that CPU can work with clock */ | ||
223 | if(rtd->cpu_dai->config_sysclk(rtd->cpu_dai, info, clk) < 0) | ||
224 | return -EINVAL; | ||
225 | |||
226 | /* can codec work with this clock */ | ||
227 | return rtd->codec_dai->config_sysclk(rtd->codec_dai, info, clk); | ||
228 | } else { | ||
229 | /* cpu master */ | ||
230 | |||
231 | /* check that codec can work with clock */ | ||
232 | if(rtd->codec_dai->config_sysclk(rtd->codec_dai, info, clk) < 0) | ||
233 | return -EINVAL; | ||
234 | |||
235 | /* can CPU work with this clock */ | ||
236 | return rtd->cpu_dai->config_sysclk(rtd->cpu_dai, info, clk); | ||
237 | } | ||
238 | } | ||
239 | |||
240 | |||
241 | |||
242 | Example 3 | ||
243 | --------- | ||
244 | |||
245 | Codec that masters at 8k ... 48k @256 FS. Codec can also be slave and | ||
246 | doesn't care about FS. The codec has an internal PLL and dividers to generate | ||
247 | the necessary internal clocks (for 256FS). | ||
248 | |||
249 | CPU can only be slave and doesn't care about FS. | ||
250 | |||
251 | MCLK is a non controllable 13MHz clock from the CPU. | ||
252 | |||
253 | |||
254 | -------- --------- | ||
255 | | | <----mclk--- | | | ||
256 | | Codec |b <----------> | CPU | | ||
257 | | |l <----------> | | | ||
258 | | | | | | ||
259 | -------- --------- | ||
260 | |||
261 | The codec driver has the following config_sysclock() | ||
262 | |||
263 | /* valid PCM clock dividers * 2 */ | ||
264 | static int pcm_divs[] = {2, 6, 11, 4, 8, 12, 16}; | ||
265 | |||
266 | static unsigned int config_vsysclk(struct snd_soc_codec_dai *dai, | ||
267 | struct snd_soc_clock_info *info, unsigned int clk) | ||
268 | { | ||
269 | int i, j, best_clk = info->fs * info->rate; | ||
270 | |||
271 | /* can we run at this clk without the PLL ? */ | ||
272 | for (i = 0; i < ARRAY_SIZE(pcm_divs); i++) { | ||
273 | if ((best_clk >> 1) * pcm_divs[i] == clk) { | ||
274 | dai->pll_in = 0; | ||
275 | dai->clk_div = pcm_divs[i]; | ||
276 | dai->mclk = best_clk; | ||
277 | return dai->mclk; | ||
278 | } | ||
279 | } | ||
280 | |||
281 | /* now check for PLL support */ | ||
282 | for (i = 0; i < ARRAY_SIZE(pll_div); i++) { | ||
283 | if (pll_div[i].pll_in == clk) { | ||
284 | for (j = 0; j < ARRAY_SIZE(pcm_divs); j++) { | ||
285 | if (pll_div[i].pll_out == pcm_divs[j] * (best_clk >> 1)) { | ||
286 | dai->pll_in = clk; | ||
287 | dai->pll_out = pll_div[i].pll_out; | ||
288 | dai->clk_div = pcm_divs[j]; | ||
289 | dai->mclk = best_clk; | ||
290 | return dai->mclk; | ||
291 | } | ||
292 | } | ||
293 | } | ||
294 | } | ||
295 | |||
296 | /* this clk is not supported */ | ||
297 | return 0; | ||
298 | } | ||
299 | |||
300 | |||
301 | The CPU I2S DAI driver has the does not need a config_sysclk() as it can slave | ||
302 | at any FS. | ||
303 | |||
304 | unsigned int config_sysclk(struct snd_soc_pcm_runtime *rtd, | ||
305 | struct snd_soc_clock_info *info) | ||
306 | { | ||
307 | /* codec has pll that generates mclk from 13MHz xtal */ | ||
308 | return rtd->codec_dai->config_sysclk(rtd->codec_dai, info, 13000000); | ||
309 | } | ||