1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * Copyright 2011 Freescale Semiconductor, Inc. |
4 | */ |
5 | |
6 | #include <linux/module.h> |
7 | #include <linux/init.h> |
8 | #include <linux/of.h> |
9 | #include <linux/platform_device.h> |
10 | #include <linux/slab.h> |
11 | #include <linux/dma-mapping.h> |
12 | #include <linux/clk.h> |
13 | #include <linux/clk-provider.h> |
14 | #include <linux/delay.h> |
15 | #include <linux/io.h> |
16 | #include <linux/time.h> |
17 | #include <sound/core.h> |
18 | #include <sound/pcm.h> |
19 | #include <sound/pcm_params.h> |
20 | #include <sound/soc.h> |
21 | |
22 | #include "mxs-saif.h" |
23 | |
24 | #define MXS_SET_ADDR 0x4 |
25 | #define MXS_CLR_ADDR 0x8 |
26 | |
27 | static struct mxs_saif *mxs_saif[2]; |
28 | |
29 | /* |
30 | * SAIF is a little different with other normal SOC DAIs on clock using. |
31 | * |
32 | * For MXS, two SAIF modules are instantiated on-chip. |
33 | * Each SAIF has a set of clock pins and can be operating in master |
34 | * mode simultaneously if they are connected to different off-chip codecs. |
35 | * Also, one of the two SAIFs can master or drive the clock pins while the |
36 | * other SAIF, in slave mode, receives clocking from the master SAIF. |
37 | * This also means that both SAIFs must operate at the same sample rate. |
38 | * |
39 | * We abstract this as each saif has a master, the master could be |
40 | * itself or other saifs. In the generic saif driver, saif does not need |
41 | * to know the different clkmux. Saif only needs to know who is its master |
42 | * and operating its master to generate the proper clock rate for it. |
43 | * The master id is provided in mach-specific layer according to different |
44 | * clkmux setting. |
45 | */ |
46 | |
47 | static int mxs_saif_set_dai_sysclk(struct snd_soc_dai *cpu_dai, |
48 | int clk_id, unsigned int freq, int dir) |
49 | { |
50 | struct mxs_saif *saif = snd_soc_dai_get_drvdata(dai: cpu_dai); |
51 | |
52 | switch (clk_id) { |
53 | case MXS_SAIF_MCLK: |
54 | saif->mclk = freq; |
55 | break; |
56 | default: |
57 | return -EINVAL; |
58 | } |
59 | return 0; |
60 | } |
61 | |
62 | /* |
63 | * Since SAIF may work on EXTMASTER mode, IOW, it's working BITCLK&LRCLK |
64 | * is provided by other SAIF, we provide a interface here to get its master |
65 | * from its master_id. |
66 | * Note that the master could be itself. |
67 | */ |
68 | static inline struct mxs_saif *mxs_saif_get_master(struct mxs_saif * saif) |
69 | { |
70 | return mxs_saif[saif->master_id]; |
71 | } |
72 | |
73 | /* |
74 | * Set SAIF clock and MCLK |
75 | */ |
76 | static int mxs_saif_set_clk(struct mxs_saif *saif, |
77 | unsigned int mclk, |
78 | unsigned int rate) |
79 | { |
80 | u32 scr; |
81 | int ret; |
82 | struct mxs_saif *master_saif; |
83 | |
84 | dev_dbg(saif->dev, "mclk %d rate %d\n" , mclk, rate); |
85 | |
86 | /* Set master saif to generate proper clock */ |
87 | master_saif = mxs_saif_get_master(saif); |
88 | if (!master_saif) |
89 | return -EINVAL; |
90 | |
91 | dev_dbg(saif->dev, "master saif%d\n" , master_saif->id); |
92 | |
93 | /* Checking if can playback and capture simutaneously */ |
94 | if (master_saif->ongoing && rate != master_saif->cur_rate) { |
95 | dev_err(saif->dev, |
96 | "can not change clock, master saif%d(rate %d) is ongoing\n" , |
97 | master_saif->id, master_saif->cur_rate); |
98 | return -EINVAL; |
99 | } |
100 | |
101 | scr = __raw_readl(addr: master_saif->base + SAIF_CTRL); |
102 | scr &= ~BM_SAIF_CTRL_BITCLK_MULT_RATE; |
103 | scr &= ~BM_SAIF_CTRL_BITCLK_BASE_RATE; |
104 | |
105 | /* |
106 | * Set SAIF clock |
107 | * |
108 | * The SAIF clock should be either 384*fs or 512*fs. |
109 | * If MCLK is used, the SAIF clk ratio needs to match mclk ratio. |
110 | * For 256x, 128x, 64x, and 32x sub-rates, set saif clk as 512*fs. |
111 | * For 192x, 96x, and 48x sub-rates, set saif clk as 384*fs. |
112 | * |
113 | * If MCLK is not used, we just set saif clk to 512*fs. |
114 | */ |
115 | ret = clk_prepare_enable(clk: master_saif->clk); |
116 | if (ret) |
117 | return ret; |
118 | |
119 | if (master_saif->mclk_in_use) { |
120 | switch (mclk / rate) { |
121 | case 32: |
122 | case 64: |
123 | case 128: |
124 | case 256: |
125 | case 512: |
126 | scr &= ~BM_SAIF_CTRL_BITCLK_BASE_RATE; |
127 | ret = clk_set_rate(clk: master_saif->clk, rate: 512 * rate); |
128 | break; |
129 | case 48: |
130 | case 96: |
131 | case 192: |
132 | case 384: |
133 | scr |= BM_SAIF_CTRL_BITCLK_BASE_RATE; |
134 | ret = clk_set_rate(clk: master_saif->clk, rate: 384 * rate); |
135 | break; |
136 | default: |
137 | /* SAIF MCLK should be a sub-rate of 512x or 384x */ |
138 | clk_disable_unprepare(clk: master_saif->clk); |
139 | return -EINVAL; |
140 | } |
141 | } else { |
142 | ret = clk_set_rate(clk: master_saif->clk, rate: 512 * rate); |
143 | scr &= ~BM_SAIF_CTRL_BITCLK_BASE_RATE; |
144 | } |
145 | |
146 | clk_disable_unprepare(clk: master_saif->clk); |
147 | |
148 | if (ret) |
149 | return ret; |
150 | |
151 | master_saif->cur_rate = rate; |
152 | |
153 | if (!master_saif->mclk_in_use) { |
154 | __raw_writel(val: scr, addr: master_saif->base + SAIF_CTRL); |
155 | return 0; |
156 | } |
157 | |
158 | /* |
159 | * Program the over-sample rate for MCLK output |
160 | * |
161 | * The available MCLK range is 32x, 48x... 512x. The rate |
162 | * could be from 8kHz to 192kH. |
163 | */ |
164 | switch (mclk / rate) { |
165 | case 32: |
166 | scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(4); |
167 | break; |
168 | case 64: |
169 | scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(3); |
170 | break; |
171 | case 128: |
172 | scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(2); |
173 | break; |
174 | case 256: |
175 | scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(1); |
176 | break; |
177 | case 512: |
178 | scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(0); |
179 | break; |
180 | case 48: |
181 | scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(3); |
182 | break; |
183 | case 96: |
184 | scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(2); |
185 | break; |
186 | case 192: |
187 | scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(1); |
188 | break; |
189 | case 384: |
190 | scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(0); |
191 | break; |
192 | default: |
193 | return -EINVAL; |
194 | } |
195 | |
196 | __raw_writel(val: scr, addr: master_saif->base + SAIF_CTRL); |
197 | |
198 | return 0; |
199 | } |
200 | |
201 | /* |
202 | * Put and disable MCLK. |
203 | */ |
204 | int mxs_saif_put_mclk(unsigned int saif_id) |
205 | { |
206 | struct mxs_saif *saif = mxs_saif[saif_id]; |
207 | u32 stat; |
208 | |
209 | if (!saif) |
210 | return -EINVAL; |
211 | |
212 | stat = __raw_readl(addr: saif->base + SAIF_STAT); |
213 | if (stat & BM_SAIF_STAT_BUSY) { |
214 | dev_err(saif->dev, "error: busy\n" ); |
215 | return -EBUSY; |
216 | } |
217 | |
218 | clk_disable_unprepare(clk: saif->clk); |
219 | |
220 | /* disable MCLK output */ |
221 | __raw_writel(BM_SAIF_CTRL_CLKGATE, |
222 | addr: saif->base + SAIF_CTRL + MXS_SET_ADDR); |
223 | __raw_writel(BM_SAIF_CTRL_RUN, |
224 | addr: saif->base + SAIF_CTRL + MXS_CLR_ADDR); |
225 | |
226 | saif->mclk_in_use = 0; |
227 | return 0; |
228 | } |
229 | EXPORT_SYMBOL_GPL(mxs_saif_put_mclk); |
230 | |
231 | /* |
232 | * Get MCLK and set clock rate, then enable it |
233 | * |
234 | * This interface is used for codecs who are using MCLK provided |
235 | * by saif. |
236 | */ |
237 | int mxs_saif_get_mclk(unsigned int saif_id, unsigned int mclk, |
238 | unsigned int rate) |
239 | { |
240 | struct mxs_saif *saif = mxs_saif[saif_id]; |
241 | u32 stat; |
242 | int ret; |
243 | struct mxs_saif *master_saif; |
244 | |
245 | if (!saif) |
246 | return -EINVAL; |
247 | |
248 | /* Clear Reset */ |
249 | __raw_writel(BM_SAIF_CTRL_SFTRST, |
250 | addr: saif->base + SAIF_CTRL + MXS_CLR_ADDR); |
251 | |
252 | /* FIXME: need clear clk gate for register r/w */ |
253 | __raw_writel(BM_SAIF_CTRL_CLKGATE, |
254 | addr: saif->base + SAIF_CTRL + MXS_CLR_ADDR); |
255 | |
256 | master_saif = mxs_saif_get_master(saif); |
257 | if (saif != master_saif) { |
258 | dev_err(saif->dev, "can not get mclk from a non-master saif\n" ); |
259 | return -EINVAL; |
260 | } |
261 | |
262 | stat = __raw_readl(addr: saif->base + SAIF_STAT); |
263 | if (stat & BM_SAIF_STAT_BUSY) { |
264 | dev_err(saif->dev, "error: busy\n" ); |
265 | return -EBUSY; |
266 | } |
267 | |
268 | saif->mclk_in_use = 1; |
269 | ret = mxs_saif_set_clk(saif, mclk, rate); |
270 | if (ret) |
271 | return ret; |
272 | |
273 | ret = clk_prepare_enable(clk: saif->clk); |
274 | if (ret) |
275 | return ret; |
276 | |
277 | /* enable MCLK output */ |
278 | __raw_writel(BM_SAIF_CTRL_RUN, |
279 | addr: saif->base + SAIF_CTRL + MXS_SET_ADDR); |
280 | |
281 | return 0; |
282 | } |
283 | EXPORT_SYMBOL_GPL(mxs_saif_get_mclk); |
284 | |
285 | /* |
286 | * SAIF DAI format configuration. |
287 | * Should only be called when port is inactive. |
288 | */ |
289 | static int mxs_saif_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) |
290 | { |
291 | u32 scr, stat; |
292 | u32 scr0; |
293 | struct mxs_saif *saif = snd_soc_dai_get_drvdata(dai: cpu_dai); |
294 | |
295 | stat = __raw_readl(addr: saif->base + SAIF_STAT); |
296 | if (stat & BM_SAIF_STAT_BUSY) { |
297 | dev_err(cpu_dai->dev, "error: busy\n" ); |
298 | return -EBUSY; |
299 | } |
300 | |
301 | /* If SAIF1 is configured as slave, the clk gate needs to be cleared |
302 | * before the register can be written. |
303 | */ |
304 | if (saif->id != saif->master_id) { |
305 | __raw_writel(BM_SAIF_CTRL_SFTRST, |
306 | addr: saif->base + SAIF_CTRL + MXS_CLR_ADDR); |
307 | __raw_writel(BM_SAIF_CTRL_CLKGATE, |
308 | addr: saif->base + SAIF_CTRL + MXS_CLR_ADDR); |
309 | } |
310 | |
311 | scr0 = __raw_readl(addr: saif->base + SAIF_CTRL); |
312 | scr0 = scr0 & ~BM_SAIF_CTRL_BITCLK_EDGE & ~BM_SAIF_CTRL_LRCLK_POLARITY \ |
313 | & ~BM_SAIF_CTRL_JUSTIFY & ~BM_SAIF_CTRL_DELAY; |
314 | scr = 0; |
315 | |
316 | /* DAI mode */ |
317 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { |
318 | case SND_SOC_DAIFMT_I2S: |
319 | /* data frame low 1clk before data */ |
320 | scr |= BM_SAIF_CTRL_DELAY; |
321 | scr &= ~BM_SAIF_CTRL_LRCLK_POLARITY; |
322 | break; |
323 | case SND_SOC_DAIFMT_LEFT_J: |
324 | /* data frame high with data */ |
325 | scr &= ~BM_SAIF_CTRL_DELAY; |
326 | scr &= ~BM_SAIF_CTRL_LRCLK_POLARITY; |
327 | scr &= ~BM_SAIF_CTRL_JUSTIFY; |
328 | break; |
329 | default: |
330 | return -EINVAL; |
331 | } |
332 | |
333 | /* DAI clock inversion */ |
334 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { |
335 | case SND_SOC_DAIFMT_IB_IF: |
336 | scr |= BM_SAIF_CTRL_BITCLK_EDGE; |
337 | scr |= BM_SAIF_CTRL_LRCLK_POLARITY; |
338 | break; |
339 | case SND_SOC_DAIFMT_IB_NF: |
340 | scr |= BM_SAIF_CTRL_BITCLK_EDGE; |
341 | scr &= ~BM_SAIF_CTRL_LRCLK_POLARITY; |
342 | break; |
343 | case SND_SOC_DAIFMT_NB_IF: |
344 | scr &= ~BM_SAIF_CTRL_BITCLK_EDGE; |
345 | scr |= BM_SAIF_CTRL_LRCLK_POLARITY; |
346 | break; |
347 | case SND_SOC_DAIFMT_NB_NF: |
348 | scr &= ~BM_SAIF_CTRL_BITCLK_EDGE; |
349 | scr &= ~BM_SAIF_CTRL_LRCLK_POLARITY; |
350 | break; |
351 | } |
352 | |
353 | /* |
354 | * Note: We simply just support master mode since SAIF TX can only |
355 | * work as master. |
356 | * Here the master is relative to codec side. |
357 | * Saif internally could be slave when working on EXTMASTER mode. |
358 | * We just hide this to machine driver. |
359 | */ |
360 | switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { |
361 | case SND_SOC_DAIFMT_BP_FP: |
362 | if (saif->id == saif->master_id) |
363 | scr &= ~BM_SAIF_CTRL_SLAVE_MODE; |
364 | else |
365 | scr |= BM_SAIF_CTRL_SLAVE_MODE; |
366 | |
367 | __raw_writel(val: scr | scr0, addr: saif->base + SAIF_CTRL); |
368 | break; |
369 | default: |
370 | return -EINVAL; |
371 | } |
372 | |
373 | return 0; |
374 | } |
375 | |
376 | static int mxs_saif_startup(struct snd_pcm_substream *substream, |
377 | struct snd_soc_dai *cpu_dai) |
378 | { |
379 | struct mxs_saif *saif = snd_soc_dai_get_drvdata(dai: cpu_dai); |
380 | int ret; |
381 | |
382 | /* clear error status to 0 for each re-open */ |
383 | saif->fifo_underrun = 0; |
384 | saif->fifo_overrun = 0; |
385 | |
386 | /* Clear Reset for normal operations */ |
387 | __raw_writel(BM_SAIF_CTRL_SFTRST, |
388 | addr: saif->base + SAIF_CTRL + MXS_CLR_ADDR); |
389 | |
390 | /* clear clock gate */ |
391 | __raw_writel(BM_SAIF_CTRL_CLKGATE, |
392 | addr: saif->base + SAIF_CTRL + MXS_CLR_ADDR); |
393 | |
394 | ret = clk_prepare(clk: saif->clk); |
395 | if (ret) |
396 | return ret; |
397 | |
398 | return 0; |
399 | } |
400 | |
401 | static void mxs_saif_shutdown(struct snd_pcm_substream *substream, |
402 | struct snd_soc_dai *cpu_dai) |
403 | { |
404 | struct mxs_saif *saif = snd_soc_dai_get_drvdata(dai: cpu_dai); |
405 | |
406 | clk_unprepare(clk: saif->clk); |
407 | } |
408 | |
409 | /* |
410 | * Should only be called when port is inactive. |
411 | * although can be called multiple times by upper layers. |
412 | */ |
413 | static int mxs_saif_hw_params(struct snd_pcm_substream *substream, |
414 | struct snd_pcm_hw_params *params, |
415 | struct snd_soc_dai *cpu_dai) |
416 | { |
417 | struct mxs_saif *saif = snd_soc_dai_get_drvdata(dai: cpu_dai); |
418 | struct mxs_saif *master_saif; |
419 | u32 scr, stat; |
420 | int ret; |
421 | |
422 | master_saif = mxs_saif_get_master(saif); |
423 | if (!master_saif) |
424 | return -EINVAL; |
425 | |
426 | /* mclk should already be set */ |
427 | if (!saif->mclk && saif->mclk_in_use) { |
428 | dev_err(cpu_dai->dev, "set mclk first\n" ); |
429 | return -EINVAL; |
430 | } |
431 | |
432 | stat = __raw_readl(addr: saif->base + SAIF_STAT); |
433 | if (!saif->mclk_in_use && (stat & BM_SAIF_STAT_BUSY)) { |
434 | dev_err(cpu_dai->dev, "error: busy\n" ); |
435 | return -EBUSY; |
436 | } |
437 | |
438 | /* |
439 | * Set saif clk based on sample rate. |
440 | * If mclk is used, we also set mclk, if not, saif->mclk is |
441 | * default 0, means not used. |
442 | */ |
443 | ret = mxs_saif_set_clk(saif, mclk: saif->mclk, rate: params_rate(p: params)); |
444 | if (ret) { |
445 | dev_err(cpu_dai->dev, "unable to get proper clk\n" ); |
446 | return ret; |
447 | } |
448 | |
449 | if (saif != master_saif) { |
450 | /* |
451 | * Set an initial clock rate for the saif internal logic to work |
452 | * properly. This is important when working in EXTMASTER mode |
453 | * that uses the other saif's BITCLK&LRCLK but it still needs a |
454 | * basic clock which should be fast enough for the internal |
455 | * logic. |
456 | */ |
457 | ret = clk_enable(clk: saif->clk); |
458 | if (ret) |
459 | return ret; |
460 | |
461 | ret = clk_set_rate(clk: saif->clk, rate: 24000000); |
462 | clk_disable(clk: saif->clk); |
463 | if (ret) |
464 | return ret; |
465 | |
466 | ret = clk_prepare(clk: master_saif->clk); |
467 | if (ret) |
468 | return ret; |
469 | } |
470 | |
471 | scr = __raw_readl(addr: saif->base + SAIF_CTRL); |
472 | |
473 | scr &= ~BM_SAIF_CTRL_WORD_LENGTH; |
474 | scr &= ~BM_SAIF_CTRL_BITCLK_48XFS_ENABLE; |
475 | switch (params_format(p: params)) { |
476 | case SNDRV_PCM_FORMAT_S16_LE: |
477 | scr |= BF_SAIF_CTRL_WORD_LENGTH(0); |
478 | break; |
479 | case SNDRV_PCM_FORMAT_S20_3LE: |
480 | scr |= BF_SAIF_CTRL_WORD_LENGTH(4); |
481 | scr |= BM_SAIF_CTRL_BITCLK_48XFS_ENABLE; |
482 | break; |
483 | case SNDRV_PCM_FORMAT_S24_LE: |
484 | scr |= BF_SAIF_CTRL_WORD_LENGTH(8); |
485 | scr |= BM_SAIF_CTRL_BITCLK_48XFS_ENABLE; |
486 | break; |
487 | default: |
488 | return -EINVAL; |
489 | } |
490 | |
491 | /* Tx/Rx config */ |
492 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
493 | /* enable TX mode */ |
494 | scr &= ~BM_SAIF_CTRL_READ_MODE; |
495 | } else { |
496 | /* enable RX mode */ |
497 | scr |= BM_SAIF_CTRL_READ_MODE; |
498 | } |
499 | |
500 | __raw_writel(val: scr, addr: saif->base + SAIF_CTRL); |
501 | return 0; |
502 | } |
503 | |
504 | static int mxs_saif_prepare(struct snd_pcm_substream *substream, |
505 | struct snd_soc_dai *cpu_dai) |
506 | { |
507 | struct mxs_saif *saif = snd_soc_dai_get_drvdata(dai: cpu_dai); |
508 | |
509 | /* enable FIFO error irqs */ |
510 | __raw_writel(BM_SAIF_CTRL_FIFO_ERROR_IRQ_EN, |
511 | addr: saif->base + SAIF_CTRL + MXS_SET_ADDR); |
512 | |
513 | return 0; |
514 | } |
515 | |
516 | static int mxs_saif_trigger(struct snd_pcm_substream *substream, int cmd, |
517 | struct snd_soc_dai *cpu_dai) |
518 | { |
519 | struct mxs_saif *saif = snd_soc_dai_get_drvdata(dai: cpu_dai); |
520 | struct mxs_saif *master_saif; |
521 | u32 delay; |
522 | int ret; |
523 | |
524 | master_saif = mxs_saif_get_master(saif); |
525 | if (!master_saif) |
526 | return -EINVAL; |
527 | |
528 | switch (cmd) { |
529 | case SNDRV_PCM_TRIGGER_START: |
530 | case SNDRV_PCM_TRIGGER_RESUME: |
531 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
532 | if (saif->state == MXS_SAIF_STATE_RUNNING) |
533 | return 0; |
534 | |
535 | dev_dbg(cpu_dai->dev, "start\n" ); |
536 | |
537 | ret = clk_enable(clk: master_saif->clk); |
538 | if (ret) { |
539 | dev_err(saif->dev, "Failed to enable master clock\n" ); |
540 | return ret; |
541 | } |
542 | |
543 | /* |
544 | * If the saif's master is not itself, we also need to enable |
545 | * itself clk for its internal basic logic to work. |
546 | */ |
547 | if (saif != master_saif) { |
548 | ret = clk_enable(clk: saif->clk); |
549 | if (ret) { |
550 | dev_err(saif->dev, "Failed to enable master clock\n" ); |
551 | clk_disable(clk: master_saif->clk); |
552 | return ret; |
553 | } |
554 | |
555 | __raw_writel(BM_SAIF_CTRL_RUN, |
556 | addr: saif->base + SAIF_CTRL + MXS_SET_ADDR); |
557 | } |
558 | |
559 | if (!master_saif->mclk_in_use) |
560 | __raw_writel(BM_SAIF_CTRL_RUN, |
561 | addr: master_saif->base + SAIF_CTRL + MXS_SET_ADDR); |
562 | |
563 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
564 | /* |
565 | * write data to saif data register to trigger |
566 | * the transfer. |
567 | * For 24-bit format the 32-bit FIFO register stores |
568 | * only one channel, so we need to write twice. |
569 | * This is also safe for the other non 24-bit formats. |
570 | */ |
571 | __raw_writel(val: 0, addr: saif->base + SAIF_DATA); |
572 | __raw_writel(val: 0, addr: saif->base + SAIF_DATA); |
573 | } else { |
574 | /* |
575 | * read data from saif data register to trigger |
576 | * the receive. |
577 | * For 24-bit format the 32-bit FIFO register stores |
578 | * only one channel, so we need to read twice. |
579 | * This is also safe for the other non 24-bit formats. |
580 | */ |
581 | __raw_readl(addr: saif->base + SAIF_DATA); |
582 | __raw_readl(addr: saif->base + SAIF_DATA); |
583 | } |
584 | |
585 | master_saif->ongoing = 1; |
586 | saif->state = MXS_SAIF_STATE_RUNNING; |
587 | |
588 | dev_dbg(saif->dev, "CTRL 0x%x STAT 0x%x\n" , |
589 | __raw_readl(saif->base + SAIF_CTRL), |
590 | __raw_readl(saif->base + SAIF_STAT)); |
591 | |
592 | dev_dbg(master_saif->dev, "CTRL 0x%x STAT 0x%x\n" , |
593 | __raw_readl(master_saif->base + SAIF_CTRL), |
594 | __raw_readl(master_saif->base + SAIF_STAT)); |
595 | break; |
596 | case SNDRV_PCM_TRIGGER_SUSPEND: |
597 | case SNDRV_PCM_TRIGGER_STOP: |
598 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
599 | if (saif->state == MXS_SAIF_STATE_STOPPED) |
600 | return 0; |
601 | |
602 | dev_dbg(cpu_dai->dev, "stop\n" ); |
603 | |
604 | /* wait a while for the current sample to complete */ |
605 | delay = USEC_PER_SEC / master_saif->cur_rate; |
606 | |
607 | if (!master_saif->mclk_in_use) { |
608 | __raw_writel(BM_SAIF_CTRL_RUN, |
609 | addr: master_saif->base + SAIF_CTRL + MXS_CLR_ADDR); |
610 | udelay(delay); |
611 | } |
612 | clk_disable(clk: master_saif->clk); |
613 | |
614 | if (saif != master_saif) { |
615 | __raw_writel(BM_SAIF_CTRL_RUN, |
616 | addr: saif->base + SAIF_CTRL + MXS_CLR_ADDR); |
617 | udelay(delay); |
618 | clk_disable(clk: saif->clk); |
619 | } |
620 | |
621 | master_saif->ongoing = 0; |
622 | saif->state = MXS_SAIF_STATE_STOPPED; |
623 | |
624 | break; |
625 | default: |
626 | return -EINVAL; |
627 | } |
628 | |
629 | return 0; |
630 | } |
631 | |
632 | #define MXS_SAIF_RATES SNDRV_PCM_RATE_8000_192000 |
633 | #define MXS_SAIF_FORMATS \ |
634 | (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ |
635 | SNDRV_PCM_FMTBIT_S24_LE) |
636 | |
637 | static const struct snd_soc_dai_ops mxs_saif_dai_ops = { |
638 | .startup = mxs_saif_startup, |
639 | .shutdown = mxs_saif_shutdown, |
640 | .trigger = mxs_saif_trigger, |
641 | .prepare = mxs_saif_prepare, |
642 | .hw_params = mxs_saif_hw_params, |
643 | .set_sysclk = mxs_saif_set_dai_sysclk, |
644 | .set_fmt = mxs_saif_set_dai_fmt, |
645 | }; |
646 | |
647 | static struct snd_soc_dai_driver mxs_saif_dai = { |
648 | .name = "mxs-saif" , |
649 | .playback = { |
650 | .channels_min = 2, |
651 | .channels_max = 2, |
652 | .rates = MXS_SAIF_RATES, |
653 | .formats = MXS_SAIF_FORMATS, |
654 | }, |
655 | .capture = { |
656 | .channels_min = 2, |
657 | .channels_max = 2, |
658 | .rates = MXS_SAIF_RATES, |
659 | .formats = MXS_SAIF_FORMATS, |
660 | }, |
661 | .ops = &mxs_saif_dai_ops, |
662 | }; |
663 | |
664 | static const struct snd_soc_component_driver mxs_saif_component = { |
665 | .name = "mxs-saif" , |
666 | .legacy_dai_naming = 1, |
667 | }; |
668 | |
669 | static irqreturn_t mxs_saif_irq(int irq, void *dev_id) |
670 | { |
671 | struct mxs_saif *saif = dev_id; |
672 | unsigned int stat; |
673 | |
674 | stat = __raw_readl(addr: saif->base + SAIF_STAT); |
675 | if (!(stat & (BM_SAIF_STAT_FIFO_UNDERFLOW_IRQ | |
676 | BM_SAIF_STAT_FIFO_OVERFLOW_IRQ))) |
677 | return IRQ_NONE; |
678 | |
679 | if (stat & BM_SAIF_STAT_FIFO_UNDERFLOW_IRQ) { |
680 | dev_dbg(saif->dev, "underrun!!! %d\n" , ++saif->fifo_underrun); |
681 | __raw_writel(BM_SAIF_STAT_FIFO_UNDERFLOW_IRQ, |
682 | addr: saif->base + SAIF_STAT + MXS_CLR_ADDR); |
683 | } |
684 | |
685 | if (stat & BM_SAIF_STAT_FIFO_OVERFLOW_IRQ) { |
686 | dev_dbg(saif->dev, "overrun!!! %d\n" , ++saif->fifo_overrun); |
687 | __raw_writel(BM_SAIF_STAT_FIFO_OVERFLOW_IRQ, |
688 | addr: saif->base + SAIF_STAT + MXS_CLR_ADDR); |
689 | } |
690 | |
691 | dev_dbg(saif->dev, "SAIF_CTRL %x SAIF_STAT %x\n" , |
692 | __raw_readl(saif->base + SAIF_CTRL), |
693 | __raw_readl(saif->base + SAIF_STAT)); |
694 | |
695 | return IRQ_HANDLED; |
696 | } |
697 | |
698 | static int mxs_saif_mclk_init(struct platform_device *pdev) |
699 | { |
700 | struct mxs_saif *saif = platform_get_drvdata(pdev); |
701 | struct device_node *np = pdev->dev.of_node; |
702 | struct clk *clk; |
703 | int ret; |
704 | |
705 | clk = clk_register_divider(&pdev->dev, "mxs_saif_mclk" , |
706 | __clk_get_name(saif->clk), 0, |
707 | saif->base + SAIF_CTRL, |
708 | BP_SAIF_CTRL_BITCLK_MULT_RATE, 3, |
709 | 0, NULL); |
710 | if (IS_ERR(ptr: clk)) { |
711 | ret = PTR_ERR(ptr: clk); |
712 | if (ret == -EEXIST) |
713 | return 0; |
714 | dev_err(&pdev->dev, "failed to register mclk: %d\n" , ret); |
715 | return PTR_ERR(ptr: clk); |
716 | } |
717 | |
718 | ret = of_clk_add_provider(np, clk_src_get: of_clk_src_simple_get, data: clk); |
719 | if (ret) |
720 | return ret; |
721 | |
722 | return 0; |
723 | } |
724 | |
725 | static int mxs_saif_probe(struct platform_device *pdev) |
726 | { |
727 | struct device_node *np = pdev->dev.of_node; |
728 | struct mxs_saif *saif; |
729 | int irq, ret; |
730 | struct device_node *master; |
731 | |
732 | saif = devm_kzalloc(dev: &pdev->dev, size: sizeof(*saif), GFP_KERNEL); |
733 | if (!saif) |
734 | return -ENOMEM; |
735 | |
736 | ret = of_alias_get_id(np, stem: "saif" ); |
737 | if (ret < 0) |
738 | return ret; |
739 | else |
740 | saif->id = ret; |
741 | |
742 | if (saif->id >= ARRAY_SIZE(mxs_saif)) { |
743 | dev_err(&pdev->dev, "get wrong saif id\n" ); |
744 | return -EINVAL; |
745 | } |
746 | |
747 | /* |
748 | * If there is no "fsl,saif-master" phandle, it's a saif |
749 | * master. Otherwise, it's a slave and its phandle points |
750 | * to the master. |
751 | */ |
752 | master = of_parse_phandle(np, phandle_name: "fsl,saif-master" , index: 0); |
753 | if (!master) { |
754 | saif->master_id = saif->id; |
755 | } else { |
756 | ret = of_alias_get_id(np: master, stem: "saif" ); |
757 | of_node_put(node: master); |
758 | if (ret < 0) |
759 | return ret; |
760 | else |
761 | saif->master_id = ret; |
762 | |
763 | if (saif->master_id >= ARRAY_SIZE(mxs_saif)) { |
764 | dev_err(&pdev->dev, "get wrong master id\n" ); |
765 | return -EINVAL; |
766 | } |
767 | } |
768 | |
769 | mxs_saif[saif->id] = saif; |
770 | |
771 | saif->clk = devm_clk_get(dev: &pdev->dev, NULL); |
772 | if (IS_ERR(ptr: saif->clk)) { |
773 | ret = PTR_ERR(ptr: saif->clk); |
774 | dev_err(&pdev->dev, "Cannot get the clock: %d\n" , |
775 | ret); |
776 | return ret; |
777 | } |
778 | |
779 | saif->base = devm_platform_ioremap_resource(pdev, index: 0); |
780 | if (IS_ERR(ptr: saif->base)) |
781 | return PTR_ERR(ptr: saif->base); |
782 | |
783 | irq = platform_get_irq(pdev, 0); |
784 | if (irq < 0) |
785 | return irq; |
786 | |
787 | saif->dev = &pdev->dev; |
788 | ret = devm_request_irq(dev: &pdev->dev, irq, handler: mxs_saif_irq, irqflags: 0, |
789 | devname: dev_name(dev: &pdev->dev), dev_id: saif); |
790 | if (ret) { |
791 | dev_err(&pdev->dev, "failed to request irq\n" ); |
792 | return ret; |
793 | } |
794 | |
795 | platform_set_drvdata(pdev, data: saif); |
796 | |
797 | /* We only support saif0 being tx and clock master */ |
798 | if (saif->id == 0) { |
799 | ret = mxs_saif_mclk_init(pdev); |
800 | if (ret) |
801 | dev_warn(&pdev->dev, "failed to init clocks\n" ); |
802 | } |
803 | |
804 | ret = devm_snd_soc_register_component(dev: &pdev->dev, component_driver: &mxs_saif_component, |
805 | dai_drv: &mxs_saif_dai, num_dai: 1); |
806 | if (ret) { |
807 | dev_err(&pdev->dev, "register DAI failed\n" ); |
808 | return ret; |
809 | } |
810 | |
811 | ret = mxs_pcm_platform_register(dev: &pdev->dev); |
812 | if (ret) { |
813 | dev_err(&pdev->dev, "register PCM failed: %d\n" , ret); |
814 | return ret; |
815 | } |
816 | |
817 | return 0; |
818 | } |
819 | |
820 | static const struct of_device_id mxs_saif_dt_ids[] = { |
821 | { .compatible = "fsl,imx28-saif" , }, |
822 | { /* sentinel */ } |
823 | }; |
824 | MODULE_DEVICE_TABLE(of, mxs_saif_dt_ids); |
825 | |
826 | static struct platform_driver mxs_saif_driver = { |
827 | .probe = mxs_saif_probe, |
828 | |
829 | .driver = { |
830 | .name = "mxs-saif" , |
831 | .of_match_table = mxs_saif_dt_ids, |
832 | }, |
833 | }; |
834 | |
835 | module_platform_driver(mxs_saif_driver); |
836 | |
837 | MODULE_AUTHOR("Freescale Semiconductor, Inc." ); |
838 | MODULE_DESCRIPTION("MXS ASoC SAIF driver" ); |
839 | MODULE_LICENSE("GPL" ); |
840 | MODULE_ALIAS("platform:mxs-saif" ); |
841 | |