arm64: dts: qcom: sm8550: add TRNG node
[linux-modified.git] / sound / soc / kirkwood / kirkwood-i2s.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * kirkwood-i2s.c
4  *
5  * (c) 2010 Arnaud Patard <apatard@mandriva.com>
6  * (c) 2010 Arnaud Patard <arnaud.patard@rtp-net.org>
7  */
8
9 #include <linux/init.h>
10 #include <linux/module.h>
11 #include <linux/platform_device.h>
12 #include <linux/io.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>
21 #include <linux/of.h>
22
23 #include "kirkwood.h"
24
25 #define KIRKWOOD_I2S_FORMATS \
26         (SNDRV_PCM_FMTBIT_S16_LE | \
27          SNDRV_PCM_FMTBIT_S24_LE | \
28          SNDRV_PCM_FMTBIT_S32_LE)
29
30 #define KIRKWOOD_SPDIF_FORMATS \
31         (SNDRV_PCM_FMTBIT_S16_LE | \
32          SNDRV_PCM_FMTBIT_S24_LE)
33
34 /* These registers are relative to the second register region -
35  * audio pll configuration.
36  */
37 #define A38X_PLL_CONF_REG0                      0x0
38 #define     A38X_PLL_FB_CLK_DIV_OFFSET          10
39 #define     A38X_PLL_FB_CLK_DIV_MASK            0x7fc00
40 #define A38X_PLL_CONF_REG1                      0x4
41 #define     A38X_PLL_FREQ_OFFSET_MASK           0xffff
42 #define     A38X_PLL_FREQ_OFFSET_VALID          BIT(16)
43 #define     A38X_PLL_SW_RESET                   BIT(31)
44 #define A38X_PLL_CONF_REG2                      0x8
45 #define     A38X_PLL_AUDIO_POSTDIV_MASK         0x7f
46
47 /* Bit below belongs to SoC control register corresponding to the third
48  * register region.
49  */
50 #define A38X_SPDIF_MODE_ENABLE                  BIT(27)
51
52 static int armada_38x_i2s_init_quirk(struct platform_device *pdev,
53                                      struct kirkwood_dma_data *priv,
54                                      struct snd_soc_dai_driver *dai_drv)
55 {
56         struct device_node *np = pdev->dev.of_node;
57         u32 reg_val;
58         int i;
59
60         priv->pll_config = devm_platform_ioremap_resource_byname(pdev, "pll_regs");
61         if (IS_ERR(priv->pll_config))
62                 return -ENOMEM;
63
64         priv->soc_control = devm_platform_ioremap_resource_byname(pdev, "soc_ctrl");
65         if (IS_ERR(priv->soc_control))
66                 return -ENOMEM;
67
68         /* Select one of exceptive modes: I2S or S/PDIF */
69         reg_val = readl(priv->soc_control);
70         if (of_property_read_bool(np, "spdif-mode")) {
71                 reg_val |= A38X_SPDIF_MODE_ENABLE;
72                 dev_info(&pdev->dev, "using S/PDIF mode\n");
73         } else {
74                 reg_val &= ~A38X_SPDIF_MODE_ENABLE;
75                 dev_info(&pdev->dev, "using I2S mode\n");
76         }
77         writel(reg_val, priv->soc_control);
78
79         /* Update available rates of mclk's fs */
80         for (i = 0; i < 2; i++) {
81                 dai_drv[i].playback.rates |= SNDRV_PCM_RATE_192000;
82                 dai_drv[i].capture.rates |= SNDRV_PCM_RATE_192000;
83         }
84
85         return 0;
86 }
87
88 static inline void armada_38x_set_pll(void __iomem *base, unsigned long rate)
89 {
90         u32 reg_val;
91         u16 freq_offset = 0x22b0;
92         u8 audio_postdiv, fb_clk_div = 0x1d;
93
94         /* Set frequency offset value to not valid and enable PLL reset */
95         reg_val = readl(base + A38X_PLL_CONF_REG1);
96         reg_val &= ~A38X_PLL_FREQ_OFFSET_VALID;
97         reg_val &= ~A38X_PLL_SW_RESET;
98         writel(reg_val, base + A38X_PLL_CONF_REG1);
99
100         udelay(1);
101
102         /* Update PLL parameters */
103         switch (rate) {
104         default:
105         case 44100:
106                 freq_offset = 0x735;
107                 fb_clk_div = 0x1b;
108                 audio_postdiv = 0xc;
109                 break;
110         case 48000:
111                 audio_postdiv = 0xc;
112                 break;
113         case 96000:
114                 audio_postdiv = 0x6;
115                 break;
116         case 192000:
117                 audio_postdiv = 0x3;
118                 break;
119         }
120
121         reg_val = readl(base + A38X_PLL_CONF_REG0);
122         reg_val &= ~A38X_PLL_FB_CLK_DIV_MASK;
123         reg_val |= (fb_clk_div << A38X_PLL_FB_CLK_DIV_OFFSET);
124         writel(reg_val, base + A38X_PLL_CONF_REG0);
125
126         reg_val = readl(base + A38X_PLL_CONF_REG2);
127         reg_val &= ~A38X_PLL_AUDIO_POSTDIV_MASK;
128         reg_val |= audio_postdiv;
129         writel(reg_val, base + A38X_PLL_CONF_REG2);
130
131         reg_val = readl(base + A38X_PLL_CONF_REG1);
132         reg_val &= ~A38X_PLL_FREQ_OFFSET_MASK;
133         reg_val |= freq_offset;
134         writel(reg_val, base + A38X_PLL_CONF_REG1);
135
136         udelay(1);
137
138         /* Disable reset */
139         reg_val |= A38X_PLL_SW_RESET;
140         writel(reg_val, base + A38X_PLL_CONF_REG1);
141
142         /* Wait 50us for PLL to lock */
143         udelay(50);
144
145         /* Restore frequency offset value validity */
146         reg_val |= A38X_PLL_FREQ_OFFSET_VALID;
147         writel(reg_val, base + A38X_PLL_CONF_REG1);
148 }
149
150 static int kirkwood_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
151                 unsigned int fmt)
152 {
153         struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(cpu_dai);
154         unsigned long mask;
155         unsigned long value;
156
157         switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
158         case SND_SOC_DAIFMT_RIGHT_J:
159                 mask = KIRKWOOD_I2S_CTL_RJ;
160                 break;
161         case SND_SOC_DAIFMT_LEFT_J:
162                 mask = KIRKWOOD_I2S_CTL_LJ;
163                 break;
164         case SND_SOC_DAIFMT_I2S:
165                 mask = KIRKWOOD_I2S_CTL_I2S;
166                 break;
167         default:
168                 return -EINVAL;
169         }
170
171         /*
172          * Set same format for playback and record
173          * This avoids some troubles.
174          */
175         value = readl(priv->io+KIRKWOOD_I2S_PLAYCTL);
176         value &= ~KIRKWOOD_I2S_CTL_JUST_MASK;
177         value |= mask;
178         writel(value, priv->io+KIRKWOOD_I2S_PLAYCTL);
179
180         value = readl(priv->io+KIRKWOOD_I2S_RECCTL);
181         value &= ~KIRKWOOD_I2S_CTL_JUST_MASK;
182         value |= mask;
183         writel(value, priv->io+KIRKWOOD_I2S_RECCTL);
184
185         return 0;
186 }
187
188 static inline void kirkwood_set_dco(void __iomem *io, unsigned long rate)
189 {
190         unsigned long value;
191
192         value = KIRKWOOD_DCO_CTL_OFFSET_0;
193         switch (rate) {
194         default:
195         case 44100:
196                 value |= KIRKWOOD_DCO_CTL_FREQ_11;
197                 break;
198         case 48000:
199                 value |= KIRKWOOD_DCO_CTL_FREQ_12;
200                 break;
201         case 96000:
202                 value |= KIRKWOOD_DCO_CTL_FREQ_24;
203                 break;
204         }
205         writel(value, io + KIRKWOOD_DCO_CTL);
206
207         /* wait for dco locked */
208         do {
209                 cpu_relax();
210                 value = readl(io + KIRKWOOD_DCO_SPCR_STATUS);
211                 value &= KIRKWOOD_DCO_SPCR_STATUS_DCO_LOCK;
212         } while (value == 0);
213 }
214
215 static void kirkwood_set_rate(struct snd_soc_dai *dai,
216         struct kirkwood_dma_data *priv, unsigned long rate)
217 {
218         uint32_t clks_ctrl;
219
220         if (IS_ERR(priv->extclk)) {
221                 /* use internal dco for the supported rates
222                  * defined in kirkwood_i2s_dai */
223                 dev_dbg(dai->dev, "%s: dco set rate = %lu\n",
224                         __func__, rate);
225                 if (priv->pll_config)
226                         armada_38x_set_pll(priv->pll_config, rate);
227                 else
228                         kirkwood_set_dco(priv->io, rate);
229
230                 clks_ctrl = KIRKWOOD_MCLK_SOURCE_DCO;
231         } else {
232                 /* use the external clock for the other rates
233                  * defined in kirkwood_i2s_dai_extclk */
234                 dev_dbg(dai->dev, "%s: extclk set rate = %lu -> %lu\n",
235                         __func__, rate, 256 * rate);
236                 clk_set_rate(priv->extclk, 256 * rate);
237
238                 clks_ctrl = KIRKWOOD_MCLK_SOURCE_EXTCLK;
239         }
240         writel(clks_ctrl, priv->io + KIRKWOOD_CLOCKS_CTRL);
241 }
242
243 static int kirkwood_i2s_startup(struct snd_pcm_substream *substream,
244                 struct snd_soc_dai *dai)
245 {
246         struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
247
248         snd_soc_dai_set_dma_data(dai, substream, priv);
249         return 0;
250 }
251
252 static int kirkwood_i2s_hw_params(struct snd_pcm_substream *substream,
253                                  struct snd_pcm_hw_params *params,
254                                  struct snd_soc_dai *dai)
255 {
256         struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
257         uint32_t ctl_play, ctl_rec;
258         unsigned int i2s_reg;
259         unsigned long i2s_value;
260
261         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
262                 i2s_reg = KIRKWOOD_I2S_PLAYCTL;
263         } else {
264                 i2s_reg = KIRKWOOD_I2S_RECCTL;
265         }
266
267         kirkwood_set_rate(dai, priv, params_rate(params));
268
269         i2s_value = readl(priv->io+i2s_reg);
270         i2s_value &= ~KIRKWOOD_I2S_CTL_SIZE_MASK;
271
272         /*
273          * Size settings in play/rec i2s control regs and play/rec control
274          * regs must be the same.
275          */
276         switch (params_format(params)) {
277         case SNDRV_PCM_FORMAT_S16_LE:
278                 i2s_value |= KIRKWOOD_I2S_CTL_SIZE_16;
279                 ctl_play = KIRKWOOD_PLAYCTL_SIZE_16_C |
280                            KIRKWOOD_PLAYCTL_I2S_EN |
281                            KIRKWOOD_PLAYCTL_SPDIF_EN;
282                 ctl_rec = KIRKWOOD_RECCTL_SIZE_16_C |
283                           KIRKWOOD_RECCTL_I2S_EN |
284                           KIRKWOOD_RECCTL_SPDIF_EN;
285                 break;
286         /*
287          * doesn't work... S20_3LE != kirkwood 20bit format ?
288          *
289         case SNDRV_PCM_FORMAT_S20_3LE:
290                 i2s_value |= KIRKWOOD_I2S_CTL_SIZE_20;
291                 ctl_play = KIRKWOOD_PLAYCTL_SIZE_20 |
292                            KIRKWOOD_PLAYCTL_I2S_EN;
293                 ctl_rec = KIRKWOOD_RECCTL_SIZE_20 |
294                           KIRKWOOD_RECCTL_I2S_EN;
295                 break;
296         */
297         case SNDRV_PCM_FORMAT_S24_LE:
298                 i2s_value |= KIRKWOOD_I2S_CTL_SIZE_24;
299                 ctl_play = KIRKWOOD_PLAYCTL_SIZE_24 |
300                            KIRKWOOD_PLAYCTL_I2S_EN |
301                            KIRKWOOD_PLAYCTL_SPDIF_EN;
302                 ctl_rec = KIRKWOOD_RECCTL_SIZE_24 |
303                           KIRKWOOD_RECCTL_I2S_EN |
304                           KIRKWOOD_RECCTL_SPDIF_EN;
305                 break;
306         case SNDRV_PCM_FORMAT_S32_LE:
307                 i2s_value |= KIRKWOOD_I2S_CTL_SIZE_32;
308                 ctl_play = KIRKWOOD_PLAYCTL_SIZE_32 |
309                            KIRKWOOD_PLAYCTL_I2S_EN;
310                 ctl_rec = KIRKWOOD_RECCTL_SIZE_32 |
311                           KIRKWOOD_RECCTL_I2S_EN;
312                 break;
313         default:
314                 return -EINVAL;
315         }
316
317         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
318                 if (params_channels(params) == 1)
319                         ctl_play |= KIRKWOOD_PLAYCTL_MONO_BOTH;
320                 else
321                         ctl_play |= KIRKWOOD_PLAYCTL_MONO_OFF;
322
323                 priv->ctl_play &= ~(KIRKWOOD_PLAYCTL_MONO_MASK |
324                                     KIRKWOOD_PLAYCTL_ENABLE_MASK |
325                                     KIRKWOOD_PLAYCTL_SIZE_MASK);
326                 priv->ctl_play |= ctl_play;
327         } else {
328                 priv->ctl_rec &= ~(KIRKWOOD_RECCTL_ENABLE_MASK |
329                                    KIRKWOOD_RECCTL_SIZE_MASK);
330                 priv->ctl_rec |= ctl_rec;
331         }
332
333         writel(i2s_value, priv->io+i2s_reg);
334
335         return 0;
336 }
337
338 static unsigned kirkwood_i2s_play_mute(unsigned ctl)
339 {
340         if (!(ctl & KIRKWOOD_PLAYCTL_I2S_EN))
341                 ctl |= KIRKWOOD_PLAYCTL_I2S_MUTE;
342         if (!(ctl & KIRKWOOD_PLAYCTL_SPDIF_EN))
343                 ctl |= KIRKWOOD_PLAYCTL_SPDIF_MUTE;
344         return ctl;
345 }
346
347 static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream,
348                                 int cmd, struct snd_soc_dai *dai)
349 {
350         struct snd_pcm_runtime *runtime = substream->runtime;
351         struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
352         uint32_t ctl, value;
353
354         ctl = readl(priv->io + KIRKWOOD_PLAYCTL);
355         if ((ctl & KIRKWOOD_PLAYCTL_ENABLE_MASK) == 0) {
356                 unsigned timeout = 5000;
357                 /*
358                  * The Armada510 spec says that if we enter pause mode, the
359                  * busy bit must be read back as clear _twice_.  Make sure
360                  * we respect that otherwise we get DMA underruns.
361                  */
362                 do {
363                         value = ctl;
364                         ctl = readl(priv->io + KIRKWOOD_PLAYCTL);
365                         if (!((ctl | value) & KIRKWOOD_PLAYCTL_PLAY_BUSY))
366                                 break;
367                         udelay(1);
368                 } while (timeout--);
369
370                 if ((ctl | value) & KIRKWOOD_PLAYCTL_PLAY_BUSY)
371                         dev_notice(dai->dev, "timed out waiting for busy to deassert: %08x\n",
372                                    ctl);
373         }
374
375         switch (cmd) {
376         case SNDRV_PCM_TRIGGER_START:
377                 /* configure */
378                 ctl = priv->ctl_play;
379                 if (dai->id == 0)
380                         ctl &= ~KIRKWOOD_PLAYCTL_SPDIF_EN;      /* i2s */
381                 else
382                         ctl &= ~KIRKWOOD_PLAYCTL_I2S_EN;        /* spdif */
383                 ctl = kirkwood_i2s_play_mute(ctl);
384                 value = ctl & ~KIRKWOOD_PLAYCTL_ENABLE_MASK;
385                 writel(value, priv->io + KIRKWOOD_PLAYCTL);
386
387                 /* enable interrupts */
388                 if (!runtime->no_period_wakeup) {
389                         value = readl(priv->io + KIRKWOOD_INT_MASK);
390                         value |= KIRKWOOD_INT_CAUSE_PLAY_BYTES;
391                         writel(value, priv->io + KIRKWOOD_INT_MASK);
392                 }
393
394                 /* enable playback */
395                 writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
396                 break;
397
398         case SNDRV_PCM_TRIGGER_STOP:
399                 /* stop audio, disable interrupts */
400                 ctl |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE |
401                                 KIRKWOOD_PLAYCTL_SPDIF_MUTE;
402                 writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
403
404                 value = readl(priv->io + KIRKWOOD_INT_MASK);
405                 value &= ~KIRKWOOD_INT_CAUSE_PLAY_BYTES;
406                 writel(value, priv->io + KIRKWOOD_INT_MASK);
407
408                 /* disable all playbacks */
409                 ctl &= ~KIRKWOOD_PLAYCTL_ENABLE_MASK;
410                 writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
411                 break;
412
413         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
414         case SNDRV_PCM_TRIGGER_SUSPEND:
415                 ctl |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE |
416                                 KIRKWOOD_PLAYCTL_SPDIF_MUTE;
417                 writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
418                 break;
419
420         case SNDRV_PCM_TRIGGER_RESUME:
421         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
422                 ctl &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE |
423                                 KIRKWOOD_PLAYCTL_SPDIF_MUTE);
424                 ctl = kirkwood_i2s_play_mute(ctl);
425                 writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
426                 break;
427
428         default:
429                 return -EINVAL;
430         }
431
432         return 0;
433 }
434
435 static int kirkwood_i2s_rec_trigger(struct snd_pcm_substream *substream,
436                                 int cmd, struct snd_soc_dai *dai)
437 {
438         struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
439         uint32_t ctl, value;
440
441         value = readl(priv->io + KIRKWOOD_RECCTL);
442
443         switch (cmd) {
444         case SNDRV_PCM_TRIGGER_START:
445                 /* configure */
446                 ctl = priv->ctl_rec;
447                 if (dai->id == 0)
448                         ctl &= ~KIRKWOOD_RECCTL_SPDIF_EN;       /* i2s */
449                 else
450                         ctl &= ~KIRKWOOD_RECCTL_I2S_EN;         /* spdif */
451
452                 value = ctl & ~KIRKWOOD_RECCTL_ENABLE_MASK;
453                 writel(value, priv->io + KIRKWOOD_RECCTL);
454
455                 /* enable interrupts */
456                 value = readl(priv->io + KIRKWOOD_INT_MASK);
457                 value |= KIRKWOOD_INT_CAUSE_REC_BYTES;
458                 writel(value, priv->io + KIRKWOOD_INT_MASK);
459
460                 /* enable record */
461                 writel(ctl, priv->io + KIRKWOOD_RECCTL);
462                 break;
463
464         case SNDRV_PCM_TRIGGER_STOP:
465                 /* stop audio, disable interrupts */
466                 value = readl(priv->io + KIRKWOOD_RECCTL);
467                 value |= KIRKWOOD_RECCTL_PAUSE | KIRKWOOD_RECCTL_MUTE;
468                 writel(value, priv->io + KIRKWOOD_RECCTL);
469
470                 value = readl(priv->io + KIRKWOOD_INT_MASK);
471                 value &= ~KIRKWOOD_INT_CAUSE_REC_BYTES;
472                 writel(value, priv->io + KIRKWOOD_INT_MASK);
473
474                 /* disable all records */
475                 value = readl(priv->io + KIRKWOOD_RECCTL);
476                 value &= ~KIRKWOOD_RECCTL_ENABLE_MASK;
477                 writel(value, priv->io + KIRKWOOD_RECCTL);
478                 break;
479
480         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
481         case SNDRV_PCM_TRIGGER_SUSPEND:
482                 value = readl(priv->io + KIRKWOOD_RECCTL);
483                 value |= KIRKWOOD_RECCTL_PAUSE | KIRKWOOD_RECCTL_MUTE;
484                 writel(value, priv->io + KIRKWOOD_RECCTL);
485                 break;
486
487         case SNDRV_PCM_TRIGGER_RESUME:
488         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
489                 value = readl(priv->io + KIRKWOOD_RECCTL);
490                 value &= ~(KIRKWOOD_RECCTL_PAUSE | KIRKWOOD_RECCTL_MUTE);
491                 writel(value, priv->io + KIRKWOOD_RECCTL);
492                 break;
493
494         default:
495                 return -EINVAL;
496         }
497
498         return 0;
499 }
500
501 static int kirkwood_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
502                                struct snd_soc_dai *dai)
503 {
504         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
505                 return kirkwood_i2s_play_trigger(substream, cmd, dai);
506         else
507                 return kirkwood_i2s_rec_trigger(substream, cmd, dai);
508
509         return 0;
510 }
511
512 static int kirkwood_i2s_init(struct kirkwood_dma_data *priv)
513 {
514         unsigned long value;
515         unsigned int reg_data;
516
517         /* put system in a "safe" state : */
518         /* disable audio interrupts */
519         writel(0xffffffff, priv->io + KIRKWOOD_INT_CAUSE);
520         writel(0, priv->io + KIRKWOOD_INT_MASK);
521
522         reg_data = readl(priv->io + 0x1200);
523         reg_data &= (~(0x333FF8));
524         reg_data |= 0x111D18;
525         writel(reg_data, priv->io + 0x1200);
526
527         msleep(500);
528
529         reg_data = readl(priv->io + 0x1200);
530         reg_data &= (~(0x333FF8));
531         reg_data |= 0x111D18;
532         writel(reg_data, priv->io + 0x1200);
533
534         /* disable playback/record */
535         value = readl(priv->io + KIRKWOOD_PLAYCTL);
536         value &= ~KIRKWOOD_PLAYCTL_ENABLE_MASK;
537         writel(value, priv->io + KIRKWOOD_PLAYCTL);
538
539         value = readl(priv->io + KIRKWOOD_RECCTL);
540         value &= ~KIRKWOOD_RECCTL_ENABLE_MASK;
541         writel(value, priv->io + KIRKWOOD_RECCTL);
542
543         return 0;
544
545 }
546
547 static const struct snd_soc_dai_ops kirkwood_i2s_dai_ops = {
548         .startup        = kirkwood_i2s_startup,
549         .trigger        = kirkwood_i2s_trigger,
550         .hw_params      = kirkwood_i2s_hw_params,
551         .set_fmt        = kirkwood_i2s_set_fmt,
552 };
553
554 static struct snd_soc_dai_driver kirkwood_i2s_dai[2] = {
555     {
556         .name = "i2s",
557         .id = 0,
558         .playback = {
559                 .channels_min = 1,
560                 .channels_max = 2,
561                 .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
562                                 SNDRV_PCM_RATE_96000,
563                 .formats = KIRKWOOD_I2S_FORMATS,
564         },
565         .capture = {
566                 .channels_min = 1,
567                 .channels_max = 2,
568                 .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
569                                 SNDRV_PCM_RATE_96000,
570                 .formats = KIRKWOOD_I2S_FORMATS,
571         },
572         .ops = &kirkwood_i2s_dai_ops,
573     },
574     {
575         .name = "spdif",
576         .id = 1,
577         .playback = {
578                 .channels_min = 1,
579                 .channels_max = 2,
580                 .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
581                                 SNDRV_PCM_RATE_96000,
582                 .formats = KIRKWOOD_SPDIF_FORMATS,
583         },
584         .capture = {
585                 .channels_min = 1,
586                 .channels_max = 2,
587                 .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
588                                 SNDRV_PCM_RATE_96000,
589                 .formats = KIRKWOOD_SPDIF_FORMATS,
590         },
591         .ops = &kirkwood_i2s_dai_ops,
592     },
593 };
594
595 static struct snd_soc_dai_driver kirkwood_i2s_dai_extclk[2] = {
596     {
597         .name = "i2s",
598         .id = 0,
599         .playback = {
600                 .channels_min = 1,
601                 .channels_max = 2,
602                 .rates = SNDRV_PCM_RATE_CONTINUOUS,
603                 .rate_min = 5512,
604                 .rate_max = 192000,
605                 .formats = KIRKWOOD_I2S_FORMATS,
606         },
607         .capture = {
608                 .channels_min = 1,
609                 .channels_max = 2,
610                 .rates = SNDRV_PCM_RATE_CONTINUOUS,
611                 .rate_min = 5512,
612                 .rate_max = 192000,
613                 .formats = KIRKWOOD_I2S_FORMATS,
614         },
615         .ops = &kirkwood_i2s_dai_ops,
616     },
617     {
618         .name = "spdif",
619         .id = 1,
620         .playback = {
621                 .channels_min = 1,
622                 .channels_max = 2,
623                 .rates = SNDRV_PCM_RATE_CONTINUOUS,
624                 .rate_min = 5512,
625                 .rate_max = 192000,
626                 .formats = KIRKWOOD_SPDIF_FORMATS,
627         },
628         .capture = {
629                 .channels_min = 1,
630                 .channels_max = 2,
631                 .rates = SNDRV_PCM_RATE_CONTINUOUS,
632                 .rate_min = 5512,
633                 .rate_max = 192000,
634                 .formats = KIRKWOOD_SPDIF_FORMATS,
635         },
636         .ops = &kirkwood_i2s_dai_ops,
637     },
638 };
639
640 static int kirkwood_i2s_dev_probe(struct platform_device *pdev)
641 {
642         struct kirkwood_asoc_platform_data *data = pdev->dev.platform_data;
643         struct snd_soc_dai_driver *soc_dai = kirkwood_i2s_dai;
644         struct kirkwood_dma_data *priv;
645         struct device_node *np = pdev->dev.of_node;
646         int err;
647
648         priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
649         if (!priv)
650                 return -ENOMEM;
651
652         dev_set_drvdata(&pdev->dev, priv);
653
654         if (of_device_is_compatible(np, "marvell,armada-380-audio"))
655                 priv->io = devm_platform_ioremap_resource_byname(pdev, "i2s_regs");
656         else
657                 priv->io = devm_platform_ioremap_resource(pdev, 0);
658         if (IS_ERR(priv->io))
659                 return PTR_ERR(priv->io);
660
661         priv->irq = platform_get_irq(pdev, 0);
662         if (priv->irq < 0)
663                 return priv->irq;
664
665         if (of_device_is_compatible(np, "marvell,armada-380-audio")) {
666                 err = armada_38x_i2s_init_quirk(pdev, priv, soc_dai);
667                 if (err < 0)
668                         return err;
669                 /* Set initial pll frequency */
670                 armada_38x_set_pll(priv->pll_config, 44100);
671         }
672
673         if (np) {
674                 priv->burst = 128;              /* might be 32 or 128 */
675         } else if (data) {
676                 priv->burst = data->burst;
677         } else {
678                 dev_err(&pdev->dev, "no DT nor platform data ?!\n");
679                 return -EINVAL;
680         }
681
682         priv->clk = devm_clk_get(&pdev->dev, np ? "internal" : NULL);
683         if (IS_ERR(priv->clk)) {
684                 dev_err(&pdev->dev, "no clock\n");
685                 return PTR_ERR(priv->clk);
686         }
687
688         priv->extclk = devm_clk_get(&pdev->dev, "extclk");
689         if (IS_ERR(priv->extclk)) {
690                 if (PTR_ERR(priv->extclk) == -EPROBE_DEFER)
691                         return -EPROBE_DEFER;
692         } else {
693                 if (clk_is_match(priv->extclk, priv->clk)) {
694                         devm_clk_put(&pdev->dev, priv->extclk);
695                         priv->extclk = ERR_PTR(-EINVAL);
696                 } else {
697                         dev_info(&pdev->dev, "found external clock\n");
698                         clk_prepare_enable(priv->extclk);
699                         soc_dai = kirkwood_i2s_dai_extclk;
700                 }
701         }
702
703         err = clk_prepare_enable(priv->clk);
704         if (err < 0)
705                 return err;
706
707         /* Some sensible defaults - this reflects the powerup values */
708         priv->ctl_play = KIRKWOOD_PLAYCTL_SIZE_24;
709         priv->ctl_rec = KIRKWOOD_RECCTL_SIZE_24;
710
711         /* Select the burst size */
712         if (priv->burst == 32) {
713                 priv->ctl_play |= KIRKWOOD_PLAYCTL_BURST_32;
714                 priv->ctl_rec |= KIRKWOOD_RECCTL_BURST_32;
715         } else {
716                 priv->ctl_play |= KIRKWOOD_PLAYCTL_BURST_128;
717                 priv->ctl_rec |= KIRKWOOD_RECCTL_BURST_128;
718         }
719
720         err = snd_soc_register_component(&pdev->dev, &kirkwood_soc_component,
721                                          soc_dai, 2);
722         if (err) {
723                 dev_err(&pdev->dev, "snd_soc_register_component failed\n");
724                 goto err_component;
725         }
726
727         kirkwood_i2s_init(priv);
728
729         return 0;
730
731  err_component:
732         if (!IS_ERR(priv->extclk))
733                 clk_disable_unprepare(priv->extclk);
734         clk_disable_unprepare(priv->clk);
735
736         return err;
737 }
738
739 static void kirkwood_i2s_dev_remove(struct platform_device *pdev)
740 {
741         struct kirkwood_dma_data *priv = dev_get_drvdata(&pdev->dev);
742
743         snd_soc_unregister_component(&pdev->dev);
744         if (!IS_ERR(priv->extclk))
745                 clk_disable_unprepare(priv->extclk);
746         clk_disable_unprepare(priv->clk);
747 }
748
749 #ifdef CONFIG_OF
750 static const struct of_device_id mvebu_audio_of_match[] = {
751         { .compatible = "marvell,kirkwood-audio" },
752         { .compatible = "marvell,dove-audio" },
753         { .compatible = "marvell,armada370-audio" },
754         { .compatible = "marvell,armada-380-audio" },
755         { }
756 };
757 MODULE_DEVICE_TABLE(of, mvebu_audio_of_match);
758 #endif
759
760 static struct platform_driver kirkwood_i2s_driver = {
761         .probe  = kirkwood_i2s_dev_probe,
762         .remove_new = kirkwood_i2s_dev_remove,
763         .driver = {
764                 .name = DRV_NAME,
765                 .of_match_table = of_match_ptr(mvebu_audio_of_match),
766         },
767 };
768
769 module_platform_driver(kirkwood_i2s_driver);
770
771 /* Module information */
772 MODULE_AUTHOR("Arnaud Patard, <arnaud.patard@rtp-net.org>");
773 MODULE_DESCRIPTION("Kirkwood I2S SoC Interface");
774 MODULE_LICENSE("GPL");
775 MODULE_ALIAS("platform:mvebu-audio");