1 /*$_FOR_ROCKCHIP_RBOX_$*/
2 /*$_rbox_$_modify_$_huangzhibao for spdif output*/
4 /* sound/soc/rockchip/rk_spdif.c
6 * ALSA SoC Audio Layer - rockchip S/PDIF Controller driver
8 * Copyright (c) 2010 rockchip Electronics Co. Ltd
9 * http://www.rockchip.com/
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.
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>
24 #include <linux/of_gpio.h>
25 #include <linux/clk.h>
27 #include <linux/platform_device.h>
28 #include <linux/pm_runtime.h>
29 #include <linux/regmap.h>
30 #include <linux/slab.h>
32 #include <linux/rockchip/iomap.h>
33 #include <linux/rockchip/grf.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 <linux/spinlock.h>
49 #define RK_SPDIF_DBG(x...) pr_info("rk_spdif:"x)
51 #define RK_SPDIF_DBG(x...) do { } while (0)
63 #define SPDIF_CHNSR00_ADDR 0xC0
64 #define SPDIF_CHNSR01_ADDR 0xC4
65 #define SPDIF_CHNSR02_ADDR 0xC8
66 #define SPDIF_CHNSR03_ADDR 0xCC
67 #define SPDIF_CHNSR04_ADDR 0xD0
68 #define SPDIF_CHNSR05_ADDR 0xD4
69 #define SPDIF_CHNSR06_ADDR 0xD8
70 #define SPDIF_CHNSR07_ADDR 0xDC
71 #define SPDIF_CHNSR08_ADDR 0xE0
72 #define SPDIF_CHNSR09_ADDR 0xE4
73 #define SPDIF_CHNSR10_ADDR 0xE8
74 #define SPDIF_CHNSR11_ADDR 0xEC
76 #define SPDIF_BURST_INFO 0x100
77 #define SPDIF_REPETTION 0x104
79 #define DATA_OUTBUF 0x20
81 #define SPDIF_CHANNEL_SEL_8CH ((0x2<<16)|(0x0<<0))
82 #define SPDIF_CHANNEL_SEL_2CH ((0x2<<16)|(0x2<<0))
84 /* burst_info bit0:6 AC-3:0x01, DTS-I -II -III:11,12,13 */
85 #define burst_info_DATA_TYPE_AC3 0x01
86 #define burst_info_DATA_TYPE_EAC3 0x15
87 #define BURST_INFO_DATA_TYPE_DTS_I 0x0b
89 #define CFGR_MASK 0x0ffffff
90 #define CFGR_VALID_DATA_16bit (00)
91 #define CFGR_VALID_DATA_20bit (01)
92 #define CFGR_VALID_DATA_24bit (10)
93 #define CFGR_VALID_DATA_MASK (11)
95 #define CFGR_HALFWORD_TX_ENABLE (0x1<<2)
96 #define CFGR_HALFWORD_TX_DISABLE (0x0<<2)
97 #define CFGR_HALFWORD_TX_MASK (0x1<<2)
99 #define CFGR_CLK_RATE_MASK (0xFF<<16)
101 #define CFGR_JUSTIFIED_RIGHT (0<<3)
102 #define CFGR_JUSTIFIED_LEFT (1<<3)
103 #define CFGR_JUSTIFIED_MASK (1<<3)
105 /* CSE:channel status enable */
106 /* The bit should be set to 1 when the channel conveys non-linear PCM */
107 #define CFGR_CSE_DISABLE (0<<6)
108 #define CFGR_CSE_ENABLE (1<<6)
109 #define CFGR_CSE_MASK (1<<6)
111 #define CFGR_MCLK_CLR (1<<7)
113 #define CFGR_LINEAR_PCM (0<<8)
114 #define CFGR_NON_LINEAR_PCM (1<<8)
115 #define CFGR_LINEAR_MASK (1<<8)
117 /* support 7.1 amplifier,new */
118 #define CFGR_PRE_CHANGE_ENALBLE (1<<9)
119 #define CFGR_PRE_CHANGE_DISABLE (0<<9)
120 #define CFGR_PRE_CHANGE_MASK (1<<9)
122 #define XFER_TRAN_STOP (0)
123 #define XFER_TRAN_START (1)
124 #define XFER_MASK (1)
126 #define DMACR_TRAN_DMA_DISABLE (0<<5)
127 #define DMACR_TRAN_DMA_ENABLE (1<<5)
128 #define DMACR_TRAN_DMA_CTL_MASK (1<<5)
130 #define DMACR_TRAN_DATA_LEVEL 0x10
131 #define DMACR_TRAN_DATA_LEVEL_MASK 0x1F
132 #define DMACR_TRAN_DMA_MASK 0x3F
134 /* Sample Date Buffer empty interrupt enable, new */
135 #define INTCR_SDBEIE_DISABLE (0<<4)
136 #define INTCR_SDBEIE_ENABLE (1<<4)
137 #define INTCR_SDBEIE_MASK (1<<4)
139 struct rockchip_spdif_info {
140 spinlock_t lock;/*lock parmeter setting.*/
142 unsigned long clk_rate;
145 struct snd_dmaengine_dai_dma_data dma_playback;
148 static inline struct rockchip_spdif_info *to_info(struct snd_soc_dai *cpu_dai)
150 return snd_soc_dai_get_drvdata(cpu_dai);
153 static void spdif_snd_txctrl(struct rockchip_spdif_info *spdif, int on)
155 void __iomem *regs = spdif->regs;
158 RK_SPDIF_DBG("Entered %s\n", __func__);
160 xfer = readl(regs + XFER) & XFER_MASK;
161 opr = readl(regs + DMACR) & DMACR_TRAN_DMA_MASK
162 & (~DMACR_TRAN_DMA_CTL_MASK);
165 xfer |= XFER_TRAN_START;
166 opr |= DMACR_TRAN_DMA_ENABLE;
167 writel(xfer, regs + XFER);
168 writel(opr, regs + DMACR);
169 RK_SPDIF_DBG("on xfer=0x%x,opr=0x%x\n", readl(
170 regs + XFER), readl(regs + DMACR));
172 xfer &= ~XFER_TRAN_START;
173 opr &= ~DMACR_TRAN_DMA_ENABLE;
174 writel(xfer, regs + XFER);
175 writel(opr, regs + DMACR);
176 writel(1<<7, regs + CFGR);
177 RK_SPDIF_DBG("off xfer=0x%x,opr=0x%x\n", readl(
178 regs + XFER), readl(regs + DMACR));
182 static int spdif_set_syclk(struct snd_soc_dai *
183 cpu_dai, int clk_id, unsigned int freq, int dir)
185 struct rockchip_spdif_info *spdif = to_info(cpu_dai);
187 RK_SPDIF_DBG("Entered %s sysclk=%d\n", __func__, freq);
189 spdif->clk_rate = freq;
190 clk_set_rate(spdif->clk, freq);
195 static int spdif_trigger(struct snd_pcm_substream *
196 substream, int cmd, struct snd_soc_dai *dai)
198 struct snd_soc_pcm_runtime *rtd = substream->private_data;
199 struct rockchip_spdif_info *spdif = to_info(rtd->cpu_dai);
202 RK_SPDIF_DBG("Entered %s\n", __func__);
205 case SNDRV_PCM_TRIGGER_START:
206 case SNDRV_PCM_TRIGGER_RESUME:
207 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
208 spin_lock_irqsave(&spdif->lock, flags);
209 spdif_snd_txctrl(spdif, 1);
210 spin_unlock_irqrestore(&spdif->lock, flags);
212 case SNDRV_PCM_TRIGGER_STOP:
213 case SNDRV_PCM_TRIGGER_SUSPEND:
214 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
215 spin_lock_irqsave(&spdif->lock, flags);
216 spdif_snd_txctrl(spdif, 0);
217 spin_unlock_irqrestore(&spdif->lock, flags);
226 static int spdif_hw_params(struct snd_pcm_substream *
227 substream, struct snd_pcm_hw_params *params,
228 struct snd_soc_dai *dai)
230 struct rockchip_spdif_info *spdif = to_info(dai);
231 void __iomem *regs = spdif->regs;
233 int cfgr, dmac, intcr, chnsr_byte[5] = {0};
234 int data_type, err_flag, data_len, data_info;
235 int bs_num, repetition, burst_info;
237 RK_SPDIF_DBG("Entered %s\n", __func__);
239 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
240 dai->playback_dma_data = &spdif->dma_playback;
242 pr_err("spdif:Capture is not supported\n");
246 spin_lock_irqsave(&spdif->lock, flags);
248 cfgr = readl(regs + CFGR) & CFGR_VALID_DATA_MASK;
250 cfgr &= ~CFGR_VALID_DATA_MASK;
251 switch (params_format(params)) {
252 case SNDRV_PCM_FORMAT_S16_LE:
253 cfgr |= CFGR_VALID_DATA_16bit;
255 case SNDRV_PCM_FORMAT_S20_3LE:
256 cfgr |= CFGR_VALID_DATA_20bit;
258 case SNDRV_PCM_FORMAT_S24_LE:
259 cfgr |= CFGR_VALID_DATA_24bit;
265 cfgr &= ~CFGR_HALFWORD_TX_MASK;
266 cfgr |= CFGR_HALFWORD_TX_ENABLE;
268 /* set most MCLK:192kHz */
269 cfgr &= ~CFGR_CLK_RATE_MASK;
272 cfgr &= ~CFGR_JUSTIFIED_MASK;
273 cfgr |= CFGR_JUSTIFIED_RIGHT;
275 cfgr &= ~CFGR_CSE_MASK;
276 cfgr |= CFGR_CSE_DISABLE;
278 cfgr &= ~CFGR_LINEAR_MASK;
279 cfgr |= CFGR_LINEAR_PCM;
282 if (!snd_pcm_format_linear(params_format(params)))
283 cfgr |= CFGR_NON_LINEAR_PCM;
285 cfgr &= ~CFGR_PRE_CHANGE_MASK;
286 cfgr |= CFGR_PRE_CHANGE_ENALBLE;
288 writel(cfgr, regs + CFGR);
290 intcr = readl(regs + INTCR) & INTCR_SDBEIE_MASK;
291 intcr |= INTCR_SDBEIE_ENABLE;
292 writel(intcr, regs + INTCR);
294 dmac = readl(regs + DMACR) & DMACR_TRAN_DMA_MASK &
295 (~DMACR_TRAN_DATA_LEVEL_MASK);
297 writel(dmac, regs + DMACR);
302 * 1 Main data field represents linear PCM samples.
303 * 0 Main data field used for purposes other purposes.
305 chnsr_byte[0] = (0x0) | (0x0 << 1) |
306 (0x0 << 2) | (0x0 << 3) |
308 chnsr_byte[1] = (0x0);
309 chnsr_byte[2] = (0x0) | (0x0 << 4) | (0x0 << 6);
310 chnsr_byte[3] = (0x00) | (0x00);
311 chnsr_byte[4] = (0x0 << 4) | (0x01 << 1 | 0x0);
313 /* set stream type */
314 if (!snd_pcm_format_linear(params_format(params))) {
315 chnsr_byte[0] |= (0x1<<1);
316 chnsr_byte[4] = (0x0<<4)|(0x00<<1|0x0);
318 writel((chnsr_byte[4] << 16)
320 regs + SPDIF_CHNSR02_ADDR);
321 writel((chnsr_byte[3] << 24) | (chnsr_byte[2] << 16) |
322 (chnsr_byte[3] << 8) | (chnsr_byte[2]),
323 regs + SPDIF_CHNSR01_ADDR);
324 writel((chnsr_byte[1] << 24) | (chnsr_byte[0] << 16) |
325 (chnsr_byte[1] << 8) | (chnsr_byte[0]),
326 regs + SPDIF_CHNSR00_ADDR);
328 /* set non-linear params */
329 if (!snd_pcm_format_linear(params_format(params))) {
330 switch (params_format(params)) {
331 case SNDRV_NON_LINEAR_PCM_FORMAT_AC3:
332 /* bit0:6 AC-3:0x01, DTS-I -II -III:11,12,13 */
333 data_type = burst_info_DATA_TYPE_AC3;
335 * repetition:AC-3:1536
336 * DTS-I -II -III:512,1024,2048 EAC3:6144
340 case SNDRV_NON_LINEAR_PCM_FORMAT_DTS_I:
341 data_type = BURST_INFO_DATA_TYPE_DTS_I;
344 case SNDRV_NON_LINEAR_PCM_FORMAT_EAC3:
345 data_type = burst_info_DATA_TYPE_EAC3;
352 data_len = params_period_size(params) * 2 * 16;
355 burst_info = (data_len << 16) | (bs_num << 13) |
356 (data_info << 8) | (err_flag << 7) | data_type;
357 writel(burst_info, regs + SPDIF_BURST_INFO);
358 writel(repetition, regs + SPDIF_REPETTION);
360 spin_unlock_irqrestore(&spdif->lock, flags);
364 spin_unlock_irqrestore(&spdif->lock, flags);
369 static int spdif_suspend(struct snd_soc_dai *cpu_dai)
371 RK_SPDIF_DBG("spdif:Entered %s\n", __func__);
376 static int spdif_resume(struct snd_soc_dai *cpu_dai)
378 RK_SPDIF_DBG("spdif:Entered %s\n", __func__);
383 #define spdif_suspend NULL
384 #define spdif_resume NULL
387 static struct snd_soc_dai_ops spdif_dai_ops = {
388 .set_sysclk = spdif_set_syclk,
389 .trigger = spdif_trigger,
390 .hw_params = spdif_hw_params,
393 struct snd_soc_dai_driver rockchip_spdif_dai = {
394 .name = "rockchip-spdif",
396 .stream_name = "SPDIF Playback",
399 .rates = (SNDRV_PCM_RATE_32000 |
400 SNDRV_PCM_RATE_44100 |
401 SNDRV_PCM_RATE_48000 |
402 SNDRV_PCM_RATE_96000),
403 .formats = SNDRV_PCM_FMTBIT_S16_LE|
404 SNDRV_PCM_FMTBIT_S20_3LE|
405 SNDRV_PCM_FMTBIT_S24_LE, },
406 .ops = &spdif_dai_ops,
407 .suspend = spdif_suspend,
408 .resume = spdif_resume,
411 static const struct snd_soc_component_driver rockchip_spdif_component = {
412 .name = "rockchip-spdif",
415 static int spdif_probe(struct platform_device *pdev)
417 /*struct device_node *spdif_np = pdev->dev.of_node;*/
418 struct resource *memregion;
419 struct resource *mem_res;
420 struct rockchip_spdif_info *spdif;
423 RK_SPDIF_DBG("Entered %s\n", __func__);
425 spdif = devm_kzalloc(&pdev->dev, sizeof(
426 struct rockchip_spdif_info), GFP_KERNEL);
428 dev_err(&pdev->dev, "Can't allocate spdif info\n");
431 platform_set_drvdata(pdev, spdif);
433 spin_lock_init(&spdif->lock);
435 /* get spdif register regoin. */
436 mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
438 dev_err(&pdev->dev, "No memory resource\n");
442 memregion = devm_request_mem_region(&pdev->
444 resource_size(mem_res), "rockchip-spdif");
446 dev_err(&pdev->dev, "Memory region already claimed\n");
450 spdif->regs = devm_ioremap(&pdev->dev, memregion->
451 start, resource_size(memregion));
453 dev_err(&pdev->dev, "ioremap failed\n");
458 /* get spdif clock and init. */
459 spdif->hclk = devm_clk_get(&pdev->dev, "spdif_hclk");
460 if (IS_ERR(spdif->hclk)) {
461 dev_err(&pdev->dev, "Can't retrieve spdif hclock\n");
464 clk_prepare_enable(spdif->hclk);
466 /* get spdif clock and init. */
467 spdif->clk = devm_clk_get(&pdev->dev, "spdif_mclk");
468 if (IS_ERR(spdif->clk)) {
469 dev_err(&pdev->dev, "Can't retrieve spdif clock\n");
473 clk_set_rate(spdif->clk, 12288000);
474 clk_set_rate(spdif->clk, 11289600);
475 clk_prepare_enable(spdif->clk);
477 spdif->dma_playback.addr = mem_res->start + DATA_OUTBUF;
478 spdif->dma_playback.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
479 spdif->dma_playback.maxburst = 4;
481 /* set dev name to driver->name for sound card register */
482 dev_set_name(&pdev->dev, "%s", pdev->dev.driver->name);
484 ret = snd_soc_register_component(&pdev->
485 dev, &rockchip_spdif_component, &rockchip_spdif_dai, 1);
487 dev_err(&pdev->dev, "Could not register DAI: %d\n", ret);
492 ret = rockchip_pcm_platform_register(&pdev->dev);
494 dev_err(&pdev->dev, "Could not register PCM: %d\n", ret);
498 RK_SPDIF_DBG("spdif:spdif probe ok!\n");
503 platform_set_drvdata(pdev, NULL);
508 static int spdif_remove(struct platform_device *pdev)
510 RK_SPDIF_DBG("Entered %s\n", __func__);
512 rockchip_pcm_platform_unregister(&pdev->dev);
513 snd_soc_unregister_component(&pdev->dev);
519 static const struct of_device_id exynos_spdif_match[] = {
520 { .compatible = "rockchip-spdif"},
523 MODULE_DEVICE_TABLE(of, exynos_spdif_match);
526 static struct platform_driver rockchip_spdif_driver = {
527 .probe = spdif_probe,
528 .remove = spdif_remove,
530 .name = "rockchip-spdif",
531 .owner = THIS_MODULE,
532 .of_match_table = of_match_ptr(exynos_spdif_match),
535 module_platform_driver(rockchip_spdif_driver);
537 MODULE_AUTHOR("Seungwhan Youn, <sw.youn@rockchip.com>");
538 MODULE_DESCRIPTION("rockchip S/PDIF Controller Driver");
539 MODULE_LICENSE("GPL");
540 MODULE_ALIAS("platform:rockchip-spdif");