GNU Linux-libre 4.14.259-gnu1
[releases.git] / sound / soc / sunxi / sun4i-spdif.c
1 /*
2  * ALSA SoC SPDIF Audio Layer
3  *
4  * Copyright 2015 Andrea Venturi <be17068@iperbole.bo.it>
5  * Copyright 2015 Marcus Cooper <codekipper@gmail.com>
6  *
7  * Based on the Allwinner SDK driver, released under the GPL.
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  */
19
20 #include <linux/clk.h>
21 #include <linux/delay.h>
22 #include <linux/device.h>
23 #include <linux/kernel.h>
24 #include <linux/init.h>
25 #include <linux/regmap.h>
26 #include <linux/of_address.h>
27 #include <linux/of_device.h>
28 #include <linux/ioport.h>
29 #include <linux/module.h>
30 #include <linux/platform_device.h>
31 #include <linux/pm_runtime.h>
32 #include <linux/reset.h>
33 #include <sound/dmaengine_pcm.h>
34 #include <sound/pcm_params.h>
35 #include <sound/soc.h>
36
37 #define SUN4I_SPDIF_CTL         (0x00)
38         #define SUN4I_SPDIF_CTL_MCLKDIV(v)              ((v) << 4) /* v even */
39         #define SUN4I_SPDIF_CTL_MCLKOUTEN               BIT(2)
40         #define SUN4I_SPDIF_CTL_GEN                     BIT(1)
41         #define SUN4I_SPDIF_CTL_RESET                   BIT(0)
42
43 #define SUN4I_SPDIF_TXCFG       (0x04)
44         #define SUN4I_SPDIF_TXCFG_SINGLEMOD             BIT(31)
45         #define SUN4I_SPDIF_TXCFG_ASS                   BIT(17)
46         #define SUN4I_SPDIF_TXCFG_NONAUDIO              BIT(16)
47         #define SUN4I_SPDIF_TXCFG_TXRATIO(v)            ((v) << 4)
48         #define SUN4I_SPDIF_TXCFG_TXRATIO_MASK          GENMASK(8, 4)
49         #define SUN4I_SPDIF_TXCFG_FMTRVD                GENMASK(3, 2)
50         #define SUN4I_SPDIF_TXCFG_FMT16BIT              (0 << 2)
51         #define SUN4I_SPDIF_TXCFG_FMT20BIT              (1 << 2)
52         #define SUN4I_SPDIF_TXCFG_FMT24BIT              (2 << 2)
53         #define SUN4I_SPDIF_TXCFG_CHSTMODE              BIT(1)
54         #define SUN4I_SPDIF_TXCFG_TXEN                  BIT(0)
55
56 #define SUN4I_SPDIF_RXCFG       (0x08)
57         #define SUN4I_SPDIF_RXCFG_LOCKFLAG              BIT(4)
58         #define SUN4I_SPDIF_RXCFG_CHSTSRC               BIT(3)
59         #define SUN4I_SPDIF_RXCFG_CHSTCP                BIT(1)
60         #define SUN4I_SPDIF_RXCFG_RXEN                  BIT(0)
61
62 #define SUN4I_SPDIF_TXFIFO      (0x0C)
63
64 #define SUN4I_SPDIF_RXFIFO      (0x10)
65
66 #define SUN4I_SPDIF_FCTL        (0x14)
67         #define SUN4I_SPDIF_FCTL_FIFOSRC                BIT(31)
68         #define SUN4I_SPDIF_FCTL_FTX                    BIT(17)
69         #define SUN4I_SPDIF_FCTL_FRX                    BIT(16)
70         #define SUN4I_SPDIF_FCTL_TXTL(v)                ((v) << 8)
71         #define SUN4I_SPDIF_FCTL_TXTL_MASK              GENMASK(12, 8)
72         #define SUN4I_SPDIF_FCTL_RXTL(v)                ((v) << 3)
73         #define SUN4I_SPDIF_FCTL_RXTL_MASK              GENMASK(7, 3)
74         #define SUN4I_SPDIF_FCTL_TXIM                   BIT(2)
75         #define SUN4I_SPDIF_FCTL_RXOM(v)                ((v) << 0)
76         #define SUN4I_SPDIF_FCTL_RXOM_MASK              GENMASK(1, 0)
77
78 #define SUN4I_SPDIF_FSTA        (0x18)
79         #define SUN4I_SPDIF_FSTA_TXE                    BIT(14)
80         #define SUN4I_SPDIF_FSTA_TXECNTSHT              (8)
81         #define SUN4I_SPDIF_FSTA_RXA                    BIT(6)
82         #define SUN4I_SPDIF_FSTA_RXACNTSHT              (0)
83
84 #define SUN4I_SPDIF_INT         (0x1C)
85         #define SUN4I_SPDIF_INT_RXLOCKEN                BIT(18)
86         #define SUN4I_SPDIF_INT_RXUNLOCKEN              BIT(17)
87         #define SUN4I_SPDIF_INT_RXPARERREN              BIT(16)
88         #define SUN4I_SPDIF_INT_TXDRQEN                 BIT(7)
89         #define SUN4I_SPDIF_INT_TXUIEN                  BIT(6)
90         #define SUN4I_SPDIF_INT_TXOIEN                  BIT(5)
91         #define SUN4I_SPDIF_INT_TXEIEN                  BIT(4)
92         #define SUN4I_SPDIF_INT_RXDRQEN                 BIT(2)
93         #define SUN4I_SPDIF_INT_RXOIEN                  BIT(1)
94         #define SUN4I_SPDIF_INT_RXAIEN                  BIT(0)
95
96 #define SUN4I_SPDIF_ISTA        (0x20)
97         #define SUN4I_SPDIF_ISTA_RXLOCKSTA              BIT(18)
98         #define SUN4I_SPDIF_ISTA_RXUNLOCKSTA            BIT(17)
99         #define SUN4I_SPDIF_ISTA_RXPARERRSTA            BIT(16)
100         #define SUN4I_SPDIF_ISTA_TXUSTA                 BIT(6)
101         #define SUN4I_SPDIF_ISTA_TXOSTA                 BIT(5)
102         #define SUN4I_SPDIF_ISTA_TXESTA                 BIT(4)
103         #define SUN4I_SPDIF_ISTA_RXOSTA                 BIT(1)
104         #define SUN4I_SPDIF_ISTA_RXASTA                 BIT(0)
105
106 #define SUN8I_SPDIF_TXFIFO      (0x20)
107
108 #define SUN4I_SPDIF_TXCNT       (0x24)
109
110 #define SUN4I_SPDIF_RXCNT       (0x28)
111
112 #define SUN4I_SPDIF_TXCHSTA0    (0x2C)
113         #define SUN4I_SPDIF_TXCHSTA0_CLK(v)             ((v) << 28)
114         #define SUN4I_SPDIF_TXCHSTA0_SAMFREQ(v)         ((v) << 24)
115         #define SUN4I_SPDIF_TXCHSTA0_SAMFREQ_MASK       GENMASK(27, 24)
116         #define SUN4I_SPDIF_TXCHSTA0_CHNUM(v)           ((v) << 20)
117         #define SUN4I_SPDIF_TXCHSTA0_CHNUM_MASK         GENMASK(23, 20)
118         #define SUN4I_SPDIF_TXCHSTA0_SRCNUM(v)          ((v) << 16)
119         #define SUN4I_SPDIF_TXCHSTA0_CATACOD(v)         ((v) << 8)
120         #define SUN4I_SPDIF_TXCHSTA0_MODE(v)            ((v) << 6)
121         #define SUN4I_SPDIF_TXCHSTA0_EMPHASIS(v)        ((v) << 3)
122         #define SUN4I_SPDIF_TXCHSTA0_CP                 BIT(2)
123         #define SUN4I_SPDIF_TXCHSTA0_AUDIO              BIT(1)
124         #define SUN4I_SPDIF_TXCHSTA0_PRO                BIT(0)
125
126 #define SUN4I_SPDIF_TXCHSTA1    (0x30)
127         #define SUN4I_SPDIF_TXCHSTA1_CGMSA(v)           ((v) << 8)
128         #define SUN4I_SPDIF_TXCHSTA1_ORISAMFREQ(v)      ((v) << 4)
129         #define SUN4I_SPDIF_TXCHSTA1_ORISAMFREQ_MASK    GENMASK(7, 4)
130         #define SUN4I_SPDIF_TXCHSTA1_SAMWORDLEN(v)      ((v) << 1)
131         #define SUN4I_SPDIF_TXCHSTA1_MAXWORDLEN         BIT(0)
132
133 #define SUN4I_SPDIF_RXCHSTA0    (0x34)
134         #define SUN4I_SPDIF_RXCHSTA0_CLK(v)             ((v) << 28)
135         #define SUN4I_SPDIF_RXCHSTA0_SAMFREQ(v)         ((v) << 24)
136         #define SUN4I_SPDIF_RXCHSTA0_CHNUM(v)           ((v) << 20)
137         #define SUN4I_SPDIF_RXCHSTA0_SRCNUM(v)          ((v) << 16)
138         #define SUN4I_SPDIF_RXCHSTA0_CATACOD(v)         ((v) << 8)
139         #define SUN4I_SPDIF_RXCHSTA0_MODE(v)            ((v) << 6)
140         #define SUN4I_SPDIF_RXCHSTA0_EMPHASIS(v)        ((v) << 3)
141         #define SUN4I_SPDIF_RXCHSTA0_CP                 BIT(2)
142         #define SUN4I_SPDIF_RXCHSTA0_AUDIO              BIT(1)
143         #define SUN4I_SPDIF_RXCHSTA0_PRO                BIT(0)
144
145 #define SUN4I_SPDIF_RXCHSTA1    (0x38)
146         #define SUN4I_SPDIF_RXCHSTA1_CGMSA(v)           ((v) << 8)
147         #define SUN4I_SPDIF_RXCHSTA1_ORISAMFREQ(v)      ((v) << 4)
148         #define SUN4I_SPDIF_RXCHSTA1_SAMWORDLEN(v)      ((v) << 1)
149         #define SUN4I_SPDIF_RXCHSTA1_MAXWORDLEN         BIT(0)
150
151 /* Defines for Sampling Frequency */
152 #define SUN4I_SPDIF_SAMFREQ_44_1KHZ             0x0
153 #define SUN4I_SPDIF_SAMFREQ_NOT_INDICATED       0x1
154 #define SUN4I_SPDIF_SAMFREQ_48KHZ               0x2
155 #define SUN4I_SPDIF_SAMFREQ_32KHZ               0x3
156 #define SUN4I_SPDIF_SAMFREQ_22_05KHZ            0x4
157 #define SUN4I_SPDIF_SAMFREQ_24KHZ               0x6
158 #define SUN4I_SPDIF_SAMFREQ_88_2KHZ             0x8
159 #define SUN4I_SPDIF_SAMFREQ_76_8KHZ             0x9
160 #define SUN4I_SPDIF_SAMFREQ_96KHZ               0xa
161 #define SUN4I_SPDIF_SAMFREQ_176_4KHZ            0xc
162 #define SUN4I_SPDIF_SAMFREQ_192KHZ              0xe
163
164 struct sun4i_spdif_dev {
165         struct platform_device *pdev;
166         struct clk *spdif_clk;
167         struct clk *apb_clk;
168         struct reset_control *rst;
169         struct snd_soc_dai_driver cpu_dai_drv;
170         struct regmap *regmap;
171         struct snd_dmaengine_dai_dma_data dma_params_tx;
172 };
173
174 static void sun4i_spdif_configure(struct sun4i_spdif_dev *host)
175 {
176         /* soft reset SPDIF */
177         regmap_write(host->regmap, SUN4I_SPDIF_CTL, SUN4I_SPDIF_CTL_RESET);
178
179         /* flush TX FIFO */
180         regmap_update_bits(host->regmap, SUN4I_SPDIF_FCTL,
181                            SUN4I_SPDIF_FCTL_FTX, SUN4I_SPDIF_FCTL_FTX);
182
183         /* clear TX counter */
184         regmap_write(host->regmap, SUN4I_SPDIF_TXCNT, 0);
185 }
186
187 static void sun4i_snd_txctrl_on(struct snd_pcm_substream *substream,
188                                 struct sun4i_spdif_dev *host)
189 {
190         if (substream->runtime->channels == 1)
191                 regmap_update_bits(host->regmap, SUN4I_SPDIF_TXCFG,
192                                    SUN4I_SPDIF_TXCFG_SINGLEMOD,
193                                    SUN4I_SPDIF_TXCFG_SINGLEMOD);
194
195         /* SPDIF TX ENABLE */
196         regmap_update_bits(host->regmap, SUN4I_SPDIF_TXCFG,
197                            SUN4I_SPDIF_TXCFG_TXEN, SUN4I_SPDIF_TXCFG_TXEN);
198
199         /* DRQ ENABLE */
200         regmap_update_bits(host->regmap, SUN4I_SPDIF_INT,
201                            SUN4I_SPDIF_INT_TXDRQEN, SUN4I_SPDIF_INT_TXDRQEN);
202
203         /* Global enable */
204         regmap_update_bits(host->regmap, SUN4I_SPDIF_CTL,
205                            SUN4I_SPDIF_CTL_GEN, SUN4I_SPDIF_CTL_GEN);
206 }
207
208 static void sun4i_snd_txctrl_off(struct snd_pcm_substream *substream,
209                                  struct sun4i_spdif_dev *host)
210 {
211         /* SPDIF TX DISABLE */
212         regmap_update_bits(host->regmap, SUN4I_SPDIF_TXCFG,
213                            SUN4I_SPDIF_TXCFG_TXEN, 0);
214
215         /* DRQ DISABLE */
216         regmap_update_bits(host->regmap, SUN4I_SPDIF_INT,
217                            SUN4I_SPDIF_INT_TXDRQEN, 0);
218
219         /* Global disable */
220         regmap_update_bits(host->regmap, SUN4I_SPDIF_CTL,
221                            SUN4I_SPDIF_CTL_GEN, 0);
222 }
223
224 static int sun4i_spdif_startup(struct snd_pcm_substream *substream,
225                                struct snd_soc_dai *cpu_dai)
226 {
227         struct snd_soc_pcm_runtime *rtd = substream->private_data;
228         struct sun4i_spdif_dev *host = snd_soc_dai_get_drvdata(rtd->cpu_dai);
229
230         if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
231                 return -EINVAL;
232
233         sun4i_spdif_configure(host);
234
235         return 0;
236 }
237
238 static int sun4i_spdif_hw_params(struct snd_pcm_substream *substream,
239                                  struct snd_pcm_hw_params *params,
240                                  struct snd_soc_dai *cpu_dai)
241 {
242         int ret = 0;
243         int fmt;
244         unsigned long rate = params_rate(params);
245         u32 mclk_div = 0;
246         unsigned int mclk = 0;
247         u32 reg_val;
248         struct sun4i_spdif_dev *host = snd_soc_dai_get_drvdata(cpu_dai);
249         struct platform_device *pdev = host->pdev;
250
251         /* Add the PCM and raw data select interface */
252         switch (params_channels(params)) {
253         case 1: /* PCM mode */
254         case 2:
255                 fmt = 0;
256                 break;
257         case 4: /* raw data mode */
258                 fmt = SUN4I_SPDIF_TXCFG_NONAUDIO;
259                 break;
260         default:
261                 return -EINVAL;
262         }
263
264         switch (params_format(params)) {
265         case SNDRV_PCM_FORMAT_S16_LE:
266                 fmt |= SUN4I_SPDIF_TXCFG_FMT16BIT;
267                 break;
268         case SNDRV_PCM_FORMAT_S20_3LE:
269                 fmt |= SUN4I_SPDIF_TXCFG_FMT20BIT;
270                 break;
271         case SNDRV_PCM_FORMAT_S24_LE:
272                 fmt |= SUN4I_SPDIF_TXCFG_FMT24BIT;
273                 break;
274         default:
275                 return -EINVAL;
276         }
277
278         switch (rate) {
279         case 22050:
280         case 44100:
281         case 88200:
282         case 176400:
283                 mclk = 22579200;
284                 break;
285         case 24000:
286         case 32000:
287         case 48000:
288         case 96000:
289         case 192000:
290                 mclk = 24576000;
291                 break;
292         default:
293                 return -EINVAL;
294         }
295
296         ret = clk_set_rate(host->spdif_clk, mclk);
297         if (ret < 0) {
298                 dev_err(&pdev->dev,
299                         "Setting SPDIF clock rate for %d Hz failed!\n", mclk);
300                 return ret;
301         }
302
303         regmap_update_bits(host->regmap, SUN4I_SPDIF_FCTL,
304                            SUN4I_SPDIF_FCTL_TXIM, SUN4I_SPDIF_FCTL_TXIM);
305
306         switch (rate) {
307         case 22050:
308         case 24000:
309                 mclk_div = 8;
310                 break;
311         case 32000:
312                 mclk_div = 6;
313                 break;
314         case 44100:
315         case 48000:
316                 mclk_div = 4;
317                 break;
318         case 88200:
319         case 96000:
320                 mclk_div = 2;
321                 break;
322         case 176400:
323         case 192000:
324                 mclk_div = 1;
325                 break;
326         default:
327                 return -EINVAL;
328         }
329
330         reg_val = 0;
331         reg_val |= SUN4I_SPDIF_TXCFG_ASS;
332         reg_val |= fmt; /* set non audio and bit depth */
333         reg_val |= SUN4I_SPDIF_TXCFG_CHSTMODE;
334         reg_val |= SUN4I_SPDIF_TXCFG_TXRATIO(mclk_div - 1);
335         regmap_write(host->regmap, SUN4I_SPDIF_TXCFG, reg_val);
336
337         return 0;
338 }
339
340 static int sun4i_spdif_trigger(struct snd_pcm_substream *substream, int cmd,
341                                struct snd_soc_dai *dai)
342 {
343         int ret = 0;
344         struct sun4i_spdif_dev *host = snd_soc_dai_get_drvdata(dai);
345
346         if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
347                 return -EINVAL;
348
349         switch (cmd) {
350         case SNDRV_PCM_TRIGGER_START:
351         case SNDRV_PCM_TRIGGER_RESUME:
352         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
353                 sun4i_snd_txctrl_on(substream, host);
354                 break;
355
356         case SNDRV_PCM_TRIGGER_STOP:
357         case SNDRV_PCM_TRIGGER_SUSPEND:
358         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
359                 sun4i_snd_txctrl_off(substream, host);
360                 break;
361
362         default:
363                 ret = -EINVAL;
364                 break;
365         }
366         return ret;
367 }
368
369 static int sun4i_spdif_soc_dai_probe(struct snd_soc_dai *dai)
370 {
371         struct sun4i_spdif_dev *host = snd_soc_dai_get_drvdata(dai);
372
373         snd_soc_dai_init_dma_data(dai, &host->dma_params_tx, NULL);
374         return 0;
375 }
376
377 static const struct snd_soc_dai_ops sun4i_spdif_dai_ops = {
378         .startup        = sun4i_spdif_startup,
379         .trigger        = sun4i_spdif_trigger,
380         .hw_params      = sun4i_spdif_hw_params,
381 };
382
383 static const struct regmap_config sun4i_spdif_regmap_config = {
384         .reg_bits = 32,
385         .reg_stride = 4,
386         .val_bits = 32,
387         .max_register = SUN4I_SPDIF_RXCHSTA1,
388 };
389
390 #define SUN4I_RATES     SNDRV_PCM_RATE_8000_192000
391
392 #define SUN4I_FORMATS   (SNDRV_PCM_FORMAT_S16_LE | \
393                                 SNDRV_PCM_FORMAT_S20_3LE | \
394                                 SNDRV_PCM_FORMAT_S24_LE)
395
396 static struct snd_soc_dai_driver sun4i_spdif_dai = {
397         .playback = {
398                 .channels_min = 1,
399                 .channels_max = 2,
400                 .rates = SUN4I_RATES,
401                 .formats = SUN4I_FORMATS,
402         },
403         .probe = sun4i_spdif_soc_dai_probe,
404         .ops = &sun4i_spdif_dai_ops,
405         .name = "spdif",
406 };
407
408 struct sun4i_spdif_quirks {
409         unsigned int reg_dac_txdata;    /* TX FIFO offset for DMA config */
410         bool has_reset;
411 };
412
413 static const struct sun4i_spdif_quirks sun4i_a10_spdif_quirks = {
414         .reg_dac_txdata = SUN4I_SPDIF_TXFIFO,
415 };
416
417 static const struct sun4i_spdif_quirks sun6i_a31_spdif_quirks = {
418         .reg_dac_txdata = SUN4I_SPDIF_TXFIFO,
419         .has_reset      = true,
420 };
421
422 static const struct sun4i_spdif_quirks sun8i_h3_spdif_quirks = {
423         .reg_dac_txdata = SUN8I_SPDIF_TXFIFO,
424         .has_reset      = true,
425 };
426
427 static const struct of_device_id sun4i_spdif_of_match[] = {
428         {
429                 .compatible = "allwinner,sun4i-a10-spdif",
430                 .data = &sun4i_a10_spdif_quirks,
431         },
432         {
433                 .compatible = "allwinner,sun6i-a31-spdif",
434                 .data = &sun6i_a31_spdif_quirks,
435         },
436         {
437                 .compatible = "allwinner,sun8i-h3-spdif",
438                 .data = &sun8i_h3_spdif_quirks,
439         },
440         { /* sentinel */ }
441 };
442 MODULE_DEVICE_TABLE(of, sun4i_spdif_of_match);
443
444 static const struct snd_soc_component_driver sun4i_spdif_component = {
445         .name           = "sun4i-spdif",
446 };
447
448 static int sun4i_spdif_runtime_suspend(struct device *dev)
449 {
450         struct sun4i_spdif_dev *host  = dev_get_drvdata(dev);
451
452         clk_disable_unprepare(host->spdif_clk);
453         clk_disable_unprepare(host->apb_clk);
454
455         return 0;
456 }
457
458 static int sun4i_spdif_runtime_resume(struct device *dev)
459 {
460         struct sun4i_spdif_dev *host  = dev_get_drvdata(dev);
461         int ret;
462
463         ret = clk_prepare_enable(host->spdif_clk);
464         if (ret)
465                 return ret;
466         ret = clk_prepare_enable(host->apb_clk);
467         if (ret)
468                 clk_disable_unprepare(host->spdif_clk);
469
470         return ret;
471 }
472
473 static int sun4i_spdif_probe(struct platform_device *pdev)
474 {
475         struct sun4i_spdif_dev *host;
476         struct resource *res;
477         const struct sun4i_spdif_quirks *quirks;
478         int ret;
479         void __iomem *base;
480
481         dev_dbg(&pdev->dev, "Entered %s\n", __func__);
482
483         host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
484         if (!host)
485                 return -ENOMEM;
486
487         host->pdev = pdev;
488
489         /* Initialize this copy of the CPU DAI driver structure */
490         memcpy(&host->cpu_dai_drv, &sun4i_spdif_dai, sizeof(sun4i_spdif_dai));
491         host->cpu_dai_drv.name = dev_name(&pdev->dev);
492
493         /* Get the addresses */
494         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
495         base = devm_ioremap_resource(&pdev->dev, res);
496         if (IS_ERR(base))
497                 return PTR_ERR(base);
498
499         quirks = of_device_get_match_data(&pdev->dev);
500         if (quirks == NULL) {
501                 dev_err(&pdev->dev, "Failed to determine the quirks to use\n");
502                 return -ENODEV;
503         }
504
505         host->regmap = devm_regmap_init_mmio(&pdev->dev, base,
506                                                 &sun4i_spdif_regmap_config);
507
508         /* Clocks */
509         host->apb_clk = devm_clk_get(&pdev->dev, "apb");
510         if (IS_ERR(host->apb_clk)) {
511                 dev_err(&pdev->dev, "failed to get a apb clock.\n");
512                 return PTR_ERR(host->apb_clk);
513         }
514
515         host->spdif_clk = devm_clk_get(&pdev->dev, "spdif");
516         if (IS_ERR(host->spdif_clk)) {
517                 dev_err(&pdev->dev, "failed to get a spdif clock.\n");
518                 return PTR_ERR(host->spdif_clk);
519         }
520
521         host->dma_params_tx.addr = res->start + quirks->reg_dac_txdata;
522         host->dma_params_tx.maxburst = 8;
523         host->dma_params_tx.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
524
525         platform_set_drvdata(pdev, host);
526
527         if (quirks->has_reset) {
528                 host->rst = devm_reset_control_get_optional_exclusive(&pdev->dev,
529                                                                       NULL);
530                 if (IS_ERR(host->rst) && PTR_ERR(host->rst) == -EPROBE_DEFER) {
531                         ret = -EPROBE_DEFER;
532                         dev_err(&pdev->dev, "Failed to get reset: %d\n", ret);
533                         return ret;
534                 }
535                 if (!IS_ERR(host->rst))
536                         reset_control_deassert(host->rst);
537         }
538
539         ret = devm_snd_soc_register_component(&pdev->dev,
540                                 &sun4i_spdif_component, &sun4i_spdif_dai, 1);
541         if (ret)
542                 return ret;
543
544         pm_runtime_enable(&pdev->dev);
545         if (!pm_runtime_enabled(&pdev->dev)) {
546                 ret = sun4i_spdif_runtime_resume(&pdev->dev);
547                 if (ret)
548                         goto err_unregister;
549         }
550
551         ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
552         if (ret)
553                 goto err_suspend;
554         return 0;
555 err_suspend:
556         if (!pm_runtime_status_suspended(&pdev->dev))
557                 sun4i_spdif_runtime_suspend(&pdev->dev);
558 err_unregister:
559         pm_runtime_disable(&pdev->dev);
560         return ret;
561 }
562
563 static int sun4i_spdif_remove(struct platform_device *pdev)
564 {
565         pm_runtime_disable(&pdev->dev);
566         if (!pm_runtime_status_suspended(&pdev->dev))
567                 sun4i_spdif_runtime_suspend(&pdev->dev);
568
569         return 0;
570 }
571
572 static const struct dev_pm_ops sun4i_spdif_pm = {
573         SET_RUNTIME_PM_OPS(sun4i_spdif_runtime_suspend,
574                            sun4i_spdif_runtime_resume, NULL)
575 };
576
577 static struct platform_driver sun4i_spdif_driver = {
578         .driver         = {
579                 .name   = "sun4i-spdif",
580                 .of_match_table = of_match_ptr(sun4i_spdif_of_match),
581                 .pm     = &sun4i_spdif_pm,
582         },
583         .probe          = sun4i_spdif_probe,
584         .remove         = sun4i_spdif_remove,
585 };
586
587 module_platform_driver(sun4i_spdif_driver);
588
589 MODULE_AUTHOR("Marcus Cooper <codekipper@gmail.com>");
590 MODULE_AUTHOR("Andrea Venturi <be17068@iperbole.bo.it>");
591 MODULE_DESCRIPTION("Allwinner sun4i SPDIF SoC Interface");
592 MODULE_LICENSE("GPL");
593 MODULE_ALIAS("platform:sun4i-spdif");