Merge tag 'lsk-android-14.03' into develop-3.10
[firefly-linux-kernel-4.4.55.git] / sound / soc / rockchip / rk_spdif.c
1 /*$_FOR_ROCKCHIP_RBOX_$*/
2 /*$_rbox_$_modify_$_huangzhibao for spdif output*/
3
4 /* sound/soc/rockchip/rk_spdif.c
5  *
6  * ALSA SoC Audio Layer - rockchip S/PDIF Controller driver
7  *
8  * Copyright (c) 2010 rockchip Electronics Co. Ltd
9  *              http://www.rockchip.com/
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License version 2 as
13  * published by the Free Software Foundation.
14  */
15
16 #include <linux/init.h>
17 #include <linux/module.h>
18 #include <linux/interrupt.h>
19 #include <linux/device.h>
20 #include <linux/delay.h>
21 #include <linux/clk.h>
22 #include <linux/version.h>
23 #include <linux/of.h>
24 #include <linux/of_gpio.h>
25 #include <linux/clk.h>
26 #include <linux/io.h>
27 #include <linux/platform_device.h>
28 #include <linux/pm_runtime.h>
29 #include <linux/regmap.h>
30 #include <linux/slab.h>
31
32 #include <linux/rockchip/iomap.h>
33 #include <linux/rockchip/grf.h>
34
35 #include <asm/dma.h>
36 #include <sound/core.h>
37 #include <sound/pcm.h>
38 #include <sound/pcm_params.h>
39 #include <sound/initval.h>
40 #include <sound/soc.h>
41 #include <sound/dmaengine_pcm.h>
42 #include <asm/io.h>
43
44 #include <linux/spinlock.h>
45
46 #include "rk_pcm.h"
47
48 #if 0
49 #define RK_SPDIF_DBG(x...) printk(KERN_INFO "rk_spdif:"x)
50 #else
51 #define RK_SPDIF_DBG(x...) do { } while (0)
52 #endif
53
54
55 /* Registers */
56 #define CFGR                  0x00
57 #define SDBLR                 0x04
58 #define DMACR                 0x08
59 #define INTCR                 0x0C
60 #define INTSR                 0x10
61 #define XFER                  0x18
62 #define SMPDR                 0x20
63
64 #define SPDIF_CHNSR00_ADDR    0xC0
65 #define SPDIF_CHNSR01_ADDR    0xC4
66 #define SPDIF_CHNSR02_ADDR    0xC8
67 #define SPDIF_CHNSR03_ADDR    0xCC
68 #define SPDIF_CHNSR04_ADDR    0xD0
69 #define SPDIF_CHNSR05_ADDR    0xD4
70 #define SPDIF_CHNSR06_ADDR    0xD8
71 #define SPDIF_CHNSR07_ADDR    0xDC
72 #define SPDIF_CHNSR08_ADDR    0xE0
73 #define SPDIF_CHNSR09_ADDR    0xE4
74 #define SPDIF_CHNSR10_ADDR    0xE8
75 #define SPDIF_CHNSR11_ADDR    0xEC
76
77 #define SPDIF_BURSTINFO       0x100
78 #define SPDIF_REPETTION       0x104
79
80 #define DATA_OUTBUF           0x20
81
82 #define SPDIF_CHANNEL_SEL_8CH   ((0x2<<16)|(0x0<<0))
83 #define SPDIF_CHANNEL_SEL_2CH   ((0x2<<16)|(0x2<<0))
84
85 //BURSTINFO bit0:6 //AC-3:0x01, DTS-I -II -III:11,12,13
86 #define BURSTINFO_DATA_TYPE_AC3     0x01
87 #define BURSTINFO_DATA_TYPE_EAC3    0x15
88 #define BURSTINFO_DATA_TYPE_DTS_I   0x0b
89
90 #define CFGR_MASK                   0x0ffffff
91 #define CFGR_VALID_DATA_16bit       (00)
92 #define CFGR_VALID_DATA_20bit       (01)
93 #define CFGR_VALID_DATA_24bit       (10)
94 #define CFGR_VALID_DATA_MASK        (11)
95
96 #define CFGR_HALFWORD_TX_ENABLE     (0x1<<2)
97 #define CFGR_HALFWORD_TX_DISABLE    (0x0<<2)
98 #define CFGR_HALFWORD_TX_MASK       (0x1<<2)
99
100 #define CFGR_CLK_RATE_MASK          (0xFF<<16)                 
101
102 #define CFGR_JUSTIFIED_RIGHT        (0<<3)
103 #define CFGR_JUSTIFIED_LEFT         (1<<3)
104 #define CFGR_JUSTIFIED_MASK         (1<<3)
105
106 //CSE:channel status enable
107 //The bit should be set to 1 when the channel conveys non-linear PCM
108 #define CFGR_CSE_DISABLE            (0<<6)
109 #define CFGR_CSE_ENABLE             (1<<6)
110 #define CFGR_CSE_MASK               (1<<6)
111
112
113 #define CFGR_MCLK_CLR               (1<<7)
114
115 //new
116 #define CFGR_LINEAR_PCM             (0<<8)
117 #define CFGR_NON_LINEAR_PCM         (1<<8)
118 #define CFGR_LINEAR_MASK            (1<<8)
119
120 //support 7.1 amplifier,new
121 #define CFGR_PRE_CHANGE_ENALBLE     (1<<9)
122 #define CFGR_PRE_CHANGE_DISABLE     (0<<9)
123 #define CFGR_PRE_CHANGE_MASK        (1<<9)
124
125 #define XFER_TRAN_STOP              (0)
126 #define XFER_TRAN_START             (1)
127 #define XFER_MASK                   (1)
128
129 #define DMACR_TRAN_DMA_DISABLE      (0<<5)
130 #define DMACR_TRAN_DMA_ENABLE       (1<<5)
131 #define DMACR_TRAN_DMA_CTL_MASK     (1<<5)
132
133 #define DMACR_TRAN_DATA_LEVEL       0x10
134 #define DMACR_TRAN_DATA_LEVEL_MASK  0x1F
135 #define DMACR_TRAN_DMA_MASK         0x3F
136
137 //Sample Date Buffer empty interrupt enable,new
138 #define INTCR_SDBEIE_DISABLE        (0<<4)
139 #define INTCR_SDBEIE_ENABLE         (1<<4)
140 #define INTCR_SDBEIE_MASK           (1<<4)
141
142  
143 struct rockchip_spdif_info {
144         spinlock_t      lock;
145         void __iomem    *regs;
146         unsigned long   clk_rate;
147         struct clk      *clk;
148         struct snd_dmaengine_dai_dma_data       dma_playback;
149 };
150
151 static inline struct rockchip_spdif_info *to_info(struct snd_soc_dai *cpu_dai)
152 {
153         return snd_soc_dai_get_drvdata(cpu_dai);
154 }
155
156 static void spdif_snd_txctrl(struct rockchip_spdif_info *spdif, int on)
157 {
158         void __iomem *regs = spdif->regs;
159         u32 opr,xfer;
160
161         RK_SPDIF_DBG( "Entered %s\n", __func__);
162
163         xfer = readl(regs + XFER) & XFER_MASK;
164         opr  = readl(regs + DMACR) & DMACR_TRAN_DMA_MASK & (~DMACR_TRAN_DMA_CTL_MASK);
165         
166         if (on){
167                 xfer |= XFER_TRAN_START;
168                 opr |= DMACR_TRAN_DMA_ENABLE;
169                 writel(xfer, regs + XFER);
170                 writel(opr, regs + DMACR);
171                 RK_SPDIF_DBG("on xfer=0x%x,opr=0x%x\n",readl(regs + XFER),readl(regs + DMACR));
172     }else{
173             xfer &= ~XFER_TRAN_START;
174             opr  &= ~DMACR_TRAN_DMA_ENABLE; 
175                 writel(xfer, regs + XFER);
176                 writel(opr, regs + DMACR);
177                 writel(1<<7, regs + CFGR);
178                 RK_SPDIF_DBG("off xfer=0x%x,opr=0x%x\n",readl(regs + XFER),readl(regs + DMACR));
179         }
180 }
181
182 static int spdif_set_syclk(struct snd_soc_dai *cpu_dai,
183                                 int clk_id, unsigned int freq, int dir)
184 {
185         struct rockchip_spdif_info *spdif = to_info(cpu_dai);
186
187         RK_SPDIF_DBG("Entered %s\n", __func__);
188
189         spdif->clk_rate = freq;
190
191         return 0;
192 }
193
194 static int spdif_trigger(struct snd_pcm_substream *substream, int cmd,
195                                 struct snd_soc_dai *dai)
196 {
197         struct snd_soc_pcm_runtime *rtd = substream->private_data;
198         struct rockchip_spdif_info *spdif = to_info(rtd->cpu_dai);
199         unsigned long flags;
200
201         RK_SPDIF_DBG( "Entered %s\n", __func__);
202
203         switch (cmd) {
204         case SNDRV_PCM_TRIGGER_START:
205         case SNDRV_PCM_TRIGGER_RESUME:
206         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
207                 spin_lock_irqsave(&spdif->lock, flags);
208                 spdif_snd_txctrl(spdif, 1);
209                 spin_unlock_irqrestore(&spdif->lock, flags);
210                 break;
211         case SNDRV_PCM_TRIGGER_STOP:
212         case SNDRV_PCM_TRIGGER_SUSPEND:
213         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
214                 spin_lock_irqsave(&spdif->lock, flags);
215                 spdif_snd_txctrl(spdif, 0);
216                 spin_unlock_irqrestore(&spdif->lock, flags);
217                 break;
218         default:
219                 return -EINVAL;
220         }
221
222         return 0;
223 }
224
225
226 static int spdif_hw_params(struct snd_pcm_substream *substream,
227                                 struct snd_pcm_hw_params *params,
228                                 struct snd_soc_dai *dai)
229 {
230         struct rockchip_spdif_info *spdif = to_info(dai);
231         void __iomem *regs = spdif->regs;
232         unsigned long flags;
233         int cfgr, dmac,intcr,chnsr_byte[5]={0};
234         int dataType,ErrFlag,DataLen,DataInfo,BsNum,Repetition,BurstInfo;
235
236         RK_SPDIF_DBG("Entered %s\n", __func__);
237
238         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
239                 dai->playback_dma_data = &spdif->dma_playback;
240         else {
241                 printk("spdif:Capture is not supported\n");
242                 return -EINVAL;
243         }
244
245         spin_lock_irqsave(&spdif->lock, flags);
246         
247         cfgr = readl(regs + CFGR) & CFGR_VALID_DATA_MASK;
248         
249         cfgr &= ~CFGR_VALID_DATA_MASK;
250         switch (params_format(params)) {
251         case SNDRV_PCM_FORMAT_S16_LE:
252                 cfgr |= CFGR_VALID_DATA_16bit;
253                 break;
254         case SNDRV_PCM_FORMAT_S20_3LE :
255                 cfgr |= CFGR_VALID_DATA_20bit;
256                 break;
257         case SNDRV_PCM_FORMAT_S24_LE:
258                 cfgr |= CFGR_VALID_DATA_24bit;
259                 break;                  
260         default:
261                 goto err;
262         }
263         
264         cfgr &= ~CFGR_HALFWORD_TX_MASK;
265         cfgr |= CFGR_HALFWORD_TX_ENABLE;
266         
267         cfgr &= ~CFGR_CLK_RATE_MASK;//set most MCLK:192kHz
268         cfgr |= (1<<16);
269         
270         cfgr &= ~CFGR_JUSTIFIED_MASK;
271         cfgr |= CFGR_JUSTIFIED_RIGHT;
272
273         cfgr &= ~CFGR_CSE_MASK;
274         cfgr |= CFGR_CSE_DISABLE;
275
276         cfgr &= ~CFGR_LINEAR_MASK;
277         cfgr |= CFGR_LINEAR_PCM;
278         if(!snd_pcm_format_linear(params_format(params))){//stream type
279                 cfgr |= CFGR_NON_LINEAR_PCM;
280         }
281         
282         cfgr &= ~CFGR_PRE_CHANGE_MASK;
283         cfgr |= CFGR_PRE_CHANGE_ENALBLE;
284
285         writel(cfgr, regs + CFGR);
286
287         intcr = readl(regs + INTCR) & INTCR_SDBEIE_MASK;
288         intcr |= INTCR_SDBEIE_ENABLE;
289         writel(intcr, regs + INTCR);
290
291         dmac = readl(regs + DMACR) & DMACR_TRAN_DMA_MASK & (~DMACR_TRAN_DATA_LEVEL_MASK);
292         dmac |= 0x10;
293         writel(dmac, regs + DMACR);
294
295         /*  channel byte 0:
296         Bit 1  1  Main data field represents linear PCM samples.
297                0  Main data field used for purposes other purposes.
298         */
299         chnsr_byte[0]= (0x0)|(0x0<<1)|(0x0<<2)|(0x0<<3)|(0x00<<6);//consumer|pcm|copyright?|pre-emphasis|(0x00<<6);
300         chnsr_byte[1]= (0x0);//category code general mode??
301         chnsr_byte[2]= (0x0)|(0x0<<4)|(0x0<<6);//
302         chnsr_byte[3]= (0x00)|(0x00);//khz;clock acurracy
303         chnsr_byte[4]= (0x0<<4)|(0x01<<1|0x0);//16 bit;
304
305         if(!snd_pcm_format_linear(params_format(params))){//set stream type
306                 chnsr_byte[0] |= (0x1<<1);//set 0:represent main data is linear
307                 chnsr_byte[4] = (0x0<<4)|(0x00<<1|0x0);//16 bit;
308         }
309         writel((chnsr_byte[4]<<16)|(chnsr_byte[4]),regs+SPDIF_CHNSR02_ADDR);
310         writel((chnsr_byte[3]<<24)|(chnsr_byte[2]<<16)|(chnsr_byte[3]<<8)|(chnsr_byte[2]),regs+SPDIF_CHNSR01_ADDR);
311         writel((chnsr_byte[1]<<24)|(chnsr_byte[0]<<16)|(chnsr_byte[1]<<8)|(chnsr_byte[0]),regs+SPDIF_CHNSR00_ADDR);
312
313         if(!snd_pcm_format_linear(params_format(params))) {//set non-linear params
314                 switch(params_format(params)){
315                 case SNDRV_NON_LINEAR_PCM_FORMAT_AC3:
316                         //bit0:6 //AC-3:0x01, DTS-I -II -III:11,12,13
317                         dataType = BURSTINFO_DATA_TYPE_AC3;
318                         //Repetition:AC-3:1536  DTS-I -II -III:512,1024,2048 EAC3:6144
319                         Repetition = 1536;
320                         break;
321                 case SNDRV_NON_LINEAR_PCM_FORMAT_DTS_I:
322                         dataType = BURSTINFO_DATA_TYPE_DTS_I;
323                         Repetition = 512;
324                         break;
325                 case SNDRV_NON_LINEAR_PCM_FORMAT_EAC3:
326                         dataType = BURSTINFO_DATA_TYPE_EAC3;
327                         Repetition = 6144;
328                         break;
329                 default:
330                         return -EINVAL;
331                 }
332                 ErrFlag=0x0;
333                 DataLen=params_period_size(params)*2*16;//bit32:16 //640kbps:0x5000    448kbps:0x3800
334                 DataInfo=0;
335                 BsNum=0x0;
336                 BurstInfo = (DataLen<<16)|(BsNum<<13)|(DataInfo<<8)|(ErrFlag<<7)|dataType;
337                 writel(BurstInfo,regs+SPDIF_BURSTINFO);
338                 writel(Repetition,regs+SPDIF_REPETTION);
339         }
340         spin_unlock_irqrestore(&spdif->lock, flags);
341
342         return 0;
343 err:
344         spin_unlock_irqrestore(&spdif->lock, flags);
345         return -EINVAL;
346 }
347
348 #ifdef CONFIG_PM
349 static int spdif_suspend(struct snd_soc_dai *cpu_dai)
350 {
351         RK_SPDIF_DBG( "spdif:Entered %s\n", __func__);
352
353         return 0;
354 }
355
356 static int spdif_resume(struct snd_soc_dai *cpu_dai)
357 {
358         RK_SPDIF_DBG( "spdif:Entered %s\n", __func__);
359
360         return 0;
361 }
362 #else
363 #define spdif_suspend NULL
364 #define spdif_resume NULL
365 #endif
366
367 static struct snd_soc_dai_ops spdif_dai_ops = {
368         .set_sysclk     = spdif_set_syclk,
369         .trigger        = spdif_trigger,
370         .hw_params      = spdif_hw_params,
371 };
372
373 struct snd_soc_dai_driver rockchip_spdif_dai = {
374         .name = "rockchip-spdif",
375         .playback = {
376                 .stream_name = "SPDIF Playback",
377                 .channels_min = 2,
378                 .channels_max = 2,
379                 .rates = (SNDRV_PCM_RATE_32000 |
380                                 SNDRV_PCM_RATE_44100 |
381                                 SNDRV_PCM_RATE_48000 |
382                                 SNDRV_PCM_RATE_96000),
383                 .formats = SNDRV_PCM_FMTBIT_S16_LE|
384                 SNDRV_PCM_FMTBIT_S20_3LE|
385                 SNDRV_PCM_FMTBIT_S24_LE, },
386         .ops = &spdif_dai_ops,
387         .suspend = spdif_suspend,
388         .resume = spdif_resume,
389 };
390
391 static const struct snd_soc_component_driver rockchip_spdif_component = {
392         .name           = "rockchip-spdif",
393 };
394
395 static int spdif_probe(struct platform_device *pdev)
396 {
397         struct resource *mem_res;
398         struct rockchip_spdif_info *spdif;
399         int ret;
400
401         RK_SPDIF_DBG("Entered %s\n", __func__);
402
403         spdif = devm_kzalloc(&pdev->dev, sizeof(struct rockchip_spdif_info), GFP_KERNEL);
404         if (!spdif) {
405                 dev_err(&pdev->dev, "Can't allocate spdif info\n");
406                 return -ENOMEM;
407         }
408
409         spin_lock_init(&spdif->lock);
410
411         mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
412         if (!mem_res) {
413                 printk("spdif:Unable to get register resource.\n");
414                 return -ENXIO;
415         }
416
417         spdif->clk= clk_get(&pdev->dev, "spdif_mclk");
418         if (IS_ERR(spdif->clk)) {
419                 dev_err(&pdev->dev, "Can't retrieve spdif clock\n");
420                 return PTR_ERR(spdif->clk);
421         }
422         clk_set_rate(spdif->clk, 12288000);//clk have some problem
423         clk_set_rate(spdif->clk, 11289600);
424         clk_prepare_enable(spdif->clk);
425
426
427         /* Request S/PDIF Register's memory region */
428         if (!request_mem_region(mem_res->start,
429                                 resource_size(mem_res), "rockchip-spdif")) {
430                 printk("spdif:Unable to request register region\n");
431                 ret = -EBUSY;
432                 goto err_clk_put;
433         }
434
435         spdif->regs = devm_ioremap(&pdev->dev, mem_res->start, resource_size(mem_res));
436         if (!spdif->regs) {
437                 dev_err(&pdev->dev, "ioremap failed\n");
438                 ret = -ENOMEM;
439                 goto err_clk_put;
440         }
441
442         spdif->dma_playback.addr = mem_res->start + DATA_OUTBUF;
443         spdif->dma_playback.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
444         spdif->dma_playback.maxburst = 4;
445
446         //set dev name to driver->name for sound card register
447         dev_set_name(&pdev->dev, "%s", pdev->dev.driver->name);
448
449         ret = snd_soc_register_component(&pdev->dev, &rockchip_spdif_component,
450                 &rockchip_spdif_dai, 1);
451         if (ret) {
452                 dev_err(&pdev->dev, "Could not register DAI: %d\n", ret);
453                 ret = -ENOMEM;
454                 goto err_clk_put;
455         }
456
457         ret = rockchip_pcm_platform_register(&pdev->dev);
458         if (ret) {
459                 dev_err(&pdev->dev, "Could not register PCM: %d\n", ret);
460                 goto err_unregister_component;
461         }
462
463         dev_set_drvdata(&pdev->dev, spdif);
464         writel_relaxed(SPDIF_CHANNEL_SEL_8CH, RK_GRF_VIRT + RK3288_GRF_SOC_CON2);
465
466         RK_SPDIF_DBG("spdif:spdif probe ok!\n");
467
468         return 0;
469
470 err_unregister_component:
471         snd_soc_unregister_component(&pdev->dev);
472 err_clk_put:
473         clk_put(spdif->clk);
474         return ret;
475 }
476
477 static int spdif_remove(struct platform_device *pdev)
478 {
479         RK_SPDIF_DBG("Entered %s\n", __func__);
480         
481         rockchip_pcm_platform_unregister(&pdev->dev);
482         snd_soc_unregister_component(&pdev->dev);
483
484         return 0;
485 }
486
487 #ifdef CONFIG_OF
488 static const struct of_device_id exynos_spdif_match[] = {
489         { .compatible = "rockchip-spdif"},
490         {},
491 };
492 MODULE_DEVICE_TABLE(of, exynos_spdif_match);
493 #endif
494
495 static struct platform_driver rockchip_spdif_driver = {
496         .probe  = spdif_probe,
497         .remove = spdif_remove,
498         .driver = {
499                 .name   = "rockchip-spdif",
500                 .owner  = THIS_MODULE,
501                 .of_match_table = of_match_ptr(exynos_spdif_match),
502         },
503 };
504 module_platform_driver(rockchip_spdif_driver);
505
506 MODULE_AUTHOR("Seungwhan Youn, <sw.youn@rockchip.com>");
507 MODULE_DESCRIPTION("rockchip S/PDIF Controller Driver");
508 MODULE_LICENSE("GPL");
509 MODULE_ALIAS("platform:rockchip-spdif");