f2d466cd2231e6e1d076645ff4f47677d42b95c4
[firefly-linux-kernel-4.4.55.git] / sound / soc / rockchip / rk30_i2s.c
1 /*
2  * rk30_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 #include <linux/version.h>
21 #include <linux/of.h>
22 #include <linux/of_gpio.h>
23 #include <linux/clk.h>
24 #include <linux/io.h>
25 #include <linux/platform_device.h>
26 #include <linux/pm_runtime.h>
27 #include <linux/regmap.h>
28 #include <linux/slab.h>
29 #include <asm/dma.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>
36 #include <asm/io.h>
37 #include <linux/spinlock.h>
38 #include <linux/workqueue.h>
39
40 #define CLK_SET_lATER
41
42 #include "rk_pcm.h"
43 #include "rk_i2s.h"
44
45 #if 0
46 #define I2S_DBG(x...) printk(KERN_INFO x)
47 #else
48 #define I2S_DBG(x...) do { } while (0)
49 #endif
50
51 #define pheadi2s  ((pI2S_REG)(i2s->regs))
52
53 #define MAX_I2S 3
54
55 static DEFINE_SPINLOCK(lock);
56
57 struct rk30_i2s_info {
58         void __iomem    *regs;
59
60         struct clk *i2s_clk;// i2s clk ,is bclk lrck
61         struct clk *i2s_mclk;//i2s mclk,rk32xx can different i2s clk.
62
63         struct snd_dmaengine_dai_dma_data capture_dma_data;
64         struct snd_dmaengine_dai_dma_data playback_dma_data;
65
66         bool i2s_tx_status;//active = true;
67         bool i2s_rx_status;
68 #ifdef CLK_SET_lATER
69         struct delayed_work clk_delayed_work;
70 #endif  
71 };
72
73 #define I2S_CLR_ERROR_COUNT 10// check I2S_CLR reg 
74 static struct rk30_i2s_info *rk30_i2s;
75
76 #if defined (CONFIG_RK_HDMI) && defined (CONFIG_SND_RK_SOC_HDMI_I2S)
77 extern int hdmi_get_hotplug(void);
78 #else
79 #define hdmi_get_hotplug() 0
80 #endif
81
82 static inline struct rk30_i2s_info *to_info(struct snd_soc_dai *dai)
83 {
84         return snd_soc_dai_get_drvdata(dai);
85 }
86
87 /* 
88  *Turn on or off the transmission path. 
89  */
90 static void rockchip_snd_txctrl(struct rk30_i2s_info *i2s, int on)
91 {
92         u32 opr, xfer, clr;
93         unsigned long flags;
94         bool is_need_delay = false;
95         int clr_error_count = I2S_CLR_ERROR_COUNT;
96
97         spin_lock_irqsave(&lock, flags);
98
99         opr  = readl(&(pheadi2s->I2S_DMACR));
100         xfer = readl(&(pheadi2s->I2S_XFER));
101         clr  = readl(&(pheadi2s->I2S_CLR));
102
103         I2S_DBG("rockchip_snd_txctrl: %s\n", on ? "on" : "off");
104
105         if (on) {
106                 if ((opr & I2S_TRAN_DMA_ENABLE) == 0) {
107                         opr  |= I2S_TRAN_DMA_ENABLE;
108                         writel(opr, &(pheadi2s->I2S_DMACR));
109                 }
110
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));
115                 }
116
117                 i2s->i2s_tx_status = 1;
118
119         } else { //stop tx
120                 i2s->i2s_tx_status = 0;
121                 opr  &= ~I2S_TRAN_DMA_ENABLE;
122                 writel(opr, &(pheadi2s->I2S_DMACR));
123
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));    
128
129                         clr |= I2S_TX_CLEAR;
130                         clr |= I2S_RX_CLEAR;
131                         writel(clr, &(pheadi2s->I2S_CLR));
132
133                         is_need_delay = true;
134
135                         I2S_DBG("rockchip_snd_txctrl: stop xfer\n");
136                 }
137         }
138
139         spin_unlock_irqrestore(&lock, flags);
140
141         if (is_need_delay){
142                 while(readl(&(pheadi2s->I2S_CLR)) && clr_error_count){
143                         udelay(1);
144                         clr_error_count --;
145                         if(clr_error_count == 0)
146                                 printk("%s: i2s clr reg warning =%d",__FUNCTION__,readl(&(pheadi2s->I2S_CLR)));
147                 }
148         }       
149 }
150
151 static void rockchip_snd_rxctrl(struct rk30_i2s_info *i2s, int on)
152 {
153         u32 opr, xfer, clr;
154         unsigned long flags;
155         bool is_need_delay = false;
156         int clr_error_count = I2S_CLR_ERROR_COUNT;
157
158         spin_lock_irqsave(&lock, flags);
159
160         opr  = readl(&(pheadi2s->I2S_DMACR));
161         xfer = readl(&(pheadi2s->I2S_XFER));
162         clr  = readl(&(pheadi2s->I2S_CLR));
163
164         I2S_DBG("rockchip_snd_rxctrl: %s\n", on ? "on" : "off");
165
166         if (on) {
167                 if ((opr & I2S_RECE_DMA_ENABLE) == 0) {
168                         opr  |= I2S_RECE_DMA_ENABLE;
169                         writel(opr, &(pheadi2s->I2S_DMACR));
170                 }
171
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));
176                 }
177
178                 i2s->i2s_rx_status = 1;
179         } else {
180                 i2s->i2s_rx_status = 0;
181
182                 opr  &= ~I2S_RECE_DMA_ENABLE;
183                 writel(opr, &(pheadi2s->I2S_DMACR));
184
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));
189
190                         clr |= I2S_RX_CLEAR;
191                         clr |= I2S_TX_CLEAR;
192                         writel(clr, &(pheadi2s->I2S_CLR));
193
194                         is_need_delay = true;
195
196                         I2S_DBG("rockchip_snd_rxctrl: stop xfer\n");
197                 }
198         }
199
200         spin_unlock_irqrestore(&lock, flags);
201
202         if (is_need_delay){
203                 while(readl(&(pheadi2s->I2S_CLR)) && clr_error_count){
204                         udelay(1);
205                         clr_error_count --;
206                         if(clr_error_count == 0)
207                                 printk("%s: i2s clr reg warning =%d",__FUNCTION__,readl(&(pheadi2s->I2S_CLR)));
208                 }
209         }
210 }
211
212 /*
213  * Set Rockchip I2S DAI format
214  */
215 static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
216                                                 unsigned int fmt)
217 {
218         struct rk30_i2s_info *i2s = to_info(cpu_dai);
219         u32 tx_ctl,rx_ctl;
220         u32 iis_ckr_value;//clock generation register
221         unsigned long flags;
222         int ret = 0;
223
224         I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
225
226         spin_lock_irqsave(&lock, flags);
227
228         tx_ctl = readl(&(pheadi2s->I2S_TXCR));
229         iis_ckr_value = readl(&(pheadi2s->I2S_CKR));
230
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;
236                 break;
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;
241                 break;
242         default:
243                 I2S_DBG("unknwon master/slave format\n");
244                 ret = -EINVAL;
245                 goto out_;
246         }
247
248         writel(iis_ckr_value, &(pheadi2s->I2S_CKR));
249
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;
254                 break;
255         case SND_SOC_DAIFMT_LEFT_J:
256                 tx_ctl &= ~I2S_BUS_MODE_MASK;    //I2S Bus Mode
257                 tx_ctl |= I2S_BUS_MODE_LSJM;
258                 break;
259         case SND_SOC_DAIFMT_I2S:
260                 tx_ctl &= ~I2S_BUS_MODE_MASK;    //I2S Bus Mode
261                 tx_ctl |= I2S_BUS_MODE_NOR;
262                 break;
263         default:
264                 I2S_DBG("Unknown data format\n");
265                 ret = -EINVAL;
266                 goto out_;
267         }
268
269         I2S_DBG("Enter::%s----%d, I2S_TXCR=0x%X\n",__FUNCTION__,__LINE__,tx_ctl);
270
271         writel(tx_ctl, &(pheadi2s->I2S_TXCR));
272
273         rx_ctl = tx_ctl & 0x00007FFF;
274         writel(rx_ctl, &(pheadi2s->I2S_RXCR));
275
276 out_:
277
278         spin_unlock_irqrestore(&lock, flags);
279
280         return ret;
281 }
282
283 static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream,
284                                 struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
285 {
286         struct rk30_i2s_info *i2s = to_info(dai);
287         u32 iismod;
288         u32 dmarc;
289         unsigned long flags;
290
291         I2S_DBG("Enter %s, %d \n", __func__, __LINE__);
292
293         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
294                 dai->playback_dma_data = &i2s->playback_dma_data;
295         else
296                 dai->capture_dma_data = &i2s->capture_dma_data;
297
298         spin_lock_irqsave(&lock, flags);
299
300         /* Working copies of register */
301         iismod = readl(&(pheadi2s->I2S_TXCR));
302
303         iismod &= (~((1<<5)-1));
304         switch (params_format(params)) {
305         case SNDRV_PCM_FORMAT_S8:
306                 iismod |= SAMPLE_DATA_8bit;
307                 break;
308         case SNDRV_PCM_FORMAT_S16_LE:
309                 iismod |= I2S_DATA_WIDTH(15);
310                 break;
311         case SNDRV_PCM_FORMAT_S20_3LE:
312                 iismod |= I2S_DATA_WIDTH(19);
313                 break;
314         case SNDRV_PCM_FORMAT_S24_LE:
315                 iismod |= I2S_DATA_WIDTH(23);
316                 break;
317         case SNDRV_PCM_FORMAT_S32_LE:
318                 iismod |= I2S_DATA_WIDTH(31);
319                 break;
320         }
321
322 //      writel((16<<24) |(16<<18)|(16<<12)|(16<<6)|16, &(pheadi2s->I2S_FIFOLR));
323         dmarc = readl(&(pheadi2s->I2S_DMACR));
324
325         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
326                 dmarc = ((dmarc & 0xFFFFFE00) | 16);
327         else
328                 dmarc = ((dmarc & 0xFE00FFFF) | 16<<16);
329
330         writel(dmarc, &(pheadi2s->I2S_DMACR));
331
332         I2S_DBG("Enter %s, %d I2S_TXCR=0x%08X\n", __func__, __LINE__, iismod);
333
334         writel(iismod, &(pheadi2s->I2S_TXCR));
335
336         iismod = iismod & 0x00007FFF;
337         writel(iismod, &(pheadi2s->I2S_RXCR));
338
339         spin_unlock_irqrestore(&lock, flags);
340
341         return 0;
342 }
343
344 static int rockchip_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai)
345 {
346         struct rk30_i2s_info *i2s = to_info(dai);
347         int ret = 0;
348
349         I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
350
351         switch (cmd) {
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);
357                 else
358                         rockchip_snd_txctrl(i2s, 1);
359                 break;
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);
365                 else
366                         rockchip_snd_txctrl(i2s, 0);
367                 break;
368         default:
369                 ret = -EINVAL;
370                 break;
371         }
372
373         return ret;
374 }
375
376 /*
377  * Set Rockchip I2S MCLK source
378  */
379 static int rockchip_i2s_set_sysclk(struct snd_soc_dai *cpu_dai,
380         int clk_id, unsigned int freq, int dir)
381 {
382         struct rk30_i2s_info *i2s = to_info(cpu_dai);
383
384         I2S_DBG("Enter:%s, %d, i2s=0x%p, freq=%d\n", __FUNCTION__, __LINE__, i2s, freq);
385
386         /*add scu clk source and enable clk*/
387         clk_set_rate(i2s->i2s_clk, freq);
388         return 0;
389 }
390
391 /*
392  * Set Rockchip Clock dividers
393  */
394 static int rockchip_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai,
395         int div_id, int div)
396 {
397         struct rk30_i2s_info *i2s;
398         u32 reg;
399         unsigned long flags;
400         int ret = 0;
401
402         i2s = to_info(cpu_dai);
403
404         spin_lock_irqsave(&lock, flags);
405
406         //stereo mode MCLK/SCK=4  
407         reg = readl(&(pheadi2s->I2S_CKR));
408
409         I2S_DBG("Enter:%s, %d, div_id=0x%08X, div=0x%08X\n", __FUNCTION__, __LINE__, div_id, div);
410         
411         //when i2s in master mode ,must set codec pll div
412         switch (div_id) {
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);
418                 break;
419         case ROCKCHIP_DIV_MCLK:
420                 reg &= ~I2S_MCLK_DIV_MASK;
421                 reg |= I2S_MCLK_DIV(div);
422                 break;
423         case ROCKCHIP_DIV_PRESCALER:
424                 break;
425         default:
426                 ret = -EINVAL;
427                 goto out_;
428         }
429         writel(reg, &(pheadi2s->I2S_CKR));
430
431 out_:
432         spin_unlock_irqrestore(&lock, flags);
433
434         return ret;
435 }
436
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,
443 };
444
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)
448
449 struct snd_soc_dai_driver rockchip_i2s_dai[] = {
450         {
451                 .name = "rockchip-i2s.0",
452                 .id = 0,
453                 .playback = {
454                         .channels_min = 2,
455                         .channels_max = 8,
456                         .rates = ROCKCHIP_I2S_STEREO_RATES,
457                         .formats = ROCKCHIP_I2S_FORMATS,
458                 },
459                 .capture = {
460                         .channels_min = 2,
461                         .channels_max = 2,
462                         .rates = ROCKCHIP_I2S_STEREO_RATES,
463                         .formats = ROCKCHIP_I2S_FORMATS,
464                 },
465                 .ops = &rockchip_i2s_dai_ops,
466                 .symmetric_rates = 1,
467         },
468         {
469                 .name = "rockchip-i2s.1",
470                 .id = 1,
471                 .playback = {
472                         .channels_min = 2,
473                         .channels_max = 2,
474                         .rates = ROCKCHIP_I2S_STEREO_RATES,
475                         .formats = ROCKCHIP_I2S_FORMATS,
476                 },
477                 .capture = {
478                         .channels_min = 2,
479                         .channels_max = 2,
480                         .rates = ROCKCHIP_I2S_STEREO_RATES,
481                         .formats = ROCKCHIP_I2S_FORMATS,
482                 },
483                 .ops = &rockchip_i2s_dai_ops,
484                 .symmetric_rates = 1,
485         },
486 };
487
488 static const struct snd_soc_component_driver rockchip_i2s_component = {
489         .name           = "rockchip-i2s",
490 };
491
492 #ifdef CONFIG_PM
493 static int rockchip_i2s_suspend_noirq(struct device *dev)
494 {
495         I2S_DBG("Enter %s, %d\n", __func__, __LINE__);
496
497         return pinctrl_select_state(dev->pins->p, dev->pins->sleep_state);
498 }
499
500 static int rockchip_i2s_resume_noirq(struct device *dev)
501 {
502         I2S_DBG("Enter %s, %d\n", __func__, __LINE__);
503
504         return pinctrl_select_state(dev->pins->p, dev->pins->default_state);
505 }
506 #else
507 #define rockchip_i2s_suspend_noirq NULL
508 #define rockchip_i2s_resume_noirq NULL
509 #endif
510
511 #ifdef CLK_SET_lATER
512 static void set_clk_later_work(struct work_struct *work)
513 {
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);
518 }
519 #endif
520
521 static int rockchip_i2s_probe(struct platform_device *pdev)
522 {
523         struct device_node *node = pdev->dev.of_node;
524         struct rk30_i2s_info *i2s;
525         struct resource *mem, *memregion;
526         u32 regs_base;
527         int ret;
528
529         I2S_DBG("%s()\n", __FUNCTION__);
530
531         ret = of_property_read_u32(node, "i2s-id", &pdev->id);
532         if (ret < 0) {
533                 dev_err(&pdev->dev, "%s() Can not read property: id\n", __FUNCTION__);
534                 ret = -ENOMEM;
535                 goto err;
536         }
537
538         if(pdev->id >= MAX_I2S) {
539                 dev_err(&pdev->dev, "id %d out of range\n", pdev->id);
540                 ret = -ENOMEM;
541                 goto err;
542         }
543
544         i2s = devm_kzalloc(&pdev->dev, sizeof(struct rk30_i2s_info), GFP_KERNEL);
545         if (!i2s) {
546                 dev_err(&pdev->dev, "Can't allocate i2s info\n");
547                 ret = -ENOMEM;
548                 goto err;
549         }
550
551         rk30_i2s = i2s;
552         i2s->i2s_clk= clk_get(&pdev->dev, "i2s_clk");
553         if (IS_ERR(i2s->i2s_clk)) {
554                 dev_err(&pdev->dev, "Can't retrieve i2s clock\n");
555                 ret = PTR_ERR(i2s->i2s_clk);
556                 goto err;
557         }
558 #ifdef CLK_SET_lATER
559         INIT_DELAYED_WORK(&i2s->clk_delayed_work, set_clk_later_work);
560         schedule_delayed_work(&i2s->clk_delayed_work, msecs_to_jiffies(10));
561 #else
562         clk_set_rate(i2s->iis_clk, 11289600);
563 #endif  
564         clk_prepare_enable(i2s->i2s_clk);
565
566         i2s->i2s_mclk= clk_get(&pdev->dev, "i2s_mclk");
567         if(IS_ERR(i2s->i2s_mclk) ) {
568                 printk("This platfrom have not i2s_mclk,no need to set i2s_mclk.\n");
569         }else{
570         #ifdef CLK_SET_lATER
571                 
572         #else
573                 clk_set_rate(i2s->i2s_mclk, 11289600);
574         #endif
575                 clk_prepare_enable(i2s->i2s_mclk);
576         }
577
578         mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
579         if (!mem) {
580                 dev_err(&pdev->dev, "No memory resource\n");
581                 ret = -ENODEV;
582                 goto err_clk_put;
583         }
584
585         memregion = devm_request_mem_region(&pdev->dev, mem->start,
586                                             resource_size(mem), "rockchip-i2s");
587         if (!memregion) {
588                 dev_err(&pdev->dev, "Memory region already claimed\n");
589                 ret = -EBUSY;
590                 goto err_clk_put;
591         }
592
593         i2s->regs = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
594         if (!i2s->regs) {
595                 dev_err(&pdev->dev, "ioremap failed\n");
596                 ret = -ENOMEM;
597                 goto err_clk_put;
598         }
599
600         regs_base = mem->start;
601
602         i2s->playback_dma_data.addr = regs_base + I2S_TXR_BUFF;
603         i2s->playback_dma_data.addr_width = 4;
604         i2s->playback_dma_data.maxburst = 1;
605
606         i2s->capture_dma_data.addr = regs_base + I2S_RXR_BUFF;
607         i2s->capture_dma_data.addr_width = 4;
608         i2s->capture_dma_data.maxburst = 1;
609
610         i2s->i2s_tx_status = false;
611         i2s->i2s_rx_status = false;
612
613         pm_runtime_enable(&pdev->dev);
614         if (!pm_runtime_enabled(&pdev->dev)) {
615                 ret = rockchip_i2s_resume_noirq(&pdev->dev);
616                 if (ret)
617                         goto err_pm_disable;
618         }
619
620         //set dev name to driver->name.id for sound card register
621         dev_set_name(&pdev->dev, "%s.%d", pdev->dev.driver->name, pdev->id);
622
623         ret = snd_soc_register_component(&pdev->dev, &rockchip_i2s_component,
624                 &rockchip_i2s_dai[pdev->id], 1);
625
626         if (ret) {
627                 dev_err(&pdev->dev, "Could not register DAI: %d\n", ret);
628                 ret = -ENOMEM;
629                 goto err_suspend;
630         }
631
632         ret = rockchip_pcm_platform_register(&pdev->dev);
633         if (ret) {
634                 dev_err(&pdev->dev, "Could not register PCM: %d\n", ret);
635                 goto err_unregister_component;
636         }
637
638         /* Mark ourselves as in TXRX mode so we can run through our cleanup
639          * process without warnings. */
640         rockchip_snd_txctrl(i2s, 0);
641         rockchip_snd_rxctrl(i2s, 0);
642
643         dev_set_drvdata(&pdev->dev, i2s);
644         return 0;
645
646 err_unregister_component:
647         snd_soc_unregister_component(&pdev->dev);
648 err_suspend:
649         if (!pm_runtime_status_suspended(&pdev->dev))
650                 rockchip_i2s_suspend_noirq(&pdev->dev);
651 err_pm_disable:
652         pm_runtime_disable(&pdev->dev);
653 err_clk_put:
654         clk_put(i2s->i2s_clk);
655 err:
656         return ret;
657
658 }
659
660 static int rockchip_i2s_remove(struct platform_device *pdev)
661 {
662         rockchip_pcm_platform_unregister(&pdev->dev);
663         snd_soc_unregister_component(&pdev->dev);
664
665         return 0;
666 }
667
668 #ifdef CONFIG_OF
669 static const struct of_device_id exynos_i2s_match[] = {
670         { .compatible = "rockchip-i2s"},
671         {},
672 };
673 MODULE_DEVICE_TABLE(of, exynos_i2s_match);
674 #endif
675
676 static const struct dev_pm_ops rockchip_i2s_pm_ops = {
677         SET_RUNTIME_PM_OPS(rockchip_i2s_suspend_noirq,
678                                 rockchip_i2s_resume_noirq, NULL)
679 };
680
681 static struct platform_driver rockchip_i2s_driver = {
682         .probe  = rockchip_i2s_probe,
683         .remove = rockchip_i2s_remove,
684         .driver = {
685                 .name   = "rockchip-i2s",
686                 .owner  = THIS_MODULE,
687                 .of_match_table = of_match_ptr(exynos_i2s_match),
688                 .pm     = &rockchip_i2s_pm_ops,
689         },
690 };
691 module_platform_driver(rockchip_i2s_driver);
692
693 /* Module information */
694 MODULE_AUTHOR("rockchip");
695 MODULE_DESCRIPTION("ROCKCHIP IIS ASoC Interface");
696 MODULE_LICENSE("GPL");
697
698
699 #ifdef CONFIG_PROC_FS
700 #include <linux/proc_fs.h>
701 #include <linux/seq_file.h>
702 static int proc_i2s_show(struct seq_file *s, void *v)
703 {
704
705         struct rk30_i2s_info *i2s = rk30_i2s;
706
707         printk("========Show I2S reg========\n");
708         
709         printk("I2S_TXCR = 0x%08X\n", readl(&(pheadi2s->I2S_TXCR)));
710         printk("I2S_RXCR = 0x%08X\n", readl(&(pheadi2s->I2S_RXCR)));
711         printk("I2S_CKR = 0x%08X\n", readl(&(pheadi2s->I2S_CKR)));
712         printk("I2S_DMACR = 0x%08X\n", readl(&(pheadi2s->I2S_DMACR)));
713         printk("I2S_INTCR = 0x%08X\n", readl(&(pheadi2s->I2S_INTCR)));
714         printk("I2S_INTSR = 0x%08X\n", readl(&(pheadi2s->I2S_INTSR)));
715         printk("I2S_XFER = 0x%08X\n", readl(&(pheadi2s->I2S_XFER)));
716
717         printk("========Show I2S reg========\n");
718 #if 0
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));
724         while(1)
725         {
726                 writel(0x5555aaaa, &(pheadi2s->I2S_TXDR));
727         }               
728 #endif  
729         return 0;
730 }
731
732 static ssize_t i2s_reg_write(struct file *file,
733                 const char __user *user_buf, size_t count, loff_t *ppos)
734 {
735         struct rk30_i2s_info *i2s=rk30_i2s;
736
737         char buf[32];
738         size_t buf_size;
739         char *start = buf;
740         unsigned long value;
741
742         buf_size = min(count, (sizeof(buf)-1));
743         if (copy_from_user(buf, user_buf, buf_size))
744                 return -EFAULT;
745         buf[buf_size] = 0;
746
747         while (*start == ' ')
748                 start++;
749         value = simple_strtoul(start, &start, 10);
750
751         printk("test --- freq = %ld ret=%d\n",value,clk_set_rate(i2s->i2s_clk, value));
752         return buf_size;
753 }
754
755 static int proc_i2s_open(struct inode *inode, struct file *file)
756 {
757         return single_open(file, proc_i2s_show, NULL);
758 }
759
760 static const struct file_operations proc_i2s_fops = {
761         .open           = proc_i2s_open,
762         .read           = seq_read,
763         .write = i2s_reg_write, 
764         .llseek         = seq_lseek,
765         .release        = single_release,
766 };
767
768 static int __init i2s_proc_init(void)
769 {
770         proc_create("i2s_reg", 0, NULL, &proc_i2s_fops);
771         return 0;
772 }
773 late_initcall(i2s_proc_init);
774 #endif /* CONFIG_PROC_FS */
775