1 // SPDX-License-Identifier: GPL-2.0-or-later
5 * (c) 2010 Arnaud Patard <apatard@mandriva.com>
6 * (c) 2010 Arnaud Patard <arnaud.patard@rtp-net.org>
9 #include <linux/init.h>
10 #include <linux/module.h>
11 #include <linux/platform_device.h>
13 #include <linux/slab.h>
14 #include <linux/mbus.h>
15 #include <linux/delay.h>
16 #include <linux/clk.h>
17 #include <sound/pcm.h>
18 #include <sound/pcm_params.h>
19 #include <sound/soc.h>
20 #include <linux/platform_data/asoc-kirkwood.h>
25 #define KIRKWOOD_I2S_FORMATS \
26 (SNDRV_PCM_FMTBIT_S16_LE | \
27 SNDRV_PCM_FMTBIT_S24_LE | \
28 SNDRV_PCM_FMTBIT_S32_LE)
30 #define KIRKWOOD_SPDIF_FORMATS \
31 (SNDRV_PCM_FMTBIT_S16_LE | \
32 SNDRV_PCM_FMTBIT_S24_LE)
34 static int kirkwood_i2s_set_fmt(struct snd_soc_dai
*cpu_dai
,
37 struct kirkwood_dma_data
*priv
= snd_soc_dai_get_drvdata(cpu_dai
);
41 switch (fmt
& SND_SOC_DAIFMT_FORMAT_MASK
) {
42 case SND_SOC_DAIFMT_RIGHT_J
:
43 mask
= KIRKWOOD_I2S_CTL_RJ
;
45 case SND_SOC_DAIFMT_LEFT_J
:
46 mask
= KIRKWOOD_I2S_CTL_LJ
;
48 case SND_SOC_DAIFMT_I2S
:
49 mask
= KIRKWOOD_I2S_CTL_I2S
;
56 * Set same format for playback and record
57 * This avoids some troubles.
59 value
= readl(priv
->io
+KIRKWOOD_I2S_PLAYCTL
);
60 value
&= ~KIRKWOOD_I2S_CTL_JUST_MASK
;
62 writel(value
, priv
->io
+KIRKWOOD_I2S_PLAYCTL
);
64 value
= readl(priv
->io
+KIRKWOOD_I2S_RECCTL
);
65 value
&= ~KIRKWOOD_I2S_CTL_JUST_MASK
;
67 writel(value
, priv
->io
+KIRKWOOD_I2S_RECCTL
);
72 static inline void kirkwood_set_dco(void __iomem
*io
, unsigned long rate
)
76 value
= KIRKWOOD_DCO_CTL_OFFSET_0
;
80 value
|= KIRKWOOD_DCO_CTL_FREQ_11
;
83 value
|= KIRKWOOD_DCO_CTL_FREQ_12
;
86 value
|= KIRKWOOD_DCO_CTL_FREQ_24
;
89 writel(value
, io
+ KIRKWOOD_DCO_CTL
);
91 /* wait for dco locked */
94 value
= readl(io
+ KIRKWOOD_DCO_SPCR_STATUS
);
95 value
&= KIRKWOOD_DCO_SPCR_STATUS_DCO_LOCK
;
99 static void kirkwood_set_rate(struct snd_soc_dai
*dai
,
100 struct kirkwood_dma_data
*priv
, unsigned long rate
)
104 if (IS_ERR(priv
->extclk
)) {
105 /* use internal dco for the supported rates
106 * defined in kirkwood_i2s_dai */
107 dev_dbg(dai
->dev
, "%s: dco set rate = %lu\n",
109 kirkwood_set_dco(priv
->io
, rate
);
111 clks_ctrl
= KIRKWOOD_MCLK_SOURCE_DCO
;
113 /* use the external clock for the other rates
114 * defined in kirkwood_i2s_dai_extclk */
115 dev_dbg(dai
->dev
, "%s: extclk set rate = %lu -> %lu\n",
116 __func__
, rate
, 256 * rate
);
117 clk_set_rate(priv
->extclk
, 256 * rate
);
119 clks_ctrl
= KIRKWOOD_MCLK_SOURCE_EXTCLK
;
121 writel(clks_ctrl
, priv
->io
+ KIRKWOOD_CLOCKS_CTRL
);
124 static int kirkwood_i2s_startup(struct snd_pcm_substream
*substream
,
125 struct snd_soc_dai
*dai
)
127 struct kirkwood_dma_data
*priv
= snd_soc_dai_get_drvdata(dai
);
129 snd_soc_dai_set_dma_data(dai
, substream
, priv
);
133 static int kirkwood_i2s_hw_params(struct snd_pcm_substream
*substream
,
134 struct snd_pcm_hw_params
*params
,
135 struct snd_soc_dai
*dai
)
137 struct kirkwood_dma_data
*priv
= snd_soc_dai_get_drvdata(dai
);
138 uint32_t ctl_play
, ctl_rec
;
139 unsigned int i2s_reg
;
140 unsigned long i2s_value
;
142 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
) {
143 i2s_reg
= KIRKWOOD_I2S_PLAYCTL
;
145 i2s_reg
= KIRKWOOD_I2S_RECCTL
;
148 kirkwood_set_rate(dai
, priv
, params_rate(params
));
150 i2s_value
= readl(priv
->io
+i2s_reg
);
151 i2s_value
&= ~KIRKWOOD_I2S_CTL_SIZE_MASK
;
154 * Size settings in play/rec i2s control regs and play/rec control
155 * regs must be the same.
157 switch (params_format(params
)) {
158 case SNDRV_PCM_FORMAT_S16_LE
:
159 i2s_value
|= KIRKWOOD_I2S_CTL_SIZE_16
;
160 ctl_play
= KIRKWOOD_PLAYCTL_SIZE_16_C
|
161 KIRKWOOD_PLAYCTL_I2S_EN
|
162 KIRKWOOD_PLAYCTL_SPDIF_EN
;
163 ctl_rec
= KIRKWOOD_RECCTL_SIZE_16_C
|
164 KIRKWOOD_RECCTL_I2S_EN
|
165 KIRKWOOD_RECCTL_SPDIF_EN
;
168 * doesn't work... S20_3LE != kirkwood 20bit format ?
170 case SNDRV_PCM_FORMAT_S20_3LE:
171 i2s_value |= KIRKWOOD_I2S_CTL_SIZE_20;
172 ctl_play = KIRKWOOD_PLAYCTL_SIZE_20 |
173 KIRKWOOD_PLAYCTL_I2S_EN;
174 ctl_rec = KIRKWOOD_RECCTL_SIZE_20 |
175 KIRKWOOD_RECCTL_I2S_EN;
178 case SNDRV_PCM_FORMAT_S24_LE
:
179 i2s_value
|= KIRKWOOD_I2S_CTL_SIZE_24
;
180 ctl_play
= KIRKWOOD_PLAYCTL_SIZE_24
|
181 KIRKWOOD_PLAYCTL_I2S_EN
|
182 KIRKWOOD_PLAYCTL_SPDIF_EN
;
183 ctl_rec
= KIRKWOOD_RECCTL_SIZE_24
|
184 KIRKWOOD_RECCTL_I2S_EN
|
185 KIRKWOOD_RECCTL_SPDIF_EN
;
187 case SNDRV_PCM_FORMAT_S32_LE
:
188 i2s_value
|= KIRKWOOD_I2S_CTL_SIZE_32
;
189 ctl_play
= KIRKWOOD_PLAYCTL_SIZE_32
|
190 KIRKWOOD_PLAYCTL_I2S_EN
;
191 ctl_rec
= KIRKWOOD_RECCTL_SIZE_32
|
192 KIRKWOOD_RECCTL_I2S_EN
;
198 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
) {
199 if (params_channels(params
) == 1)
200 ctl_play
|= KIRKWOOD_PLAYCTL_MONO_BOTH
;
202 ctl_play
|= KIRKWOOD_PLAYCTL_MONO_OFF
;
204 priv
->ctl_play
&= ~(KIRKWOOD_PLAYCTL_MONO_MASK
|
205 KIRKWOOD_PLAYCTL_ENABLE_MASK
|
206 KIRKWOOD_PLAYCTL_SIZE_MASK
);
207 priv
->ctl_play
|= ctl_play
;
209 priv
->ctl_rec
&= ~(KIRKWOOD_RECCTL_ENABLE_MASK
|
210 KIRKWOOD_RECCTL_SIZE_MASK
);
211 priv
->ctl_rec
|= ctl_rec
;
214 writel(i2s_value
, priv
->io
+i2s_reg
);
219 static unsigned kirkwood_i2s_play_mute(unsigned ctl
)
221 if (!(ctl
& KIRKWOOD_PLAYCTL_I2S_EN
))
222 ctl
|= KIRKWOOD_PLAYCTL_I2S_MUTE
;
223 if (!(ctl
& KIRKWOOD_PLAYCTL_SPDIF_EN
))
224 ctl
|= KIRKWOOD_PLAYCTL_SPDIF_MUTE
;
228 static int kirkwood_i2s_play_trigger(struct snd_pcm_substream
*substream
,
229 int cmd
, struct snd_soc_dai
*dai
)
231 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
232 struct kirkwood_dma_data
*priv
= snd_soc_dai_get_drvdata(dai
);
235 ctl
= readl(priv
->io
+ KIRKWOOD_PLAYCTL
);
236 if ((ctl
& KIRKWOOD_PLAYCTL_ENABLE_MASK
) == 0) {
237 unsigned timeout
= 5000;
239 * The Armada510 spec says that if we enter pause mode, the
240 * busy bit must be read back as clear _twice_. Make sure
241 * we respect that otherwise we get DMA underruns.
245 ctl
= readl(priv
->io
+ KIRKWOOD_PLAYCTL
);
246 if (!((ctl
| value
) & KIRKWOOD_PLAYCTL_PLAY_BUSY
))
251 if ((ctl
| value
) & KIRKWOOD_PLAYCTL_PLAY_BUSY
)
252 dev_notice(dai
->dev
, "timed out waiting for busy to deassert: %08x\n",
257 case SNDRV_PCM_TRIGGER_START
:
259 ctl
= priv
->ctl_play
;
261 ctl
&= ~KIRKWOOD_PLAYCTL_SPDIF_EN
; /* i2s */
263 ctl
&= ~KIRKWOOD_PLAYCTL_I2S_EN
; /* spdif */
264 ctl
= kirkwood_i2s_play_mute(ctl
);
265 value
= ctl
& ~KIRKWOOD_PLAYCTL_ENABLE_MASK
;
266 writel(value
, priv
->io
+ KIRKWOOD_PLAYCTL
);
268 /* enable interrupts */
269 if (!runtime
->no_period_wakeup
) {
270 value
= readl(priv
->io
+ KIRKWOOD_INT_MASK
);
271 value
|= KIRKWOOD_INT_CAUSE_PLAY_BYTES
;
272 writel(value
, priv
->io
+ KIRKWOOD_INT_MASK
);
275 /* enable playback */
276 writel(ctl
, priv
->io
+ KIRKWOOD_PLAYCTL
);
279 case SNDRV_PCM_TRIGGER_STOP
:
280 /* stop audio, disable interrupts */
281 ctl
|= KIRKWOOD_PLAYCTL_PAUSE
| KIRKWOOD_PLAYCTL_I2S_MUTE
|
282 KIRKWOOD_PLAYCTL_SPDIF_MUTE
;
283 writel(ctl
, priv
->io
+ KIRKWOOD_PLAYCTL
);
285 value
= readl(priv
->io
+ KIRKWOOD_INT_MASK
);
286 value
&= ~KIRKWOOD_INT_CAUSE_PLAY_BYTES
;
287 writel(value
, priv
->io
+ KIRKWOOD_INT_MASK
);
289 /* disable all playbacks */
290 ctl
&= ~KIRKWOOD_PLAYCTL_ENABLE_MASK
;
291 writel(ctl
, priv
->io
+ KIRKWOOD_PLAYCTL
);
294 case SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
295 case SNDRV_PCM_TRIGGER_SUSPEND
:
296 ctl
|= KIRKWOOD_PLAYCTL_PAUSE
| KIRKWOOD_PLAYCTL_I2S_MUTE
|
297 KIRKWOOD_PLAYCTL_SPDIF_MUTE
;
298 writel(ctl
, priv
->io
+ KIRKWOOD_PLAYCTL
);
301 case SNDRV_PCM_TRIGGER_RESUME
:
302 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
303 ctl
&= ~(KIRKWOOD_PLAYCTL_PAUSE
| KIRKWOOD_PLAYCTL_I2S_MUTE
|
304 KIRKWOOD_PLAYCTL_SPDIF_MUTE
);
305 ctl
= kirkwood_i2s_play_mute(ctl
);
306 writel(ctl
, priv
->io
+ KIRKWOOD_PLAYCTL
);
316 static int kirkwood_i2s_rec_trigger(struct snd_pcm_substream
*substream
,
317 int cmd
, struct snd_soc_dai
*dai
)
319 struct kirkwood_dma_data
*priv
= snd_soc_dai_get_drvdata(dai
);
322 value
= readl(priv
->io
+ KIRKWOOD_RECCTL
);
325 case SNDRV_PCM_TRIGGER_START
:
329 ctl
&= ~KIRKWOOD_RECCTL_SPDIF_EN
; /* i2s */
331 ctl
&= ~KIRKWOOD_RECCTL_I2S_EN
; /* spdif */
333 value
= ctl
& ~KIRKWOOD_RECCTL_ENABLE_MASK
;
334 writel(value
, priv
->io
+ KIRKWOOD_RECCTL
);
336 /* enable interrupts */
337 value
= readl(priv
->io
+ KIRKWOOD_INT_MASK
);
338 value
|= KIRKWOOD_INT_CAUSE_REC_BYTES
;
339 writel(value
, priv
->io
+ KIRKWOOD_INT_MASK
);
342 writel(ctl
, priv
->io
+ KIRKWOOD_RECCTL
);
345 case SNDRV_PCM_TRIGGER_STOP
:
346 /* stop audio, disable interrupts */
347 value
= readl(priv
->io
+ KIRKWOOD_RECCTL
);
348 value
|= KIRKWOOD_RECCTL_PAUSE
| KIRKWOOD_RECCTL_MUTE
;
349 writel(value
, priv
->io
+ KIRKWOOD_RECCTL
);
351 value
= readl(priv
->io
+ KIRKWOOD_INT_MASK
);
352 value
&= ~KIRKWOOD_INT_CAUSE_REC_BYTES
;
353 writel(value
, priv
->io
+ KIRKWOOD_INT_MASK
);
355 /* disable all records */
356 value
= readl(priv
->io
+ KIRKWOOD_RECCTL
);
357 value
&= ~KIRKWOOD_RECCTL_ENABLE_MASK
;
358 writel(value
, priv
->io
+ KIRKWOOD_RECCTL
);
361 case SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
362 case SNDRV_PCM_TRIGGER_SUSPEND
:
363 value
= readl(priv
->io
+ KIRKWOOD_RECCTL
);
364 value
|= KIRKWOOD_RECCTL_PAUSE
| KIRKWOOD_RECCTL_MUTE
;
365 writel(value
, priv
->io
+ KIRKWOOD_RECCTL
);
368 case SNDRV_PCM_TRIGGER_RESUME
:
369 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
370 value
= readl(priv
->io
+ KIRKWOOD_RECCTL
);
371 value
&= ~(KIRKWOOD_RECCTL_PAUSE
| KIRKWOOD_RECCTL_MUTE
);
372 writel(value
, priv
->io
+ KIRKWOOD_RECCTL
);
382 static int kirkwood_i2s_trigger(struct snd_pcm_substream
*substream
, int cmd
,
383 struct snd_soc_dai
*dai
)
385 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
)
386 return kirkwood_i2s_play_trigger(substream
, cmd
, dai
);
388 return kirkwood_i2s_rec_trigger(substream
, cmd
, dai
);
393 static int kirkwood_i2s_init(struct kirkwood_dma_data
*priv
)
396 unsigned int reg_data
;
398 /* put system in a "safe" state : */
399 /* disable audio interrupts */
400 writel(0xffffffff, priv
->io
+ KIRKWOOD_INT_CAUSE
);
401 writel(0, priv
->io
+ KIRKWOOD_INT_MASK
);
403 reg_data
= readl(priv
->io
+ 0x1200);
404 reg_data
&= (~(0x333FF8));
405 reg_data
|= 0x111D18;
406 writel(reg_data
, priv
->io
+ 0x1200);
410 reg_data
= readl(priv
->io
+ 0x1200);
411 reg_data
&= (~(0x333FF8));
412 reg_data
|= 0x111D18;
413 writel(reg_data
, priv
->io
+ 0x1200);
415 /* disable playback/record */
416 value
= readl(priv
->io
+ KIRKWOOD_PLAYCTL
);
417 value
&= ~KIRKWOOD_PLAYCTL_ENABLE_MASK
;
418 writel(value
, priv
->io
+ KIRKWOOD_PLAYCTL
);
420 value
= readl(priv
->io
+ KIRKWOOD_RECCTL
);
421 value
&= ~KIRKWOOD_RECCTL_ENABLE_MASK
;
422 writel(value
, priv
->io
+ KIRKWOOD_RECCTL
);
428 static const struct snd_soc_dai_ops kirkwood_i2s_dai_ops
= {
429 .startup
= kirkwood_i2s_startup
,
430 .trigger
= kirkwood_i2s_trigger
,
431 .hw_params
= kirkwood_i2s_hw_params
,
432 .set_fmt
= kirkwood_i2s_set_fmt
,
435 static struct snd_soc_dai_driver kirkwood_i2s_dai
[2] = {
442 .rates
= SNDRV_PCM_RATE_44100
| SNDRV_PCM_RATE_48000
|
443 SNDRV_PCM_RATE_96000
,
444 .formats
= KIRKWOOD_I2S_FORMATS
,
449 .rates
= SNDRV_PCM_RATE_44100
| SNDRV_PCM_RATE_48000
|
450 SNDRV_PCM_RATE_96000
,
451 .formats
= KIRKWOOD_I2S_FORMATS
,
453 .ops
= &kirkwood_i2s_dai_ops
,
461 .rates
= SNDRV_PCM_RATE_44100
| SNDRV_PCM_RATE_48000
|
462 SNDRV_PCM_RATE_96000
,
463 .formats
= KIRKWOOD_SPDIF_FORMATS
,
468 .rates
= SNDRV_PCM_RATE_44100
| SNDRV_PCM_RATE_48000
|
469 SNDRV_PCM_RATE_96000
,
470 .formats
= KIRKWOOD_SPDIF_FORMATS
,
472 .ops
= &kirkwood_i2s_dai_ops
,
476 static struct snd_soc_dai_driver kirkwood_i2s_dai_extclk
[2] = {
483 .rates
= SNDRV_PCM_RATE_CONTINUOUS
,
486 .formats
= KIRKWOOD_I2S_FORMATS
,
491 .rates
= SNDRV_PCM_RATE_CONTINUOUS
,
494 .formats
= KIRKWOOD_I2S_FORMATS
,
496 .ops
= &kirkwood_i2s_dai_ops
,
504 .rates
= SNDRV_PCM_RATE_CONTINUOUS
,
507 .formats
= KIRKWOOD_SPDIF_FORMATS
,
512 .rates
= SNDRV_PCM_RATE_CONTINUOUS
,
515 .formats
= KIRKWOOD_SPDIF_FORMATS
,
517 .ops
= &kirkwood_i2s_dai_ops
,
521 static int kirkwood_i2s_dev_probe(struct platform_device
*pdev
)
523 struct kirkwood_asoc_platform_data
*data
= pdev
->dev
.platform_data
;
524 struct snd_soc_dai_driver
*soc_dai
= kirkwood_i2s_dai
;
525 struct kirkwood_dma_data
*priv
;
526 struct device_node
*np
= pdev
->dev
.of_node
;
529 priv
= devm_kzalloc(&pdev
->dev
, sizeof(*priv
), GFP_KERNEL
);
533 dev_set_drvdata(&pdev
->dev
, priv
);
535 priv
->io
= devm_platform_ioremap_resource(pdev
, 0);
536 if (IS_ERR(priv
->io
))
537 return PTR_ERR(priv
->io
);
539 priv
->irq
= platform_get_irq(pdev
, 0);
544 priv
->burst
= 128; /* might be 32 or 128 */
546 priv
->burst
= data
->burst
;
548 dev_err(&pdev
->dev
, "no DT nor platform data ?!\n");
552 priv
->clk
= devm_clk_get(&pdev
->dev
, np
? "internal" : NULL
);
553 if (IS_ERR(priv
->clk
)) {
554 dev_err(&pdev
->dev
, "no clock\n");
555 return PTR_ERR(priv
->clk
);
558 priv
->extclk
= devm_clk_get(&pdev
->dev
, "extclk");
559 if (IS_ERR(priv
->extclk
)) {
560 if (PTR_ERR(priv
->extclk
) == -EPROBE_DEFER
)
561 return -EPROBE_DEFER
;
563 if (clk_is_match(priv
->extclk
, priv
->clk
)) {
564 devm_clk_put(&pdev
->dev
, priv
->extclk
);
565 priv
->extclk
= ERR_PTR(-EINVAL
);
567 dev_info(&pdev
->dev
, "found external clock\n");
568 clk_prepare_enable(priv
->extclk
);
569 soc_dai
= kirkwood_i2s_dai_extclk
;
573 err
= clk_prepare_enable(priv
->clk
);
577 /* Some sensible defaults - this reflects the powerup values */
578 priv
->ctl_play
= KIRKWOOD_PLAYCTL_SIZE_24
;
579 priv
->ctl_rec
= KIRKWOOD_RECCTL_SIZE_24
;
581 /* Select the burst size */
582 if (priv
->burst
== 32) {
583 priv
->ctl_play
|= KIRKWOOD_PLAYCTL_BURST_32
;
584 priv
->ctl_rec
|= KIRKWOOD_RECCTL_BURST_32
;
586 priv
->ctl_play
|= KIRKWOOD_PLAYCTL_BURST_128
;
587 priv
->ctl_rec
|= KIRKWOOD_RECCTL_BURST_128
;
590 err
= snd_soc_register_component(&pdev
->dev
, &kirkwood_soc_component
,
593 dev_err(&pdev
->dev
, "snd_soc_register_component failed\n");
597 kirkwood_i2s_init(priv
);
602 if (!IS_ERR(priv
->extclk
))
603 clk_disable_unprepare(priv
->extclk
);
604 clk_disable_unprepare(priv
->clk
);
609 static int kirkwood_i2s_dev_remove(struct platform_device
*pdev
)
611 struct kirkwood_dma_data
*priv
= dev_get_drvdata(&pdev
->dev
);
613 snd_soc_unregister_component(&pdev
->dev
);
614 if (!IS_ERR(priv
->extclk
))
615 clk_disable_unprepare(priv
->extclk
);
616 clk_disable_unprepare(priv
->clk
);
622 static const struct of_device_id mvebu_audio_of_match
[] = {
623 { .compatible
= "marvell,kirkwood-audio" },
624 { .compatible
= "marvell,dove-audio" },
625 { .compatible
= "marvell,armada370-audio" },
628 MODULE_DEVICE_TABLE(of
, mvebu_audio_of_match
);
631 static struct platform_driver kirkwood_i2s_driver
= {
632 .probe
= kirkwood_i2s_dev_probe
,
633 .remove
= kirkwood_i2s_dev_remove
,
636 .of_match_table
= of_match_ptr(mvebu_audio_of_match
),
640 module_platform_driver(kirkwood_i2s_driver
);
642 /* Module information */
643 MODULE_AUTHOR("Arnaud Patard, <arnaud.patard@rtp-net.org>");
644 MODULE_DESCRIPTION("Kirkwood I2S SoC Interface");
645 MODULE_LICENSE("GPL");
646 MODULE_ALIAS("platform:mvebu-audio");