2 * Freescale ALSA SoC Digital Audio Interface (SAI) driver.
4 * Copyright 2012-2015 Freescale Semiconductor, Inc.
6 * This program is free software, you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 2 of the License, or(at your
9 * option) any later version.
13 #include <linux/clk.h>
14 #include <linux/delay.h>
15 #include <linux/dmaengine.h>
16 #include <linux/module.h>
17 #include <linux/of_address.h>
18 #include <linux/regmap.h>
19 #include <linux/slab.h>
20 #include <linux/time.h>
21 #include <sound/core.h>
22 #include <sound/dmaengine_pcm.h>
23 #include <sound/pcm_params.h>
28 #define FSL_SAI_FLAGS (FSL_SAI_CSR_SEIE |\
31 static const unsigned int fsl_sai_rates
[] = {
32 8000, 11025, 12000, 16000, 22050,
33 24000, 32000, 44100, 48000, 64000,
34 88200, 96000, 176400, 192000
37 static const struct snd_pcm_hw_constraint_list fsl_sai_rate_constraints
= {
38 .count
= ARRAY_SIZE(fsl_sai_rates
),
39 .list
= fsl_sai_rates
,
42 static irqreturn_t
fsl_sai_isr(int irq
, void *devid
)
44 struct fsl_sai
*sai
= (struct fsl_sai
*)devid
;
45 struct device
*dev
= &sai
->pdev
->dev
;
46 u32 flags
, xcsr
, mask
;
50 * Both IRQ status bits and IRQ mask bits are in the xCSR but
51 * different shifts. And we here create a mask only for those
52 * IRQs that we activated.
54 mask
= (FSL_SAI_FLAGS
>> FSL_SAI_CSR_xIE_SHIFT
) << FSL_SAI_CSR_xF_SHIFT
;
57 regmap_read(sai
->regmap
, FSL_SAI_TCSR
, &xcsr
);
65 if (flags
& FSL_SAI_CSR_WSF
)
66 dev_dbg(dev
, "isr: Start of Tx word detected\n");
68 if (flags
& FSL_SAI_CSR_SEF
)
69 dev_warn(dev
, "isr: Tx Frame sync error detected\n");
71 if (flags
& FSL_SAI_CSR_FEF
) {
72 dev_warn(dev
, "isr: Transmit underrun detected\n");
73 /* FIFO reset for safety */
74 xcsr
|= FSL_SAI_CSR_FR
;
77 if (flags
& FSL_SAI_CSR_FWF
)
78 dev_dbg(dev
, "isr: Enabled transmit FIFO is empty\n");
80 if (flags
& FSL_SAI_CSR_FRF
)
81 dev_dbg(dev
, "isr: Transmit FIFO watermark has been reached\n");
83 flags
&= FSL_SAI_CSR_xF_W_MASK
;
84 xcsr
&= ~FSL_SAI_CSR_xF_MASK
;
87 regmap_write(sai
->regmap
, FSL_SAI_TCSR
, flags
| xcsr
);
91 regmap_read(sai
->regmap
, FSL_SAI_RCSR
, &xcsr
);
99 if (flags
& FSL_SAI_CSR_WSF
)
100 dev_dbg(dev
, "isr: Start of Rx word detected\n");
102 if (flags
& FSL_SAI_CSR_SEF
)
103 dev_warn(dev
, "isr: Rx Frame sync error detected\n");
105 if (flags
& FSL_SAI_CSR_FEF
) {
106 dev_warn(dev
, "isr: Receive overflow detected\n");
107 /* FIFO reset for safety */
108 xcsr
|= FSL_SAI_CSR_FR
;
111 if (flags
& FSL_SAI_CSR_FWF
)
112 dev_dbg(dev
, "isr: Enabled receive FIFO is full\n");
114 if (flags
& FSL_SAI_CSR_FRF
)
115 dev_dbg(dev
, "isr: Receive FIFO watermark has been reached\n");
117 flags
&= FSL_SAI_CSR_xF_W_MASK
;
118 xcsr
&= ~FSL_SAI_CSR_xF_MASK
;
121 regmap_write(sai
->regmap
, FSL_SAI_RCSR
, flags
| xcsr
);
130 static int fsl_sai_set_dai_tdm_slot(struct snd_soc_dai
*cpu_dai
, u32 tx_mask
,
131 u32 rx_mask
, int slots
, int slot_width
)
133 struct fsl_sai
*sai
= snd_soc_dai_get_drvdata(cpu_dai
);
136 sai
->slot_width
= slot_width
;
141 static int fsl_sai_set_dai_sysclk_tr(struct snd_soc_dai
*cpu_dai
,
142 int clk_id
, unsigned int freq
, int fsl_dir
)
144 struct fsl_sai
*sai
= snd_soc_dai_get_drvdata(cpu_dai
);
145 bool tx
= fsl_dir
== FSL_FMT_TRANSMITTER
;
149 case FSL_SAI_CLK_BUS
:
150 val_cr2
|= FSL_SAI_CR2_MSEL_BUS
;
152 case FSL_SAI_CLK_MAST1
:
153 val_cr2
|= FSL_SAI_CR2_MSEL_MCLK1
;
155 case FSL_SAI_CLK_MAST2
:
156 val_cr2
|= FSL_SAI_CR2_MSEL_MCLK2
;
158 case FSL_SAI_CLK_MAST3
:
159 val_cr2
|= FSL_SAI_CR2_MSEL_MCLK3
;
165 regmap_update_bits(sai
->regmap
, FSL_SAI_xCR2(tx
),
166 FSL_SAI_CR2_MSEL_MASK
, val_cr2
);
171 static int fsl_sai_set_dai_sysclk(struct snd_soc_dai
*cpu_dai
,
172 int clk_id
, unsigned int freq
, int dir
)
176 if (dir
== SND_SOC_CLOCK_IN
)
179 ret
= fsl_sai_set_dai_sysclk_tr(cpu_dai
, clk_id
, freq
,
180 FSL_FMT_TRANSMITTER
);
182 dev_err(cpu_dai
->dev
, "Cannot set tx sysclk: %d\n", ret
);
186 ret
= fsl_sai_set_dai_sysclk_tr(cpu_dai
, clk_id
, freq
,
189 dev_err(cpu_dai
->dev
, "Cannot set rx sysclk: %d\n", ret
);
194 static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai
*cpu_dai
,
195 unsigned int fmt
, int fsl_dir
)
197 struct fsl_sai
*sai
= snd_soc_dai_get_drvdata(cpu_dai
);
198 bool tx
= fsl_dir
== FSL_FMT_TRANSMITTER
;
199 u32 val_cr2
= 0, val_cr4
= 0;
201 if (!sai
->is_lsb_first
)
202 val_cr4
|= FSL_SAI_CR4_MF
;
205 switch (fmt
& SND_SOC_DAIFMT_FORMAT_MASK
) {
206 case SND_SOC_DAIFMT_I2S
:
208 * Frame low, 1clk before data, one word length for frame sync,
209 * frame sync starts one serial clock cycle earlier,
210 * that is, together with the last bit of the previous
213 val_cr2
|= FSL_SAI_CR2_BCP
;
214 val_cr4
|= FSL_SAI_CR4_FSE
| FSL_SAI_CR4_FSP
;
216 case SND_SOC_DAIFMT_LEFT_J
:
218 * Frame high, one word length for frame sync,
219 * frame sync asserts with the first bit of the frame.
221 val_cr2
|= FSL_SAI_CR2_BCP
;
223 case SND_SOC_DAIFMT_DSP_A
:
225 * Frame high, 1clk before data, one bit for frame sync,
226 * frame sync starts one serial clock cycle earlier,
227 * that is, together with the last bit of the previous
230 val_cr2
|= FSL_SAI_CR2_BCP
;
231 val_cr4
|= FSL_SAI_CR4_FSE
;
232 sai
->is_dsp_mode
= true;
234 case SND_SOC_DAIFMT_DSP_B
:
236 * Frame high, one bit for frame sync,
237 * frame sync asserts with the first bit of the frame.
239 val_cr2
|= FSL_SAI_CR2_BCP
;
240 sai
->is_dsp_mode
= true;
242 case SND_SOC_DAIFMT_RIGHT_J
:
248 /* DAI clock inversion */
249 switch (fmt
& SND_SOC_DAIFMT_INV_MASK
) {
250 case SND_SOC_DAIFMT_IB_IF
:
251 /* Invert both clocks */
252 val_cr2
^= FSL_SAI_CR2_BCP
;
253 val_cr4
^= FSL_SAI_CR4_FSP
;
255 case SND_SOC_DAIFMT_IB_NF
:
256 /* Invert bit clock */
257 val_cr2
^= FSL_SAI_CR2_BCP
;
259 case SND_SOC_DAIFMT_NB_IF
:
260 /* Invert frame clock */
261 val_cr4
^= FSL_SAI_CR4_FSP
;
263 case SND_SOC_DAIFMT_NB_NF
:
264 /* Nothing to do for both normal cases */
270 /* DAI clock master masks */
271 switch (fmt
& SND_SOC_DAIFMT_MASTER_MASK
) {
272 case SND_SOC_DAIFMT_CBS_CFS
:
273 val_cr2
|= FSL_SAI_CR2_BCD_MSTR
;
274 val_cr4
|= FSL_SAI_CR4_FSD_MSTR
;
276 case SND_SOC_DAIFMT_CBM_CFM
:
277 sai
->is_slave_mode
= true;
279 case SND_SOC_DAIFMT_CBS_CFM
:
280 val_cr2
|= FSL_SAI_CR2_BCD_MSTR
;
282 case SND_SOC_DAIFMT_CBM_CFS
:
283 val_cr4
|= FSL_SAI_CR4_FSD_MSTR
;
284 sai
->is_slave_mode
= true;
290 regmap_update_bits(sai
->regmap
, FSL_SAI_xCR2(tx
),
291 FSL_SAI_CR2_BCP
| FSL_SAI_CR2_BCD_MSTR
, val_cr2
);
292 regmap_update_bits(sai
->regmap
, FSL_SAI_xCR4(tx
),
293 FSL_SAI_CR4_MF
| FSL_SAI_CR4_FSE
|
294 FSL_SAI_CR4_FSP
| FSL_SAI_CR4_FSD_MSTR
, val_cr4
);
299 static int fsl_sai_set_dai_fmt(struct snd_soc_dai
*cpu_dai
, unsigned int fmt
)
303 ret
= fsl_sai_set_dai_fmt_tr(cpu_dai
, fmt
, FSL_FMT_TRANSMITTER
);
305 dev_err(cpu_dai
->dev
, "Cannot set tx format: %d\n", ret
);
309 ret
= fsl_sai_set_dai_fmt_tr(cpu_dai
, fmt
, FSL_FMT_RECEIVER
);
311 dev_err(cpu_dai
->dev
, "Cannot set rx format: %d\n", ret
);
316 static int fsl_sai_set_bclk(struct snd_soc_dai
*dai
, bool tx
, u32 freq
)
318 struct fsl_sai
*sai
= snd_soc_dai_get_drvdata(dai
);
319 unsigned long clk_rate
;
320 u32 savediv
= 0, ratio
, savesub
= freq
;
324 /* Don't apply to slave mode */
325 if (sai
->is_slave_mode
)
328 for (id
= 0; id
< FSL_SAI_MCLK_MAX
; id
++) {
329 clk_rate
= clk_get_rate(sai
->mclk_clk
[id
]);
333 ratio
= clk_rate
/ freq
;
335 ret
= clk_rate
- ratio
* freq
;
338 * Drop the source that can not be
339 * divided into the required rate.
341 if (ret
!= 0 && clk_rate
/ ret
< 1000)
345 "ratio %d for freq %dHz based on clock %ldHz\n",
346 ratio
, freq
, clk_rate
);
348 if (ratio
% 2 == 0 && ratio
>= 2 && ratio
<= 512)
355 sai
->mclk_id
[tx
] = id
;
364 dev_err(dai
->dev
, "failed to derive required %cx rate: %d\n",
365 tx
? 'T' : 'R', freq
);
370 * 1) For Asynchronous mode, we must set RCR2 register for capture, and
371 * set TCR2 register for playback.
372 * 2) For Tx sync with Rx clock, we must set RCR2 register for playback
374 * 3) For Rx sync with Tx clock, we must set TCR2 register for playback
376 * 4) For Tx and Rx are both Synchronous with another SAI, we just
379 if ((sai
->synchronous
[TX
] && !sai
->synchronous
[RX
]) ||
380 (!tx
&& !sai
->synchronous
[RX
])) {
381 regmap_update_bits(sai
->regmap
, FSL_SAI_RCR2
,
382 FSL_SAI_CR2_MSEL_MASK
,
383 FSL_SAI_CR2_MSEL(sai
->mclk_id
[tx
]));
384 regmap_update_bits(sai
->regmap
, FSL_SAI_RCR2
,
385 FSL_SAI_CR2_DIV_MASK
, savediv
- 1);
386 } else if ((sai
->synchronous
[RX
] && !sai
->synchronous
[TX
]) ||
387 (tx
&& !sai
->synchronous
[TX
])) {
388 regmap_update_bits(sai
->regmap
, FSL_SAI_TCR2
,
389 FSL_SAI_CR2_MSEL_MASK
,
390 FSL_SAI_CR2_MSEL(sai
->mclk_id
[tx
]));
391 regmap_update_bits(sai
->regmap
, FSL_SAI_TCR2
,
392 FSL_SAI_CR2_DIV_MASK
, savediv
- 1);
395 dev_dbg(dai
->dev
, "best fit: clock id=%d, div=%d, deviation =%d\n",
396 sai
->mclk_id
[tx
], savediv
, savesub
);
401 static int fsl_sai_hw_params(struct snd_pcm_substream
*substream
,
402 struct snd_pcm_hw_params
*params
,
403 struct snd_soc_dai
*cpu_dai
)
405 struct fsl_sai
*sai
= snd_soc_dai_get_drvdata(cpu_dai
);
406 bool tx
= substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
;
407 unsigned int channels
= params_channels(params
);
408 u32 word_width
= params_width(params
);
409 u32 val_cr4
= 0, val_cr5
= 0;
410 u32 slots
= (channels
== 1) ? 2 : channels
;
411 u32 slot_width
= word_width
;
418 slot_width
= sai
->slot_width
;
420 if (!sai
->is_slave_mode
) {
421 ret
= fsl_sai_set_bclk(cpu_dai
, tx
,
422 slots
* slot_width
* params_rate(params
));
426 /* Do not enable the clock if it is already enabled */
427 if (!(sai
->mclk_streams
& BIT(substream
->stream
))) {
428 ret
= clk_prepare_enable(sai
->mclk_clk
[sai
->mclk_id
[tx
]]);
432 sai
->mclk_streams
|= BIT(substream
->stream
);
436 if (!sai
->is_dsp_mode
)
437 val_cr4
|= FSL_SAI_CR4_SYWD(slot_width
);
439 val_cr5
|= FSL_SAI_CR5_WNW(slot_width
);
440 val_cr5
|= FSL_SAI_CR5_W0W(slot_width
);
442 if (sai
->is_lsb_first
)
443 val_cr5
|= FSL_SAI_CR5_FBT(0);
445 val_cr5
|= FSL_SAI_CR5_FBT(word_width
- 1);
447 val_cr4
|= FSL_SAI_CR4_FRSZ(slots
);
450 * For SAI master mode, when Tx(Rx) sync with Rx(Tx) clock, Rx(Tx) will
451 * generate bclk and frame clock for Tx(Rx), we should set RCR4(TCR4),
452 * RCR5(TCR5) and RMR(TMR) for playback(capture), or there will be sync
456 if (!sai
->is_slave_mode
) {
457 if (!sai
->synchronous
[TX
] && sai
->synchronous
[RX
] && !tx
) {
458 regmap_update_bits(sai
->regmap
, FSL_SAI_TCR4
,
459 FSL_SAI_CR4_SYWD_MASK
| FSL_SAI_CR4_FRSZ_MASK
,
461 regmap_update_bits(sai
->regmap
, FSL_SAI_TCR5
,
462 FSL_SAI_CR5_WNW_MASK
| FSL_SAI_CR5_W0W_MASK
|
463 FSL_SAI_CR5_FBT_MASK
, val_cr5
);
464 regmap_write(sai
->regmap
, FSL_SAI_TMR
,
465 ~0UL - ((1 << channels
) - 1));
466 } else if (!sai
->synchronous
[RX
] && sai
->synchronous
[TX
] && tx
) {
467 regmap_update_bits(sai
->regmap
, FSL_SAI_RCR4
,
468 FSL_SAI_CR4_SYWD_MASK
| FSL_SAI_CR4_FRSZ_MASK
,
470 regmap_update_bits(sai
->regmap
, FSL_SAI_RCR5
,
471 FSL_SAI_CR5_WNW_MASK
| FSL_SAI_CR5_W0W_MASK
|
472 FSL_SAI_CR5_FBT_MASK
, val_cr5
);
473 regmap_write(sai
->regmap
, FSL_SAI_RMR
,
474 ~0UL - ((1 << channels
) - 1));
478 regmap_update_bits(sai
->regmap
, FSL_SAI_xCR4(tx
),
479 FSL_SAI_CR4_SYWD_MASK
| FSL_SAI_CR4_FRSZ_MASK
,
481 regmap_update_bits(sai
->regmap
, FSL_SAI_xCR5(tx
),
482 FSL_SAI_CR5_WNW_MASK
| FSL_SAI_CR5_W0W_MASK
|
483 FSL_SAI_CR5_FBT_MASK
, val_cr5
);
484 regmap_write(sai
->regmap
, FSL_SAI_xMR(tx
), ~0UL - ((1 << channels
) - 1));
489 static int fsl_sai_hw_free(struct snd_pcm_substream
*substream
,
490 struct snd_soc_dai
*cpu_dai
)
492 struct fsl_sai
*sai
= snd_soc_dai_get_drvdata(cpu_dai
);
493 bool tx
= substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
;
495 if (!sai
->is_slave_mode
&&
496 sai
->mclk_streams
& BIT(substream
->stream
)) {
497 clk_disable_unprepare(sai
->mclk_clk
[sai
->mclk_id
[tx
]]);
498 sai
->mclk_streams
&= ~BIT(substream
->stream
);
505 static int fsl_sai_trigger(struct snd_pcm_substream
*substream
, int cmd
,
506 struct snd_soc_dai
*cpu_dai
)
508 struct fsl_sai
*sai
= snd_soc_dai_get_drvdata(cpu_dai
);
509 bool tx
= substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
;
510 u32 xcsr
, count
= 100;
513 * Asynchronous mode: Clear SYNC for both Tx and Rx.
514 * Rx sync with Tx clocks: Clear SYNC for Tx, set it for Rx.
515 * Tx sync with Rx clocks: Clear SYNC for Rx, set it for Tx.
517 regmap_update_bits(sai
->regmap
, FSL_SAI_TCR2
, FSL_SAI_CR2_SYNC
,
518 sai
->synchronous
[TX
] ? FSL_SAI_CR2_SYNC
: 0);
519 regmap_update_bits(sai
->regmap
, FSL_SAI_RCR2
, FSL_SAI_CR2_SYNC
,
520 sai
->synchronous
[RX
] ? FSL_SAI_CR2_SYNC
: 0);
523 * It is recommended that the transmitter is the last enabled
524 * and the first disabled.
527 case SNDRV_PCM_TRIGGER_START
:
528 case SNDRV_PCM_TRIGGER_RESUME
:
529 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
530 regmap_update_bits(sai
->regmap
, FSL_SAI_xCSR(tx
),
531 FSL_SAI_CSR_FRDE
, FSL_SAI_CSR_FRDE
);
533 regmap_update_bits(sai
->regmap
, FSL_SAI_RCSR
,
534 FSL_SAI_CSR_TERE
, FSL_SAI_CSR_TERE
);
535 regmap_update_bits(sai
->regmap
, FSL_SAI_TCSR
,
536 FSL_SAI_CSR_TERE
, FSL_SAI_CSR_TERE
);
538 regmap_update_bits(sai
->regmap
, FSL_SAI_xCSR(tx
),
539 FSL_SAI_CSR_xIE_MASK
, FSL_SAI_FLAGS
);
541 case SNDRV_PCM_TRIGGER_STOP
:
542 case SNDRV_PCM_TRIGGER_SUSPEND
:
543 case SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
544 regmap_update_bits(sai
->regmap
, FSL_SAI_xCSR(tx
),
545 FSL_SAI_CSR_FRDE
, 0);
546 regmap_update_bits(sai
->regmap
, FSL_SAI_xCSR(tx
),
547 FSL_SAI_CSR_xIE_MASK
, 0);
549 /* Check if the opposite FRDE is also disabled */
550 regmap_read(sai
->regmap
, FSL_SAI_xCSR(!tx
), &xcsr
);
551 if (!(xcsr
& FSL_SAI_CSR_FRDE
)) {
552 /* Disable both directions and reset their FIFOs */
553 regmap_update_bits(sai
->regmap
, FSL_SAI_TCSR
,
554 FSL_SAI_CSR_TERE
, 0);
555 regmap_update_bits(sai
->regmap
, FSL_SAI_RCSR
,
556 FSL_SAI_CSR_TERE
, 0);
558 /* TERE will remain set till the end of current frame */
561 regmap_read(sai
->regmap
, FSL_SAI_xCSR(tx
), &xcsr
);
562 } while (--count
&& xcsr
& FSL_SAI_CSR_TERE
);
564 regmap_update_bits(sai
->regmap
, FSL_SAI_TCSR
,
565 FSL_SAI_CSR_FR
, FSL_SAI_CSR_FR
);
566 regmap_update_bits(sai
->regmap
, FSL_SAI_RCSR
,
567 FSL_SAI_CSR_FR
, FSL_SAI_CSR_FR
);
570 * For sai master mode, after several open/close sai,
571 * there will be no frame clock, and can't recover
572 * anymore. Add software reset to fix this issue.
573 * This is a hardware bug, and will be fix in the
576 if (!sai
->is_slave_mode
) {
577 /* Software Reset for both Tx and Rx */
578 regmap_write(sai
->regmap
,
579 FSL_SAI_TCSR
, FSL_SAI_CSR_SR
);
580 regmap_write(sai
->regmap
,
581 FSL_SAI_RCSR
, FSL_SAI_CSR_SR
);
582 /* Clear SR bit to finish the reset */
583 regmap_write(sai
->regmap
, FSL_SAI_TCSR
, 0);
584 regmap_write(sai
->regmap
, FSL_SAI_RCSR
, 0);
595 static int fsl_sai_startup(struct snd_pcm_substream
*substream
,
596 struct snd_soc_dai
*cpu_dai
)
598 struct fsl_sai
*sai
= snd_soc_dai_get_drvdata(cpu_dai
);
599 bool tx
= substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
;
600 struct device
*dev
= &sai
->pdev
->dev
;
603 ret
= clk_prepare_enable(sai
->bus_clk
);
605 dev_err(dev
, "failed to enable bus clock: %d\n", ret
);
609 regmap_update_bits(sai
->regmap
, FSL_SAI_xCR3(tx
), FSL_SAI_CR3_TRCE
,
612 ret
= snd_pcm_hw_constraint_list(substream
->runtime
, 0,
613 SNDRV_PCM_HW_PARAM_RATE
, &fsl_sai_rate_constraints
);
618 static void fsl_sai_shutdown(struct snd_pcm_substream
*substream
,
619 struct snd_soc_dai
*cpu_dai
)
621 struct fsl_sai
*sai
= snd_soc_dai_get_drvdata(cpu_dai
);
622 bool tx
= substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
;
624 regmap_update_bits(sai
->regmap
, FSL_SAI_xCR3(tx
), FSL_SAI_CR3_TRCE
, 0);
626 clk_disable_unprepare(sai
->bus_clk
);
629 static const struct snd_soc_dai_ops fsl_sai_pcm_dai_ops
= {
630 .set_sysclk
= fsl_sai_set_dai_sysclk
,
631 .set_fmt
= fsl_sai_set_dai_fmt
,
632 .set_tdm_slot
= fsl_sai_set_dai_tdm_slot
,
633 .hw_params
= fsl_sai_hw_params
,
634 .hw_free
= fsl_sai_hw_free
,
635 .trigger
= fsl_sai_trigger
,
636 .startup
= fsl_sai_startup
,
637 .shutdown
= fsl_sai_shutdown
,
640 static int fsl_sai_dai_probe(struct snd_soc_dai
*cpu_dai
)
642 struct fsl_sai
*sai
= dev_get_drvdata(cpu_dai
->dev
);
644 /* Software Reset for both Tx and Rx */
645 regmap_write(sai
->regmap
, FSL_SAI_TCSR
, FSL_SAI_CSR_SR
);
646 regmap_write(sai
->regmap
, FSL_SAI_RCSR
, FSL_SAI_CSR_SR
);
647 /* Clear SR bit to finish the reset */
648 regmap_write(sai
->regmap
, FSL_SAI_TCSR
, 0);
649 regmap_write(sai
->regmap
, FSL_SAI_RCSR
, 0);
651 regmap_update_bits(sai
->regmap
, FSL_SAI_TCR1
, FSL_SAI_CR1_RFW_MASK
,
652 FSL_SAI_MAXBURST_TX
* 2);
653 regmap_update_bits(sai
->regmap
, FSL_SAI_RCR1
, FSL_SAI_CR1_RFW_MASK
,
654 FSL_SAI_MAXBURST_RX
- 1);
656 snd_soc_dai_init_dma_data(cpu_dai
, &sai
->dma_params_tx
,
657 &sai
->dma_params_rx
);
659 snd_soc_dai_set_drvdata(cpu_dai
, sai
);
664 static struct snd_soc_dai_driver fsl_sai_dai
= {
665 .probe
= fsl_sai_dai_probe
,
667 .stream_name
= "CPU-Playback",
672 .rates
= SNDRV_PCM_RATE_KNOT
,
673 .formats
= FSL_SAI_FORMATS
,
676 .stream_name
= "CPU-Capture",
681 .rates
= SNDRV_PCM_RATE_KNOT
,
682 .formats
= FSL_SAI_FORMATS
,
684 .ops
= &fsl_sai_pcm_dai_ops
,
687 static const struct snd_soc_component_driver fsl_component
= {
691 static struct reg_default fsl_sai_reg_defaults
[] = {
707 static bool fsl_sai_readable_reg(struct device
*dev
, unsigned int reg
)
733 static bool fsl_sai_volatile_reg(struct device
*dev
, unsigned int reg
)
747 static bool fsl_sai_writeable_reg(struct device
*dev
, unsigned int reg
)
771 static const struct regmap_config fsl_sai_regmap_config
= {
776 .max_register
= FSL_SAI_RMR
,
777 .reg_defaults
= fsl_sai_reg_defaults
,
778 .num_reg_defaults
= ARRAY_SIZE(fsl_sai_reg_defaults
),
779 .readable_reg
= fsl_sai_readable_reg
,
780 .volatile_reg
= fsl_sai_volatile_reg
,
781 .writeable_reg
= fsl_sai_writeable_reg
,
782 .cache_type
= REGCACHE_FLAT
,
785 static int fsl_sai_probe(struct platform_device
*pdev
)
787 struct device_node
*np
= pdev
->dev
.of_node
;
789 struct resource
*res
;
794 sai
= devm_kzalloc(&pdev
->dev
, sizeof(*sai
), GFP_KERNEL
);
800 if (of_device_is_compatible(pdev
->dev
.of_node
, "fsl,imx6sx-sai"))
801 sai
->sai_on_imx
= true;
803 sai
->is_lsb_first
= of_property_read_bool(np
, "lsb-first");
805 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
806 base
= devm_ioremap_resource(&pdev
->dev
, res
);
808 return PTR_ERR(base
);
810 sai
->regmap
= devm_regmap_init_mmio_clk(&pdev
->dev
,
811 "bus", base
, &fsl_sai_regmap_config
);
813 /* Compatible with old DTB cases */
814 if (IS_ERR(sai
->regmap
))
815 sai
->regmap
= devm_regmap_init_mmio_clk(&pdev
->dev
,
816 "sai", base
, &fsl_sai_regmap_config
);
817 if (IS_ERR(sai
->regmap
)) {
818 dev_err(&pdev
->dev
, "regmap init failed\n");
819 return PTR_ERR(sai
->regmap
);
822 /* No error out for old DTB cases but only mark the clock NULL */
823 sai
->bus_clk
= devm_clk_get(&pdev
->dev
, "bus");
824 if (IS_ERR(sai
->bus_clk
)) {
825 dev_err(&pdev
->dev
, "failed to get bus clock: %ld\n",
826 PTR_ERR(sai
->bus_clk
));
830 sai
->mclk_clk
[0] = sai
->bus_clk
;
831 for (i
= 1; i
< FSL_SAI_MCLK_MAX
; i
++) {
832 sprintf(tmp
, "mclk%d", i
);
833 sai
->mclk_clk
[i
] = devm_clk_get(&pdev
->dev
, tmp
);
834 if (IS_ERR(sai
->mclk_clk
[i
])) {
835 dev_err(&pdev
->dev
, "failed to get mclk%d clock: %ld\n",
836 i
+ 1, PTR_ERR(sai
->mclk_clk
[i
]));
837 sai
->mclk_clk
[i
] = NULL
;
841 irq
= platform_get_irq(pdev
, 0);
843 dev_err(&pdev
->dev
, "no irq for node %s\n", pdev
->name
);
847 ret
= devm_request_irq(&pdev
->dev
, irq
, fsl_sai_isr
, 0, np
->name
, sai
);
849 dev_err(&pdev
->dev
, "failed to claim irq %u\n", irq
);
853 /* Sync Tx with Rx as default by following old DT binding */
854 sai
->synchronous
[RX
] = true;
855 sai
->synchronous
[TX
] = false;
856 fsl_sai_dai
.symmetric_rates
= 1;
857 fsl_sai_dai
.symmetric_channels
= 1;
858 fsl_sai_dai
.symmetric_samplebits
= 1;
860 if (of_find_property(np
, "fsl,sai-synchronous-rx", NULL
) &&
861 of_find_property(np
, "fsl,sai-asynchronous", NULL
)) {
862 /* error out if both synchronous and asynchronous are present */
863 dev_err(&pdev
->dev
, "invalid binding for synchronous mode\n");
867 if (of_find_property(np
, "fsl,sai-synchronous-rx", NULL
)) {
868 /* Sync Rx with Tx */
869 sai
->synchronous
[RX
] = false;
870 sai
->synchronous
[TX
] = true;
871 } else if (of_find_property(np
, "fsl,sai-asynchronous", NULL
)) {
872 /* Discard all settings for asynchronous mode */
873 sai
->synchronous
[RX
] = false;
874 sai
->synchronous
[TX
] = false;
875 fsl_sai_dai
.symmetric_rates
= 0;
876 fsl_sai_dai
.symmetric_channels
= 0;
877 fsl_sai_dai
.symmetric_samplebits
= 0;
880 sai
->dma_params_rx
.addr
= res
->start
+ FSL_SAI_RDR
;
881 sai
->dma_params_tx
.addr
= res
->start
+ FSL_SAI_TDR
;
882 sai
->dma_params_rx
.maxburst
= FSL_SAI_MAXBURST_RX
;
883 sai
->dma_params_tx
.maxburst
= FSL_SAI_MAXBURST_TX
;
885 platform_set_drvdata(pdev
, sai
);
887 ret
= devm_snd_soc_register_component(&pdev
->dev
, &fsl_component
,
893 return imx_pcm_dma_init(pdev
, IMX_SAI_DMABUF_SIZE
);
895 return devm_snd_dmaengine_pcm_register(&pdev
->dev
, NULL
, 0);
898 static const struct of_device_id fsl_sai_ids
[] = {
899 { .compatible
= "fsl,vf610-sai", },
900 { .compatible
= "fsl,imx6sx-sai", },
903 MODULE_DEVICE_TABLE(of
, fsl_sai_ids
);
905 #ifdef CONFIG_PM_SLEEP
906 static int fsl_sai_suspend(struct device
*dev
)
908 struct fsl_sai
*sai
= dev_get_drvdata(dev
);
910 regcache_cache_only(sai
->regmap
, true);
911 regcache_mark_dirty(sai
->regmap
);
916 static int fsl_sai_resume(struct device
*dev
)
918 struct fsl_sai
*sai
= dev_get_drvdata(dev
);
920 regcache_cache_only(sai
->regmap
, false);
921 regmap_write(sai
->regmap
, FSL_SAI_TCSR
, FSL_SAI_CSR_SR
);
922 regmap_write(sai
->regmap
, FSL_SAI_RCSR
, FSL_SAI_CSR_SR
);
923 usleep_range(1000, 2000);
924 regmap_write(sai
->regmap
, FSL_SAI_TCSR
, 0);
925 regmap_write(sai
->regmap
, FSL_SAI_RCSR
, 0);
926 return regcache_sync(sai
->regmap
);
928 #endif /* CONFIG_PM_SLEEP */
930 static const struct dev_pm_ops fsl_sai_pm_ops
= {
931 SET_SYSTEM_SLEEP_PM_OPS(fsl_sai_suspend
, fsl_sai_resume
)
934 static struct platform_driver fsl_sai_driver
= {
935 .probe
= fsl_sai_probe
,
938 .pm
= &fsl_sai_pm_ops
,
939 .of_match_table
= fsl_sai_ids
,
942 module_platform_driver(fsl_sai_driver
);
944 MODULE_DESCRIPTION("Freescale Soc SAI Interface");
945 MODULE_AUTHOR("Xiubo Li, <Li.Xiubo@freescale.com>");
946 MODULE_ALIAS("platform:fsl-sai");
947 MODULE_LICENSE("GPL");