a5fd9aa488ffdd2cca6c52a7c63aaf1e4cd2e11c
[firefly-linux-kernel-4.4.55.git] / sound / soc / rk29 / rk29_i2s.c
1 /*
2  * rk29_i2s.c  --  ALSA SoC ROCKCHIP IIS Audio Layer Platform driver
3  *
4  * Driver for rockchip iis audio
5  *
6  *
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.
11  *
12  */
13
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
21 #include <asm/dma.h>
22 #include <sound/core.h>
23 #include <sound/pcm.h>
24 #include <sound/pcm_params.h>
25 #include <sound/initval.h>
26 #include <sound/soc.h>
27 #include <asm/io.h>
28
29 #include <mach/hardware.h>
30 #include <mach/board.h>
31 #include <mach/rk29_iomap.h>
32 #include <mach/rk29-dma-pl330.h>
33 #include <mach/iomux.h>
34
35 #include "rk29_pcm.h"
36 #include "rk29_i2s.h"
37
38
39 #if 0
40 #define I2S_DBG(x...) printk(KERN_INFO x)
41 #else
42 #define I2S_DBG(x...) do { } while (0)
43 #endif
44
45 #define pheadi2s  ((pI2S_REG)(i2s->regs))
46
47 #define MAX_I2S         2
48
49 struct rk29_i2s_info {
50         struct device   *dev;
51         void __iomem    *regs;
52         
53         u32     feature;
54
55         struct clk      *iis_clk;
56         struct clk      *iis_pclk;
57
58         unsigned char   master;
59
60         struct rockchip_pcm_dma_params  *dma_playback;
61         struct rockchip_pcm_dma_params  *dma_capture;
62
63         u32              suspend_iismod;
64         u32              suspend_iiscon;
65         u32              suspend_iispsr;
66 };
67
68 static struct rk29_dma_client rk29_dma_client_out = {
69         .name = "I2S PCM Stereo Out"
70 };
71
72 static struct rk29_dma_client rk29_dma_client_in = {
73         .name = "I2S PCM Stereo In"
74 };
75
76 static inline struct rk29_i2s_info *to_info(struct snd_soc_dai *cpu_dai)
77 {
78         return cpu_dai->private_data;
79 }
80
81 static struct rockchip_pcm_dma_params rk29_i2s_pcm_stereo_out[MAX_I2S];
82 static struct rockchip_pcm_dma_params rk29_i2s_pcm_stereo_in[MAX_I2S];
83 static struct rk29_i2s_info rk29_i2s[MAX_I2S];
84
85 struct snd_soc_dai rk29_i2s_dai[MAX_I2S];
86 EXPORT_SYMBOL_GPL(rk29_i2s_dai);
87
88 /*
89 static struct rockchip_pcm_dma_params rockchip_i2s_pcm_stereo_out[MAX_I2S] = {
90         [0] = {
91                 .client         = &rk29_dma_client_out,
92                 .channel        = DMACH_I2S_2CH_TX, ///0,  //DMACH_I2S_OUT,
93                 .dma_addr       = RK29_I2S_2CH_PHYS + I2S_TXR_BUFF,
94                 .dma_size       = 4,
95         },
96         [1] = {
97                 .client         = &rk29_dma_client_out,
98                 .channel        = DMACH_I2S_8CH_TX, ///0,  //DMACH_I2S_OUT,
99                 .dma_addr       = RK29_I2S_8CH_PHYS + I2S_TXR_BUFF,
100                 .dma_size       = 4,
101         },
102 };
103
104 static struct rockchip_pcm_dma_params rockchip_i2s_pcm_stereo_in[MAX_I2S] = {
105         [0] = {
106                 .client         = &rk29_dma_client_in,
107                 .channel        = DMACH_I2S_2CH_RX,  ///1,  //DMACH_I2S_IN,
108                 .dma_addr       = RK29_I2S_2CH_PHYS + I2S_RXR_BUFF,
109                 .dma_size       = 4,
110         },
111         [1] = {
112                 .client         = &rk29_dma_client_in,
113                 .channel        = DMACH_I2S_8CH_RX,  ///1,  //DMACH_I2S_IN,
114                 .dma_addr       = RK29_I2S_8CH_PHYS + I2S_RXR_BUFF,
115                 .dma_size       = 4,
116         },
117 };
118 */
119
120
121
122
123 /* 
124  *Turn on or off the transmission path. 
125  */
126 static void rockchip_snd_txctrl(struct rk29_i2s_info *i2s, int on)
127 {
128         u32 opr,xfer,fifosts;
129     
130         I2S_DBG("Enter %s, %d >>>>>>>>>>>\n", __func__, __LINE__);
131         opr  = readl(&(pheadi2s->I2S_DMACR));
132         xfer = readl(&(pheadi2s->I2S_XFER));
133         opr  &= ~I2S_TRAN_DMA_ENABLE;
134         xfer &= ~I2S_TX_TRAN_START;       
135         if (on) 
136         {                
137                 writel(opr, &(pheadi2s->I2S_DMACR));
138                 writel(xfer, &(pheadi2s->I2S_XFER));
139                 udelay(5);
140
141                 opr  |= I2S_TRAN_DMA_ENABLE;
142                 xfer |= I2S_TX_TRAN_START;
143                 writel(opr, &(pheadi2s->I2S_DMACR));
144                 writel(xfer, &(pheadi2s->I2S_XFER));
145         }
146         else
147         {
148                 writel(opr, &(pheadi2s->I2S_DMACR));
149                 writel(xfer, &(pheadi2s->I2S_XFER));
150         } 
151 }
152
153 static void rockchip_snd_rxctrl(struct rk29_i2s_info *i2s, int on)
154 {
155         u32 opr,xfer,fifosts;
156           
157         I2S_DBG("Enter %s, %d >>>>>>>>>>>\n", __func__, __LINE__);
158
159         opr  = readl(&(pheadi2s->I2S_DMACR));
160         xfer = readl(&(pheadi2s->I2S_XFER));
161         
162         opr  &= ~I2S_RECE_DMA_ENABLE;
163         xfer &= ~I2S_RX_TRAN_START;
164         
165         if (on) 
166         {                
167                 writel(opr, &(pheadi2s->I2S_DMACR));
168                 writel(xfer, &(pheadi2s->I2S_XFER));
169                 udelay(5);
170
171                 opr  |= I2S_RECE_DMA_ENABLE;
172                 xfer |= I2S_RX_TRAN_START;
173                 writel(opr, &(pheadi2s->I2S_DMACR));
174                 writel(xfer, &(pheadi2s->I2S_XFER));
175         }
176         else
177         {
178                 writel(opr, &(pheadi2s->I2S_DMACR));
179                 writel(xfer, &(pheadi2s->I2S_XFER));
180         }  
181 }
182
183 /*
184  * Set Rockchip I2S DAI format
185  */
186 static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
187                 unsigned int fmt)
188 {
189         struct rk29_i2s_info *i2s = to_info(cpu_dai);   
190         u32 tx_ctl,rx_ctl;
191
192         I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
193
194         tx_ctl = readl(&(pheadi2s->I2S_TXCR));
195
196         switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
197                 case SND_SOC_DAIFMT_CBM_CFM:    
198                         tx_ctl &= ~I2S_MODE_MASK;  
199                         tx_ctl |= I2S_MASTER_MODE;
200                         break;
201                 case SND_SOC_DAIFMT_CBS_CFS:
202                         tx_ctl &= ~I2S_MODE_MASK;   
203                         tx_ctl |= I2S_SLAVE_MODE;
204                         break;
205                 default:
206                         I2S_DBG("unknwon master/slave format\n");
207                         return -EINVAL;
208         }       
209
210         switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
211                 case SND_SOC_DAIFMT_RIGHT_J:
212                         tx_ctl &= ~I2S_BUS_MODE_MASK;    //I2S Bus Mode
213                         tx_ctl |= I2S_BUS_MODE_RSJM;
214                         break;
215                 case SND_SOC_DAIFMT_LEFT_J:
216                         tx_ctl &= ~I2S_BUS_MODE_MASK;    //I2S Bus Mode
217                         tx_ctl |= I2S_BUS_MODE_LSJM;
218                         break;
219                 case SND_SOC_DAIFMT_I2S:
220                         tx_ctl &= ~I2S_BUS_MODE_MASK;    //I2S Bus Mode
221                         tx_ctl |= I2S_BUS_MODE_NOR;
222                         break;
223                 default:
224                         I2S_DBG("Unknown data format\n");
225                         return -EINVAL;
226         }
227         I2S_DBG("Enter::%s----%d, I2S_TXCR=0x%X\n",__FUNCTION__,__LINE__,tx_ctl);
228         writel(tx_ctl, &(pheadi2s->I2S_TXCR));
229         rx_ctl = tx_ctl & 0x00007FFF;
230         writel(rx_ctl, &(pheadi2s->I2S_RXCR));
231         return 0;
232 }
233
234 static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream,
235                                 struct snd_pcm_hw_params *params, struct snd_soc_dai *socdai)
236 {
237         struct snd_soc_pcm_runtime *rtd = substream->private_data;
238         struct snd_soc_dai_link *dai = rtd->dai;
239         struct rk29_i2s_info *i2s = to_info(dai->cpu_dai);
240         u32 iismod;
241           
242         I2S_DBG("Enter %s, %d >>>>>>>>>>>\n", __func__, __LINE__);
243         /*by Vincent Hsiung for EQ Vol Change*/
244         #define HW_PARAMS_FLAG_EQVOL_ON 0x21
245         #define HW_PARAMS_FLAG_EQVOL_OFF 0x22
246         if ((params->flags == HW_PARAMS_FLAG_EQVOL_ON)||(params->flags == HW_PARAMS_FLAG_EQVOL_OFF))
247         {
248                 return 0;
249         }
250            
251         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
252                 dai->cpu_dai->dma_data = i2s->dma_playback;
253         else
254                 dai->cpu_dai->dma_data = i2s->dma_capture;
255                 
256         /* Working copies of register */
257         iismod = readl(&(pheadi2s->I2S_TXCR));
258         //iismod &= (~((1<<5)-1));
259         switch (params_format(params)) {
260         case SNDRV_PCM_FORMAT_S8:
261                 iismod |= SAMPLE_DATA_8bit;
262                 break;
263         case SNDRV_PCM_FORMAT_S16_LE:
264                 iismod |= I2S_DATA_WIDTH(15);
265                 break;
266         case SNDRV_PCM_FORMAT_S20_3LE:
267                 iismod |= I2S_DATA_WIDTH(19);
268                 break;
269         case SNDRV_PCM_FORMAT_S24_LE:
270                 iismod |= I2S_DATA_WIDTH(23);
271                 break;
272         case SNDRV_PCM_FORMAT_S32_LE:
273                 iismod |= I2S_DATA_WIDTH(31);
274                 break;
275         }
276         #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) 
277         iismod |= I2S_MASTER_MODE;
278         #endif
279
280         #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) 
281         iismod |= I2S_SLAVE_MODE;
282         #endif
283
284         writel((16<<24) |(16<<18)|(16<<12)|(16<<6)|16, &(pheadi2s->I2S_FIFOLR));
285
286         I2S_DBG("Enter %s, %d I2S_TXCR=0x%08X\n", __func__, __LINE__, iismod);  
287         writel(iismod, &(pheadi2s->I2S_TXCR));
288         iismod = iismod & 0x00007FFF;
289         writel(iismod, &(pheadi2s->I2S_RXCR));        
290         return 0;
291 }
292
293
294 static int rockchip_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai)
295 {    
296         int ret = 0;
297         struct snd_soc_pcm_runtime *rtd = substream->private_data;
298         struct rk29_i2s_info *i2s = to_info(rtd->dai->cpu_dai);
299
300         I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
301
302         switch (cmd) {
303         case SNDRV_PCM_TRIGGER_START:
304         case SNDRV_PCM_TRIGGER_RESUME:
305         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:   
306                 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
307                         rockchip_snd_rxctrl(i2s, 1);
308                 else
309                         rockchip_snd_txctrl(i2s, 1);
310                 break;
311         case SNDRV_PCM_TRIGGER_STOP:
312         case SNDRV_PCM_TRIGGER_SUSPEND:
313         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
314                 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
315                         rockchip_snd_rxctrl(i2s, 0);
316                 else
317                         rockchip_snd_txctrl(i2s, 0);
318                 break;
319         default:
320                 ret = -EINVAL;
321                 break;
322         }
323
324         return ret;
325 }
326 /*
327  * Set Rockchip Clock source
328  */
329 static int rockchip_i2s_set_sysclk(struct snd_soc_dai *cpu_dai,
330         int clk_id, unsigned int freq, int dir)
331 {
332         struct rk29_i2s_info *i2s;        
333
334         i2s = to_info(cpu_dai);
335         
336         I2S_DBG("Enter:%s, %d, i2s=0x%p, freq=%d\n", __FUNCTION__, __LINE__, i2s, freq);
337         /*add scu clk source and enable clk*/
338         clk_set_rate(i2s->iis_clk, freq);
339         return 0;
340 }
341
342 /*
343  * Set Rockchip Clock dividers
344  */
345 static int rockchip_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai,
346         int div_id, int div)
347 {
348         struct rk29_i2s_info *i2s;
349         u32    reg;
350
351         i2s = to_info(cpu_dai);
352         
353         /*stereo mode MCLK/SCK=4*/  
354         
355         reg    = readl(&(pheadi2s->I2S_TXCKR));
356
357         I2S_DBG("Enter:%s, %d, div_id=0x%08X, div=0x%08X\n", __FUNCTION__, __LINE__, div_id, div);
358         
359         /*when i2s in master mode ,must set codec pll div*/
360         switch (div_id) {
361         case ROCKCHIP_DIV_BCLK:
362                 reg &= ~I2S_TX_SCLK_DIV_MASK;
363                 reg |= I2S_TX_SCLK_DIV(div);
364                 break;
365         case ROCKCHIP_DIV_MCLK:
366                 reg &= ~I2S_MCLK_DIV_MASK;
367                 reg |= I2S_MCLK_DIV(div);
368                 break;
369         case ROCKCHIP_DIV_PRESCALER:
370                 
371                 break;
372         default:
373                 return -EINVAL;
374         }
375         writel(reg, &(pheadi2s->I2S_TXCKR));
376         writel(reg, &(pheadi2s->I2S_RXCKR));
377         return 0;
378 }
379
380 static int rockchip_set_sysclk(struct snd_soc_dai *cpu_dai,
381                                 int clk_id, unsigned int freq, int dir)
382 {
383         return 0;
384 }
385
386
387 /*
388  * To avoid duplicating clock code, allow machine driver to
389  * get the clockrate from here.
390  */
391 u32 rockchip_i2s_get_clockrate(void)
392 {
393         I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
394         return 0;  ///clk_get_rate(s3c24xx_i2s.iis_clk);
395 }
396 EXPORT_SYMBOL_GPL(rockchip_i2s_get_clockrate);
397
398 #ifdef CONFIG_PM
399 int rockchip_i2s_suspend(struct snd_soc_dai *cpu_dai)
400 {
401         I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
402         //clk_disable(clk);
403         return 0;
404 }
405
406 int rockchip_i2s_resume(struct snd_soc_dai *cpu_dai)
407 {
408         I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
409         //clk_enable(clk);
410         return 0;
411 }               
412 #else
413 #define rockchip_i2s_suspend NULL
414 #define rockchip_i2s_resume NULL
415 #endif
416
417 #define ROCKCHIP_I2S_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
418                             SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\
419                             SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
420
421 static struct snd_soc_dai_ops rockchip_i2s_dai_ops = {
422         .trigger = rockchip_i2s_trigger,
423         .hw_params = rockchip_i2s_hw_params,
424         .set_fmt = rockchip_i2s_set_fmt,
425         .set_clkdiv = rockchip_i2s_set_clkdiv,
426         .set_sysclk = rockchip_i2s_set_sysclk,
427 };
428
429 static int rockchip_i2s_dai_probe(struct platform_device *pdev, struct snd_soc_dai *dai)
430 {       
431         I2S_DBG("Enter %s, %d >>>>>>>>>>>\n", __func__, __LINE__);
432
433         switch(dai->id) {
434         case 0:
435                 rk29_mux_api_set(GPIO2D0_I2S0CLK_MIIRXCLKIN_NAME, GPIO2H_I2S0_CLK);                
436                 rk29_mux_api_set(GPIO2D1_I2S0SCLK_MIICRS_NAME, GPIO2H_I2S0_SCLK);
437                 rk29_mux_api_set(GPIO2D2_I2S0LRCKRX_MIITXERR_NAME, GPIO2H_I2S0_LRCK_RX);
438                 rk29_mux_api_set(GPIO2D3_I2S0SDI_MIICOL_NAME, GPIO2H_I2S0_SDI);
439                 rk29_mux_api_set(GPIO2D4_I2S0SDO0_MIIRXD2_NAME, GPIO2H_I2S0_SDO0);
440                 rk29_mux_api_set(GPIO2D5_I2S0SDO1_MIIRXD3_NAME, GPIO2H_I2S0_SDO1);
441                 rk29_mux_api_set(GPIO2D6_I2S0SDO2_MIITXD2_NAME, GPIO2H_I2S0_SDO2);
442                 rk29_mux_api_set(GPIO2D7_I2S0SDO3_MIITXD3_NAME, GPIO2H_I2S0_SDO3);
443                 
444                 rk29_mux_api_set(GPIO4D6_I2S0LRCKTX0_NAME, GPIO4H_I2S0_LRCK_TX0);
445                 rk29_mux_api_set(GPIO4D7_I2S0LRCKTX1_NAME, GPIO4H_I2S0_LRCK_TX1);
446                 break;
447         case 1:
448                 rk29_mux_api_set(GPIO3A0_I2S1CLK_NAME, GPIO3L_I2S1_CLK);
449                 rk29_mux_api_set(GPIO3A1_I2S1SCLK_NAME, GPIO3L_I2S1_SCLK);
450                 rk29_mux_api_set(GPIO3A2_I2S1LRCKRX_NAME, GPIO3L_I2S1_LRCK_RX);
451                 rk29_mux_api_set(GPIO3A3_I2S1SDI_NAME, GPIO3L_I2S1_SDI);
452                 rk29_mux_api_set(GPIO3A4_I2S1SDO_NAME, GPIO3L_I2S1_SDO);
453                 rk29_mux_api_set(GPIO3A5_I2S1LRCKTX_NAME, GPIO3L_I2S1_LRCK_TX);
454                 break;
455         default:
456                 I2S_DBG("Enter:%s, %d, Error For DevId!!!", __FUNCTION__, __LINE__);
457                 return -EINVAL;
458         }
459         return 0;
460 }
461
462 static int rk29_i2s_probe(struct platform_device *pdev,
463                     struct snd_soc_dai *dai,
464                     struct rk29_i2s_info *i2s,
465                     unsigned long base)
466 {
467         struct device *dev = &pdev->dev;
468         struct resource *res;
469
470         I2S_DBG("Enter %s, %d >>>>>>>>>>>\n", __func__, __LINE__);
471
472         i2s->dev = dev;
473
474         /* record our i2s structure for later use in the callbacks */
475         dai->private_data = i2s;
476
477         if (!base) {
478                 res = platform_get_resource(pdev,
479                                              IORESOURCE_MEM,
480                                              0);
481                 if (!res) {
482                         dev_err(dev, "Unable to get register resource\n");
483                         return -ENXIO;
484                 }
485
486                 if (!request_mem_region(res->start, resource_size(res),
487                                         "rk29_i2s")) {
488                         dev_err(dev, "Unable to request register region\n");
489                         return -EBUSY;
490                 }
491
492                 base = res->start;
493         }
494
495         i2s->regs = ioremap(base, (res->end - res->start) + 1); ////res));
496         if (i2s->regs == NULL) {
497                 dev_err(dev, "cannot ioremap registers\n");
498                 return -ENXIO;
499         }
500
501         i2s->iis_pclk = clk_get(dev, "i2s");
502         if (IS_ERR(i2s->iis_pclk)) {
503                 dev_err(dev, "failed to get iis_clock\n");
504                 iounmap(i2s->regs);
505                 return -ENOENT;
506         }
507
508         clk_enable(i2s->iis_pclk);
509
510         /* Mark ourselves as in TXRX mode so we can run through our cleanup
511          * process without warnings. */
512         rockchip_snd_txctrl(i2s, 0);
513         rockchip_snd_rxctrl(i2s, 0);
514
515         return 0;
516 }
517
518 static int rk29_i2s_register_dai(struct snd_soc_dai *dai)
519 {
520         struct snd_soc_dai_ops *ops = dai->ops;
521
522         ops->trigger = rockchip_i2s_trigger;
523         if (!ops->hw_params)
524                 ops->hw_params = rockchip_i2s_hw_params;
525         ops->set_fmt = rockchip_i2s_set_fmt;
526         ops->set_clkdiv = rockchip_i2s_set_clkdiv;
527         ops->set_sysclk = rockchip_i2s_set_sysclk;
528
529         dai->suspend = rockchip_i2s_suspend;
530         dai->resume = rockchip_i2s_resume;
531
532         return snd_soc_register_dai(dai);
533 }
534
535 static int __devinit rockchip_i2s_probe(struct platform_device *pdev)
536 {
537         struct rk29_i2s_info *i2s;
538         struct snd_soc_dai *dai;
539         int    ret;
540
541         I2S_DBG("Enter %s, %d pdev->id = %d >>>>>>>>>>>\n", __func__, __LINE__, pdev->id);
542
543         if(pdev->id >= MAX_I2S) {
544                 dev_err(&pdev->dev, "id %d out of range\n", pdev->id);
545                 return -EINVAL;        
546         }
547
548         i2s = &rk29_i2s[pdev->id];
549         dai = &rk29_i2s_dai[pdev->id];
550         dai->dev = &pdev->dev;
551         dai->name = "rk29_i2s";
552         dai->id = pdev->id;
553         dai->symmetric_rates = 1;
554         if(pdev->id == 0) {
555                 dai->playback.channels_min = 2;
556                 dai->playback.channels_max = 8;
557         }else{
558                 dai->playback.channels_min = 2;
559                 dai->playback.channels_max = 2;
560         }
561         dai->playback.rates = ROCKCHIP_I2S_RATES;
562         dai->playback.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE;
563         dai->capture.channels_min = 2;
564         dai->capture.channels_max = 2;
565         dai->capture.rates = SNDRV_PCM_RATE_44100;//ROCKCHIP_I2S_RATES;
566         dai->capture.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE;
567         dai->probe = rockchip_i2s_dai_probe; 
568         dai->ops = &rockchip_i2s_dai_ops;
569
570         //i2s->feature |= S3C_FEATURE_CDCLKCON;
571
572         i2s->dma_capture = &rk29_i2s_pcm_stereo_in[pdev->id];
573         i2s->dma_playback = &rk29_i2s_pcm_stereo_out[pdev->id];
574
575         if (pdev->id == 1) {
576                 i2s->dma_capture->channel = DMACH_I2S_2CH_RX;
577                 i2s->dma_capture->dma_addr = RK29_I2S_2CH_PHYS + I2S_RXR_BUFF;
578                 i2s->dma_playback->channel = DMACH_I2S_2CH_TX;
579                 i2s->dma_playback->dma_addr = RK29_I2S_2CH_PHYS + I2S_TXR_BUFF;
580         } else {
581                 i2s->dma_capture->channel = DMACH_I2S_8CH_RX;
582                 i2s->dma_capture->dma_addr = RK29_I2S_8CH_PHYS + I2S_RXR_BUFF;
583                 i2s->dma_playback->channel = DMACH_I2S_8CH_TX;
584                 i2s->dma_playback->dma_addr = RK29_I2S_8CH_PHYS + I2S_TXR_BUFF;
585         }
586
587         i2s->dma_capture->client = &rk29_dma_client_in;
588         i2s->dma_capture->dma_size = 4;
589         i2s->dma_playback->client = &rk29_dma_client_out;
590         i2s->dma_playback->dma_size = 4;
591
592         i2s->iis_clk = clk_get(&pdev->dev, "i2s");
593         I2S_DBG("Enter:%s, %d, iis_clk=%d\n", __FUNCTION__, __LINE__, i2s->iis_clk);
594         if (IS_ERR(i2s->iis_clk)) {
595                 dev_err(&pdev->dev, "failed to get i2s clk\n");
596                 ret = PTR_ERR(i2s->iis_clk);
597                 goto err;
598         }
599
600         clk_enable(i2s->iis_clk);
601         clk_set_rate(i2s->iis_clk, 11289600);
602         ret = rk29_i2s_probe(pdev, dai, i2s, 0);
603         if (ret)
604                 goto err_clk;
605
606         ret = rk29_i2s_register_dai(dai);
607         if (ret != 0)
608                 goto err_i2sv2;
609
610         return 0;
611
612 err_i2sv2:
613         /* Not implemented for I2Sv2 core yet */
614 err_clk:
615         clk_put(i2s->iis_clk);
616 err:
617         return ret;
618 }
619
620
621 static int __devexit rockchip_i2s_remove(struct platform_device *pdev)
622 {
623         snd_soc_unregister_dai(&rk29_i2s_dai);
624
625         return 0;
626 }
627
628 static struct platform_driver rockchip_i2s_driver = {
629         .probe  = rockchip_i2s_probe,
630         .remove = __devexit_p(rockchip_i2s_remove),
631         .driver = {
632                 .name   = "rk29_i2s",
633                 .owner  = THIS_MODULE,
634         },
635 };
636
637 static int __init rockchip_i2s_init(void)
638 {
639         I2S_DBG("Enter %s, %d >>>>>>>>>>>\n", __func__, __LINE__);
640         
641         return  platform_driver_register(&rockchip_i2s_driver);
642 }
643 module_init(rockchip_i2s_init);
644
645 static void __exit rockchip_i2s_exit(void)
646 {
647         platform_driver_unregister(&rockchip_i2s_driver);
648 }
649 module_exit(rockchip_i2s_exit);
650
651 /* Module information */
652 MODULE_AUTHOR("rockchip");
653 MODULE_DESCRIPTION("ROCKCHIP IIS ASoC Interface");
654 MODULE_LICENSE("GPL");
655