ASoC: rockchip: spdif: refactor driver code.
[firefly-linux-kernel-4.4.55.git] / sound / soc / rockchip / rk_spdif.c
1 /*
2  * Rockchip S/PDIF ALSA SoC Digital Audio Interface(DAI)  driver
3  *
4  * Copyright (C) 2015 Fuzhou Rockchip Electronics Co., Ltd
5  *
6  * This software is licensed under the terms of the GNU General Public
7  * License version 2, as published by the Free Software Foundation, and
8  * may be copied, distributed, and modified under those terms.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  */
16
17 #include <linux/init.h>
18 #include <linux/module.h>
19 #include <linux/interrupt.h>
20 #include <linux/device.h>
21 #include <linux/delay.h>
22 #include <linux/clk.h>
23 #include <linux/version.h>
24 #include <linux/of.h>
25 #include <linux/of_gpio.h>
26 #include <linux/clk.h>
27 #include <linux/io.h>
28 #include <linux/platform_device.h>
29 #include <linux/pm_runtime.h>
30 #include <linux/regmap.h>
31 #include <linux/slab.h>
32
33 #include <linux/rockchip/iomap.h>
34 #include <linux/rockchip/grf.h>
35
36 #include <asm/dma.h>
37 #include <sound/core.h>
38 #include <sound/pcm.h>
39 #include <sound/pcm_params.h>
40 #include <sound/initval.h>
41 #include <sound/soc.h>
42 #include <sound/dmaengine_pcm.h>
43 #include <linux/spinlock.h>
44 #include "rk_pcm.h"
45
46 /*
47  * channel status register
48  * 192 frame channel status bits: include 384 subframe bits
49  */
50 #define SPDIF_CHNSR00_ADDR      0xC0
51 #define SPDIF_CHNSR01_ADDR      0xC4
52 #define SPDIF_CHNSR02_ADDR      0xC8
53 #define SPDIF_CHNSR03_ADDR      0xCC
54 #define SPDIF_CHNSR04_ADDR      0xD0
55 #define SPDIF_CHNSR05_ADDR      0xD4
56 #define SPDIF_CHNSR06_ADDR      0xD8
57 #define SPDIF_CHNSR07_ADDR      0xDC
58 #define SPDIF_CHNSR08_ADDR      0xE0
59 #define SPDIF_CHNSR09_ADDR      0xE4
60 #define SPDIF_CHNSR10_ADDR      0xE8
61 #define SPDIF_CHNSR11_ADDR      0xEC
62
63 /*
64  * according to iec958, we only care about
65  * the first meaningful 5 bytes(40 bits)
66  */
67 #define CHNSTA_BYTES            (5)
68 #define BIT_1_LPCM              (0X0<<1)
69 #define BIT_1_NLPCM             (0x1<<1)
70
71 /* sample word length bit 32~35 */
72 #define CHNS_SAMPLE_WORD_LEN_16 (0x2)
73 #define CHNS_SAMPLE_WORD_LEN_24 (0xb)
74
75
76 /* Registers */
77 #define CFGR                    0x00
78 #define SDBLR                   0x04
79 #define DMACR                   0x08
80 #define INTCR                   0x0C
81 #define INTSR                   0x10
82 #define XFER                    0x18
83 #define SMPDR                   0x20
84
85 /* transfer configuration register */
86 #define CFGR_VALID_DATA_16bit           (0x0 << 0)
87 #define CFGR_VALID_DATA_20bit           (0x1 << 0)
88 #define CFGR_VALID_DATA_24bit           (0x2 << 0)
89 #define CFGR_VALID_DATA_MASK            (0x3 << 0)
90 #define CFGR_HALFWORD_TX_ENABLE         (0x1 << 2)
91 #define CFGR_HALFWORD_TX_DISABLE        (0x0 << 2)
92 #define CFGR_HALFWORD_TX_MASK           (0x1 << 2)
93 #define CFGR_JUSTIFIED_RIGHT            (0x0 << 3)
94 #define CFGR_JUSTIFIED_LEFT             (0x1 << 3)
95 #define CFGR_JUSTIFIED_MASK             (0x1 << 3)
96 #define CFGR_CSE_DISABLE                (0x0 << 6)
97 #define CFGR_CSE_ENABLE                 (0x1 << 6)
98 #define CFGR_CSE_MASK                   (0x1 << 6)
99 #define CFGR_MCLK_CLR                   (0x1 << 7)
100 #define CFGR_LINEAR_PCM                 (0x0 << 8)
101 #define CFGR_NON_LINEAR_PCM             (0x1 << 8)
102 #define CFGR_LINEAR_MASK                (0x1 << 8)
103 #define CFGR_PRE_CHANGE_ENALBLE         (0x1 << 9)
104 #define CFGR_PRE_CHANGE_DISABLE         (0x0 << 9)
105 #define CFGR_PRE_CHANGE_MASK            (0x1 << 9)
106 #define CFGR_CLK_RATE_MASK              (0xFF << 16)
107
108 /* transfer start register */
109 #define XFER_TRAN_STOP                  (0x0 << 0)
110 #define XFER_TRAN_START                 (0x1 << 0)
111 #define XFER_MASK                       (0x1 << 0)
112
113 /* dma control register */
114 #define DMACR_TRAN_DMA_DISABLE          (0x0 << 5)
115 #define DMACR_TRAN_DMA_ENABLE           (0x1 << 5)
116 #define DMACR_TRAN_DMA_CTL_MASK         (0x1 << 5)
117 #define DMACR_TRAN_DATA_LEVEL           (0x10)
118 #define DMACR_TRAN_DATA_LEVEL_MASK      (0x1F)
119 #define DMACR_TRAN_DMA_MASK             (0x3F)
120 #define DMA_DATA_LEVEL_16               (0x10)
121
122 /* interrupt control register */
123 #define INTCR_SDBEIE_DISABLE            (0x0 << 4)
124 #define INTCR_SDBEIE_ENABLE             (0x1 << 4)
125 #define INTCR_SDBEIE_MASK               (0x1 << 4)
126
127 struct rockchip_spdif_info {
128         spinlock_t lock;/*lock parmeter setting.*/
129         void __iomem *regs;
130         unsigned long clk_rate;
131         struct clk *hclk;
132         struct clk *clk;
133         struct device *dev;
134         struct snd_dmaengine_dai_dma_data dma_playback;
135 };
136
137 static inline struct rockchip_spdif_info *to_info(struct snd_soc_dai *cpu_dai)
138 {
139         return snd_soc_dai_get_drvdata(cpu_dai);
140 }
141
142 static void spdif_snd_txctrl(struct rockchip_spdif_info *spdif, int on)
143 {
144         void __iomem *regs = spdif->regs;
145         u32 dmacr, xfer;
146
147         xfer = readl(regs + XFER) & (~XFER_MASK);
148         dmacr = readl(regs + DMACR) & (~DMACR_TRAN_DMA_CTL_MASK);
149
150         if (on) {
151                 xfer |= XFER_TRAN_START;
152                 dmacr |= DMACR_TRAN_DMA_ENABLE;
153                 writel(dmacr, regs + DMACR);
154                 writel(xfer, regs + XFER);
155         } else {
156                 xfer &= XFER_TRAN_STOP;
157                 dmacr &= DMACR_TRAN_DMA_DISABLE;
158                 writel(xfer, regs + XFER);
159                 writel(dmacr, regs + DMACR);
160                 writel(CFGR_MCLK_CLR, regs + CFGR);
161         }
162
163         dev_dbg(spdif->dev, "on: %d, xfer = 0x%x, dmacr = 0x%x\n",
164                 on, readl(regs + XFER), readl(regs + DMACR));
165 }
166
167 static int spdif_set_syclk(struct snd_soc_dai *cpu_dai, int clk_id,
168                            unsigned int freq, int dir)
169 {
170         struct rockchip_spdif_info *spdif = to_info(cpu_dai);
171
172         dev_dbg(spdif->dev, "%s: sysclk = %d\n", __func__, freq);
173
174         spdif->clk_rate = freq;
175         clk_set_rate(spdif->clk, freq);
176
177         return 0;
178 }
179
180 static int spdif_trigger(struct snd_pcm_substream *substream, int cmd,
181                          struct snd_soc_dai *dai)
182 {
183         struct snd_soc_pcm_runtime *rtd = substream->private_data;
184         struct rockchip_spdif_info *spdif = to_info(rtd->cpu_dai);
185         unsigned long flags;
186
187         dev_dbg(spdif->dev, "%s: cmd: %d\n", __func__, cmd);
188
189         switch (cmd) {
190         case SNDRV_PCM_TRIGGER_START:
191         case SNDRV_PCM_TRIGGER_RESUME:
192         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
193                 spin_lock_irqsave(&spdif->lock, flags);
194                 spdif_snd_txctrl(spdif, 1);
195                 spin_unlock_irqrestore(&spdif->lock, flags);
196                 break;
197         case SNDRV_PCM_TRIGGER_STOP:
198         case SNDRV_PCM_TRIGGER_SUSPEND:
199         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
200                 spin_lock_irqsave(&spdif->lock, flags);
201                 spdif_snd_txctrl(spdif, 0);
202                 spin_unlock_irqrestore(&spdif->lock, flags);
203                 break;
204         default:
205                 return -EINVAL;
206         }
207
208         return 0;
209 }
210
211 static int spdif_hw_params(struct snd_pcm_substream *substream,
212                            struct snd_pcm_hw_params *params,
213                            struct snd_soc_dai *dai)
214 {
215         struct rockchip_spdif_info *spdif = to_info(dai);
216         void __iomem *regs = spdif->regs;
217         unsigned long flags;
218         int cfgr, dmac, intcr, chnsta[CHNSTA_BYTES], chnregval;
219
220         dev_dbg(spdif->dev, "%s\n", __func__);
221
222         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
223                 dai->playback_dma_data = &spdif->dma_playback;
224         } else {
225                 dev_err(spdif->dev, "capture is not supported\n");
226                 return -EINVAL;
227         }
228
229         spin_lock_irqsave(&spdif->lock, flags);
230
231         cfgr = readl(regs + CFGR);
232
233         cfgr &= ~CFGR_VALID_DATA_MASK;
234         switch (params_format(params)) {
235         case SNDRV_PCM_FORMAT_S16_LE:
236                 cfgr |= CFGR_VALID_DATA_16bit;
237                 break;
238         case SNDRV_PCM_FORMAT_S20_3LE:
239                 cfgr |= CFGR_VALID_DATA_20bit;
240                 break;
241         case SNDRV_PCM_FORMAT_S24_LE:
242                 cfgr |= CFGR_VALID_DATA_24bit;
243                 break;
244         default:
245                 goto err;
246         }
247
248         cfgr &= ~CFGR_HALFWORD_TX_MASK;
249         cfgr |= CFGR_HALFWORD_TX_ENABLE;
250
251         cfgr &= ~CFGR_CLK_RATE_MASK;
252         cfgr |= (1<<16);
253
254         cfgr &= ~CFGR_JUSTIFIED_MASK;
255         cfgr |= CFGR_JUSTIFIED_RIGHT;
256
257         cfgr &= ~CFGR_CSE_MASK;
258         cfgr |= CFGR_CSE_ENABLE;
259
260         cfgr &= ~CFGR_LINEAR_MASK;
261         cfgr |= CFGR_LINEAR_PCM;
262
263         cfgr &= ~CFGR_PRE_CHANGE_MASK;
264         cfgr |= CFGR_PRE_CHANGE_ENALBLE;
265
266         writel(cfgr, regs + CFGR);
267
268         intcr = readl(regs + INTCR) & (~INTCR_SDBEIE_MASK);
269         intcr |= INTCR_SDBEIE_DISABLE;
270         writel(intcr, regs + INTCR);
271
272         dmac = readl(regs + DMACR) & (~DMACR_TRAN_DATA_LEVEL_MASK);
273         dmac |= DMA_DATA_LEVEL_16;
274         writel(dmac, regs + DMACR);
275
276         /* channel status bit */
277         memset(chnsta, 0x0, CHNSTA_BYTES);
278         chnsta[0] |= BIT_1_LPCM;
279         chnsta[4] |= CHNS_SAMPLE_WORD_LEN_16;
280
281         chnregval = (chnsta[4] << 16) | (chnsta[4]);
282         writel(chnregval, regs + SPDIF_CHNSR02_ADDR);
283         chnregval = (chnsta[1] << 24) | (chnsta[0] << 16) |
284                                 (chnsta[1] << 8) | (chnsta[0]);
285         writel(chnregval, regs + SPDIF_CHNSR00_ADDR);
286
287         spin_unlock_irqrestore(&spdif->lock, flags);
288
289         return 0;
290 err:
291         spin_unlock_irqrestore(&spdif->lock, flags);
292         return -EINVAL;
293 }
294
295 #ifdef CONFIG_PM
296 static int spdif_suspend(struct snd_soc_dai *cpu_dai)
297 {
298         struct rockchip_spdif_info *spdif = to_info(cpu_dai);
299
300         dev_dbg(spdif->dev, "%s\n", __func__);
301         return 0;
302 }
303
304 static int spdif_resume(struct snd_soc_dai *cpu_dai)
305 {
306         struct rockchip_spdif_info *spdif = to_info(cpu_dai);
307
308         dev_dbg(spdif->dev, "%s\n", __func__);
309         return 0;
310 }
311 #else
312 #define spdif_suspend NULL
313 #define spdif_resume NULL
314 #endif
315
316 static struct snd_soc_dai_ops spdif_dai_ops = {
317         .set_sysclk     = spdif_set_syclk,
318         .trigger        = spdif_trigger,
319         .hw_params      = spdif_hw_params,
320 };
321
322 struct snd_soc_dai_driver rockchip_spdif_dai = {
323         .name = "rockchip-spdif",
324         .playback = {
325                 .stream_name = "SPDIF Playback",
326                 .channels_min = 2,
327                 .channels_max = 2,
328                 .rates = (SNDRV_PCM_RATE_32000 |
329                                 SNDRV_PCM_RATE_44100 |
330                                 SNDRV_PCM_RATE_48000 |
331                                 SNDRV_PCM_RATE_96000),
332                 .formats = SNDRV_PCM_FMTBIT_S16_LE|
333                 SNDRV_PCM_FMTBIT_S20_3LE|
334                 SNDRV_PCM_FMTBIT_S24_LE, },
335         .ops = &spdif_dai_ops,
336         .suspend = spdif_suspend,
337         .resume = spdif_resume,
338 };
339
340 static const struct snd_soc_component_driver rockchip_spdif_component = {
341         .name = "rockchip-spdif",
342 };
343
344 static int spdif_probe(struct platform_device *pdev)
345 {
346         struct resource *memregion;
347         struct resource *mem_res;
348         struct rockchip_spdif_info *spdif;
349         int ret;
350
351         spdif = devm_kzalloc(&pdev->dev, sizeof(
352                 struct rockchip_spdif_info), GFP_KERNEL);
353         if (!spdif) {
354                 dev_err(&pdev->dev, "Can't allocate spdif info\n");
355                 return -ENOMEM;
356         }
357
358         spdif->dev = &pdev->dev;
359         platform_set_drvdata(pdev, spdif);
360
361         spin_lock_init(&spdif->lock);
362
363         /* get spdif register region. */
364         mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
365         if (!mem_res) {
366                 dev_err(&pdev->dev, "No memory resource\n");
367                 ret = -ENOENT;
368                 goto err_;
369         }
370         memregion = devm_request_mem_region(&pdev->dev,
371                                             mem_res->start,
372                                             resource_size(mem_res),
373                                             "rockchip-spdif");
374         if (!memregion) {
375                 dev_err(&pdev->dev, "Memory region already claimed\n");
376                 ret = -EBUSY;
377                 goto err_;
378         }
379         spdif->regs = devm_ioremap(&pdev->dev,
380                                    memregion->start,
381                                    resource_size(memregion));
382         if (!spdif->regs) {
383                 dev_err(&pdev->dev, "ioremap failed\n");
384                 ret = -ENOMEM;
385                 goto err_;
386         }
387
388         /* get spdif clock and init. */
389         spdif->hclk = devm_clk_get(&pdev->dev, "spdif_hclk");
390         if (IS_ERR(spdif->hclk)) {
391                 dev_err(&pdev->dev, "Can't retrieve spdif hclk\n");
392                 spdif->hclk = NULL;
393         }
394         clk_prepare_enable(spdif->hclk);
395
396         spdif->clk = devm_clk_get(&pdev->dev, "spdif_mclk");
397         if (IS_ERR(spdif->clk)) {
398                 dev_err(&pdev->dev, "Can't retrieve spdif mclk\n");
399                 ret = -ENOMEM;
400                 goto err_;
401         }
402         /* init freq */
403         clk_set_rate(spdif->clk, 11289600);
404         clk_prepare_enable(spdif->clk);
405
406         spdif->dma_playback.addr = mem_res->start + SMPDR;
407         spdif->dma_playback.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
408         spdif->dma_playback.maxburst = 4;
409
410         ret = snd_soc_register_component(&pdev->dev,
411                                          &rockchip_spdif_component,
412                                          &rockchip_spdif_dai, 1);
413         if (ret) {
414                 dev_err(&pdev->dev, "Could not register DAI: %d\n", ret);
415                 ret = -ENOMEM;
416                 goto err_;
417         }
418
419         ret = rockchip_pcm_platform_register(&pdev->dev);
420         if (ret) {
421                 dev_err(&pdev->dev, "Could not register PCM: %d\n", ret);
422                 goto err_;
423         }
424
425         dev_info(&pdev->dev, "spdif ready.\n");
426
427         return 0;
428
429 err_:
430         platform_set_drvdata(pdev, NULL);
431
432         return ret;
433 }
434
435 static int spdif_remove(struct platform_device *pdev)
436 {
437         rockchip_pcm_platform_unregister(&pdev->dev);
438         snd_soc_unregister_component(&pdev->dev);
439
440         return 0;
441 }
442
443 #ifdef CONFIG_OF
444 static const struct of_device_id rockchip_spdif_match[] = {
445         { .compatible = "rockchip-spdif", },
446         {},
447 };
448 MODULE_DEVICE_TABLE(of, rockchip_spdif_match);
449 #endif
450
451 static struct platform_driver rockchip_spdif_driver = {
452         .probe  = spdif_probe,
453         .remove = spdif_remove,
454         .driver = {
455                 .name   = "rockchip-spdif",
456                 .owner  = THIS_MODULE,
457                 .of_match_table = of_match_ptr(rockchip_spdif_match),
458         },
459 };
460 module_platform_driver(rockchip_spdif_driver);
461
462 MODULE_AUTHOR("Sugar <sugar.zhang@rock-chips.com>");
463 MODULE_DESCRIPTION("Rockchip S/PDIF Controller Driver");
464 MODULE_LICENSE("GPL v2");
465 MODULE_ALIAS("platform:rockchip-spdif");