4 * (c) 2010 Arnaud Patard <apatard@mandriva.com>
5 * (c) 2010 Arnaud Patard <arnaud.patard@rtp-net.org>
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
13 #include <linux/init.h>
14 #include <linux/module.h>
15 #include <linux/platform_device.h>
17 #include <linux/slab.h>
18 #include <linux/mbus.h>
19 #include <linux/delay.h>
20 #include <linux/clk.h>
21 #include <sound/pcm.h>
22 #include <sound/pcm_params.h>
23 #include <sound/soc.h>
24 #include <linux/platform_data/asoc-kirkwood.h>
27 #define DRV_NAME "kirkwood-i2s"
29 #define KIRKWOOD_I2S_RATES \
30 (SNDRV_PCM_RATE_44100 | \
31 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000)
32 #define KIRKWOOD_I2S_FORMATS \
33 (SNDRV_PCM_FMTBIT_S16_LE | \
34 SNDRV_PCM_FMTBIT_S24_LE | \
35 SNDRV_PCM_FMTBIT_S32_LE)
37 static int kirkwood_i2s_set_fmt(struct snd_soc_dai
*cpu_dai
,
40 struct kirkwood_dma_data
*priv
= snd_soc_dai_get_drvdata(cpu_dai
);
44 switch (fmt
& SND_SOC_DAIFMT_FORMAT_MASK
) {
45 case SND_SOC_DAIFMT_RIGHT_J
:
46 mask
= KIRKWOOD_I2S_CTL_RJ
;
48 case SND_SOC_DAIFMT_LEFT_J
:
49 mask
= KIRKWOOD_I2S_CTL_LJ
;
51 case SND_SOC_DAIFMT_I2S
:
52 mask
= KIRKWOOD_I2S_CTL_I2S
;
59 * Set same format for playback and record
60 * This avoids some troubles.
62 value
= readl(priv
->io
+KIRKWOOD_I2S_PLAYCTL
);
63 value
&= ~KIRKWOOD_I2S_CTL_JUST_MASK
;
65 writel(value
, priv
->io
+KIRKWOOD_I2S_PLAYCTL
);
67 value
= readl(priv
->io
+KIRKWOOD_I2S_RECCTL
);
68 value
&= ~KIRKWOOD_I2S_CTL_JUST_MASK
;
70 writel(value
, priv
->io
+KIRKWOOD_I2S_RECCTL
);
75 static inline void kirkwood_set_dco(void __iomem
*io
, unsigned long rate
)
79 value
= KIRKWOOD_DCO_CTL_OFFSET_0
;
83 value
|= KIRKWOOD_DCO_CTL_FREQ_11
;
86 value
|= KIRKWOOD_DCO_CTL_FREQ_12
;
89 value
|= KIRKWOOD_DCO_CTL_FREQ_24
;
92 writel(value
, io
+ KIRKWOOD_DCO_CTL
);
94 /* wait for dco locked */
97 value
= readl(io
+ KIRKWOOD_DCO_SPCR_STATUS
);
98 value
&= KIRKWOOD_DCO_SPCR_STATUS_DCO_LOCK
;
102 static void kirkwood_set_rate(struct snd_soc_dai
*dai
,
103 struct kirkwood_dma_data
*priv
, unsigned long rate
)
107 if (rate
== 44100 || rate
== 48000 || rate
== 96000) {
108 /* use internal dco for supported rates */
109 dev_dbg(dai
->dev
, "%s: dco set rate = %lu\n",
111 kirkwood_set_dco(priv
->io
, rate
);
113 clks_ctrl
= KIRKWOOD_MCLK_SOURCE_DCO
;
114 } else if (!IS_ERR(priv
->extclk
)) {
115 /* use optional external clk for other rates */
116 dev_dbg(dai
->dev
, "%s: extclk set rate = %lu -> %lu\n",
117 __func__
, rate
, 256 * rate
);
118 clk_set_rate(priv
->extclk
, 256 * rate
);
120 clks_ctrl
= KIRKWOOD_MCLK_SOURCE_EXTCLK
;
122 writel(clks_ctrl
, priv
->io
+ KIRKWOOD_CLOCKS_CTRL
);
125 static int kirkwood_i2s_startup(struct snd_pcm_substream
*substream
,
126 struct snd_soc_dai
*dai
)
128 struct kirkwood_dma_data
*priv
= snd_soc_dai_get_drvdata(dai
);
130 snd_soc_dai_set_dma_data(dai
, substream
, priv
);
134 static int kirkwood_i2s_hw_params(struct snd_pcm_substream
*substream
,
135 struct snd_pcm_hw_params
*params
,
136 struct snd_soc_dai
*dai
)
138 struct kirkwood_dma_data
*priv
= snd_soc_dai_get_drvdata(dai
);
139 uint32_t ctl_play
, ctl_rec
;
140 unsigned int i2s_reg
;
141 unsigned long i2s_value
;
143 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
) {
144 i2s_reg
= KIRKWOOD_I2S_PLAYCTL
;
146 i2s_reg
= KIRKWOOD_I2S_RECCTL
;
149 kirkwood_set_rate(dai
, priv
, params_rate(params
));
151 i2s_value
= readl(priv
->io
+i2s_reg
);
152 i2s_value
&= ~KIRKWOOD_I2S_CTL_SIZE_MASK
;
155 * Size settings in play/rec i2s control regs and play/rec control
156 * regs must be the same.
158 switch (params_format(params
)) {
159 case SNDRV_PCM_FORMAT_S16_LE
:
160 i2s_value
|= KIRKWOOD_I2S_CTL_SIZE_16
;
161 ctl_play
= KIRKWOOD_PLAYCTL_SIZE_16_C
|
162 KIRKWOOD_PLAYCTL_I2S_EN
;
163 ctl_rec
= KIRKWOOD_RECCTL_SIZE_16_C
|
164 KIRKWOOD_RECCTL_I2S_EN
;
167 * doesn't work... S20_3LE != kirkwood 20bit format ?
169 case SNDRV_PCM_FORMAT_S20_3LE:
170 i2s_value |= KIRKWOOD_I2S_CTL_SIZE_20;
171 ctl_play = KIRKWOOD_PLAYCTL_SIZE_20 |
172 KIRKWOOD_PLAYCTL_I2S_EN;
173 ctl_rec = KIRKWOOD_RECCTL_SIZE_20 |
174 KIRKWOOD_RECCTL_I2S_EN;
177 case SNDRV_PCM_FORMAT_S24_LE
:
178 i2s_value
|= KIRKWOOD_I2S_CTL_SIZE_24
;
179 ctl_play
= KIRKWOOD_PLAYCTL_SIZE_24
|
180 KIRKWOOD_PLAYCTL_I2S_EN
;
181 ctl_rec
= KIRKWOOD_RECCTL_SIZE_24
|
182 KIRKWOOD_RECCTL_I2S_EN
;
184 case SNDRV_PCM_FORMAT_S32_LE
:
185 i2s_value
|= KIRKWOOD_I2S_CTL_SIZE_32
;
186 ctl_play
= KIRKWOOD_PLAYCTL_SIZE_32
|
187 KIRKWOOD_PLAYCTL_I2S_EN
;
188 ctl_rec
= KIRKWOOD_RECCTL_SIZE_32
|
189 KIRKWOOD_RECCTL_I2S_EN
;
195 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
) {
196 if (params_channels(params
) == 1)
197 ctl_play
|= KIRKWOOD_PLAYCTL_MONO_BOTH
;
199 ctl_play
|= KIRKWOOD_PLAYCTL_MONO_OFF
;
201 priv
->ctl_play
&= ~(KIRKWOOD_PLAYCTL_MONO_MASK
|
202 KIRKWOOD_PLAYCTL_I2S_EN
|
203 KIRKWOOD_PLAYCTL_SPDIF_EN
|
204 KIRKWOOD_PLAYCTL_SIZE_MASK
);
205 priv
->ctl_play
|= ctl_play
;
207 priv
->ctl_rec
&= ~KIRKWOOD_RECCTL_SIZE_MASK
;
208 priv
->ctl_rec
|= ctl_rec
;
211 writel(i2s_value
, priv
->io
+i2s_reg
);
216 static int kirkwood_i2s_play_trigger(struct snd_pcm_substream
*substream
,
217 int cmd
, struct snd_soc_dai
*dai
)
219 struct kirkwood_dma_data
*priv
= snd_soc_dai_get_drvdata(dai
);
222 ctl
= readl(priv
->io
+ KIRKWOOD_PLAYCTL
);
223 if (ctl
& KIRKWOOD_PLAYCTL_PAUSE
) {
224 unsigned timeout
= 5000;
226 * The Armada510 spec says that if we enter pause mode, the
227 * busy bit must be read back as clear _twice_. Make sure
228 * we respect that otherwise we get DMA underruns.
232 ctl
= readl(priv
->io
+ KIRKWOOD_PLAYCTL
);
233 if (!((ctl
| value
) & KIRKWOOD_PLAYCTL_PLAY_BUSY
))
238 if ((ctl
| value
) & KIRKWOOD_PLAYCTL_PLAY_BUSY
)
239 dev_notice(dai
->dev
, "timed out waiting for busy to deassert: %08x\n",
244 case SNDRV_PCM_TRIGGER_START
:
246 ctl
= priv
->ctl_play
;
247 value
= ctl
& ~(KIRKWOOD_PLAYCTL_I2S_EN
|
248 KIRKWOOD_PLAYCTL_SPDIF_EN
);
249 writel(value
, priv
->io
+ KIRKWOOD_PLAYCTL
);
251 /* enable interrupts */
252 value
= readl(priv
->io
+ KIRKWOOD_INT_MASK
);
253 value
|= KIRKWOOD_INT_CAUSE_PLAY_BYTES
;
254 writel(value
, priv
->io
+ KIRKWOOD_INT_MASK
);
256 /* enable playback */
257 writel(ctl
, priv
->io
+ KIRKWOOD_PLAYCTL
);
260 case SNDRV_PCM_TRIGGER_STOP
:
261 /* stop audio, disable interrupts */
262 ctl
|= KIRKWOOD_PLAYCTL_PAUSE
| KIRKWOOD_PLAYCTL_I2S_MUTE
;
263 writel(ctl
, priv
->io
+ KIRKWOOD_PLAYCTL
);
265 value
= readl(priv
->io
+ KIRKWOOD_INT_MASK
);
266 value
&= ~KIRKWOOD_INT_CAUSE_PLAY_BYTES
;
267 writel(value
, priv
->io
+ KIRKWOOD_INT_MASK
);
269 /* disable all playbacks */
270 ctl
&= ~(KIRKWOOD_PLAYCTL_I2S_EN
| KIRKWOOD_PLAYCTL_SPDIF_EN
);
271 writel(ctl
, priv
->io
+ KIRKWOOD_PLAYCTL
);
274 case SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
275 case SNDRV_PCM_TRIGGER_SUSPEND
:
276 ctl
|= KIRKWOOD_PLAYCTL_PAUSE
| KIRKWOOD_PLAYCTL_I2S_MUTE
;
277 writel(ctl
, priv
->io
+ KIRKWOOD_PLAYCTL
);
280 case SNDRV_PCM_TRIGGER_RESUME
:
281 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
282 ctl
&= ~(KIRKWOOD_PLAYCTL_PAUSE
| KIRKWOOD_PLAYCTL_I2S_MUTE
);
283 writel(ctl
, priv
->io
+ KIRKWOOD_PLAYCTL
);
293 static int kirkwood_i2s_rec_trigger(struct snd_pcm_substream
*substream
,
294 int cmd
, struct snd_soc_dai
*dai
)
296 struct kirkwood_dma_data
*priv
= snd_soc_dai_get_drvdata(dai
);
299 value
= readl(priv
->io
+ KIRKWOOD_RECCTL
);
302 case SNDRV_PCM_TRIGGER_START
:
305 value
= ctl
& ~KIRKWOOD_RECCTL_I2S_EN
;
306 writel(value
, priv
->io
+ KIRKWOOD_RECCTL
);
308 /* enable interrupts */
309 value
= readl(priv
->io
+ KIRKWOOD_INT_MASK
);
310 value
|= KIRKWOOD_INT_CAUSE_REC_BYTES
;
311 writel(value
, priv
->io
+ KIRKWOOD_INT_MASK
);
314 writel(ctl
, priv
->io
+ KIRKWOOD_RECCTL
);
317 case SNDRV_PCM_TRIGGER_STOP
:
318 /* stop audio, disable interrupts */
319 value
= readl(priv
->io
+ KIRKWOOD_RECCTL
);
320 value
|= KIRKWOOD_RECCTL_PAUSE
| KIRKWOOD_RECCTL_MUTE
;
321 writel(value
, priv
->io
+ KIRKWOOD_RECCTL
);
323 value
= readl(priv
->io
+ KIRKWOOD_INT_MASK
);
324 value
&= ~KIRKWOOD_INT_CAUSE_REC_BYTES
;
325 writel(value
, priv
->io
+ KIRKWOOD_INT_MASK
);
327 /* disable all records */
328 value
= readl(priv
->io
+ KIRKWOOD_RECCTL
);
329 value
&= ~(KIRKWOOD_RECCTL_I2S_EN
| KIRKWOOD_RECCTL_SPDIF_EN
);
330 writel(value
, priv
->io
+ KIRKWOOD_RECCTL
);
333 case SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
334 case SNDRV_PCM_TRIGGER_SUSPEND
:
335 value
= readl(priv
->io
+ KIRKWOOD_RECCTL
);
336 value
|= KIRKWOOD_RECCTL_PAUSE
| KIRKWOOD_RECCTL_MUTE
;
337 writel(value
, priv
->io
+ KIRKWOOD_RECCTL
);
340 case SNDRV_PCM_TRIGGER_RESUME
:
341 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
342 value
= readl(priv
->io
+ KIRKWOOD_RECCTL
);
343 value
&= ~(KIRKWOOD_RECCTL_PAUSE
| KIRKWOOD_RECCTL_MUTE
);
344 writel(value
, priv
->io
+ KIRKWOOD_RECCTL
);
354 static int kirkwood_i2s_trigger(struct snd_pcm_substream
*substream
, int cmd
,
355 struct snd_soc_dai
*dai
)
357 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
)
358 return kirkwood_i2s_play_trigger(substream
, cmd
, dai
);
360 return kirkwood_i2s_rec_trigger(substream
, cmd
, dai
);
365 static int kirkwood_i2s_probe(struct snd_soc_dai
*dai
)
367 struct kirkwood_dma_data
*priv
= snd_soc_dai_get_drvdata(dai
);
369 unsigned int reg_data
;
371 /* put system in a "safe" state : */
372 /* disable audio interrupts */
373 writel(0xffffffff, priv
->io
+ KIRKWOOD_INT_CAUSE
);
374 writel(0, priv
->io
+ KIRKWOOD_INT_MASK
);
376 reg_data
= readl(priv
->io
+ 0x1200);
377 reg_data
&= (~(0x333FF8));
378 reg_data
|= 0x111D18;
379 writel(reg_data
, priv
->io
+ 0x1200);
383 reg_data
= readl(priv
->io
+ 0x1200);
384 reg_data
&= (~(0x333FF8));
385 reg_data
|= 0x111D18;
386 writel(reg_data
, priv
->io
+ 0x1200);
388 /* disable playback/record */
389 value
= readl(priv
->io
+ KIRKWOOD_PLAYCTL
);
390 value
&= ~(KIRKWOOD_PLAYCTL_I2S_EN
|KIRKWOOD_PLAYCTL_SPDIF_EN
);
391 writel(value
, priv
->io
+ KIRKWOOD_PLAYCTL
);
393 value
= readl(priv
->io
+ KIRKWOOD_RECCTL
);
394 value
&= ~(KIRKWOOD_RECCTL_I2S_EN
| KIRKWOOD_RECCTL_SPDIF_EN
);
395 writel(value
, priv
->io
+ KIRKWOOD_RECCTL
);
401 static int kirkwood_i2s_remove(struct snd_soc_dai
*dai
)
406 static const struct snd_soc_dai_ops kirkwood_i2s_dai_ops
= {
407 .startup
= kirkwood_i2s_startup
,
408 .trigger
= kirkwood_i2s_trigger
,
409 .hw_params
= kirkwood_i2s_hw_params
,
410 .set_fmt
= kirkwood_i2s_set_fmt
,
414 static struct snd_soc_dai_driver kirkwood_i2s_dai
= {
415 .probe
= kirkwood_i2s_probe
,
416 .remove
= kirkwood_i2s_remove
,
420 .rates
= KIRKWOOD_I2S_RATES
,
421 .formats
= KIRKWOOD_I2S_FORMATS
,
426 .rates
= KIRKWOOD_I2S_RATES
,
427 .formats
= KIRKWOOD_I2S_FORMATS
,
429 .ops
= &kirkwood_i2s_dai_ops
,
432 static struct snd_soc_dai_driver kirkwood_i2s_dai_extclk
= {
433 .probe
= kirkwood_i2s_probe
,
434 .remove
= kirkwood_i2s_remove
,
438 .rates
= SNDRV_PCM_RATE_8000_192000
|
439 SNDRV_PCM_RATE_CONTINUOUS
|
441 .formats
= KIRKWOOD_I2S_FORMATS
,
446 .rates
= SNDRV_PCM_RATE_8000_192000
|
447 SNDRV_PCM_RATE_CONTINUOUS
|
449 .formats
= KIRKWOOD_I2S_FORMATS
,
451 .ops
= &kirkwood_i2s_dai_ops
,
454 static const struct snd_soc_component_driver kirkwood_i2s_component
= {
458 static int kirkwood_i2s_dev_probe(struct platform_device
*pdev
)
460 struct kirkwood_asoc_platform_data
*data
= pdev
->dev
.platform_data
;
461 struct snd_soc_dai_driver
*soc_dai
= &kirkwood_i2s_dai
;
462 struct kirkwood_dma_data
*priv
;
463 struct resource
*mem
;
466 priv
= devm_kzalloc(&pdev
->dev
, sizeof(*priv
), GFP_KERNEL
);
468 dev_err(&pdev
->dev
, "allocation failed\n");
471 dev_set_drvdata(&pdev
->dev
, priv
);
473 mem
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
474 priv
->io
= devm_ioremap_resource(&pdev
->dev
, mem
);
475 if (IS_ERR(priv
->io
))
476 return PTR_ERR(priv
->io
);
478 priv
->irq
= platform_get_irq(pdev
, 0);
479 if (priv
->irq
<= 0) {
480 dev_err(&pdev
->dev
, "platform_get_irq failed\n");
485 dev_err(&pdev
->dev
, "no platform data ?!\n");
489 priv
->burst
= data
->burst
;
491 priv
->clk
= devm_clk_get(&pdev
->dev
, NULL
);
492 if (IS_ERR(priv
->clk
)) {
493 dev_err(&pdev
->dev
, "no clock\n");
494 return PTR_ERR(priv
->clk
);
497 err
= clk_prepare_enable(priv
->clk
);
501 priv
->extclk
= clk_get(&pdev
->dev
, "extclk");
502 if (!IS_ERR(priv
->extclk
)) {
503 if (priv
->extclk
== priv
->clk
) {
504 clk_put(priv
->extclk
);
505 priv
->extclk
= ERR_PTR(-EINVAL
);
507 dev_info(&pdev
->dev
, "found external clock\n");
508 clk_prepare_enable(priv
->extclk
);
509 soc_dai
= &kirkwood_i2s_dai_extclk
;
513 /* Some sensible defaults - this reflects the powerup values */
514 priv
->ctl_play
= KIRKWOOD_PLAYCTL_SIZE_24
;
515 priv
->ctl_rec
= KIRKWOOD_RECCTL_SIZE_24
;
517 /* Select the burst size */
518 if (data
->burst
== 32) {
519 priv
->ctl_play
|= KIRKWOOD_PLAYCTL_BURST_32
;
520 priv
->ctl_rec
|= KIRKWOOD_RECCTL_BURST_32
;
522 priv
->ctl_play
|= KIRKWOOD_PLAYCTL_BURST_128
;
523 priv
->ctl_rec
|= KIRKWOOD_RECCTL_BURST_128
;
526 err
= snd_soc_register_component(&pdev
->dev
, &kirkwood_i2s_component
,
530 dev_err(&pdev
->dev
, "snd_soc_register_component failed\n");
532 if (!IS_ERR(priv
->extclk
)) {
533 clk_disable_unprepare(priv
->extclk
);
534 clk_put(priv
->extclk
);
536 clk_disable_unprepare(priv
->clk
);
541 static int kirkwood_i2s_dev_remove(struct platform_device
*pdev
)
543 struct kirkwood_dma_data
*priv
= dev_get_drvdata(&pdev
->dev
);
545 snd_soc_unregister_component(&pdev
->dev
);
547 if (!IS_ERR(priv
->extclk
)) {
548 clk_disable_unprepare(priv
->extclk
);
549 clk_put(priv
->extclk
);
551 clk_disable_unprepare(priv
->clk
);
556 static struct platform_driver kirkwood_i2s_driver
= {
557 .probe
= kirkwood_i2s_dev_probe
,
558 .remove
= kirkwood_i2s_dev_remove
,
561 .owner
= THIS_MODULE
,
565 module_platform_driver(kirkwood_i2s_driver
);
567 /* Module information */
568 MODULE_AUTHOR("Arnaud Patard, <arnaud.patard@rtp-net.org>");
569 MODULE_DESCRIPTION("Kirkwood I2S SoC Interface");
570 MODULE_LICENSE("GPL");
571 MODULE_ALIAS("platform:kirkwood-i2s");