2 * Rockchip S/PDIF ALSA SoC Digital Audio Interface(DAI) driver
4 * Copyright (C) 2015 Fuzhou Rockchip Electronics Co., Ltd
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.
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.
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>
25 #include <linux/of_gpio.h>
26 #include <linux/clk.h>
28 #include <linux/platform_device.h>
29 #include <linux/pm_runtime.h>
30 #include <linux/regmap.h>
31 #include <linux/slab.h>
33 #include <linux/rockchip/iomap.h>
34 #include <linux/rockchip/grf.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>
47 * channel status register
48 * 192 frame channel status bits: include 384 subframe bits
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
64 * according to iec958, we only care about
65 * the first meaningful 5 bytes(40 bits)
67 #define CHNSTA_BYTES (5)
68 #define BIT_1_LPCM (0X0<<1)
69 #define BIT_1_NLPCM (0x1<<1)
71 /* sample word length bit 32~35 */
72 #define CHNS_SAMPLE_WORD_LEN_16 (0x2)
73 #define CHNS_SAMPLE_WORD_LEN_24 (0xb)
75 /* sample frequency bit 24~27 */
76 #define CHNS_SAMPLE_FREQ_22P05K (0X4)
77 #define CHNS_SAMPLE_FREQ_44P1K (0X0)
78 #define CHNS_SAMPLE_FREQ_88P2K (0X8)
79 #define CHNS_SAMPLE_FREQ_176P4K (0Xc)
80 #define CHNS_SAMPLE_FREQ_24K (0X6)
81 #define CHNS_SAMPLE_FREQ_48K (0X2)
82 #define CHNS_SAMPLE_FREQ_96K (0Xa)
83 #define CHNS_SAMPLE_FREQ_192K (0Xe)
84 #define CHNS_SAMPLE_FREQ_32K (0X3)
85 #define CHNS_SAMPLE_FREQ_768K (0X9)
96 /* transfer configuration register */
97 #define CFGR_VALID_DATA_16bit (0x0 << 0)
98 #define CFGR_VALID_DATA_20bit (0x1 << 0)
99 #define CFGR_VALID_DATA_24bit (0x2 << 0)
100 #define CFGR_VALID_DATA_MASK (0x3 << 0)
101 #define CFGR_HALFWORD_TX_ENABLE (0x1 << 2)
102 #define CFGR_HALFWORD_TX_DISABLE (0x0 << 2)
103 #define CFGR_HALFWORD_TX_MASK (0x1 << 2)
104 #define CFGR_JUSTIFIED_RIGHT (0x0 << 3)
105 #define CFGR_JUSTIFIED_LEFT (0x1 << 3)
106 #define CFGR_JUSTIFIED_MASK (0x1 << 3)
107 #define CFGR_CSE_DISABLE (0x0 << 6)
108 #define CFGR_CSE_ENABLE (0x1 << 6)
109 #define CFGR_CSE_MASK (0x1 << 6)
110 #define CFGR_MCLK_CLR (0x1 << 7)
111 #define CFGR_LINEAR_PCM (0x0 << 8)
112 #define CFGR_NON_LINEAR_PCM (0x1 << 8)
113 #define CFGR_LINEAR_MASK (0x1 << 8)
114 #define CFGR_PRE_CHANGE_ENALBLE (0x1 << 9)
115 #define CFGR_PRE_CHANGE_DISABLE (0x0 << 9)
116 #define CFGR_PRE_CHANGE_MASK (0x1 << 9)
117 #define CFGR_CLK_RATE_MASK (0xFF << 16)
119 /* transfer start register */
120 #define XFER_TRAN_STOP (0x0 << 0)
121 #define XFER_TRAN_START (0x1 << 0)
122 #define XFER_MASK (0x1 << 0)
124 /* dma control register */
125 #define DMACR_TRAN_DMA_DISABLE (0x0 << 5)
126 #define DMACR_TRAN_DMA_ENABLE (0x1 << 5)
127 #define DMACR_TRAN_DMA_CTL_MASK (0x1 << 5)
128 #define DMACR_TRAN_DATA_LEVEL (0x10)
129 #define DMACR_TRAN_DATA_LEVEL_MASK (0x1F)
130 #define DMACR_TRAN_DMA_MASK (0x3F)
131 #define DMA_DATA_LEVEL_16 (0x10)
133 /* interrupt control register */
134 #define INTCR_SDBEIE_DISABLE (0x0 << 4)
135 #define INTCR_SDBEIE_ENABLE (0x1 << 4)
136 #define INTCR_SDBEIE_MASK (0x1 << 4)
138 /* size * width: 16*4 = 64 bytes */
139 #define SPDIF_DMA_BURST_SIZE (16)
141 struct rockchip_spdif_info {
142 spinlock_t lock;/*lock parmeter setting.*/
144 unsigned long clk_rate;
148 struct snd_dmaengine_dai_dma_data dma_playback;
153 static inline struct rockchip_spdif_info *to_info(struct snd_soc_dai *cpu_dai)
155 return snd_soc_dai_get_drvdata(cpu_dai);
158 static void spdif_snd_txctrl(struct rockchip_spdif_info *spdif, int on)
160 void __iomem *regs = spdif->regs;
163 xfer = readl(regs + XFER) & (~XFER_MASK);
164 dmacr = readl(regs + DMACR) & (~DMACR_TRAN_DMA_CTL_MASK);
167 xfer |= XFER_TRAN_START;
168 dmacr |= DMACR_TRAN_DMA_ENABLE;
169 dmacr |= spdif->dmac;
170 writel(spdif->cfgr, regs + CFGR);
171 writel(dmacr, regs + DMACR);
172 writel(xfer, regs + XFER);
174 xfer &= XFER_TRAN_STOP;
175 dmacr &= DMACR_TRAN_DMA_DISABLE;
176 writel(xfer, regs + XFER);
177 writel(dmacr, regs + DMACR);
178 writel(CFGR_MCLK_CLR, regs + CFGR);
181 dev_dbg(spdif->dev, "on: %d, xfer = 0x%x, dmacr = 0x%x\n",
182 on, readl(regs + XFER), readl(regs + DMACR));
185 static int spdif_set_syclk(struct snd_soc_dai *cpu_dai, int clk_id,
186 unsigned int freq, int dir)
188 struct rockchip_spdif_info *spdif = to_info(cpu_dai);
190 dev_dbg(spdif->dev, "%s: sysclk = %d\n", __func__, freq);
192 spdif->clk_rate = freq;
193 clk_set_rate(spdif->clk, freq);
198 static int spdif_trigger(struct snd_pcm_substream *substream, int cmd,
199 struct snd_soc_dai *dai)
201 struct snd_soc_pcm_runtime *rtd = substream->private_data;
202 struct rockchip_spdif_info *spdif = to_info(rtd->cpu_dai);
205 dev_dbg(spdif->dev, "%s: cmd: %d\n", __func__, cmd);
208 case SNDRV_PCM_TRIGGER_START:
209 case SNDRV_PCM_TRIGGER_RESUME:
210 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
211 spin_lock_irqsave(&spdif->lock, flags);
212 spdif_snd_txctrl(spdif, 1);
213 spin_unlock_irqrestore(&spdif->lock, flags);
215 case SNDRV_PCM_TRIGGER_STOP:
216 case SNDRV_PCM_TRIGGER_SUSPEND:
217 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
218 spin_lock_irqsave(&spdif->lock, flags);
219 spdif_snd_txctrl(spdif, 0);
220 spin_unlock_irqrestore(&spdif->lock, flags);
229 static int spdif_hw_params(struct snd_pcm_substream *substream,
230 struct snd_pcm_hw_params *params,
231 struct snd_soc_dai *dai)
233 struct rockchip_spdif_info *spdif = to_info(dai);
234 void __iomem *regs = spdif->regs;
237 u32 cfgr, dmac, intcr, chnregval;
238 char chnsta[CHNSTA_BYTES];
240 dev_dbg(spdif->dev, "%s\n", __func__);
242 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
243 dai->playback_dma_data = &spdif->dma_playback;
245 dev_err(spdif->dev, "capture is not supported\n");
249 spin_lock_irqsave(&spdif->lock, flags);
251 cfgr = readl(regs + CFGR);
253 cfgr &= ~CFGR_VALID_DATA_MASK;
254 switch (params_format(params)) {
255 case SNDRV_PCM_FORMAT_S16_LE:
256 cfgr |= CFGR_VALID_DATA_16bit;
258 case SNDRV_PCM_FORMAT_S20_3LE:
259 cfgr |= CFGR_VALID_DATA_20bit;
261 case SNDRV_PCM_FORMAT_S24_LE:
262 cfgr |= CFGR_VALID_DATA_24bit;
268 cfgr &= ~CFGR_HALFWORD_TX_MASK;
269 cfgr |= CFGR_HALFWORD_TX_ENABLE;
271 /* no need divder, let set_syclk care about this */
272 cfgr &= ~CFGR_CLK_RATE_MASK;
275 cfgr &= ~CFGR_JUSTIFIED_MASK;
276 cfgr |= CFGR_JUSTIFIED_RIGHT;
278 cfgr &= ~CFGR_CSE_MASK;
279 cfgr |= CFGR_CSE_ENABLE;
281 cfgr &= ~CFGR_LINEAR_MASK;
282 cfgr |= CFGR_LINEAR_PCM;
284 cfgr &= ~CFGR_PRE_CHANGE_MASK;
285 cfgr |= CFGR_PRE_CHANGE_ENALBLE;
288 writel(cfgr, regs + CFGR);
290 intcr = readl(regs + INTCR) & (~INTCR_SDBEIE_MASK);
291 intcr |= INTCR_SDBEIE_DISABLE;
292 writel(intcr, regs + INTCR);
294 dmac = readl(regs + DMACR) & (~DMACR_TRAN_DATA_LEVEL_MASK);
295 dmac |= DMA_DATA_LEVEL_16;
297 writel(dmac, regs + DMACR);
299 /* channel status bit */
300 memset(chnsta, 0x0, CHNSTA_BYTES);
301 switch (params_rate(params)) {
303 val = CHNS_SAMPLE_FREQ_44P1K;
306 val = CHNS_SAMPLE_FREQ_48K;
309 val = CHNS_SAMPLE_FREQ_88P2K;
312 val = CHNS_SAMPLE_FREQ_96K;
315 val = CHNS_SAMPLE_FREQ_176P4K;
318 val = CHNS_SAMPLE_FREQ_192K;
321 val = CHNS_SAMPLE_FREQ_44P1K;
325 chnsta[0] |= BIT_1_LPCM;
327 chnsta[4] |= ((~val)<<4 | CHNS_SAMPLE_WORD_LEN_16);
329 chnregval = (chnsta[4] << 16) | (chnsta[4]);
330 writel(chnregval, regs + SPDIF_CHNSR02_ADDR);
332 chnregval = (chnsta[3] << 24) | (chnsta[3] << 8);
333 writel(chnregval, regs + SPDIF_CHNSR01_ADDR);
335 chnregval = (chnsta[1] << 24) | (chnsta[0] << 16) |
336 (chnsta[1] << 8) | (chnsta[0]);
337 writel(chnregval, regs + SPDIF_CHNSR00_ADDR);
339 spin_unlock_irqrestore(&spdif->lock, flags);
343 spin_unlock_irqrestore(&spdif->lock, flags);
348 static int spdif_suspend(struct snd_soc_dai *cpu_dai)
350 struct rockchip_spdif_info *spdif = to_info(cpu_dai);
352 dev_dbg(spdif->dev, "%s\n", __func__);
356 static int spdif_resume(struct snd_soc_dai *cpu_dai)
358 struct rockchip_spdif_info *spdif = to_info(cpu_dai);
360 dev_dbg(spdif->dev, "%s\n", __func__);
364 #define spdif_suspend NULL
365 #define spdif_resume NULL
368 static struct snd_soc_dai_ops spdif_dai_ops = {
369 .set_sysclk = spdif_set_syclk,
370 .trigger = spdif_trigger,
371 .hw_params = spdif_hw_params,
374 struct snd_soc_dai_driver rockchip_spdif_dai = {
375 .name = "rockchip-spdif",
377 .stream_name = "SPDIF Playback",
380 .rates = SNDRV_PCM_RATE_8000_192000,
381 .formats = SNDRV_PCM_FMTBIT_S16_LE |
382 SNDRV_PCM_FMTBIT_S20_3LE |
383 SNDRV_PCM_FMTBIT_S24_LE, },
384 .ops = &spdif_dai_ops,
385 .suspend = spdif_suspend,
386 .resume = spdif_resume,
389 static const struct snd_soc_component_driver rockchip_spdif_component = {
390 .name = "rockchip-spdif",
393 static int spdif_probe(struct platform_device *pdev)
395 struct resource *memregion;
396 struct resource *mem_res;
397 struct rockchip_spdif_info *spdif;
400 spdif = devm_kzalloc(&pdev->dev, sizeof(
401 struct rockchip_spdif_info), GFP_KERNEL);
403 dev_err(&pdev->dev, "Can't allocate spdif info\n");
407 spdif->dev = &pdev->dev;
408 platform_set_drvdata(pdev, spdif);
410 spin_lock_init(&spdif->lock);
412 /* get spdif register region. */
413 mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
415 dev_err(&pdev->dev, "No memory resource\n");
419 memregion = devm_request_mem_region(&pdev->dev,
421 resource_size(mem_res),
424 dev_err(&pdev->dev, "Memory region already claimed\n");
428 spdif->regs = devm_ioremap(&pdev->dev,
430 resource_size(memregion));
432 dev_err(&pdev->dev, "ioremap failed\n");
437 /* get spdif clock and init. */
438 spdif->hclk = devm_clk_get(&pdev->dev, "spdif_hclk");
439 if (IS_ERR(spdif->hclk)) {
440 dev_err(&pdev->dev, "Can't retrieve spdif hclk\n");
443 clk_prepare_enable(spdif->hclk);
445 spdif->clk = devm_clk_get(&pdev->dev, "spdif_mclk");
446 if (IS_ERR(spdif->clk)) {
447 dev_err(&pdev->dev, "Can't retrieve spdif mclk\n");
452 clk_set_rate(spdif->clk, 11289600);
453 clk_prepare_enable(spdif->clk);
455 spdif->dma_playback.addr = mem_res->start + SMPDR;
456 spdif->dma_playback.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
457 spdif->dma_playback.maxburst = SPDIF_DMA_BURST_SIZE;
459 ret = snd_soc_register_component(&pdev->dev,
460 &rockchip_spdif_component,
461 &rockchip_spdif_dai, 1);
463 dev_err(&pdev->dev, "Could not register DAI: %d\n", ret);
468 ret = rockchip_pcm_platform_register(&pdev->dev);
470 dev_err(&pdev->dev, "Could not register PCM: %d\n", ret);
474 dev_info(&pdev->dev, "spdif ready.\n");
479 platform_set_drvdata(pdev, NULL);
484 static int spdif_remove(struct platform_device *pdev)
486 rockchip_pcm_platform_unregister(&pdev->dev);
487 snd_soc_unregister_component(&pdev->dev);
493 static const struct of_device_id rockchip_spdif_match[] = {
494 { .compatible = "rockchip-spdif", },
497 MODULE_DEVICE_TABLE(of, rockchip_spdif_match);
500 static struct platform_driver rockchip_spdif_driver = {
501 .probe = spdif_probe,
502 .remove = spdif_remove,
504 .name = "rockchip-spdif",
505 .of_match_table = of_match_ptr(rockchip_spdif_match),
508 module_platform_driver(rockchip_spdif_driver);
510 MODULE_AUTHOR("Sugar <sugar.zhang@rock-chips.com>");
511 MODULE_DESCRIPTION("Rockchip S/PDIF Controller Driver");
512 MODULE_LICENSE("GPL v2");
513 MODULE_ALIAS("platform:rockchip-spdif");