2 * Freescale ALSA SoC Digital Audio Interface (SAI) driver.
4 * Copyright 2012-2013 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 <sound/core.h>
21 #include <sound/dmaengine_pcm.h>
22 #include <sound/pcm_params.h>
27 #define FSL_SAI_FLAGS (FSL_SAI_CSR_SEIE |\
30 static irqreturn_t
fsl_sai_isr(int irq
, void *devid
)
32 struct fsl_sai
*sai
= (struct fsl_sai
*)devid
;
33 struct device
*dev
= &sai
->pdev
->dev
;
34 u32 flags
, xcsr
, mask
;
38 * Both IRQ status bits and IRQ mask bits are in the xCSR but
39 * different shifts. And we here create a mask only for those
40 * IRQs that we activated.
42 mask
= (FSL_SAI_FLAGS
>> FSL_SAI_CSR_xIE_SHIFT
) << FSL_SAI_CSR_xF_SHIFT
;
45 regmap_read(sai
->regmap
, FSL_SAI_TCSR
, &xcsr
);
53 if (flags
& FSL_SAI_CSR_WSF
)
54 dev_dbg(dev
, "isr: Start of Tx word detected\n");
56 if (flags
& FSL_SAI_CSR_SEF
)
57 dev_warn(dev
, "isr: Tx Frame sync error detected\n");
59 if (flags
& FSL_SAI_CSR_FEF
) {
60 dev_warn(dev
, "isr: Transmit underrun detected\n");
61 /* FIFO reset for safety */
62 xcsr
|= FSL_SAI_CSR_FR
;
65 if (flags
& FSL_SAI_CSR_FWF
)
66 dev_dbg(dev
, "isr: Enabled transmit FIFO is empty\n");
68 if (flags
& FSL_SAI_CSR_FRF
)
69 dev_dbg(dev
, "isr: Transmit FIFO watermark has been reached\n");
71 flags
&= FSL_SAI_CSR_xF_W_MASK
;
72 xcsr
&= ~FSL_SAI_CSR_xF_MASK
;
75 regmap_write(sai
->regmap
, FSL_SAI_TCSR
, flags
| xcsr
);
79 regmap_read(sai
->regmap
, FSL_SAI_RCSR
, &xcsr
);
87 if (flags
& FSL_SAI_CSR_WSF
)
88 dev_dbg(dev
, "isr: Start of Rx word detected\n");
90 if (flags
& FSL_SAI_CSR_SEF
)
91 dev_warn(dev
, "isr: Rx Frame sync error detected\n");
93 if (flags
& FSL_SAI_CSR_FEF
) {
94 dev_warn(dev
, "isr: Receive overflow detected\n");
95 /* FIFO reset for safety */
96 xcsr
|= FSL_SAI_CSR_FR
;
99 if (flags
& FSL_SAI_CSR_FWF
)
100 dev_dbg(dev
, "isr: Enabled receive FIFO is full\n");
102 if (flags
& FSL_SAI_CSR_FRF
)
103 dev_dbg(dev
, "isr: Receive FIFO watermark has been reached\n");
105 flags
&= FSL_SAI_CSR_xF_W_MASK
;
106 xcsr
&= ~FSL_SAI_CSR_xF_MASK
;
109 regmap_write(sai
->regmap
, FSL_SAI_TCSR
, flags
| xcsr
);
118 static int fsl_sai_set_dai_sysclk_tr(struct snd_soc_dai
*cpu_dai
,
119 int clk_id
, unsigned int freq
, int fsl_dir
)
121 struct fsl_sai
*sai
= snd_soc_dai_get_drvdata(cpu_dai
);
122 bool tx
= fsl_dir
== FSL_FMT_TRANSMITTER
;
126 case FSL_SAI_CLK_BUS
:
127 val_cr2
|= FSL_SAI_CR2_MSEL_BUS
;
129 case FSL_SAI_CLK_MAST1
:
130 val_cr2
|= FSL_SAI_CR2_MSEL_MCLK1
;
132 case FSL_SAI_CLK_MAST2
:
133 val_cr2
|= FSL_SAI_CR2_MSEL_MCLK2
;
135 case FSL_SAI_CLK_MAST3
:
136 val_cr2
|= FSL_SAI_CR2_MSEL_MCLK3
;
142 regmap_update_bits(sai
->regmap
, FSL_SAI_xCR2(tx
),
143 FSL_SAI_CR2_MSEL_MASK
, val_cr2
);
148 static int fsl_sai_set_dai_sysclk(struct snd_soc_dai
*cpu_dai
,
149 int clk_id
, unsigned int freq
, int dir
)
153 if (dir
== SND_SOC_CLOCK_IN
)
156 ret
= fsl_sai_set_dai_sysclk_tr(cpu_dai
, clk_id
, freq
,
157 FSL_FMT_TRANSMITTER
);
159 dev_err(cpu_dai
->dev
, "Cannot set tx sysclk: %d\n", ret
);
163 ret
= fsl_sai_set_dai_sysclk_tr(cpu_dai
, clk_id
, freq
,
166 dev_err(cpu_dai
->dev
, "Cannot set rx sysclk: %d\n", ret
);
171 static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai
*cpu_dai
,
172 unsigned int fmt
, int fsl_dir
)
174 struct fsl_sai
*sai
= snd_soc_dai_get_drvdata(cpu_dai
);
175 bool tx
= fsl_dir
== FSL_FMT_TRANSMITTER
;
176 u32 val_cr2
= 0, val_cr4
= 0;
178 if (!sai
->big_endian_data
)
179 val_cr4
|= FSL_SAI_CR4_MF
;
182 switch (fmt
& SND_SOC_DAIFMT_FORMAT_MASK
) {
183 case SND_SOC_DAIFMT_I2S
:
185 * Frame low, 1clk before data, one word length for frame sync,
186 * frame sync starts one serial clock cycle earlier,
187 * that is, together with the last bit of the previous
190 val_cr2
|= FSL_SAI_CR2_BCP
;
191 val_cr4
|= FSL_SAI_CR4_FSE
| FSL_SAI_CR4_FSP
;
193 case SND_SOC_DAIFMT_LEFT_J
:
195 * Frame high, one word length for frame sync,
196 * frame sync asserts with the first bit of the frame.
198 val_cr2
|= FSL_SAI_CR2_BCP
;
200 case SND_SOC_DAIFMT_DSP_A
:
202 * Frame high, 1clk before data, one bit for frame sync,
203 * frame sync starts one serial clock cycle earlier,
204 * that is, together with the last bit of the previous
207 val_cr2
|= FSL_SAI_CR2_BCP
;
208 val_cr4
|= FSL_SAI_CR4_FSE
;
209 sai
->is_dsp_mode
= true;
211 case SND_SOC_DAIFMT_DSP_B
:
213 * Frame high, one bit for frame sync,
214 * frame sync asserts with the first bit of the frame.
216 val_cr2
|= FSL_SAI_CR2_BCP
;
217 sai
->is_dsp_mode
= true;
219 case SND_SOC_DAIFMT_RIGHT_J
:
225 /* DAI clock inversion */
226 switch (fmt
& SND_SOC_DAIFMT_INV_MASK
) {
227 case SND_SOC_DAIFMT_IB_IF
:
228 /* Invert both clocks */
229 val_cr2
^= FSL_SAI_CR2_BCP
;
230 val_cr4
^= FSL_SAI_CR4_FSP
;
232 case SND_SOC_DAIFMT_IB_NF
:
233 /* Invert bit clock */
234 val_cr2
^= FSL_SAI_CR2_BCP
;
236 case SND_SOC_DAIFMT_NB_IF
:
237 /* Invert frame clock */
238 val_cr4
^= FSL_SAI_CR4_FSP
;
240 case SND_SOC_DAIFMT_NB_NF
:
241 /* Nothing to do for both normal cases */
247 /* DAI clock master masks */
248 switch (fmt
& SND_SOC_DAIFMT_MASTER_MASK
) {
249 case SND_SOC_DAIFMT_CBS_CFS
:
250 val_cr2
|= FSL_SAI_CR2_BCD_MSTR
;
251 val_cr4
|= FSL_SAI_CR4_FSD_MSTR
;
253 case SND_SOC_DAIFMT_CBM_CFM
:
255 case SND_SOC_DAIFMT_CBS_CFM
:
256 val_cr2
|= FSL_SAI_CR2_BCD_MSTR
;
258 case SND_SOC_DAIFMT_CBM_CFS
:
259 val_cr4
|= FSL_SAI_CR4_FSD_MSTR
;
265 regmap_update_bits(sai
->regmap
, FSL_SAI_xCR2(tx
),
266 FSL_SAI_CR2_BCP
| FSL_SAI_CR2_BCD_MSTR
, val_cr2
);
267 regmap_update_bits(sai
->regmap
, FSL_SAI_xCR4(tx
),
268 FSL_SAI_CR4_MF
| FSL_SAI_CR4_FSE
|
269 FSL_SAI_CR4_FSP
| FSL_SAI_CR4_FSD_MSTR
, val_cr4
);
274 static int fsl_sai_set_dai_fmt(struct snd_soc_dai
*cpu_dai
, unsigned int fmt
)
278 ret
= fsl_sai_set_dai_fmt_tr(cpu_dai
, fmt
, FSL_FMT_TRANSMITTER
);
280 dev_err(cpu_dai
->dev
, "Cannot set tx format: %d\n", ret
);
284 ret
= fsl_sai_set_dai_fmt_tr(cpu_dai
, fmt
, FSL_FMT_RECEIVER
);
286 dev_err(cpu_dai
->dev
, "Cannot set rx format: %d\n", ret
);
291 static int fsl_sai_hw_params(struct snd_pcm_substream
*substream
,
292 struct snd_pcm_hw_params
*params
,
293 struct snd_soc_dai
*cpu_dai
)
295 struct fsl_sai
*sai
= snd_soc_dai_get_drvdata(cpu_dai
);
296 bool tx
= substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
;
297 unsigned int channels
= params_channels(params
);
298 u32 word_width
= snd_pcm_format_width(params_format(params
));
299 u32 val_cr4
= 0, val_cr5
= 0;
301 if (!sai
->is_dsp_mode
)
302 val_cr4
|= FSL_SAI_CR4_SYWD(word_width
);
304 val_cr5
|= FSL_SAI_CR5_WNW(word_width
);
305 val_cr5
|= FSL_SAI_CR5_W0W(word_width
);
307 if (sai
->big_endian_data
)
308 val_cr5
|= FSL_SAI_CR5_FBT(0);
310 val_cr5
|= FSL_SAI_CR5_FBT(word_width
- 1);
312 val_cr4
|= FSL_SAI_CR4_FRSZ(channels
);
314 regmap_update_bits(sai
->regmap
, FSL_SAI_xCR4(tx
),
315 FSL_SAI_CR4_SYWD_MASK
| FSL_SAI_CR4_FRSZ_MASK
,
317 regmap_update_bits(sai
->regmap
, FSL_SAI_xCR5(tx
),
318 FSL_SAI_CR5_WNW_MASK
| FSL_SAI_CR5_W0W_MASK
|
319 FSL_SAI_CR5_FBT_MASK
, val_cr5
);
320 regmap_write(sai
->regmap
, FSL_SAI_xMR(tx
), ~0UL - ((1 << channels
) - 1));
325 static int fsl_sai_trigger(struct snd_pcm_substream
*substream
, int cmd
,
326 struct snd_soc_dai
*cpu_dai
)
328 struct fsl_sai
*sai
= snd_soc_dai_get_drvdata(cpu_dai
);
329 bool tx
= substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
;
333 * The transmitter bit clock and frame sync are to be
334 * used by both the transmitter and receiver.
336 regmap_update_bits(sai
->regmap
, FSL_SAI_TCR2
, FSL_SAI_CR2_SYNC
,
338 regmap_update_bits(sai
->regmap
, FSL_SAI_RCR2
, FSL_SAI_CR2_SYNC
,
341 regmap_read(sai
->regmap
, FSL_SAI_TCSR
, &tcsr
);
342 regmap_read(sai
->regmap
, FSL_SAI_RCSR
, &rcsr
);
345 * It is recommended that the transmitter is the last enabled
346 * and the first disabled.
349 case SNDRV_PCM_TRIGGER_START
:
350 case SNDRV_PCM_TRIGGER_RESUME
:
351 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
352 if (!(tcsr
& FSL_SAI_CSR_FRDE
|| rcsr
& FSL_SAI_CSR_FRDE
)) {
353 regmap_update_bits(sai
->regmap
, FSL_SAI_RCSR
,
354 FSL_SAI_CSR_TERE
, FSL_SAI_CSR_TERE
);
355 regmap_update_bits(sai
->regmap
, FSL_SAI_TCSR
,
356 FSL_SAI_CSR_TERE
, FSL_SAI_CSR_TERE
);
359 regmap_update_bits(sai
->regmap
, FSL_SAI_xCSR(tx
),
360 FSL_SAI_CSR_xIE_MASK
, FSL_SAI_FLAGS
);
361 regmap_update_bits(sai
->regmap
, FSL_SAI_xCSR(tx
),
362 FSL_SAI_CSR_FRDE
, FSL_SAI_CSR_FRDE
);
364 case SNDRV_PCM_TRIGGER_STOP
:
365 case SNDRV_PCM_TRIGGER_SUSPEND
:
366 case SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
367 regmap_update_bits(sai
->regmap
, FSL_SAI_xCSR(tx
),
368 FSL_SAI_CSR_FRDE
, 0);
369 regmap_update_bits(sai
->regmap
, FSL_SAI_xCSR(tx
),
370 FSL_SAI_CSR_xIE_MASK
, 0);
372 /* Check if the opposite FRDE is also disabled */
373 if (!(tx
? rcsr
& FSL_SAI_CSR_FRDE
: tcsr
& FSL_SAI_CSR_FRDE
)) {
374 regmap_update_bits(sai
->regmap
, FSL_SAI_TCSR
,
375 FSL_SAI_CSR_TERE
, 0);
376 regmap_update_bits(sai
->regmap
, FSL_SAI_RCSR
,
377 FSL_SAI_CSR_TERE
, 0);
387 static int fsl_sai_startup(struct snd_pcm_substream
*substream
,
388 struct snd_soc_dai
*cpu_dai
)
390 struct fsl_sai
*sai
= snd_soc_dai_get_drvdata(cpu_dai
);
391 bool tx
= substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
;
392 struct device
*dev
= &sai
->pdev
->dev
;
395 ret
= clk_prepare_enable(sai
->bus_clk
);
397 dev_err(dev
, "failed to enable bus clock: %d\n", ret
);
401 regmap_update_bits(sai
->regmap
, FSL_SAI_xCR3(tx
), FSL_SAI_CR3_TRCE
,
407 static void fsl_sai_shutdown(struct snd_pcm_substream
*substream
,
408 struct snd_soc_dai
*cpu_dai
)
410 struct fsl_sai
*sai
= snd_soc_dai_get_drvdata(cpu_dai
);
411 bool tx
= substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
;
413 regmap_update_bits(sai
->regmap
, FSL_SAI_xCR3(tx
), FSL_SAI_CR3_TRCE
, 0);
415 clk_disable_unprepare(sai
->bus_clk
);
418 static const struct snd_soc_dai_ops fsl_sai_pcm_dai_ops
= {
419 .set_sysclk
= fsl_sai_set_dai_sysclk
,
420 .set_fmt
= fsl_sai_set_dai_fmt
,
421 .hw_params
= fsl_sai_hw_params
,
422 .trigger
= fsl_sai_trigger
,
423 .startup
= fsl_sai_startup
,
424 .shutdown
= fsl_sai_shutdown
,
427 static int fsl_sai_dai_probe(struct snd_soc_dai
*cpu_dai
)
429 struct fsl_sai
*sai
= dev_get_drvdata(cpu_dai
->dev
);
431 regmap_update_bits(sai
->regmap
, FSL_SAI_TCSR
, 0xffffffff, 0x0);
432 regmap_update_bits(sai
->regmap
, FSL_SAI_RCSR
, 0xffffffff, 0x0);
433 regmap_update_bits(sai
->regmap
, FSL_SAI_TCR1
, FSL_SAI_CR1_RFW_MASK
,
434 FSL_SAI_MAXBURST_TX
* 2);
435 regmap_update_bits(sai
->regmap
, FSL_SAI_RCR1
, FSL_SAI_CR1_RFW_MASK
,
436 FSL_SAI_MAXBURST_RX
- 1);
438 snd_soc_dai_init_dma_data(cpu_dai
, &sai
->dma_params_tx
,
439 &sai
->dma_params_rx
);
441 snd_soc_dai_set_drvdata(cpu_dai
, sai
);
446 static struct snd_soc_dai_driver fsl_sai_dai
= {
447 .probe
= fsl_sai_dai_probe
,
451 .rates
= SNDRV_PCM_RATE_8000_96000
,
452 .formats
= FSL_SAI_FORMATS
,
457 .rates
= SNDRV_PCM_RATE_8000_96000
,
458 .formats
= FSL_SAI_FORMATS
,
460 .ops
= &fsl_sai_pcm_dai_ops
,
463 static const struct snd_soc_component_driver fsl_component
= {
467 static bool fsl_sai_readable_reg(struct device
*dev
, unsigned int reg
)
493 static bool fsl_sai_volatile_reg(struct device
*dev
, unsigned int reg
)
507 static bool fsl_sai_writeable_reg(struct device
*dev
, unsigned int reg
)
531 static struct regmap_config fsl_sai_regmap_config
= {
536 .max_register
= FSL_SAI_RMR
,
537 .readable_reg
= fsl_sai_readable_reg
,
538 .volatile_reg
= fsl_sai_volatile_reg
,
539 .writeable_reg
= fsl_sai_writeable_reg
,
542 static int fsl_sai_probe(struct platform_device
*pdev
)
544 struct device_node
*np
= pdev
->dev
.of_node
;
546 struct resource
*res
;
551 sai
= devm_kzalloc(&pdev
->dev
, sizeof(*sai
), GFP_KERNEL
);
557 if (of_device_is_compatible(pdev
->dev
.of_node
, "fsl,imx6sx-sai"))
558 sai
->sai_on_imx
= true;
560 sai
->big_endian_regs
= of_property_read_bool(np
, "big-endian-regs");
561 if (sai
->big_endian_regs
)
562 fsl_sai_regmap_config
.val_format_endian
= REGMAP_ENDIAN_BIG
;
564 sai
->big_endian_data
= of_property_read_bool(np
, "big-endian-data");
566 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
567 base
= devm_ioremap_resource(&pdev
->dev
, res
);
569 return PTR_ERR(base
);
571 sai
->regmap
= devm_regmap_init_mmio_clk(&pdev
->dev
,
572 "bus", base
, &fsl_sai_regmap_config
);
574 /* Compatible with old DTB cases */
575 if (IS_ERR(sai
->regmap
))
576 sai
->regmap
= devm_regmap_init_mmio_clk(&pdev
->dev
,
577 "sai", base
, &fsl_sai_regmap_config
);
578 if (IS_ERR(sai
->regmap
)) {
579 dev_err(&pdev
->dev
, "regmap init failed\n");
580 return PTR_ERR(sai
->regmap
);
583 /* No error out for old DTB cases but only mark the clock NULL */
584 sai
->bus_clk
= devm_clk_get(&pdev
->dev
, "bus");
585 if (IS_ERR(sai
->bus_clk
)) {
586 dev_err(&pdev
->dev
, "failed to get bus clock: %ld\n",
587 PTR_ERR(sai
->bus_clk
));
591 for (i
= 0; i
< FSL_SAI_MCLK_MAX
; i
++) {
592 sprintf(tmp
, "mclk%d", i
+ 1);
593 sai
->mclk_clk
[i
] = devm_clk_get(&pdev
->dev
, tmp
);
594 if (IS_ERR(sai
->mclk_clk
[i
])) {
595 dev_err(&pdev
->dev
, "failed to get mclk%d clock: %ld\n",
596 i
+ 1, PTR_ERR(sai
->mclk_clk
[i
]));
597 sai
->mclk_clk
[i
] = NULL
;
601 irq
= platform_get_irq(pdev
, 0);
603 dev_err(&pdev
->dev
, "no irq for node %s\n", np
->full_name
);
607 ret
= devm_request_irq(&pdev
->dev
, irq
, fsl_sai_isr
, 0, np
->name
, sai
);
609 dev_err(&pdev
->dev
, "failed to claim irq %u\n", irq
);
613 sai
->dma_params_rx
.addr
= res
->start
+ FSL_SAI_RDR
;
614 sai
->dma_params_tx
.addr
= res
->start
+ FSL_SAI_TDR
;
615 sai
->dma_params_rx
.maxburst
= FSL_SAI_MAXBURST_RX
;
616 sai
->dma_params_tx
.maxburst
= FSL_SAI_MAXBURST_TX
;
618 platform_set_drvdata(pdev
, sai
);
620 ret
= devm_snd_soc_register_component(&pdev
->dev
, &fsl_component
,
626 return imx_pcm_dma_init(pdev
);
628 return devm_snd_dmaengine_pcm_register(&pdev
->dev
, NULL
,
629 SND_DMAENGINE_PCM_FLAG_NO_RESIDUE
);
632 static const struct of_device_id fsl_sai_ids
[] = {
633 { .compatible
= "fsl,vf610-sai", },
634 { .compatible
= "fsl,imx6sx-sai", },
638 static struct platform_driver fsl_sai_driver
= {
639 .probe
= fsl_sai_probe
,
642 .owner
= THIS_MODULE
,
643 .of_match_table
= fsl_sai_ids
,
646 module_platform_driver(fsl_sai_driver
);
648 MODULE_DESCRIPTION("Freescale Soc SAI Interface");
649 MODULE_AUTHOR("Xiubo Li, <Li.Xiubo@freescale.com>");
650 MODULE_ALIAS("platform:fsl-sai");
651 MODULE_LICENSE("GPL");