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/board.h>
31 #include <mach/hardware.h>
33 #include <mach/gpio.h>
34 #include <mach/iomux.h>
35 #include <mach/dma-pl330.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 return snd_soc_dai_get_drvdata(cpu_dai);
83 static struct rockchip_pcm_dma_params rk29_i2s_pcm_stereo_out[MAX_I2S];
84 static struct rockchip_pcm_dma_params rk29_i2s_pcm_stereo_in[MAX_I2S];
85 static struct rk29_i2s_info rk29_i2s[MAX_I2S];
87 struct snd_soc_dai_driver rk29_i2s_dai[MAX_I2S];
88 EXPORT_SYMBOL_GPL(rk29_i2s_dai);
90 static u32 i2s0_clk_enter(void)
95 static void i2s0_clk_exit(u32 clk)
100 *Turn on or off the transmission path.
103 static int flag_i2s_tx = 0;
104 static int flag_i2s_rx = 0;
105 static void rockchip_snd_txctrl(struct rk29_i2s_info *i2s, int on, bool stopI2S)
110 opr = readl(&(pheadi2s->I2S_DMACR));
111 xfer = readl(&(pheadi2s->I2S_XFER));
115 I2S_DBG("rockchip_snd_txctrl: on\n");
118 //if ((flag_i2s_tx == 0) && (flag_i2s_rx == 0))
119 if ((xfer&I2S_TX_TRAN_START)==0 || (xfer&I2S_RX_TRAN_START)==0)
121 clk = i2s0_clk_enter();
123 //if start tx & rx clk, need reset i2s
124 xfer |= I2S_TX_TRAN_START;
125 xfer |= I2S_RX_TRAN_START;
126 writel(xfer, &(pheadi2s->I2S_XFER));
131 if ((opr & I2S_TRAN_DMA_ENABLE) == 0)
133 opr |= I2S_TRAN_DMA_ENABLE;
134 writel(opr, &(pheadi2s->I2S_DMACR));
143 if ((flag_i2s_rx == 0) && (flag_i2s_tx == 0))
145 opr &= ~I2S_TRAN_DMA_ENABLE;
146 writel(opr, &(pheadi2s->I2S_DMACR));
149 clk = i2s0_clk_enter();
151 xfer &= ~I2S_RX_TRAN_START;
152 xfer &= ~I2S_TX_TRAN_START;
153 writel(xfer, &(pheadi2s->I2S_XFER));
158 //after stop rx & tx clk, reset i2s
159 //writel(0x001,&(pheadi2s->I2S_TXRST));
160 //writel(0x001,&(pheadi2s->I2S_RXRST));
163 I2S_DBG("rockchip_snd_txctrl: off\n");
168 static void rockchip_snd_rxctrl(struct rk29_i2s_info *i2s, int on, bool stopI2S)
173 opr = readl(&(pheadi2s->I2S_DMACR));
174 xfer = readl(&(pheadi2s->I2S_XFER));
178 I2S_DBG("rockchip_snd_rxctrl: on\n");
181 //if ((flag_i2s_tx == 0) && (flag_i2s_rx == 0))
182 if ((xfer&I2S_TX_TRAN_START)==0 || (xfer&I2S_RX_TRAN_START)==0)
184 clk = i2s0_clk_enter();
186 xfer |= I2S_TX_TRAN_START;
187 xfer |= I2S_RX_TRAN_START;
188 writel(xfer, &(pheadi2s->I2S_XFER));
193 if ((opr & I2S_RECE_DMA_ENABLE) == 0)
195 opr |= I2S_RECE_DMA_ENABLE;
196 writel(opr, &(pheadi2s->I2S_DMACR));
200 #if (CONFIG_SND_SOC_RT5631)
202 schedule_delayed_work(&rt5631_delay_cap,HZ/4);
210 if ((flag_i2s_rx == 0) && (flag_i2s_tx == 0))
212 opr &= ~I2S_RECE_DMA_ENABLE;
213 writel(opr, &(pheadi2s->I2S_DMACR));
217 clk = i2s0_clk_enter();
219 xfer &= ~I2S_RX_TRAN_START;
220 xfer &= ~I2S_TX_TRAN_START;
221 writel(xfer, &(pheadi2s->I2S_XFER));
226 //after stop rx & tx clk, reset i2s
227 //writel(0x001,&(pheadi2s->I2S_TXRST));
228 //writel(0x001,&(pheadi2s->I2S_RXRST));
231 I2S_DBG("rockchip_snd_rxctrl: off\n");
236 * Set Rockchip I2S DAI format
238 static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
241 struct rk29_i2s_info *i2s = to_info(cpu_dai);
243 u32 iis_ckr_value;//clock generation register
245 I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
247 tx_ctl = readl(&(pheadi2s->I2S_TXCR));
248 iis_ckr_value = readl(&(pheadi2s->I2S_CKR));
250 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
251 case SND_SOC_DAIFMT_CBM_CFM:
252 iis_ckr_value &= ~I2S_MODE_MASK;
253 iis_ckr_value |= I2S_MASTER_MODE;
255 case SND_SOC_DAIFMT_CBS_CFS:
256 iis_ckr_value &= ~I2S_MODE_MASK;
257 iis_ckr_value |= I2S_SLAVE_MODE;
260 I2S_DBG("unknwon master/slave format\n");
263 writel(iis_ckr_value, &(pheadi2s->I2S_CKR));
264 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
265 case SND_SOC_DAIFMT_RIGHT_J:
266 tx_ctl &= ~I2S_BUS_MODE_MASK; //I2S Bus Mode
267 tx_ctl |= I2S_BUS_MODE_RSJM;
269 case SND_SOC_DAIFMT_LEFT_J:
270 tx_ctl &= ~I2S_BUS_MODE_MASK; //I2S Bus Mode
271 tx_ctl |= I2S_BUS_MODE_LSJM;
273 case SND_SOC_DAIFMT_I2S:
274 tx_ctl &= ~I2S_BUS_MODE_MASK; //I2S Bus Mode
275 tx_ctl |= I2S_BUS_MODE_NOR;
278 I2S_DBG("Unknown data format\n");
281 I2S_DBG("Enter::%s----%d, I2S_TXCR=0x%X\n",__FUNCTION__,__LINE__,tx_ctl);
282 #if 0//defined(CONFIG_SND_RK29_SOC_alc5631) || defined(CONFIG_SND_RK29_SOC_alc5621)
284 rx_ctl &= ~I2S_MODE_MASK;
285 rx_ctl |= I2S_SLAVE_MODE; // set tx slave, rx master
286 writel(rx_ctl, &(pheadi2s->I2S_TXCR));
288 writel(tx_ctl, &(pheadi2s->I2S_TXCR));
290 rx_ctl = tx_ctl & 0x00007FFF;
291 writel(rx_ctl, &(pheadi2s->I2S_RXCR));
295 static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream,
296 struct snd_pcm_hw_params *params, struct snd_soc_dai *socdai)
298 struct rk29_i2s_info *i2s = to_info(socdai);
301 u32 iis_ckr_value;//clock generation register
303 I2S_DBG("Enter %s, %d >>>>>>>>>>>\n", __func__, __LINE__);
305 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
306 snd_soc_dai_set_dma_data(socdai, substream, i2s->dma_playback);
308 snd_soc_dai_set_dma_data(socdai, substream, i2s->dma_capture);
310 /* Working copies of register */
311 iismod = readl(&(pheadi2s->I2S_TXCR));
313 // iismod &= (~((1<<5)-1));
314 switch (params_format(params)) {
315 case SNDRV_PCM_FORMAT_S8:
316 iismod |= SAMPLE_DATA_8bit;
318 case SNDRV_PCM_FORMAT_S16_LE:
319 iismod |= I2S_DATA_WIDTH(15);
321 case SNDRV_PCM_FORMAT_S20_3LE:
322 iismod |= I2S_DATA_WIDTH(19);
324 case SNDRV_PCM_FORMAT_S24_LE:
325 iismod |= I2S_DATA_WIDTH(23);
327 case SNDRV_PCM_FORMAT_S32_LE:
328 iismod |= I2S_DATA_WIDTH(31);
332 iis_ckr_value = readl(&(pheadi2s->I2S_CKR));
333 #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE)
334 iis_ckr_value &= ~I2S_SLAVE_MODE;
336 #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER)
337 iis_ckr_value |= I2S_SLAVE_MODE;
339 writel(iis_ckr_value, &(pheadi2s->I2S_CKR));
341 // writel((16<<24) |(16<<18)|(16<<12)|(16<<6)|16, &(pheadi2s->I2S_FIFOLR));
342 dmarc = readl(&(pheadi2s->I2S_DMACR));
344 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
345 dmarc = ((dmarc & 0xFFFFFE00) | 16);
347 dmarc = ((dmarc & 0xFE00FFFF) | 16<<16);
349 writel(dmarc, &(pheadi2s->I2S_DMACR));
350 I2S_DBG("Enter %s, %d I2S_TXCR=0x%08X\n", __func__, __LINE__, iismod);
351 #if 0//defined(CONFIG_SND_RK29_SOC_alc5631) || defined(CONFIG_SND_RK29_SOC_alc5621)
353 dmarc &= ~I2S_MODE_MASK;
354 dmarc |= I2S_SLAVE_MODE; // set tx slave, rx master
355 writel(dmarc, &(pheadi2s->I2S_TXCR));
357 writel(iismod, &(pheadi2s->I2S_TXCR));
359 iismod = iismod & 0x00007FFF;
360 writel(iismod, &(pheadi2s->I2S_RXCR));
365 static int rockchip_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai)
368 struct snd_soc_pcm_runtime *rtd = substream->private_data;
369 struct rk29_i2s_info *i2s = to_info(rtd->cpu_dai);
370 bool stopI2S = false;
372 I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
374 case SNDRV_PCM_TRIGGER_START:
375 case SNDRV_PCM_TRIGGER_RESUME:
376 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
377 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
378 rockchip_snd_rxctrl(i2s, 1, stopI2S);
380 rockchip_snd_txctrl(i2s, 1, stopI2S);
383 case SNDRV_PCM_TRIGGER_SUSPEND:
385 case SNDRV_PCM_TRIGGER_STOP:
386 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
387 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
388 rockchip_snd_rxctrl(i2s, 0, stopI2S);
390 rockchip_snd_txctrl(i2s, 0, stopI2S);
401 * Set Rockchip I2S MCLK source
403 static int rockchip_i2s_set_sysclk(struct snd_soc_dai *cpu_dai,
404 int clk_id, unsigned int freq, int dir)
406 struct rk29_i2s_info *i2s;
408 i2s = to_info(cpu_dai);
410 I2S_DBG("Enter:%s, %d, i2s=0x%p, freq=%d\n", __FUNCTION__, __LINE__, i2s, freq);
411 /*add scu clk source and enable clk*/
412 clk_set_rate(i2s->iis_clk, freq);
417 * Set Rockchip Clock dividers
419 static int rockchip_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai,
422 struct rk29_i2s_info *i2s;
425 i2s = to_info(cpu_dai);
427 //stereo mode MCLK/SCK=4
428 reg = readl(&(pheadi2s->I2S_CKR));
430 I2S_DBG("Enter:%s, %d, div_id=0x%08X, div=0x%08X\n", __FUNCTION__, __LINE__, div_id, div);
432 //when i2s in master mode ,must set codec pll div
434 case ROCKCHIP_DIV_BCLK:
435 reg &= ~I2S_TX_SCLK_DIV_MASK;
436 reg |= I2S_TX_SCLK_DIV(div);
437 reg &= ~I2S_RX_SCLK_DIV_MASK;
438 reg |= I2S_RX_SCLK_DIV(div);
440 case ROCKCHIP_DIV_MCLK:
441 reg &= ~I2S_MCLK_DIV_MASK;
442 reg |= I2S_MCLK_DIV(div);
444 case ROCKCHIP_DIV_PRESCALER:
449 writel(reg, &(pheadi2s->I2S_CKR));
455 int rockchip_i2s_suspend(struct snd_soc_dai *cpu_dai)
457 I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
462 int rockchip_i2s_resume(struct snd_soc_dai *cpu_dai)
464 I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
469 #define rockchip_i2s_suspend NULL
470 #define rockchip_i2s_resume NULL
473 #if defined(CONFIG_SND_RK29_SOC_alc5631) || defined(CONFIG_SND_RK29_SOC_alc5621)
474 #define ROCKCHIP_I2S_RATES (SNDRV_PCM_RATE_44100) //zyy 20110704, playback and record use same sample rate
476 #define ROCKCHIP_I2S_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
477 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\
478 SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
481 static struct snd_soc_dai_ops rockchip_i2s_dai_ops = {
482 .trigger = rockchip_i2s_trigger,
483 .hw_params = rockchip_i2s_hw_params,
484 .set_fmt = rockchip_i2s_set_fmt,
485 .set_clkdiv = rockchip_i2s_set_clkdiv,
486 .set_sysclk = rockchip_i2s_set_sysclk,
489 static int rockchip_i2s_dai_probe(struct snd_soc_dai *dai)
491 I2S_DBG("Enter %s, %d >>>>>>>>>>>\n", __func__, __LINE__);
493 #if defined(CONFIG_ARCH_RK3066B)
495 rk30_mux_api_set(GPIO1C0_I2SCLK_NAME, GPIO1C_I2SCLK);
496 rk30_mux_api_set(GPIO1C1_I2SSCLK_NAME, GPIO1C_I2SSCLK);
497 rk30_mux_api_set(GPIO1C2_I2SLRCLKRX_NAME, GPIO1C_I2SLRCLKRX);
498 rk30_mux_api_set(GPIO1C3_I2SLRCLKTX_NAME, GPIO1C_I2SLRCLKTX);
499 rk30_mux_api_set(GPIO1C4_I2SSDI_NAME, GPIO1C_I2SSDI);
500 rk30_mux_api_set(GPIO1C5_I2SSDO_NAME, GPIO1C_I2SSDO);
502 #elif defined(CONFIG_ARCH_RK30)
504 rk30_mux_api_set(GPIO0A7_I2S8CHSDI_NAME, GPIO0A_I2S_8CH_SDI);
505 rk30_mux_api_set(GPIO0B0_I2S8CHCLK_NAME, GPIO0B_I2S_8CH_CLK);
506 rk30_mux_api_set(GPIO0B1_I2S8CHSCLK_NAME, GPIO0B_I2S_8CH_SCLK);
507 rk30_mux_api_set(GPIO0B2_I2S8CHLRCKRX_NAME, GPIO0B_I2S_8CH_LRCK_RX);
508 rk30_mux_api_set(GPIO0B3_I2S8CHLRCKTX_NAME, GPIO0B_I2S_8CH_LRCK_TX);
509 rk30_mux_api_set(GPIO0B4_I2S8CHSDO0_NAME, GPIO0B_I2S_8CH_SDO0);
510 //rk30_mux_api_set(GPIO0B5_I2S8CHSDO1_NAME, GPIO0B_I2S_8CH_SDO1);
511 //rk30_mux_api_set(GPIO0B6_I2S8CHSDO2_NAME, GPIO0B_I2S_8CH_SDO2);
512 //rk30_mux_api_set(GPIO0B7_I2S8CHSDO3_NAME, GPIO0B_I2S_8CH_SDO3);
515 rk30_mux_api_set(GPIO0C0_I2S12CHCLK_NAME, GPIO0C_I2S1_2CH_CLK);
516 rk30_mux_api_set(GPIO0C1_I2S12CHSCLK_NAME, GPIO0C_I2S1_2CH_SCLK);
517 rk30_mux_api_set(GPIO0C2_I2S12CHLRCKRX_NAME, GPIO0C_I2S1_2CH_LRCK_RX);
518 rk30_mux_api_set(GPIO0C3_I2S12CHLRCKTX_NAME, GPIO0C_I2S1_2CH_LRCK_TX);
519 rk30_mux_api_set(GPIO0C4_I2S12CHSDI_NAME, GPIO0C_I2S1_2CH_SDI);
520 rk30_mux_api_set(GPIO0C5_I2S12CHSDO_NAME, GPIO0C_I2S1_2CH_SDO);
523 rk30_mux_api_set(GPIO0D0_I2S22CHCLK_SMCCSN0_NAME, GPIO0D_I2S2_2CH_CLK);
524 rk30_mux_api_set(GPIO0D1_I2S22CHSCLK_SMCWEN_NAME, GPIO0D_I2S2_2CH_SCLK);
525 rk30_mux_api_set(GPIO0D2_I2S22CHLRCKRX_SMCOEN_NAME, GPIO0D_I2S2_2CH_LRCK_RX);
526 rk30_mux_api_set(GPIO0D3_I2S22CHLRCKTX_SMCADVN_NAME, GPIO0D_I2S2_2CH_LRCK_TX);
527 rk30_mux_api_set(GPIO0D4_I2S22CHSDI_SMCADDR0_NAME, GPIO0D_I2S2_2CH_SDI);
528 rk30_mux_api_set(GPIO0D5_I2S22CHSDO_SMCADDR1_NAME, GPIO0D_I2S2_2CH_SDO);
531 #ifdef CONFIG_ARCH_RK2928
533 #if 0 //iomux --> gps(.ko)
534 rk30_mux_api_set(GPIO1A0_I2S_MCLK_NAME, GPIO1A_I2S_MCLK);
535 rk30_mux_api_set(GPIO1A1_I2S_SCLK_NAME, GPIO1A_I2S_SCLK);
536 rk30_mux_api_set(GPIO1A2_I2S_LRCKRX_GPS_CLK_NAME, GPIO1A_I2S_LRCKRX);
537 rk30_mux_api_set(GPIO1A3_I2S_LRCKTX_NAME, GPIO1A_I2S_LRCKTX);
538 rk30_mux_api_set(GPIO1A4_I2S_SDO_GPS_MAG_NAME, GPIO1A_I2S_SDO);
539 rk30_mux_api_set(GPIO1A5_I2S_SDI_GPS_SIGN_NAME, GPIO1A_I2S_SDI);
544 I2S_DBG("Enter:%s, %d, Error For DevId!!!", __FUNCTION__, __LINE__);
550 static int rk29_i2s_probe(struct platform_device *pdev,
551 struct snd_soc_dai_driver *dai,
552 struct rk29_i2s_info *i2s,
555 struct device *dev = &pdev->dev;
556 struct resource *res;
558 I2S_DBG("Enter %s, %d >>>>>>>>>>>\n", __func__, __LINE__);
562 /* record our i2s structure for later use in the callbacks */
563 dev_set_drvdata(&pdev->dev, i2s);
566 res = platform_get_resource(pdev,
570 dev_err(dev, "Unable to get register resource\n");
574 if (!request_mem_region(res->start, resource_size(res),
576 dev_err(dev, "Unable to request register region\n");
583 i2s->regs = ioremap(base, (res->end - res->start) + 1); ////res));
584 if (i2s->regs == NULL) {
585 dev_err(dev, "cannot ioremap registers\n");
589 i2s->iis_pclk = clk_get(dev, "hclk_i2s");
590 if (IS_ERR(i2s->iis_pclk)) {
591 dev_err(dev, "failed to get iis_clock\n");
595 clk_enable(i2s->iis_pclk);
598 /* Mark ourselves as in TXRX mode so we can run through our cleanup
599 * process without warnings. */
600 rockchip_snd_txctrl(i2s, 0, true);
601 rockchip_snd_rxctrl(i2s, 0, true);
606 static int __devinit rockchip_i2s_probe(struct platform_device *pdev)
608 struct rk29_i2s_info *i2s;
609 struct snd_soc_dai_driver *dai;
612 I2S_DBG("Enter %s, %d pdev->id = %d >>>>>>>>>>>\n", __func__, __LINE__, pdev->id);
614 if(pdev->id >= MAX_I2S) {
615 dev_err(&pdev->dev, "id %d out of range\n", pdev->id);
619 i2s = &rk29_i2s[pdev->id];
620 dai = &rk29_i2s_dai[pdev->id];
622 dai->symmetric_rates = 1;
627 dai->name = "rk29_i2s.0";
628 dai->playback.channels_min = 2;
629 dai->playback.channels_max = 8;
632 dai->name = "rk29_i2s.1";
633 dai->playback.channels_min = 2;
634 dai->playback.channels_max = 2;
637 dai->name = "rk29_i2s.2";
638 dai->playback.channels_min = 2;
639 dai->playback.channels_max = 2;
643 dai->playback.rates = ROCKCHIP_I2S_RATES;
644 dai->playback.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE;
645 dai->capture.channels_min = 2;
646 dai->capture.channels_max = 2;
647 dai->capture.rates = ROCKCHIP_I2S_RATES;//;SNDRV_PCM_RATE_44100
648 dai->capture.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE;
649 dai->probe = rockchip_i2s_dai_probe;
650 dai->ops = &rockchip_i2s_dai_ops;
651 dai->suspend = rockchip_i2s_suspend;
652 dai->resume = rockchip_i2s_resume;
654 i2s->dma_capture = &rk29_i2s_pcm_stereo_in[pdev->id];
655 i2s->dma_playback = &rk29_i2s_pcm_stereo_out[pdev->id];
659 #ifdef CONFIG_ARCH_RK30
661 i2s->dma_capture->channel = DMACH_I2S0_8CH_RX;
662 i2s->dma_capture->dma_addr = RK30_I2S0_8CH_PHYS + I2S_RXR_BUFF;
663 i2s->dma_playback->channel = DMACH_I2S0_8CH_TX;
664 i2s->dma_playback->dma_addr = RK30_I2S0_8CH_PHYS + I2S_TXR_BUFF;
667 i2s->dma_capture->channel = DMACH_I2S1_2CH_RX;
668 i2s->dma_capture->dma_addr = RK30_I2S1_2CH_PHYS + I2S_RXR_BUFF;
669 i2s->dma_playback->channel = DMACH_I2S1_2CH_TX;
670 i2s->dma_playback->dma_addr = RK30_I2S1_2CH_PHYS + I2S_TXR_BUFF;
673 i2s->dma_capture->channel = DMACH_I2S2_2CH_RX;
674 i2s->dma_capture->dma_addr = RK30_I2S2_2CH_PHYS + I2S_RXR_BUFF;
675 i2s->dma_playback->channel = DMACH_I2S2_2CH_TX;
676 i2s->dma_playback->dma_addr = RK30_I2S2_2CH_PHYS + I2S_TXR_BUFF;
679 #ifdef CONFIG_ARCH_RK2928
681 i2s->dma_capture->channel = DMACH_I2S0_8CH_RX;
682 i2s->dma_capture->dma_addr = RK2928_I2S_PHYS + I2S_RXR_BUFF;
683 i2s->dma_playback->channel = DMACH_I2S0_8CH_TX;
684 i2s->dma_playback->dma_addr = RK2928_I2S_PHYS + I2S_TXR_BUFF;
689 i2s->dma_capture->client = &rk29_dma_client_in;
690 i2s->dma_capture->dma_size = 4;
691 i2s->dma_capture->flag = 0; //add by sxj, used for burst change
692 i2s->dma_playback->client = &rk29_dma_client_out;
693 i2s->dma_playback->dma_size = 4;
694 i2s->dma_playback->flag = 0; //add by sxj, used for burst change
695 #ifdef CONFIG_SND_I2S_DMA_EVENT_STATIC
696 WARN_ON(rk29_dma_request(i2s->dma_playback->channel, i2s->dma_playback->client, NULL));
697 WARN_ON(rk29_dma_request(i2s->dma_capture->channel, i2s->dma_capture->client, NULL));
700 i2s->iis_clk = clk_get(&pdev->dev, "i2s");
701 I2S_DBG("Enter:%s, %d, iis_clk=%p\n", __FUNCTION__, __LINE__, i2s->iis_clk);
702 if (IS_ERR(i2s->iis_clk)) {
703 dev_err(&pdev->dev, "failed to get i2s clk\n");
704 ret = PTR_ERR(i2s->iis_clk);
708 clk_enable(i2s->iis_clk);
709 clk_set_rate(i2s->iis_clk, 11289600);
711 ret = rk29_i2s_probe(pdev, dai, i2s, 0);
715 ret = snd_soc_register_dai(&pdev->dev, dai);
719 writel(0x0000000F, &(pheadi2s->I2S_TXCR));
720 writel(0x0000000F, &(pheadi2s->I2S_RXCR));
721 writel(0x00071f1F, &(pheadi2s->I2S_CKR));
722 writel(0x001F0110, &(pheadi2s->I2S_DMACR));
723 writel(0x00000003, &(pheadi2s->I2S_XFER));
726 writel(0x5555aaaa, &(pheadi2s->I2S_TXDR));
728 // printk("-----------------------\n");
737 /* Not implemented for I2Sv2 core yet */
739 clk_put(i2s->iis_clk);
744 static int __devexit rockchip_i2s_remove(struct platform_device *pdev)
746 snd_soc_unregister_dai(&pdev->dev);
750 static struct platform_driver rockchip_i2s_driver = {
751 .probe = rockchip_i2s_probe,
752 .remove = __devexit_p(rockchip_i2s_remove),
755 .owner = THIS_MODULE,
759 static int __init rockchip_i2s_init(void)
761 I2S_DBG("Enter %s, %d >>>>>>>>>>>\n", __func__, __LINE__);
763 return platform_driver_register(&rockchip_i2s_driver);
765 module_init(rockchip_i2s_init);
767 static void __exit rockchip_i2s_exit(void)
769 platform_driver_unregister(&rockchip_i2s_driver);
771 module_exit(rockchip_i2s_exit);
773 /* Module information */
774 MODULE_AUTHOR("rockchip");
775 MODULE_DESCRIPTION("ROCKCHIP IIS ASoC Interface");
776 MODULE_LICENSE("GPL");
779 #ifdef CONFIG_PROC_FS
780 #include <linux/proc_fs.h>
781 #include <linux/seq_file.h>
782 static int proc_i2s_show(struct seq_file *s, void *v)
784 #ifdef CONFIG_SND_RK29_SOC_I2S_8CH
785 struct rk29_i2s_info *i2s=&rk29_i2s[0];
787 #ifdef CONFIG_SND_RK29_SOC_I2S_2CH
788 struct rk29_i2s_info *i2s=&rk29_i2s[1];
790 struct rk29_i2s_info *i2s=&rk29_i2s[2];
793 printk("========Show I2S reg========\n");
795 printk("I2S_TXCR = 0x%08X\n", readl(&(pheadi2s->I2S_TXCR)));
796 printk("I2S_RXCR = 0x%08X\n", readl(&(pheadi2s->I2S_RXCR)));
797 printk("I2S_CKR = 0x%08X\n", readl(&(pheadi2s->I2S_CKR)));
798 printk("I2S_DMACR = 0x%08X\n", readl(&(pheadi2s->I2S_DMACR)));
799 printk("I2S_INTCR = 0x%08X\n", readl(&(pheadi2s->I2S_INTCR)));
800 printk("I2S_INTSR = 0x%08X\n", readl(&(pheadi2s->I2S_INTSR)));
801 printk("I2S_XFER = 0x%08X\n", readl(&(pheadi2s->I2S_XFER)));
803 printk("========Show I2S reg========\n");
807 static int proc_i2s_open(struct inode *inode, struct file *file)
809 return single_open(file, proc_i2s_show, NULL);
812 static const struct file_operations proc_i2s_fops = {
813 .open = proc_i2s_open,
816 .release = single_release,
819 static int __init i2s_proc_init(void)
821 proc_create("i2s_reg", 0, NULL, &proc_i2s_fops);
824 late_initcall(i2s_proc_init);
825 #endif /* CONFIG_PROC_FS */