Change path of audio platform device from rk to rockchip
[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/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
24 #include <asm/dma.h>
25 #include <sound/core.h>
26 #include <sound/pcm.h>
27 #include <sound/pcm_params.h>
28 #include <sound/initval.h>
29 #include <sound/soc.h>
30 #include <asm/io.h>
31
32 #include <mach/board.h>
33 #include <mach/hardware.h>
34 #include <mach/io.h>
35 #include <mach/gpio.h>
36 #include <mach/iomux.h>
37
38 #if defined (CONFIG_ARCH_RK29)
39 #include <mach/rk29-dma-pl330.h>
40 #endif
41
42 #if defined (CONFIG_ARCH_RK30)
43 #include <mach/dma-pl330.h>
44 #endif
45
46 #if defined (CONFIG_ARCH_RK3188)
47 #include <mach/dma-pl330.h>
48 #endif
49
50 #include "rk_pcm.h"
51
52 #if 0
53 #define RK_SPDIF_DBG(x...) printk(KERN_INFO "rk_spdif:"x)
54 #else
55 #define RK_SPDIF_DBG(x...) do { } while (0)
56 #endif
57
58
59 /* Registers */
60 #define CFGR                            0x00
61 #define SDBLR                           0x04
62 #define DMACR                           0x08
63 #define INTCR                           0x0C
64 #define INTSR                     0x10
65 #define XFER                            0x18
66 #define SMPDR                           0x20
67
68 #define DATA_OUTBUF                     0x20   
69  
70 #define CFGR_MASK                       0x0ffffff
71 #define CFGR_VALID_DATA_16bit       (00)
72 #define CFGR_VALID_DATA_20bit       (01)
73 #define CFGR_VALID_DATA_24bit       (10)
74 #define CFGR_VALID_DATA_MASK        (11)
75
76 #define CFGR_HALFWORD_TX_ENABLE     (0x1 << 2)
77 #define CFGR_HALFWORD_TX_DISABLE    (0x0 << 2)
78 #define CFGR_HALFWORD_TX_MASK       (0x1 << 2)  
79
80 #define CFGR_CLK_RATE_MASK          (0xFF<<16)                 
81
82 #define CFGR_JUSTIFIED_RIGHT        (0<<3)
83 #define CFGR_JUSTIFIED_LEFT         (1<<3)
84 #define CFGR_JUSTIFIED_MASK         (1<<3)
85
86 #define XFER_TRAN_STOP        (0)
87 #define XFER_TRAN_START       (1)
88 #define XFER_MASK             (1)
89
90 #define DMACR_TRAN_DMA_DISABLE   (0<<5)
91 #define DMACR_TRAN_DMA_ENABLE   (1<<5)
92 #define DMACR_TRAN_DMA_CTL_MASK   (1<<5)
93
94 #define DMACR_TRAN_DATA_LEVEL       0x10
95 #define DMACR_TRAN_DATA_LEVEL_MASK  0x1F
96
97 #define DMACR_TRAN_DMA_MASK   (0x3F)
98
99
100  
101 struct rockchip_spdif_info {
102         spinlock_t      lock;
103         struct device   *dev;
104         void __iomem    *regs;
105         unsigned long   clk_rate;
106         struct clk      *hclk;
107         struct clk      *clk;
108         u32             saved_clkcon;
109         u32             saved_con;
110         u32             saved_cstas;
111         struct rockchip_pcm_dma_params  *dma_playback;
112 };
113
114 static struct rk29_dma_client spdif_dma_client_out = {
115         .name           = "SPDIF Stereo out"
116 };
117
118 static struct rockchip_pcm_dma_params spdif_stereo_out;
119
120 static struct rockchip_spdif_info spdif_info;
121
122 static inline struct rockchip_spdif_info *to_info(struct snd_soc_dai *cpu_dai)
123 {
124         return snd_soc_dai_get_drvdata(cpu_dai);
125 }
126
127 static void spdif_snd_txctrl(struct rockchip_spdif_info *spdif, int on)
128 {
129         void __iomem *regs = spdif->regs;
130         u32 opr,xfer;
131
132         RK_SPDIF_DBG( "Entered %s\n", __func__);
133
134         xfer = readl(regs + XFER) & XFER_MASK;
135         opr  = readl(regs + DMACR) & DMACR_TRAN_DMA_MASK & (~DMACR_TRAN_DMA_CTL_MASK);
136         
137         if (on){
138                 xfer |= XFER_TRAN_START;
139                 opr |= DMACR_TRAN_DMA_ENABLE;
140                 writel(xfer, regs + XFER);
141                 writel(opr|0x10, regs + DMACR);
142                 RK_SPDIF_DBG("on xfer=0x%x,opr=0x%x\n",readl(regs + XFER),readl(regs + DMACR));
143     }else{
144             xfer &= ~XFER_TRAN_START;
145             opr  &= ~DMACR_TRAN_DMA_ENABLE; 
146                 writel(xfer, regs + XFER);
147                 writel(opr|0x10, regs + DMACR);
148     }
149 }
150
151 static int spdif_set_syclk(struct snd_soc_dai *cpu_dai,
152                                 int clk_id, unsigned int freq, int dir)
153 {
154         struct rockchip_spdif_info *spdif = to_info(cpu_dai);
155         u32 clkcon;
156
157         RK_SPDIF_DBG("Entered %s\n", __func__);
158
159         spdif->clk_rate = freq;
160
161         return 0;
162 }
163
164 static int spdif_trigger(struct snd_pcm_substream *substream, int cmd,
165                                 struct snd_soc_dai *dai)
166 {
167         struct snd_soc_pcm_runtime *rtd = substream->private_data;
168         struct rockchip_spdif_info *spdif = to_info(rtd->cpu_dai);
169         unsigned long flags;
170
171         RK_SPDIF_DBG( "Entered %s\n", __func__);
172
173         switch (cmd) {
174         case SNDRV_PCM_TRIGGER_START:
175         case SNDRV_PCM_TRIGGER_RESUME:
176         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
177                 spin_lock_irqsave(&spdif->lock, flags);
178                 spdif_snd_txctrl(spdif, 1);
179                 spin_unlock_irqrestore(&spdif->lock, flags);
180                 break;
181         case SNDRV_PCM_TRIGGER_STOP:
182         case SNDRV_PCM_TRIGGER_SUSPEND:
183         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
184                 spin_lock_irqsave(&spdif->lock, flags);
185                 spdif_snd_txctrl(spdif, 0);
186                 spin_unlock_irqrestore(&spdif->lock, flags);
187                 break;
188         default:
189                 return -EINVAL;
190         }
191
192         return 0;
193 }
194
195
196 static int spdif_hw_params(struct snd_pcm_substream *substream,
197                                 struct snd_pcm_hw_params *params,
198                                 struct snd_soc_dai *socdai)
199 {
200         struct snd_soc_pcm_runtime *rtd = substream->private_data;
201         struct rockchip_spdif_info *spdif = to_info(rtd->cpu_dai);
202         void __iomem *regs = spdif->regs;
203         struct rockchip_pcm_dma_params *dma_data;
204         unsigned long flags;
205         int i, cfgr, dmac;
206
207         RK_SPDIF_DBG("Entered %s\n", __func__);
208
209         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
210                 dma_data = spdif->dma_playback;
211         else {
212                 printk("spdif:Capture is not supported\n");
213                 return -EINVAL;
214         }
215
216         snd_soc_dai_set_dma_data(rtd->cpu_dai, substream, dma_data);
217         spin_lock_irqsave(&spdif->lock, flags);
218         
219         cfgr = readl(regs + CFGR) & CFGR_VALID_DATA_MASK;
220         
221     cfgr &= ~CFGR_VALID_DATA_MASK;
222         switch (params_format(params)) {
223         case SNDRV_PCM_FORMAT_S16_LE:
224                 cfgr |= CFGR_VALID_DATA_16bit;
225                 break;
226         case SNDRV_PCM_FMTBIT_S20_3LE :
227                 cfgr |= CFGR_VALID_DATA_20bit;
228                 break;
229         case SNDRV_PCM_FORMAT_S24_LE:
230                 cfgr |= CFGR_VALID_DATA_24bit;
231                 break;                  
232         default:
233                 goto err;
234         }
235         
236         cfgr &= ~CFGR_HALFWORD_TX_MASK;
237         cfgr |= CFGR_HALFWORD_TX_ENABLE;
238         
239         cfgr &= ~CFGR_CLK_RATE_MASK;
240         cfgr |= (1<<16);
241         
242         cfgr &= ~CFGR_JUSTIFIED_MASK;
243         cfgr |= CFGR_JUSTIFIED_RIGHT;
244         
245         writel(cfgr, regs + CFGR);
246   
247     dmac = readl(regs + DMACR) & DMACR_TRAN_DMA_MASK & (~DMACR_TRAN_DATA_LEVEL_MASK);
248     dmac |= 0x10;
249     writel(dmac, regs + DMACR);
250   
251         spin_unlock_irqrestore(&spdif->lock, flags);
252
253         return 0;
254 err:
255         spin_unlock_irqrestore(&spdif->lock, flags);
256         return -EINVAL;
257 }
258
259 static void spdif_shutdown(struct snd_pcm_substream *substream,
260                                 struct snd_soc_dai *dai)
261 {
262         struct snd_soc_pcm_runtime *rtd = substream->private_data;
263         struct rockchip_spdif_info *spdif = to_info(rtd->cpu_dai);
264         void __iomem *regs = spdif->regs;
265         u32 con, clkcon;
266
267         RK_SPDIF_DBG( "spdif:Entered %s\n", __func__);
268
269 }
270
271 #ifdef CONFIG_PM
272 static int spdif_suspend(struct snd_soc_dai *cpu_dai)
273 {
274         struct rockchip_spdif_info *spdif = to_info(cpu_dai);
275         u32 con = spdif->saved_con;
276
277         RK_SPDIF_DBG( "spdif:Entered %s\n", __func__);
278
279         return 0;
280 }
281
282 static int spdif_resume(struct snd_soc_dai *cpu_dai)
283 {
284         struct rockchip_spdif_info *spdif = to_info(cpu_dai);
285
286         RK_SPDIF_DBG( "spdif:Entered %s\n", __func__);
287
288         return 0;
289 }
290 #else
291 #define spdif_suspend NULL
292 #define spdif_resume NULL
293 #endif
294
295 static struct snd_soc_dai_ops spdif_dai_ops = {
296         .set_sysclk     = spdif_set_syclk,
297         .trigger        = spdif_trigger,
298         .hw_params      = spdif_hw_params,
299         .shutdown       = spdif_shutdown,
300 };
301
302 struct snd_soc_dai_driver rockchip_spdif_dai = {
303         .name = "rk-spdif",
304         .playback = {
305                 .stream_name = "SPDIF Playback",
306                 .channels_min = 2,
307                 .channels_max = 2,
308                 .rates = (SNDRV_PCM_RATE_32000 |
309                                 SNDRV_PCM_RATE_44100 |
310                                 SNDRV_PCM_RATE_48000 |
311                                 SNDRV_PCM_RATE_96000),
312                 .formats = SNDRV_PCM_FMTBIT_S16_LE|
313                 SNDRV_PCM_FMTBIT_S20_3LE|
314                 SNDRV_PCM_FMTBIT_S24_LE, },
315         .ops = &spdif_dai_ops,
316         .suspend = spdif_suspend,
317         .resume = spdif_resume,
318 };
319
320
321 static __devinit int spdif_probe(struct platform_device *pdev)
322 {
323         struct s3c_audio_pdata *spdif_pdata;
324         struct resource *mem_res, *dma_res;
325         struct rockchip_spdif_info *spdif;
326         int ret;
327   
328         spdif_pdata = pdev->dev.platform_data;
329
330         RK_SPDIF_DBG("Entered %s\n", __func__);
331         
332 #if defined  (CONFIG_ARCH_RK29)
333     rk29_mux_api_set(GPIO4A7_SPDIFTX_NAME, GPIO4L_SPDIF_TX);
334 #endif
335
336 #if defined (CONFIG_ARCH_RK30)    
337     #if defined (CONFIG_ARCH_RK3066B)
338     iomux_set(SPDIF_TX);
339     #else
340     rk30_mux_api_set(GPIO1B2_SPDIFTX_NAME, GPIO1B_SPDIF_TX);
341     #endif
342 #elif defined (CONFIG_ARCH_RK3188)
343     iomux_set(SPDIF_TX);
344 #endif
345
346         dma_res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "spdif_dma");
347         if (!dma_res) {
348                 printk("spdif:Unable to get dma resource.\n");
349                 return -ENXIO;
350         }
351
352         mem_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "spdif_base");
353         if (!mem_res) {
354                 printk("spdif:Unable to get register resource.\n");
355                 return -ENXIO;
356         }
357
358         spdif = &spdif_info;
359         spdif->dev = &pdev->dev;
360
361         spin_lock_init(&spdif->lock);
362         
363         spdif->clk = clk_get(&pdev->dev, "spdif");
364         if (IS_ERR(spdif->clk)) {
365                 printk("spdif:failed to get internal source clock\n");
366                 ret = -ENOENT;
367                 goto err1;
368         }
369         clk_enable(spdif->clk);
370         clk_set_rate(spdif->clk, 11289600);
371                 
372         spdif->hclk = clk_get(&pdev->dev, "hclk_spdif");
373         if (IS_ERR(spdif->hclk)) {
374                 printk("spdif:failed to get spdif hclk\n");
375                 ret = -ENOENT;
376                 goto err0;
377         }
378         clk_enable(spdif->hclk);
379         clk_set_rate(spdif->hclk, 11289600);
380
381         /* Request S/PDIF Register's memory region */
382         if (!request_mem_region(mem_res->start,
383                                 resource_size(mem_res), "rockchip-spdif")) {
384                 printk("spdif:Unable to request register region\n");
385                 ret = -EBUSY;
386                 goto err2;
387         }
388
389         spdif->regs = ioremap(mem_res->start, mem_res->end - mem_res->start + 1);
390         if (spdif->regs == NULL) {
391                 printk("spdif:Cannot ioremap registers\n");
392                 ret = -ENXIO;
393                 goto err3;
394         }
395
396         dev_set_drvdata(&pdev->dev, spdif);
397         
398         ret = snd_soc_register_dai(&pdev->dev, &rockchip_spdif_dai);
399         if (ret != 0) {
400                 printk("spdif:fail to register dai\n");
401                 goto err4;
402         }
403
404         spdif_stereo_out.dma_size = 4;
405         spdif_stereo_out.client = &spdif_dma_client_out;
406         spdif_stereo_out.dma_addr = mem_res->start + DATA_OUTBUF;
407         spdif_stereo_out.channel = dma_res->start;
408
409         spdif->dma_playback = &spdif_stereo_out;
410 #ifdef CONFIG_SND_I2S_DMA_EVENT_STATIC
411         WARN_ON(rk29_dma_request(spdif_stereo_out.channel, spdif_stereo_out.client, NULL));
412 #endif
413
414         RK_SPDIF_DBG("spdif:spdif probe ok!\n");
415         
416         return 0;
417
418 err4:
419         iounmap(spdif->regs);
420 err3:
421         release_mem_region(mem_res->start, resource_size(mem_res));
422 err2:
423         clk_disable(spdif->clk);
424         clk_put(spdif->clk);
425 err1:
426         clk_disable(spdif->hclk);
427         clk_put(spdif->hclk);   
428 err0:
429         return ret;
430 }
431
432 static __devexit int spdif_remove(struct platform_device *pdev)
433 {
434         struct rockchip_spdif_info *spdif = &spdif_info;
435         struct resource *mem_res;
436         
437         RK_SPDIF_DBG("Entered %s\n", __func__);
438         
439         snd_soc_unregister_dai(&pdev->dev);
440
441         iounmap(spdif->regs);
442
443         mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
444         if (mem_res)
445                 release_mem_region(mem_res->start, resource_size(mem_res));
446
447         clk_disable(spdif->clk);
448         clk_put(spdif->clk);
449         clk_disable(spdif->hclk);
450         clk_put(spdif->hclk);
451
452         return 0;
453 }
454
455
456 static struct platform_driver rockchip_spdif_driver = {
457         .probe  = spdif_probe,
458         .remove = spdif_remove,
459         .driver = {
460                 .name   = "rk-spdif",
461                 .owner  = THIS_MODULE,
462         },
463 };
464
465
466 static int __init spdif_init(void)
467 {
468         RK_SPDIF_DBG("Entered %s\n", __func__);
469         return platform_driver_register(&rockchip_spdif_driver);
470 }
471 module_init(spdif_init);
472
473 static void __exit spdif_exit(void)
474 {
475         RK_SPDIF_DBG("Entered %s\n", __func__);
476         platform_driver_unregister(&rockchip_spdif_driver);
477 }
478 module_exit(spdif_exit);
479
480 MODULE_AUTHOR("Seungwhan Youn, <sw.youn@rockchip.com>");
481 MODULE_DESCRIPTION("rockchip S/PDIF Controller Driver");
482 MODULE_LICENSE("GPL");
483 MODULE_ALIAS("platform:rockchip-spdif");