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