2 * rk29_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>
23 #include <sound/core.h>
24 #include <sound/pcm.h>
25 #include <sound/pcm_params.h>
26 #include <sound/initval.h>
27 #include <sound/soc.h>
30 #include <mach/hardware.h>
31 #include <mach/board.h>
32 #include <mach/rk29_iomap.h>
33 #include <mach/rk29-dma-pl330.h>
34 #include <mach/iomux.h>
42 #define I2S_DBG(x...) printk(KERN_INFO x)
44 #define I2S_DBG(x...) do { } while (0)
47 #define pheadi2s ((pI2S_REG)(i2s->regs))
51 struct rk29_i2s_info {
62 struct rockchip_pcm_dma_params *dma_playback;
63 struct rockchip_pcm_dma_params *dma_capture;
70 static struct rk29_dma_client rk29_dma_client_out = {
71 .name = "I2S PCM Stereo Out"
74 static struct rk29_dma_client rk29_dma_client_in = {
75 .name = "I2S PCM Stereo In"
78 static inline struct rk29_i2s_info *to_info(struct snd_soc_dai *cpu_dai)
80 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
81 return snd_soc_dai_get_drvdata(cpu_dai);
83 return cpu_dai->private_data;
87 static struct rockchip_pcm_dma_params rk29_i2s_pcm_stereo_out[MAX_I2S];
88 static struct rockchip_pcm_dma_params rk29_i2s_pcm_stereo_in[MAX_I2S];
89 static struct rk29_i2s_info rk29_i2s[MAX_I2S];
91 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
92 struct snd_soc_dai_driver rk29_i2s_dai[MAX_I2S];
94 struct snd_soc_dai rk29_i2s_dai[MAX_I2S];
96 EXPORT_SYMBOL_GPL(rk29_i2s_dai);
99 static struct rockchip_pcm_dma_params rockchip_i2s_pcm_stereo_out[MAX_I2S] = {
101 .client = &rk29_dma_client_out,
102 .channel = DMACH_I2S_2CH_TX, ///0, //DMACH_I2S_OUT,
103 .dma_addr = RK29_I2S_2CH_PHYS + I2S_TXR_BUFF,
107 .client = &rk29_dma_client_out,
108 .channel = DMACH_I2S_8CH_TX, ///0, //DMACH_I2S_OUT,
109 .dma_addr = RK29_I2S_8CH_PHYS + I2S_TXR_BUFF,
114 static struct rockchip_pcm_dma_params rockchip_i2s_pcm_stereo_in[MAX_I2S] = {
116 .client = &rk29_dma_client_in,
117 .channel = DMACH_I2S_2CH_RX, ///1, //DMACH_I2S_IN,
118 .dma_addr = RK29_I2S_2CH_PHYS + I2S_RXR_BUFF,
122 .client = &rk29_dma_client_in,
123 .channel = DMACH_I2S_8CH_RX, ///1, //DMACH_I2S_IN,
124 .dma_addr = RK29_I2S_8CH_PHYS + I2S_RXR_BUFF,
131 static u32 i2s0_clk_enter(void)
133 u32 clk = cru_readl(CRU_CLKSEL3_CON);
134 cru_writel(0x1ffff, CRU_CLKSEL3_CON);
139 static void i2s0_clk_exit(u32 clk)
142 cru_writel(clk, CRU_CLKSEL3_CON);
146 static u32 i2s0_clk_enter()
151 static void i2s0_clk_exit(u32 clk)
157 *Turn on or off the transmission path.
160 static int flag_i2s_tx = 0;
161 static int flag_i2s_rx = 0;
162 static void rockchip_snd_txctrl(struct rk29_i2s_info *i2s, int on, bool stopI2S)
167 opr = readl(&(pheadi2s->I2S_DMACR));
168 xfer = readl(&(pheadi2s->I2S_XFER));
172 I2S_DBG("rockchip_snd_txctrl: on\n");
175 //if ((flag_i2s_tx == 0) && (flag_i2s_rx == 0))
176 if ((xfer&I2S_TX_TRAN_START)==0 || (xfer&I2S_RX_TRAN_START)==0)
178 clk = i2s0_clk_enter();
180 //if start tx & rx clk, need reset i2s
181 xfer |= I2S_TX_TRAN_START;
182 xfer |= I2S_RX_TRAN_START;
183 writel(xfer, &(pheadi2s->I2S_XFER));
188 if ((opr & I2S_TRAN_DMA_ENABLE) == 0)
190 opr |= I2S_TRAN_DMA_ENABLE;
191 writel(opr, &(pheadi2s->I2S_DMACR));
201 if ((flag_i2s_rx == 0) && (flag_i2s_tx == 0))
203 opr &= ~I2S_TRAN_DMA_ENABLE;
204 writel(opr, &(pheadi2s->I2S_DMACR));
207 clk = i2s0_clk_enter();
209 xfer &= ~I2S_RX_TRAN_START;
210 xfer &= ~I2S_TX_TRAN_START;
211 writel(xfer, &(pheadi2s->I2S_XFER));
216 //after stop rx & tx clk, reset i2s
217 //writel(0x001,&(pheadi2s->I2S_TXRST));
218 //writel(0x001,&(pheadi2s->I2S_RXRST));
221 I2S_DBG("rockchip_snd_txctrl: off\n");
225 static void rockchip_snd_rxctrl(struct rk29_i2s_info *i2s, int on, bool stopI2S)
230 opr = readl(&(pheadi2s->I2S_DMACR));
231 xfer = readl(&(pheadi2s->I2S_XFER));
235 I2S_DBG("rockchip_snd_rxctrl: on\n");
238 //if ((flag_i2s_tx == 0) && (flag_i2s_rx == 0))
239 if ((xfer&I2S_TX_TRAN_START)==0 || (xfer&I2S_RX_TRAN_START)==0)
241 clk = i2s0_clk_enter();
243 xfer |= I2S_TX_TRAN_START;
244 xfer |= I2S_RX_TRAN_START;
245 writel(xfer, &(pheadi2s->I2S_XFER));
250 if ((opr & I2S_RECE_DMA_ENABLE) == 0)
252 opr |= I2S_RECE_DMA_ENABLE;
253 writel(opr, &(pheadi2s->I2S_DMACR));
257 #if (CONFIG_SND_SOC_RT5631)
259 schedule_delayed_work(&rt5631_delay_cap,HZ/4);
267 if ((flag_i2s_rx == 0) && (flag_i2s_tx == 0))
269 opr &= ~I2S_RECE_DMA_ENABLE;
270 writel(opr, &(pheadi2s->I2S_DMACR));
274 clk = i2s0_clk_enter();
276 xfer &= ~I2S_RX_TRAN_START;
277 xfer &= ~I2S_TX_TRAN_START;
278 writel(xfer, &(pheadi2s->I2S_XFER));
283 //after stop rx & tx clk, reset i2s
284 //writel(0x001,&(pheadi2s->I2S_TXRST));
285 //writel(0x001,&(pheadi2s->I2S_RXRST));
288 I2S_DBG("rockchip_snd_rxctrl: off\n");
293 * Set Rockchip I2S DAI format
295 static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
298 struct rk29_i2s_info *i2s = to_info(cpu_dai);
301 I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
303 tx_ctl = readl(&(pheadi2s->I2S_TXCR));
305 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
306 case SND_SOC_DAIFMT_CBM_CFM:
307 tx_ctl &= ~I2S_MODE_MASK;
308 tx_ctl |= I2S_MASTER_MODE;
310 case SND_SOC_DAIFMT_CBS_CFS:
311 tx_ctl &= ~I2S_MODE_MASK;
312 tx_ctl |= I2S_SLAVE_MODE;
315 I2S_DBG("unknwon master/slave format\n");
319 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
320 case SND_SOC_DAIFMT_RIGHT_J:
321 tx_ctl &= ~I2S_BUS_MODE_MASK; //I2S Bus Mode
322 tx_ctl |= I2S_BUS_MODE_RSJM;
324 case SND_SOC_DAIFMT_LEFT_J:
325 tx_ctl &= ~I2S_BUS_MODE_MASK; //I2S Bus Mode
326 tx_ctl |= I2S_BUS_MODE_LSJM;
328 case SND_SOC_DAIFMT_I2S:
329 tx_ctl &= ~I2S_BUS_MODE_MASK; //I2S Bus Mode
330 tx_ctl |= I2S_BUS_MODE_NOR;
333 I2S_DBG("Unknown data format\n");
336 I2S_DBG("Enter::%s----%d, I2S_TXCR=0x%X\n",__FUNCTION__,__LINE__,tx_ctl);
337 #if 0//defined(CONFIG_SND_RK_SOC_alc5631) || defined(CONFIG_SND_RK_SOC_alc5621)
339 rx_ctl &= ~I2S_MODE_MASK;
340 rx_ctl |= I2S_SLAVE_MODE; // set tx slave, rx master
341 writel(rx_ctl, &(pheadi2s->I2S_TXCR));
343 writel(tx_ctl, &(pheadi2s->I2S_TXCR));
345 rx_ctl = tx_ctl & 0x00007FFF;
346 writel(rx_ctl, &(pheadi2s->I2S_RXCR));
350 static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream,
351 struct snd_pcm_hw_params *params, struct snd_soc_dai *socdai)
353 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
354 struct rk29_i2s_info *i2s = to_info(socdai);
356 struct snd_soc_pcm_runtime *rtd = substream->private_data;
357 struct snd_soc_dai_link *dai = rtd->dai;
358 struct rk29_i2s_info *i2s = to_info(dai->cpu_dai);
363 I2S_DBG("Enter %s, %d >>>>>>>>>>>\n", __func__, __LINE__);
364 /*by Vincent Hsiung for EQ Vol Change*/
365 #define HW_PARAMS_FLAG_EQVOL_ON 0x21
366 #define HW_PARAMS_FLAG_EQVOL_OFF 0x22
367 if ((params->flags == HW_PARAMS_FLAG_EQVOL_ON)||(params->flags == HW_PARAMS_FLAG_EQVOL_OFF))
372 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
373 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
374 snd_soc_dai_set_dma_data(socdai, substream, i2s->dma_playback);
376 snd_soc_dai_set_dma_data(socdai, substream, i2s->dma_capture);
377 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
378 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
379 dai->cpu_dai->playback.dma_data = i2s->dma_playback;
381 dai->cpu_dai->capture.dma_data = i2s->dma_capture;
383 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
384 dai->cpu_dai->dma_data = i2s->dma_playback;
386 dai->cpu_dai->dma_data = i2s->dma_capture;
389 /* Working copies of register */
390 iismod = readl(&(pheadi2s->I2S_TXCR));
391 //iismod &= (~((1<<5)-1));
392 switch (params_format(params)) {
393 case SNDRV_PCM_FORMAT_S8:
394 iismod |= SAMPLE_DATA_8bit;
396 case SNDRV_PCM_FORMAT_S16_LE:
397 iismod |= I2S_DATA_WIDTH(15);
399 case SNDRV_PCM_FORMAT_S20_3LE:
400 iismod |= I2S_DATA_WIDTH(19);
402 case SNDRV_PCM_FORMAT_S24_LE:
403 iismod |= I2S_DATA_WIDTH(23);
405 case SNDRV_PCM_FORMAT_S32_LE:
406 iismod |= I2S_DATA_WIDTH(31);
409 #if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE)
410 iismod &= ~I2S_SLAVE_MODE;
413 #if defined (CONFIG_SND_RK_CODEC_SOC_MASTER)
414 iismod |= I2S_SLAVE_MODE;
417 //writel((16<<24) |(16<<18)|(16<<12)|(16<<6)|16, &(pheadi2s->I2S_FIFOLR));
418 dmarc = readl(&(pheadi2s->I2S_DMACR));
420 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
421 dmarc = ((dmarc & 0xFFFFFE00) | 16);
423 dmarc = ((dmarc & 0xFE00FFFF) | 16<<16);
425 writel(dmarc, &(pheadi2s->I2S_DMACR));
426 I2S_DBG("Enter %s, %d I2S_TXCR=0x%08X\n", __func__, __LINE__, iismod);
427 #if 0//defined(CONFIG_SND_RK_SOC_alc5631) || defined(CONFIG_SND_RK_SOC_alc5621)
429 dmarc &= ~I2S_MODE_MASK;
430 dmarc |= I2S_SLAVE_MODE; // set tx slave, rx master
431 writel(dmarc, &(pheadi2s->I2S_TXCR));
433 writel(iismod, &(pheadi2s->I2S_TXCR));
435 iismod = iismod & 0x00007FFF;
436 writel(iismod, &(pheadi2s->I2S_RXCR));
441 static int rockchip_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai)
444 struct snd_soc_pcm_runtime *rtd = substream->private_data;
445 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
446 struct rk29_i2s_info *i2s = to_info(rtd->cpu_dai);
448 struct rk29_i2s_info *i2s = to_info(rtd->dai->cpu_dai);
450 bool stopI2S = false;
452 I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
454 case SNDRV_PCM_TRIGGER_START:
455 case SNDRV_PCM_TRIGGER_RESUME:
456 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
457 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
458 rockchip_snd_rxctrl(i2s, 1, stopI2S);
460 rockchip_snd_txctrl(i2s, 1, stopI2S);
463 case SNDRV_PCM_TRIGGER_SUSPEND:
465 case SNDRV_PCM_TRIGGER_STOP:
466 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
467 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
468 rockchip_snd_rxctrl(i2s, 0, stopI2S);
470 rockchip_snd_txctrl(i2s, 0, stopI2S);
480 * Set Rockchip Clock source
482 static int rockchip_i2s_set_sysclk(struct snd_soc_dai *cpu_dai,
483 int clk_id, unsigned int freq, int dir)
485 struct rk29_i2s_info *i2s;
487 i2s = to_info(cpu_dai);
489 I2S_DBG("Enter:%s, %d, i2s=0x%p, freq=%d\n", __FUNCTION__, __LINE__, i2s, freq);
490 /*add scu clk source and enable clk*/
491 clk_set_rate(i2s->iis_clk, freq);
496 * Set Rockchip Clock dividers
498 static int rockchip_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai,
501 struct rk29_i2s_info *i2s;
504 i2s = to_info(cpu_dai);
506 /*stereo mode MCLK/SCK=4*/
508 reg = readl(&(pheadi2s->I2S_TXCKR));
510 I2S_DBG("Enter:%s, %d, div_id=0x%08X, div=0x%08X\n", __FUNCTION__, __LINE__, div_id, div);
512 /*when i2s in master mode ,must set codec pll div*/
514 case ROCKCHIP_DIV_BCLK:
515 reg &= ~I2S_TX_SCLK_DIV_MASK;
516 reg |= I2S_TX_SCLK_DIV(div);
518 case ROCKCHIP_DIV_MCLK:
519 reg &= ~I2S_MCLK_DIV_MASK;
520 reg |= I2S_MCLK_DIV(div);
522 case ROCKCHIP_DIV_PRESCALER:
528 writel(reg, &(pheadi2s->I2S_TXCKR));
529 writel(reg, &(pheadi2s->I2S_RXCKR));
534 * To avoid duplicating clock code, allow machine driver to
535 * get the clockrate from here.
537 u32 rockchip_i2s_get_clockrate(void)
539 I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
540 return 0; ///clk_get_rate(s3c24xx_i2s.iis_clk);
542 EXPORT_SYMBOL_GPL(rockchip_i2s_get_clockrate);
545 int rockchip_i2s_suspend(struct snd_soc_dai *cpu_dai)
547 I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
552 int rockchip_i2s_resume(struct snd_soc_dai *cpu_dai)
554 I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
559 #define rockchip_i2s_suspend NULL
560 #define rockchip_i2s_resume NULL
563 #if defined(CONFIG_SND_RK_SOC_alc5631) || defined(CONFIG_SND_RK_SOC_alc5621)
564 #define ROCKCHIP_I2S_RATES (SNDRV_PCM_RATE_44100) //zyy 20110704, playback and record use same sample rate
566 #define ROCKCHIP_I2S_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
567 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\
568 SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
571 static struct snd_soc_dai_ops rockchip_i2s_dai_ops = {
572 .trigger = rockchip_i2s_trigger,
573 .hw_params = rockchip_i2s_hw_params,
574 .set_fmt = rockchip_i2s_set_fmt,
575 .set_clkdiv = rockchip_i2s_set_clkdiv,
576 .set_sysclk = rockchip_i2s_set_sysclk,
579 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
580 static int rockchip_i2s_dai_probe(struct snd_soc_dai *dai)
582 static int rockchip_i2s_dai_probe(struct platform_device *pdev, struct snd_soc_dai *dai)
585 I2S_DBG("Enter %s, %d >>>>>>>>>>>\n", __func__, __LINE__);
589 rk29_mux_api_set(GPIO2D0_I2S0CLK_MIIRXCLKIN_NAME, GPIO2H_I2S0_CLK);
590 rk29_mux_api_set(GPIO2D1_I2S0SCLK_MIICRS_NAME, GPIO2H_I2S0_SCLK);
591 rk29_mux_api_set(GPIO2D2_I2S0LRCKRX_MIITXERR_NAME, GPIO2H_I2S0_LRCK_RX);
592 rk29_mux_api_set(GPIO2D3_I2S0SDI_MIICOL_NAME, GPIO2H_I2S0_SDI);
593 rk29_mux_api_set(GPIO2D4_I2S0SDO0_MIIRXD2_NAME, GPIO2H_I2S0_SDO0);
594 rk29_mux_api_set(GPIO2D5_I2S0SDO1_MIIRXD3_NAME, GPIO2H_I2S0_SDO1);
595 rk29_mux_api_set(GPIO2D6_I2S0SDO2_MIITXD2_NAME, GPIO2H_I2S0_SDO2);
596 rk29_mux_api_set(GPIO2D7_I2S0SDO3_MIITXD3_NAME, GPIO2H_I2S0_SDO3);
598 rk29_mux_api_set(GPIO4D6_I2S0LRCKTX0_NAME, GPIO4H_I2S0_LRCK_TX0);
599 rk29_mux_api_set(GPIO4D7_I2S0LRCKTX1_NAME, GPIO4H_I2S0_LRCK_TX1);
602 rk29_mux_api_set(GPIO3A0_I2S1CLK_NAME, GPIO3L_I2S1_CLK);
603 rk29_mux_api_set(GPIO3A1_I2S1SCLK_NAME, GPIO3L_I2S1_SCLK);
604 rk29_mux_api_set(GPIO3A2_I2S1LRCKRX_NAME, GPIO3L_I2S1_LRCK_RX);
605 rk29_mux_api_set(GPIO3A3_I2S1SDI_NAME, GPIO3L_I2S1_SDI);
606 rk29_mux_api_set(GPIO3A4_I2S1SDO_NAME, GPIO3L_I2S1_SDO);
607 rk29_mux_api_set(GPIO3A5_I2S1LRCKTX_NAME, GPIO3L_I2S1_LRCK_TX);
610 I2S_DBG("Enter:%s, %d, Error For DevId!!!", __FUNCTION__, __LINE__);
616 static int rk29_i2s_probe(struct platform_device *pdev,
617 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
618 struct snd_soc_dai_driver *dai,
620 struct snd_soc_dai *dai,
622 struct rk29_i2s_info *i2s,
625 struct device *dev = &pdev->dev;
626 struct resource *res;
628 I2S_DBG("Enter %s, %d >>>>>>>>>>>\n", __func__, __LINE__);
632 /* record our i2s structure for later use in the callbacks */
633 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
634 dev_set_drvdata(&pdev->dev, i2s);
636 dai->private_data = i2s;
640 res = platform_get_resource(pdev,
644 dev_err(dev, "Unable to get register resource\n");
648 if (!request_mem_region(res->start, resource_size(res),
650 dev_err(dev, "Unable to request register region\n");
657 i2s->regs = ioremap(base, (res->end - res->start) + 1); ////res));
658 if (i2s->regs == NULL) {
659 dev_err(dev, "cannot ioremap registers\n");
663 i2s->iis_pclk = clk_get(dev, "i2s");
664 if (IS_ERR(i2s->iis_pclk)) {
665 dev_err(dev, "failed to get iis_clock\n");
670 clk_enable(i2s->iis_pclk);
672 /* Mark ourselves as in TXRX mode so we can run through our cleanup
673 * process without warnings. */
674 rockchip_snd_txctrl(i2s, 0, true);
675 rockchip_snd_rxctrl(i2s, 0, true);
680 static int __devinit rockchip_i2s_probe(struct platform_device *pdev)
682 struct rk29_i2s_info *i2s;
683 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
684 struct snd_soc_dai_driver *dai;
686 struct snd_soc_dai *dai;
690 I2S_DBG("Enter %s, %d pdev->id = %d >>>>>>>>>>>\n", __func__, __LINE__, pdev->id);
692 if(pdev->id >= MAX_I2S) {
693 dev_err(&pdev->dev, "id %d out of range\n", pdev->id);
697 i2s = &rk29_i2s[pdev->id];
698 dai = &rk29_i2s_dai[pdev->id];
699 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37))
700 dai->dev = &pdev->dev;
703 dai->symmetric_rates = 1;
705 dai->name = "rk_i2s.0";
706 dai->playback.channels_min = 2;
707 dai->playback.channels_max = 8;
709 dai->name = "rk_i2s.1";
710 dai->playback.channels_min = 2;
711 dai->playback.channels_max = 2;
713 dai->playback.rates = ROCKCHIP_I2S_RATES;
714 dai->playback.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE;
715 dai->capture.channels_min = 2;
716 dai->capture.channels_max = 2;
717 dai->capture.rates = ROCKCHIP_I2S_RATES;//;SNDRV_PCM_RATE_44100
718 dai->capture.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE;
719 dai->probe = rockchip_i2s_dai_probe;
720 dai->ops = &rockchip_i2s_dai_ops;
721 dai->suspend = rockchip_i2s_suspend;
722 dai->resume = rockchip_i2s_resume;
724 //i2s->feature |= S3C_FEATURE_CDCLKCON;
726 i2s->dma_capture = &rk29_i2s_pcm_stereo_in[pdev->id];
727 i2s->dma_playback = &rk29_i2s_pcm_stereo_out[pdev->id];
730 i2s->dma_capture->channel = DMACH_I2S_2CH_RX;
731 i2s->dma_capture->dma_addr = RK29_I2S_2CH_PHYS + I2S_RXR_BUFF;
732 i2s->dma_playback->channel = DMACH_I2S_2CH_TX;
733 i2s->dma_playback->dma_addr = RK29_I2S_2CH_PHYS + I2S_TXR_BUFF;
735 i2s->dma_capture->channel = DMACH_I2S_8CH_RX;
736 i2s->dma_capture->dma_addr = RK29_I2S_8CH_PHYS + I2S_RXR_BUFF;
737 i2s->dma_playback->channel = DMACH_I2S_8CH_TX;
738 i2s->dma_playback->dma_addr = RK29_I2S_8CH_PHYS + I2S_TXR_BUFF;
741 i2s->dma_capture->client = &rk29_dma_client_in;
742 i2s->dma_capture->dma_size = 4;
743 i2s->dma_capture->flag = 0; //add by sxj, used for burst change
744 i2s->dma_playback->client = &rk29_dma_client_out;
745 i2s->dma_playback->dma_size = 4;
746 i2s->dma_playback->flag = 0; //add by sxj, used for burst change
747 #ifdef CONFIG_SND_I2S_DMA_EVENT_STATIC
748 WARN_ON(rk29_dma_request(i2s->dma_playback->channel, i2s->dma_playback->client, NULL));
749 WARN_ON(rk29_dma_request(i2s->dma_capture->channel, i2s->dma_capture->client, NULL));
751 i2s->iis_clk = clk_get(&pdev->dev, "i2s");
752 I2S_DBG("Enter:%s, %d, iis_clk=%p\n", __FUNCTION__, __LINE__, i2s->iis_clk);
753 if (IS_ERR(i2s->iis_clk)) {
754 dev_err(&pdev->dev, "failed to get i2s clk\n");
755 ret = PTR_ERR(i2s->iis_clk);
759 clk_enable(i2s->iis_clk);
760 clk_set_rate(i2s->iis_clk, 11289600);
761 ret = rk29_i2s_probe(pdev, dai, i2s, 0);
765 ret = snd_soc_register_dai(&pdev->dev, dai);
772 /* Not implemented for I2Sv2 core yet */
774 clk_put(i2s->iis_clk);
780 static int __devexit rockchip_i2s_remove(struct platform_device *pdev)
782 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
783 snd_soc_unregister_dai(&pdev->dev);
785 snd_soc_unregister_dai(&rk29_i2s_dai);
791 static struct platform_driver rockchip_i2s_driver = {
792 .probe = rockchip_i2s_probe,
793 .remove = __devexit_p(rockchip_i2s_remove),
796 .owner = THIS_MODULE,
800 static int __init rockchip_i2s_init(void)
802 I2S_DBG("Enter %s, %d >>>>>>>>>>>\n", __func__, __LINE__);
804 return platform_driver_register(&rockchip_i2s_driver);
806 module_init(rockchip_i2s_init);
808 static void __exit rockchip_i2s_exit(void)
810 platform_driver_unregister(&rockchip_i2s_driver);
812 module_exit(rockchip_i2s_exit);
814 /* Module information */
815 MODULE_AUTHOR("rockchip");
816 MODULE_DESCRIPTION("ROCKCHIP IIS ASoC Interface");
817 MODULE_LICENSE("GPL");
820 #ifdef CONFIG_PROC_FS
821 #include <linux/proc_fs.h>
822 #include <linux/seq_file.h>
823 static int proc_i2s_show(struct seq_file *s, void *v)
825 struct rk29_i2s_info *i2s=&rk29_i2s[0];
827 printk("========Show I2S reg========\n");
829 printk("I2S_TXCR = 0x%08X\n", readl(&(pheadi2s->I2S_TXCR)));
830 printk("I2S_RXCR = 0x%08X\n", readl(&(pheadi2s->I2S_RXCR)));
831 printk("I2S_TXCKR = 0x%08X\n", readl(&(pheadi2s->I2S_TXCKR)));
832 printk("I2S_RXCKR = 0x%08X\n", readl(&(pheadi2s->I2S_RXCKR)));
833 printk("I2S_DMACR = 0x%08X\n", readl(&(pheadi2s->I2S_DMACR)));
834 printk("I2S_INTCR = 0x%08X\n", readl(&(pheadi2s->I2S_INTCR)));
835 printk("I2S_INTSR = 0x%08X\n", readl(&(pheadi2s->I2S_INTSR)));
836 printk("I2S_XFER = 0x%08X\n", readl(&(pheadi2s->I2S_XFER)));
838 printk("========Show I2S reg========\n");
842 static int proc_i2s_open(struct inode *inode, struct file *file)
844 return single_open(file, proc_i2s_show, NULL);
847 static const struct file_operations proc_i2s_fops = {
848 .open = proc_i2s_open,
851 .release = single_release,
854 static int __init i2s_proc_init(void)
856 proc_create("i2s_reg", 0, NULL, &proc_i2s_fops);
860 late_initcall(i2s_proc_init);
861 #endif /* CONFIG_PROC_FS */