2 * rk30_i2s.c -- ALSA SoC ROCKCHIP IIS Audio Layer Platform driver
4 * Driver for rockchip iis audio
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
14 #include <linux/init.h>
15 #include <linux/module.h>
16 #include <linux/interrupt.h>
17 #include <linux/device.h>
18 #include <linux/delay.h>
19 #include <linux/clk.h>
20 #include <linux/version.h>
22 #include <linux/of_gpio.h>
23 #include <linux/clk.h>
25 #include <linux/platform_device.h>
26 #include <linux/pm_runtime.h>
27 #include <linux/regmap.h>
28 #include <linux/slab.h>
30 #include <sound/core.h>
31 #include <sound/pcm.h>
32 #include <sound/pcm_params.h>
33 #include <sound/initval.h>
34 #include <sound/soc.h>
35 #include <sound/dmaengine_pcm.h>
37 #include <linux/spinlock.h>
38 #include <linux/workqueue.h>
46 #define I2S_DBG(x...) printk(KERN_INFO x)
48 #define I2S_DBG(x...) do { } while (0)
51 #define pheadi2s ((pI2S_REG)(i2s->regs))
55 static DEFINE_SPINLOCK(lock);
57 struct rk30_i2s_info {
60 struct clk *i2s_clk;// i2s clk ,is bclk lrck
61 struct clk *i2s_mclk;//i2s mclk,rk32xx can different i2s clk.
63 struct snd_dmaengine_dai_dma_data capture_dma_data;
64 struct snd_dmaengine_dai_dma_data playback_dma_data;
66 bool i2s_tx_status;//active = true;
69 struct delayed_work clk_delayed_work;
73 #define I2S_CLR_ERROR_COUNT 10// check I2S_CLR reg
74 static struct rk30_i2s_info *rk30_i2s;
76 #if defined (CONFIG_RK_HDMI) && defined (CONFIG_SND_RK_SOC_HDMI_I2S)
77 extern int hdmi_get_hotplug(void);
79 #define hdmi_get_hotplug() 0
82 static inline struct rk30_i2s_info *to_info(struct snd_soc_dai *dai)
84 return snd_soc_dai_get_drvdata(dai);
88 *Turn on or off the transmission path.
90 static void rockchip_snd_txctrl(struct rk30_i2s_info *i2s, int on)
94 bool is_need_delay = false;
95 int clr_error_count = I2S_CLR_ERROR_COUNT;
97 spin_lock_irqsave(&lock, flags);
99 opr = readl(&(pheadi2s->I2S_DMACR));
100 xfer = readl(&(pheadi2s->I2S_XFER));
101 clr = readl(&(pheadi2s->I2S_CLR));
103 I2S_DBG("rockchip_snd_txctrl: %s\n", on ? "on" : "off");
106 if ((opr & I2S_TRAN_DMA_ENABLE) == 0) {
107 opr |= I2S_TRAN_DMA_ENABLE;
108 writel(opr, &(pheadi2s->I2S_DMACR));
111 if ((xfer & I2S_TX_TRAN_START) == 0 || (xfer & I2S_RX_TRAN_START) == 0) {
112 xfer |= I2S_TX_TRAN_START;
113 xfer |= I2S_RX_TRAN_START;
114 writel(xfer, &(pheadi2s->I2S_XFER));
117 i2s->i2s_tx_status = 1;
120 i2s->i2s_tx_status = 0;
121 opr &= ~I2S_TRAN_DMA_ENABLE;
122 writel(opr, &(pheadi2s->I2S_DMACR));
124 if (i2s->i2s_rx_status == 0 && hdmi_get_hotplug() == 0) {
125 xfer &= ~I2S_TX_TRAN_START;
126 xfer &= ~I2S_RX_TRAN_START;
127 writel(xfer, &(pheadi2s->I2S_XFER));
131 writel(clr, &(pheadi2s->I2S_CLR));
133 is_need_delay = true;
135 I2S_DBG("rockchip_snd_txctrl: stop xfer\n");
139 spin_unlock_irqrestore(&lock, flags);
142 while(readl(&(pheadi2s->I2S_CLR)) && clr_error_count){
145 if(clr_error_count == 0)
146 printk("%s: i2s clr reg warning =%d",__FUNCTION__,readl(&(pheadi2s->I2S_CLR)));
151 static void rockchip_snd_rxctrl(struct rk30_i2s_info *i2s, int on)
155 bool is_need_delay = false;
156 int clr_error_count = I2S_CLR_ERROR_COUNT;
158 spin_lock_irqsave(&lock, flags);
160 opr = readl(&(pheadi2s->I2S_DMACR));
161 xfer = readl(&(pheadi2s->I2S_XFER));
162 clr = readl(&(pheadi2s->I2S_CLR));
164 I2S_DBG("rockchip_snd_rxctrl: %s\n", on ? "on" : "off");
167 if ((opr & I2S_RECE_DMA_ENABLE) == 0) {
168 opr |= I2S_RECE_DMA_ENABLE;
169 writel(opr, &(pheadi2s->I2S_DMACR));
172 if ((xfer & I2S_TX_TRAN_START)==0 || (xfer & I2S_RX_TRAN_START) == 0) {
173 xfer |= I2S_RX_TRAN_START;
174 xfer |= I2S_TX_TRAN_START;
175 writel(xfer, &(pheadi2s->I2S_XFER));
178 i2s->i2s_rx_status = 1;
180 i2s->i2s_rx_status = 0;
182 opr &= ~I2S_RECE_DMA_ENABLE;
183 writel(opr, &(pheadi2s->I2S_DMACR));
185 if (i2s->i2s_tx_status == 0 && hdmi_get_hotplug() == 0) {
186 xfer &= ~I2S_RX_TRAN_START;
187 xfer &= ~I2S_TX_TRAN_START;
188 writel(xfer, &(pheadi2s->I2S_XFER));
192 writel(clr, &(pheadi2s->I2S_CLR));
194 is_need_delay = true;
196 I2S_DBG("rockchip_snd_rxctrl: stop xfer\n");
200 spin_unlock_irqrestore(&lock, flags);
203 while(readl(&(pheadi2s->I2S_CLR)) && clr_error_count){
206 if(clr_error_count == 0)
207 printk("%s: i2s clr reg warning =%d",__FUNCTION__,readl(&(pheadi2s->I2S_CLR)));
213 * Set Rockchip I2S DAI format
215 static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
218 struct rk30_i2s_info *i2s = to_info(cpu_dai);
220 u32 iis_ckr_value;//clock generation register
224 I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
226 spin_lock_irqsave(&lock, flags);
228 tx_ctl = readl(&(pheadi2s->I2S_TXCR));
229 iis_ckr_value = readl(&(pheadi2s->I2S_CKR));
231 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
232 case SND_SOC_DAIFMT_CBM_CFM:
233 //Codec is master, so set cpu slave.
234 iis_ckr_value &= ~I2S_MODE_MASK;
235 iis_ckr_value |= I2S_SLAVE_MODE;
237 case SND_SOC_DAIFMT_CBS_CFS:
238 //Codec is slave, so set cpu master.
239 iis_ckr_value &= ~I2S_MODE_MASK;
240 iis_ckr_value |= I2S_MASTER_MODE;
243 I2S_DBG("unknwon master/slave format\n");
248 writel(iis_ckr_value, &(pheadi2s->I2S_CKR));
250 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
251 case SND_SOC_DAIFMT_RIGHT_J:
252 tx_ctl &= ~I2S_BUS_MODE_MASK; //I2S Bus Mode
253 tx_ctl |= I2S_BUS_MODE_RSJM;
255 case SND_SOC_DAIFMT_LEFT_J:
256 tx_ctl &= ~I2S_BUS_MODE_MASK; //I2S Bus Mode
257 tx_ctl |= I2S_BUS_MODE_LSJM;
259 case SND_SOC_DAIFMT_I2S:
260 tx_ctl &= ~I2S_BUS_MODE_MASK; //I2S Bus Mode
261 tx_ctl |= I2S_BUS_MODE_NOR;
264 I2S_DBG("Unknown data format\n");
269 I2S_DBG("Enter::%s----%d, I2S_TXCR=0x%X\n",__FUNCTION__,__LINE__,tx_ctl);
271 writel(tx_ctl, &(pheadi2s->I2S_TXCR));
273 rx_ctl = tx_ctl & 0x00007FFF;
274 writel(rx_ctl, &(pheadi2s->I2S_RXCR));
278 spin_unlock_irqrestore(&lock, flags);
283 static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream,
284 struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
286 struct rk30_i2s_info *i2s = to_info(dai);
291 I2S_DBG("Enter %s, %d \n", __func__, __LINE__);
293 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
294 dai->playback_dma_data = &i2s->playback_dma_data;
296 dai->capture_dma_data = &i2s->capture_dma_data;
298 spin_lock_irqsave(&lock, flags);
300 /* Working copies of register */
301 iismod = readl(&(pheadi2s->I2S_TXCR));
303 iismod &= (~((1<<5)-1));
304 switch (params_format(params)) {
305 case SNDRV_PCM_FORMAT_S8:
306 iismod |= SAMPLE_DATA_8bit;
308 case SNDRV_PCM_FORMAT_S16_LE:
309 iismod |= I2S_DATA_WIDTH(15);
311 case SNDRV_PCM_FORMAT_S20_3LE:
312 iismod |= I2S_DATA_WIDTH(19);
314 case SNDRV_PCM_FORMAT_S24_LE:
315 iismod |= I2S_DATA_WIDTH(23);
317 case SNDRV_PCM_FORMAT_S32_LE:
318 iismod |= I2S_DATA_WIDTH(31);
322 // writel((16<<24) |(16<<18)|(16<<12)|(16<<6)|16, &(pheadi2s->I2S_FIFOLR));
323 dmarc = readl(&(pheadi2s->I2S_DMACR));
325 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
326 dmarc = ((dmarc & 0xFFFFFE00) | 16);
328 dmarc = ((dmarc & 0xFE00FFFF) | 16<<16);
330 writel(dmarc, &(pheadi2s->I2S_DMACR));
332 I2S_DBG("Enter %s, %d I2S_TXCR=0x%08X\n", __func__, __LINE__, iismod);
334 writel(iismod, &(pheadi2s->I2S_TXCR));
336 iismod = iismod & 0x00007FFF;
337 writel(iismod, &(pheadi2s->I2S_RXCR));
339 spin_unlock_irqrestore(&lock, flags);
344 static int rockchip_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai)
346 struct rk30_i2s_info *i2s = to_info(dai);
349 I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
352 case SNDRV_PCM_TRIGGER_START:
353 case SNDRV_PCM_TRIGGER_RESUME:
354 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
355 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
356 rockchip_snd_rxctrl(i2s, 1);
358 rockchip_snd_txctrl(i2s, 1);
360 case SNDRV_PCM_TRIGGER_SUSPEND:
361 case SNDRV_PCM_TRIGGER_STOP:
362 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
363 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
364 rockchip_snd_rxctrl(i2s, 0);
366 rockchip_snd_txctrl(i2s, 0);
377 * Set Rockchip I2S MCLK source
379 static int rockchip_i2s_set_sysclk(struct snd_soc_dai *cpu_dai,
380 int clk_id, unsigned int freq, int dir)
382 struct rk30_i2s_info *i2s = to_info(cpu_dai);
384 I2S_DBG("Enter:%s, %d, i2s=0x%p, freq=%d\n", __FUNCTION__, __LINE__, i2s, freq);
386 /*add scu clk source and enable clk*/
387 clk_set_rate(i2s->i2s_clk, freq);
392 * Set Rockchip Clock dividers
394 static int rockchip_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai,
397 struct rk30_i2s_info *i2s;
402 i2s = to_info(cpu_dai);
404 spin_lock_irqsave(&lock, flags);
406 //stereo mode MCLK/SCK=4
407 reg = readl(&(pheadi2s->I2S_CKR));
409 I2S_DBG("Enter:%s, %d, div_id=0x%08X, div=0x%08X\n", __FUNCTION__, __LINE__, div_id, div);
411 //when i2s in master mode ,must set codec pll div
413 case ROCKCHIP_DIV_BCLK:
414 reg &= ~I2S_TX_SCLK_DIV_MASK;
415 reg |= I2S_TX_SCLK_DIV(div);
416 reg &= ~I2S_RX_SCLK_DIV_MASK;
417 reg |= I2S_RX_SCLK_DIV(div);
419 case ROCKCHIP_DIV_MCLK:
420 reg &= ~I2S_MCLK_DIV_MASK;
421 reg |= I2S_MCLK_DIV(div);
423 case ROCKCHIP_DIV_PRESCALER:
429 writel(reg, &(pheadi2s->I2S_CKR));
432 spin_unlock_irqrestore(&lock, flags);
437 static struct snd_soc_dai_ops rockchip_i2s_dai_ops = {
438 .trigger = rockchip_i2s_trigger,
439 .hw_params = rockchip_i2s_hw_params,
440 .set_fmt = rockchip_i2s_set_fmt,
441 .set_clkdiv = rockchip_i2s_set_clkdiv,
442 .set_sysclk = rockchip_i2s_set_sysclk,
445 #define ROCKCHIP_I2S_STEREO_RATES SNDRV_PCM_RATE_8000_96000
446 #define ROCKCHIP_I2S_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
447 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8)
449 struct snd_soc_dai_driver rockchip_i2s_dai[] = {
451 .name = "rockchip-i2s.0",
456 .rates = ROCKCHIP_I2S_STEREO_RATES,
457 .formats = ROCKCHIP_I2S_FORMATS,
462 .rates = ROCKCHIP_I2S_STEREO_RATES,
463 .formats = ROCKCHIP_I2S_FORMATS,
465 .ops = &rockchip_i2s_dai_ops,
466 .symmetric_rates = 1,
469 .name = "rockchip-i2s.1",
474 .rates = ROCKCHIP_I2S_STEREO_RATES,
475 .formats = ROCKCHIP_I2S_FORMATS,
480 .rates = ROCKCHIP_I2S_STEREO_RATES,
481 .formats = ROCKCHIP_I2S_FORMATS,
483 .ops = &rockchip_i2s_dai_ops,
484 .symmetric_rates = 1,
488 static const struct snd_soc_component_driver rockchip_i2s_component = {
489 .name = "rockchip-i2s",
493 static int rockchip_i2s_suspend_noirq(struct device *dev)
495 I2S_DBG("Enter %s, %d\n", __func__, __LINE__);
497 return pinctrl_pm_select_sleep_state(dev);
500 static int rockchip_i2s_resume_noirq(struct device *dev)
502 I2S_DBG("Enter %s, %d\n", __func__, __LINE__);
504 return pinctrl_pm_select_default_state(dev);
507 #define rockchip_i2s_suspend_noirq NULL
508 #define rockchip_i2s_resume_noirq NULL
512 static void set_clk_later_work(struct work_struct *work)
514 struct rk30_i2s_info *i2s = rk30_i2s;
515 clk_set_rate(i2s->i2s_clk, 11289600);
516 if(!IS_ERR(i2s->i2s_mclk) )
517 clk_set_rate(i2s->i2s_mclk, 11289600);
521 static int rockchip_i2s_probe(struct platform_device *pdev)
523 struct device_node *node = pdev->dev.of_node;
524 struct rk30_i2s_info *i2s;
525 struct resource *mem, *memregion;
529 I2S_DBG("%s()\n", __FUNCTION__);
531 ret = of_property_read_u32(node, "i2s-id", &pdev->id);
533 dev_err(&pdev->dev, "%s() Can not read property: id\n", __FUNCTION__);
538 if(pdev->id >= MAX_I2S) {
539 dev_err(&pdev->dev, "id %d out of range\n", pdev->id);
544 i2s = devm_kzalloc(&pdev->dev, sizeof(struct rk30_i2s_info), GFP_KERNEL);
546 dev_err(&pdev->dev, "Can't allocate i2s info\n");
553 i2s->i2s_hclk = clk_get(&pdev->dev, "i2s_hclk");
554 if(IS_ERR(i2s->i2s_hclk) ) {
555 dev_err(&pdev->dev, "get i2s_hclk failed.\n");
557 clk_prepare_enable(i2s->i2s_hclk);
560 i2s->i2s_clk= clk_get(&pdev->dev, "i2s_clk");
561 if (IS_ERR(i2s->i2s_clk)) {
562 dev_err(&pdev->dev, "Can't retrieve i2s clock\n");
563 ret = PTR_ERR(i2s->i2s_clk);
567 INIT_DELAYED_WORK(&i2s->clk_delayed_work, set_clk_later_work);
568 schedule_delayed_work(&i2s->clk_delayed_work, msecs_to_jiffies(10));
570 clk_set_rate(i2s->iis_clk, 11289600);
572 clk_prepare_enable(i2s->i2s_clk);
574 i2s->i2s_mclk= clk_get(&pdev->dev, "i2s_mclk");
575 if(IS_ERR(i2s->i2s_mclk) ) {
576 printk("This platfrom have not i2s_mclk,no need to set i2s_mclk.\n");
581 clk_set_rate(i2s->i2s_mclk, 11289600);
583 clk_prepare_enable(i2s->i2s_mclk);
586 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
588 dev_err(&pdev->dev, "No memory resource\n");
593 memregion = devm_request_mem_region(&pdev->dev, mem->start,
594 resource_size(mem), "rockchip-i2s");
596 dev_err(&pdev->dev, "Memory region already claimed\n");
601 i2s->regs = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
603 dev_err(&pdev->dev, "ioremap failed\n");
608 regs_base = mem->start;
610 i2s->playback_dma_data.addr = regs_base + I2S_TXR_BUFF;
611 i2s->playback_dma_data.addr_width = 4;
612 i2s->playback_dma_data.maxburst = 1;
614 i2s->capture_dma_data.addr = regs_base + I2S_RXR_BUFF;
615 i2s->capture_dma_data.addr_width = 4;
616 i2s->capture_dma_data.maxburst = 1;
618 i2s->i2s_tx_status = false;
619 i2s->i2s_rx_status = false;
621 pm_runtime_enable(&pdev->dev);
622 if (!pm_runtime_enabled(&pdev->dev)) {
623 ret = rockchip_i2s_resume_noirq(&pdev->dev);
628 //set dev name to driver->name.id for sound card register
629 dev_set_name(&pdev->dev, "%s.%d", pdev->dev.driver->name, pdev->id);
631 ret = snd_soc_register_component(&pdev->dev, &rockchip_i2s_component,
632 &rockchip_i2s_dai[pdev->id], 1);
635 dev_err(&pdev->dev, "Could not register DAI: %d\n", ret);
640 ret = rockchip_pcm_platform_register(&pdev->dev);
642 dev_err(&pdev->dev, "Could not register PCM: %d\n", ret);
643 goto err_unregister_component;
646 /* Mark ourselves as in TXRX mode so we can run through our cleanup
647 * process without warnings. */
648 rockchip_snd_txctrl(i2s, 0);
649 rockchip_snd_rxctrl(i2s, 0);
651 dev_set_drvdata(&pdev->dev, i2s);
654 err_unregister_component:
655 snd_soc_unregister_component(&pdev->dev);
657 if (!pm_runtime_status_suspended(&pdev->dev))
658 rockchip_i2s_suspend_noirq(&pdev->dev);
660 pm_runtime_disable(&pdev->dev);
662 clk_put(i2s->i2s_clk);
668 static int rockchip_i2s_remove(struct platform_device *pdev)
670 rockchip_pcm_platform_unregister(&pdev->dev);
671 snd_soc_unregister_component(&pdev->dev);
677 static const struct of_device_id exynos_i2s_match[] = {
678 { .compatible = "rockchip-i2s"},
681 MODULE_DEVICE_TABLE(of, exynos_i2s_match);
684 static const struct dev_pm_ops rockchip_i2s_pm_ops = {
685 .suspend_noirq = rockchip_i2s_suspend_noirq,
686 .resume_noirq = rockchip_i2s_resume_noirq,
689 static struct platform_driver rockchip_i2s_driver = {
690 .probe = rockchip_i2s_probe,
691 .remove = rockchip_i2s_remove,
693 .name = "rockchip-i2s",
694 .owner = THIS_MODULE,
695 .of_match_table = of_match_ptr(exynos_i2s_match),
696 .pm = &rockchip_i2s_pm_ops,
699 module_platform_driver(rockchip_i2s_driver);
701 /* Module information */
702 MODULE_AUTHOR("rockchip");
703 MODULE_DESCRIPTION("ROCKCHIP IIS ASoC Interface");
704 MODULE_LICENSE("GPL");
707 #ifdef CONFIG_PROC_FS
708 #include <linux/proc_fs.h>
709 #include <linux/seq_file.h>
710 static int proc_i2s_show(struct seq_file *s, void *v)
713 struct rk30_i2s_info *i2s = rk30_i2s;
715 printk("========Show I2S reg========\n");
717 printk("I2S_TXCR = 0x%08X\n", readl(&(pheadi2s->I2S_TXCR)));
718 printk("I2S_RXCR = 0x%08X\n", readl(&(pheadi2s->I2S_RXCR)));
719 printk("I2S_CKR = 0x%08X\n", readl(&(pheadi2s->I2S_CKR)));
720 printk("I2S_DMACR = 0x%08X\n", readl(&(pheadi2s->I2S_DMACR)));
721 printk("I2S_INTCR = 0x%08X\n", readl(&(pheadi2s->I2S_INTCR)));
722 printk("I2S_INTSR = 0x%08X\n", readl(&(pheadi2s->I2S_INTSR)));
723 printk("I2S_XFER = 0x%08X\n", readl(&(pheadi2s->I2S_XFER)));
725 printk("========Show I2S reg========\n");
727 writel(0x0000000F, &(pheadi2s->I2S_TXCR));
728 writel(0x0000000F, &(pheadi2s->I2S_RXCR));
729 writel(0x00071f1F, &(pheadi2s->I2S_CKR));
730 writel(0x001F0110, &(pheadi2s->I2S_DMACR));
731 writel(0x00000003, &(pheadi2s->I2S_XFER));
734 writel(0x5555aaaa, &(pheadi2s->I2S_TXDR));
740 static ssize_t i2s_reg_write(struct file *file,
741 const char __user *user_buf, size_t count, loff_t *ppos)
743 struct rk30_i2s_info *i2s=rk30_i2s;
750 buf_size = min(count, (sizeof(buf)-1));
751 if (copy_from_user(buf, user_buf, buf_size))
755 while (*start == ' ')
757 value = simple_strtoul(start, &start, 10);
759 printk("test --- freq = %ld ret=%d\n",value,clk_set_rate(i2s->i2s_clk, value));
763 static int proc_i2s_open(struct inode *inode, struct file *file)
765 return single_open(file, proc_i2s_show, NULL);
768 static const struct file_operations proc_i2s_fops = {
769 .open = proc_i2s_open,
771 .write = i2s_reg_write,
773 .release = single_release,
776 static int __init i2s_proc_init(void)
778 proc_create("i2s_reg", 0, NULL, &proc_i2s_fops);
781 late_initcall(i2s_proc_init);
782 #endif /* CONFIG_PROC_FS */