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