ASoC: DaVinci: McASP FIFO related updates
[pandora-kernel.git] / sound / soc / davinci / davinci-i2s.c
1 /*
2  * ALSA SoC I2S (McBSP) Audio Layer for TI DAVINCI processor
3  *
4  * Author:      Vladimir Barinov, <vbarinov@embeddedalley.com>
5  * Copyright:   (C) 2007 MontaVista Software, Inc., <source@mvista.com>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2 as
9  * published by the Free Software Foundation.
10  */
11
12 #include <linux/init.h>
13 #include <linux/module.h>
14 #include <linux/device.h>
15 #include <linux/delay.h>
16 #include <linux/io.h>
17 #include <linux/clk.h>
18
19 #include <sound/core.h>
20 #include <sound/pcm.h>
21 #include <sound/pcm_params.h>
22 #include <sound/initval.h>
23 #include <sound/soc.h>
24
25 #include <mach/asp.h>
26
27 #include "davinci-pcm.h"
28
29
30 /*
31  * NOTE:  terminology here is confusing.
32  *
33  *  - This driver supports the "Audio Serial Port" (ASP),
34  *    found on dm6446, dm355, and other DaVinci chips.
35  *
36  *  - But it labels it a "Multi-channel Buffered Serial Port"
37  *    (McBSP) as on older chips like the dm642 ... which was
38  *    backward-compatible, possibly explaining that confusion.
39  *
40  *  - OMAP chips have a controller called McBSP, which is
41  *    incompatible with the DaVinci flavor of McBSP.
42  *
43  *  - Newer DaVinci chips have a controller called McASP,
44  *    incompatible with ASP and with either McBSP.
45  *
46  * In short:  this uses ASP to implement I2S, not McBSP.
47  * And it won't be the only DaVinci implemention of I2S.
48  */
49 #define DAVINCI_MCBSP_DRR_REG   0x00
50 #define DAVINCI_MCBSP_DXR_REG   0x04
51 #define DAVINCI_MCBSP_SPCR_REG  0x08
52 #define DAVINCI_MCBSP_RCR_REG   0x0c
53 #define DAVINCI_MCBSP_XCR_REG   0x10
54 #define DAVINCI_MCBSP_SRGR_REG  0x14
55 #define DAVINCI_MCBSP_PCR_REG   0x24
56
57 #define DAVINCI_MCBSP_SPCR_RRST         (1 << 0)
58 #define DAVINCI_MCBSP_SPCR_RINTM(v)     ((v) << 4)
59 #define DAVINCI_MCBSP_SPCR_XRST         (1 << 16)
60 #define DAVINCI_MCBSP_SPCR_XINTM(v)     ((v) << 20)
61 #define DAVINCI_MCBSP_SPCR_GRST         (1 << 22)
62 #define DAVINCI_MCBSP_SPCR_FRST         (1 << 23)
63 #define DAVINCI_MCBSP_SPCR_FREE         (1 << 25)
64
65 #define DAVINCI_MCBSP_RCR_RWDLEN1(v)    ((v) << 5)
66 #define DAVINCI_MCBSP_RCR_RFRLEN1(v)    ((v) << 8)
67 #define DAVINCI_MCBSP_RCR_RDATDLY(v)    ((v) << 16)
68 #define DAVINCI_MCBSP_RCR_RFIG          (1 << 18)
69 #define DAVINCI_MCBSP_RCR_RWDLEN2(v)    ((v) << 21)
70
71 #define DAVINCI_MCBSP_XCR_XWDLEN1(v)    ((v) << 5)
72 #define DAVINCI_MCBSP_XCR_XFRLEN1(v)    ((v) << 8)
73 #define DAVINCI_MCBSP_XCR_XDATDLY(v)    ((v) << 16)
74 #define DAVINCI_MCBSP_XCR_XFIG          (1 << 18)
75 #define DAVINCI_MCBSP_XCR_XWDLEN2(v)    ((v) << 21)
76
77 #define DAVINCI_MCBSP_SRGR_FWID(v)      ((v) << 8)
78 #define DAVINCI_MCBSP_SRGR_FPER(v)      ((v) << 16)
79 #define DAVINCI_MCBSP_SRGR_FSGM         (1 << 28)
80
81 #define DAVINCI_MCBSP_PCR_CLKRP         (1 << 0)
82 #define DAVINCI_MCBSP_PCR_CLKXP         (1 << 1)
83 #define DAVINCI_MCBSP_PCR_FSRP          (1 << 2)
84 #define DAVINCI_MCBSP_PCR_FSXP          (1 << 3)
85 #define DAVINCI_MCBSP_PCR_SCLKME        (1 << 7)
86 #define DAVINCI_MCBSP_PCR_CLKRM         (1 << 8)
87 #define DAVINCI_MCBSP_PCR_CLKXM         (1 << 9)
88 #define DAVINCI_MCBSP_PCR_FSRM          (1 << 10)
89 #define DAVINCI_MCBSP_PCR_FSXM          (1 << 11)
90
91 enum {
92         DAVINCI_MCBSP_WORD_8 = 0,
93         DAVINCI_MCBSP_WORD_12,
94         DAVINCI_MCBSP_WORD_16,
95         DAVINCI_MCBSP_WORD_20,
96         DAVINCI_MCBSP_WORD_24,
97         DAVINCI_MCBSP_WORD_32,
98 };
99
100 struct davinci_mcbsp_dev {
101         /*
102          * dma_params must be first because rtd->dai->cpu_dai->private_data
103          * is cast to a pointer of an array of struct davinci_pcm_dma_params in
104          * davinci_pcm_open.
105          */
106         struct davinci_pcm_dma_params   dma_params[2];
107         void __iomem                    *base;
108 #define MOD_DSP_A       0
109 #define MOD_DSP_B       1
110         int                             mode;
111         u32                             pcr;
112         struct clk                      *clk;
113 };
114
115 static inline void davinci_mcbsp_write_reg(struct davinci_mcbsp_dev *dev,
116                                            int reg, u32 val)
117 {
118         __raw_writel(val, dev->base + reg);
119 }
120
121 static inline u32 davinci_mcbsp_read_reg(struct davinci_mcbsp_dev *dev, int reg)
122 {
123         return __raw_readl(dev->base + reg);
124 }
125
126 static void toggle_clock(struct davinci_mcbsp_dev *dev, int playback)
127 {
128         u32 m = playback ? DAVINCI_MCBSP_PCR_CLKXP : DAVINCI_MCBSP_PCR_CLKRP;
129         /* The clock needs to toggle to complete reset.
130          * So, fake it by toggling the clk polarity.
131          */
132         davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, dev->pcr ^ m);
133         davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, dev->pcr);
134 }
135
136 static void davinci_mcbsp_start(struct davinci_mcbsp_dev *dev,
137                 struct snd_pcm_substream *substream)
138 {
139         struct snd_soc_pcm_runtime *rtd = substream->private_data;
140         struct snd_soc_device *socdev = rtd->socdev;
141         struct snd_soc_platform *platform = socdev->card->platform;
142         int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
143         u32 spcr;
144         u32 mask = playback ? DAVINCI_MCBSP_SPCR_XRST : DAVINCI_MCBSP_SPCR_RRST;
145         spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
146         if (spcr & mask) {
147                 /* start off disabled */
148                 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG,
149                                 spcr & ~mask);
150                 toggle_clock(dev, playback);
151         }
152         if (dev->pcr & (DAVINCI_MCBSP_PCR_FSXM | DAVINCI_MCBSP_PCR_FSRM |
153                         DAVINCI_MCBSP_PCR_CLKXM | DAVINCI_MCBSP_PCR_CLKRM)) {
154                 /* Start the sample generator */
155                 spcr |= DAVINCI_MCBSP_SPCR_GRST;
156                 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
157         }
158
159         if (playback) {
160                 /* Stop the DMA to avoid data loss */
161                 /* while the transmitter is out of reset to handle XSYNCERR */
162                 if (platform->pcm_ops->trigger) {
163                         int ret = platform->pcm_ops->trigger(substream,
164                                 SNDRV_PCM_TRIGGER_STOP);
165                         if (ret < 0)
166                                 printk(KERN_DEBUG "Playback DMA stop failed\n");
167                 }
168
169                 /* Enable the transmitter */
170                 spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
171                 spcr |= DAVINCI_MCBSP_SPCR_XRST;
172                 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
173
174                 /* wait for any unexpected frame sync error to occur */
175                 udelay(100);
176
177                 /* Disable the transmitter to clear any outstanding XSYNCERR */
178                 spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
179                 spcr &= ~DAVINCI_MCBSP_SPCR_XRST;
180                 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
181                 toggle_clock(dev, playback);
182
183                 /* Restart the DMA */
184                 if (platform->pcm_ops->trigger) {
185                         int ret = platform->pcm_ops->trigger(substream,
186                                 SNDRV_PCM_TRIGGER_START);
187                         if (ret < 0)
188                                 printk(KERN_DEBUG "Playback DMA start failed\n");
189                 }
190         }
191
192         /* Enable transmitter or receiver */
193         spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
194         spcr |= mask;
195
196         if (dev->pcr & (DAVINCI_MCBSP_PCR_FSXM | DAVINCI_MCBSP_PCR_FSRM)) {
197                 /* Start frame sync */
198                 spcr |= DAVINCI_MCBSP_SPCR_FRST;
199         }
200         davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
201 }
202
203 static void davinci_mcbsp_stop(struct davinci_mcbsp_dev *dev, int playback)
204 {
205         u32 spcr;
206
207         /* Reset transmitter/receiver and sample rate/frame sync generators */
208         spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
209         spcr &= ~(DAVINCI_MCBSP_SPCR_GRST | DAVINCI_MCBSP_SPCR_FRST);
210         spcr &= playback ? ~DAVINCI_MCBSP_SPCR_XRST : ~DAVINCI_MCBSP_SPCR_RRST;
211         davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
212         toggle_clock(dev, playback);
213 }
214
215 #define DEFAULT_BITPERSAMPLE    16
216
217 static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
218                                    unsigned int fmt)
219 {
220         struct davinci_mcbsp_dev *dev = cpu_dai->private_data;
221         unsigned int pcr;
222         unsigned int srgr;
223         srgr = DAVINCI_MCBSP_SRGR_FSGM |
224                 DAVINCI_MCBSP_SRGR_FPER(DEFAULT_BITPERSAMPLE * 2 - 1) |
225                 DAVINCI_MCBSP_SRGR_FWID(DEFAULT_BITPERSAMPLE - 1);
226
227         /* set master/slave audio interface */
228         switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
229         case SND_SOC_DAIFMT_CBS_CFS:
230                 /* cpu is master */
231                 pcr = DAVINCI_MCBSP_PCR_FSXM |
232                         DAVINCI_MCBSP_PCR_FSRM |
233                         DAVINCI_MCBSP_PCR_CLKXM |
234                         DAVINCI_MCBSP_PCR_CLKRM;
235                 break;
236         case SND_SOC_DAIFMT_CBM_CFS:
237                 /* McBSP CLKR pin is the input for the Sample Rate Generator.
238                  * McBSP FSR and FSX are driven by the Sample Rate Generator. */
239                 pcr = DAVINCI_MCBSP_PCR_SCLKME |
240                         DAVINCI_MCBSP_PCR_FSXM |
241                         DAVINCI_MCBSP_PCR_FSRM;
242                 break;
243         case SND_SOC_DAIFMT_CBM_CFM:
244                 /* codec is master */
245                 pcr = 0;
246                 break;
247         default:
248                 printk(KERN_ERR "%s:bad master\n", __func__);
249                 return -EINVAL;
250         }
251
252         /* interface format */
253         switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
254         case SND_SOC_DAIFMT_I2S:
255                 /* Davinci doesn't support TRUE I2S, but some codecs will have
256                  * the left and right channels contiguous. This allows
257                  * dsp_a mode to be used with an inverted normal frame clk.
258                  * If your codec is master and does not have contiguous
259                  * channels, then you will have sound on only one channel.
260                  * Try using a different mode, or codec as slave.
261                  *
262                  * The TLV320AIC33 is an example of a codec where this works.
263                  * It has a variable bit clock frequency allowing it to have
264                  * valid data on every bit clock.
265                  *
266                  * The TLV320AIC23 is an example of a codec where this does not
267                  * work. It has a fixed bit clock frequency with progressively
268                  * more empty bit clock slots between channels as the sample
269                  * rate is lowered.
270                  */
271                 fmt ^= SND_SOC_DAIFMT_NB_IF;
272         case SND_SOC_DAIFMT_DSP_A:
273                 dev->mode = MOD_DSP_A;
274                 break;
275         case SND_SOC_DAIFMT_DSP_B:
276                 dev->mode = MOD_DSP_B;
277                 break;
278         default:
279                 printk(KERN_ERR "%s:bad format\n", __func__);
280                 return -EINVAL;
281         }
282
283         switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
284         case SND_SOC_DAIFMT_NB_NF:
285                 /* CLKRP Receive clock polarity,
286                  *      1 - sampled on rising edge of CLKR
287                  *      valid on rising edge
288                  * CLKXP Transmit clock polarity,
289                  *      1 - clocked on falling edge of CLKX
290                  *      valid on rising edge
291                  * FSRP  Receive frame sync pol, 0 - active high
292                  * FSXP  Transmit frame sync pol, 0 - active high
293                  */
294                 pcr |= (DAVINCI_MCBSP_PCR_CLKXP | DAVINCI_MCBSP_PCR_CLKRP);
295                 break;
296         case SND_SOC_DAIFMT_IB_IF:
297                 /* CLKRP Receive clock polarity,
298                  *      0 - sampled on falling edge of CLKR
299                  *      valid on falling edge
300                  * CLKXP Transmit clock polarity,
301                  *      0 - clocked on rising edge of CLKX
302                  *      valid on falling edge
303                  * FSRP  Receive frame sync pol, 1 - active low
304                  * FSXP  Transmit frame sync pol, 1 - active low
305                  */
306                 pcr |= (DAVINCI_MCBSP_PCR_FSXP | DAVINCI_MCBSP_PCR_FSRP);
307                 break;
308         case SND_SOC_DAIFMT_NB_IF:
309                 /* CLKRP Receive clock polarity,
310                  *      1 - sampled on rising edge of CLKR
311                  *      valid on rising edge
312                  * CLKXP Transmit clock polarity,
313                  *      1 - clocked on falling edge of CLKX
314                  *      valid on rising edge
315                  * FSRP  Receive frame sync pol, 1 - active low
316                  * FSXP  Transmit frame sync pol, 1 - active low
317                  */
318                 pcr |= (DAVINCI_MCBSP_PCR_CLKXP | DAVINCI_MCBSP_PCR_CLKRP |
319                         DAVINCI_MCBSP_PCR_FSXP | DAVINCI_MCBSP_PCR_FSRP);
320                 break;
321         case SND_SOC_DAIFMT_IB_NF:
322                 /* CLKRP Receive clock polarity,
323                  *      0 - sampled on falling edge of CLKR
324                  *      valid on falling edge
325                  * CLKXP Transmit clock polarity,
326                  *      0 - clocked on rising edge of CLKX
327                  *      valid on falling edge
328                  * FSRP  Receive frame sync pol, 0 - active high
329                  * FSXP  Transmit frame sync pol, 0 - active high
330                  */
331                 break;
332         default:
333                 return -EINVAL;
334         }
335         davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, srgr);
336         dev->pcr = pcr;
337         davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, pcr);
338         return 0;
339 }
340
341 static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
342                                  struct snd_pcm_hw_params *params,
343                                  struct snd_soc_dai *dai)
344 {
345         struct davinci_mcbsp_dev *dev = dai->private_data;
346         struct davinci_pcm_dma_params *dma_params =
347                                         &dev->dma_params[substream->stream];
348         struct snd_interval *i = NULL;
349         int mcbsp_word_length;
350         unsigned int rcr, xcr, srgr;
351         u32 spcr;
352
353         /* general line settings */
354         spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
355         if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
356                 spcr |= DAVINCI_MCBSP_SPCR_RINTM(3) | DAVINCI_MCBSP_SPCR_FREE;
357                 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
358         } else {
359                 spcr |= DAVINCI_MCBSP_SPCR_XINTM(3) | DAVINCI_MCBSP_SPCR_FREE;
360                 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
361         }
362
363         i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS);
364         srgr = DAVINCI_MCBSP_SRGR_FSGM;
365         srgr |= DAVINCI_MCBSP_SRGR_FWID(snd_interval_value(i) - 1);
366
367         i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_FRAME_BITS);
368         srgr |= DAVINCI_MCBSP_SRGR_FPER(snd_interval_value(i) - 1);
369         davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, srgr);
370
371         rcr = DAVINCI_MCBSP_RCR_RFIG;
372         xcr = DAVINCI_MCBSP_XCR_XFIG;
373         if (dev->mode == MOD_DSP_B) {
374                 rcr |= DAVINCI_MCBSP_RCR_RDATDLY(0);
375                 xcr |= DAVINCI_MCBSP_XCR_XDATDLY(0);
376         } else {
377                 rcr |= DAVINCI_MCBSP_RCR_RDATDLY(1);
378                 xcr |= DAVINCI_MCBSP_XCR_XDATDLY(1);
379         }
380         /* Determine xfer data type */
381         switch (params_format(params)) {
382         case SNDRV_PCM_FORMAT_S8:
383                 dma_params->data_type = 1;
384                 mcbsp_word_length = DAVINCI_MCBSP_WORD_8;
385                 break;
386         case SNDRV_PCM_FORMAT_S16_LE:
387                 dma_params->data_type = 2;
388                 mcbsp_word_length = DAVINCI_MCBSP_WORD_16;
389                 break;
390         case SNDRV_PCM_FORMAT_S32_LE:
391                 dma_params->data_type = 4;
392                 mcbsp_word_length = DAVINCI_MCBSP_WORD_32;
393                 break;
394         default:
395                 printk(KERN_WARNING "davinci-i2s: unsupported PCM format\n");
396                 return -EINVAL;
397         }
398
399         dma_params->acnt  = dma_params->data_type;
400         dma_params->fifo_level = 0;
401
402         rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(1);
403         xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(1);
404
405         rcr |= DAVINCI_MCBSP_RCR_RWDLEN1(mcbsp_word_length) |
406                 DAVINCI_MCBSP_RCR_RWDLEN2(mcbsp_word_length);
407         xcr |= DAVINCI_MCBSP_XCR_XWDLEN1(mcbsp_word_length) |
408                 DAVINCI_MCBSP_XCR_XWDLEN2(mcbsp_word_length);
409
410         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
411                 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG, xcr);
412         else
413                 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG, rcr);
414         return 0;
415 }
416
417 static int davinci_i2s_prepare(struct snd_pcm_substream *substream,
418                 struct snd_soc_dai *dai)
419 {
420         struct davinci_mcbsp_dev *dev = dai->private_data;
421         int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
422         davinci_mcbsp_stop(dev, playback);
423         if ((dev->pcr & DAVINCI_MCBSP_PCR_FSXM) == 0) {
424                 /* codec is master */
425                 davinci_mcbsp_start(dev, substream);
426         }
427         return 0;
428 }
429
430 static int davinci_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
431                                struct snd_soc_dai *dai)
432 {
433         struct davinci_mcbsp_dev *dev = dai->private_data;
434         int ret = 0;
435         int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
436         if ((dev->pcr & DAVINCI_MCBSP_PCR_FSXM) == 0)
437                 return 0;       /* return if codec is master */
438
439         switch (cmd) {
440         case SNDRV_PCM_TRIGGER_START:
441         case SNDRV_PCM_TRIGGER_RESUME:
442         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
443                 davinci_mcbsp_start(dev, substream);
444                 break;
445         case SNDRV_PCM_TRIGGER_STOP:
446         case SNDRV_PCM_TRIGGER_SUSPEND:
447         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
448                 davinci_mcbsp_stop(dev, playback);
449                 break;
450         default:
451                 ret = -EINVAL;
452         }
453         return ret;
454 }
455
456 static void davinci_i2s_shutdown(struct snd_pcm_substream *substream,
457                 struct snd_soc_dai *dai)
458 {
459         struct davinci_mcbsp_dev *dev = dai->private_data;
460         int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
461         davinci_mcbsp_stop(dev, playback);
462 }
463
464 #define DAVINCI_I2S_RATES       SNDRV_PCM_RATE_8000_96000
465
466 static struct snd_soc_dai_ops davinci_i2s_dai_ops = {
467         .shutdown       = davinci_i2s_shutdown,
468         .prepare        = davinci_i2s_prepare,
469         .trigger        = davinci_i2s_trigger,
470         .hw_params      = davinci_i2s_hw_params,
471         .set_fmt        = davinci_i2s_set_dai_fmt,
472
473 };
474
475 struct snd_soc_dai davinci_i2s_dai = {
476         .name = "davinci-i2s",
477         .id = 0,
478         .playback = {
479                 .channels_min = 2,
480                 .channels_max = 2,
481                 .rates = DAVINCI_I2S_RATES,
482                 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
483         .capture = {
484                 .channels_min = 2,
485                 .channels_max = 2,
486                 .rates = DAVINCI_I2S_RATES,
487                 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
488         .ops = &davinci_i2s_dai_ops,
489
490 };
491 EXPORT_SYMBOL_GPL(davinci_i2s_dai);
492
493 static int davinci_i2s_probe(struct platform_device *pdev)
494 {
495         struct snd_platform_data *pdata = pdev->dev.platform_data;
496         struct davinci_mcbsp_dev *dev;
497         struct resource *mem, *ioarea, *res;
498         int ret;
499
500         mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
501         if (!mem) {
502                 dev_err(&pdev->dev, "no mem resource?\n");
503                 return -ENODEV;
504         }
505
506         ioarea = request_mem_region(mem->start, (mem->end - mem->start) + 1,
507                                     pdev->name);
508         if (!ioarea) {
509                 dev_err(&pdev->dev, "McBSP region already claimed\n");
510                 return -EBUSY;
511         }
512
513         dev = kzalloc(sizeof(struct davinci_mcbsp_dev), GFP_KERNEL);
514         if (!dev) {
515                 ret = -ENOMEM;
516                 goto err_release_region;
517         }
518
519         dev->clk = clk_get(&pdev->dev, NULL);
520         if (IS_ERR(dev->clk)) {
521                 ret = -ENODEV;
522                 goto err_free_mem;
523         }
524         clk_enable(dev->clk);
525
526         dev->base = (void __iomem *)IO_ADDRESS(mem->start);
527
528         dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK].dma_addr =
529             (dma_addr_t)(io_v2p(dev->base) + DAVINCI_MCBSP_DXR_REG);
530
531         dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].dma_addr =
532             (dma_addr_t)(io_v2p(dev->base) + DAVINCI_MCBSP_DRR_REG);
533
534         /* first TX, then RX */
535         res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
536         if (!res) {
537                 dev_err(&pdev->dev, "no DMA resource\n");
538                 ret = -ENXIO;
539                 goto err_free_mem;
540         }
541         dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK].channel = res->start;
542
543         res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
544         if (!res) {
545                 dev_err(&pdev->dev, "no DMA resource\n");
546                 ret = -ENXIO;
547                 goto err_free_mem;
548         }
549         dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].channel = res->start;
550
551         davinci_i2s_dai.private_data = dev;
552         ret = snd_soc_register_dai(&davinci_i2s_dai);
553         if (ret != 0)
554                 goto err_free_mem;
555
556         return 0;
557
558 err_free_mem:
559         kfree(dev);
560 err_release_region:
561         release_mem_region(mem->start, (mem->end - mem->start) + 1);
562
563         return ret;
564 }
565
566 static int davinci_i2s_remove(struct platform_device *pdev)
567 {
568         struct davinci_mcbsp_dev *dev = davinci_i2s_dai.private_data;
569         struct resource *mem;
570
571         snd_soc_unregister_dai(&davinci_i2s_dai);
572         clk_disable(dev->clk);
573         clk_put(dev->clk);
574         dev->clk = NULL;
575         kfree(dev);
576         mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
577         release_mem_region(mem->start, (mem->end - mem->start) + 1);
578
579         return 0;
580 }
581
582 static struct platform_driver davinci_mcbsp_driver = {
583         .probe          = davinci_i2s_probe,
584         .remove         = davinci_i2s_remove,
585         .driver         = {
586                 .name   = "davinci-asp",
587                 .owner  = THIS_MODULE,
588         },
589 };
590
591 static int __init davinci_i2s_init(void)
592 {
593         return platform_driver_register(&davinci_mcbsp_driver);
594 }
595 module_init(davinci_i2s_init);
596
597 static void __exit davinci_i2s_exit(void)
598 {
599         platform_driver_unregister(&davinci_mcbsp_driver);
600 }
601 module_exit(davinci_i2s_exit);
602
603 MODULE_AUTHOR("Vladimir Barinov");
604 MODULE_DESCRIPTION("TI DAVINCI I2S (McBSP) SoC Interface");
605 MODULE_LICENSE("GPL");