Merge branch 'fix/asoc' into for-linus
[pandora-kernel.git] / sound / soc / omap / omap-mcbsp.c
1 /*
2  * omap-mcbsp.c  --  OMAP ALSA SoC DAI driver using McBSP port
3  *
4  * Copyright (C) 2008 Nokia Corporation
5  *
6  * Contact: Jarkko Nikula <jhnikula@gmail.com>
7  *          Peter Ujfalusi <peter.ujfalusi@nokia.com>
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * version 2 as published by the Free Software Foundation.
12  *
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21  * 02110-1301 USA
22  *
23  */
24
25 #include <linux/init.h>
26 #include <linux/module.h>
27 #include <linux/device.h>
28 #include <sound/core.h>
29 #include <sound/pcm.h>
30 #include <sound/pcm_params.h>
31 #include <sound/initval.h>
32 #include <sound/soc.h>
33
34 #include <mach/control.h>
35 #include <mach/dma.h>
36 #include <mach/mcbsp.h>
37 #include "omap-mcbsp.h"
38 #include "omap-pcm.h"
39
40 #define OMAP_MCBSP_RATES        (SNDRV_PCM_RATE_8000_96000)
41
42 struct omap_mcbsp_data {
43         unsigned int                    bus_id;
44         struct omap_mcbsp_reg_cfg       regs;
45         unsigned int                    fmt;
46         /*
47          * Flags indicating is the bus already activated and configured by
48          * another substream
49          */
50         int                             active;
51         int                             configured;
52 };
53
54 #define to_mcbsp(priv)  container_of((priv), struct omap_mcbsp_data, bus_id)
55
56 static struct omap_mcbsp_data mcbsp_data[NUM_LINKS];
57
58 /*
59  * Stream DMA parameters. DMA request line and port address are set runtime
60  * since they are different between OMAP1 and later OMAPs
61  */
62 static struct omap_pcm_dma_data omap_mcbsp_dai_dma_params[NUM_LINKS][2];
63
64 #if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX)
65 static const int omap1_dma_reqs[][2] = {
66         { OMAP_DMA_MCBSP1_TX, OMAP_DMA_MCBSP1_RX },
67         { OMAP_DMA_MCBSP2_TX, OMAP_DMA_MCBSP2_RX },
68         { OMAP_DMA_MCBSP3_TX, OMAP_DMA_MCBSP3_RX },
69 };
70 static const unsigned long omap1_mcbsp_port[][2] = {
71         { OMAP1510_MCBSP1_BASE + OMAP_MCBSP_REG_DXR1,
72           OMAP1510_MCBSP1_BASE + OMAP_MCBSP_REG_DRR1 },
73         { OMAP1510_MCBSP2_BASE + OMAP_MCBSP_REG_DXR1,
74           OMAP1510_MCBSP2_BASE + OMAP_MCBSP_REG_DRR1 },
75         { OMAP1510_MCBSP3_BASE + OMAP_MCBSP_REG_DXR1,
76           OMAP1510_MCBSP3_BASE + OMAP_MCBSP_REG_DRR1 },
77 };
78 #else
79 static const int omap1_dma_reqs[][2] = {};
80 static const unsigned long omap1_mcbsp_port[][2] = {};
81 #endif
82
83 #if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
84 static const int omap24xx_dma_reqs[][2] = {
85         { OMAP24XX_DMA_MCBSP1_TX, OMAP24XX_DMA_MCBSP1_RX },
86         { OMAP24XX_DMA_MCBSP2_TX, OMAP24XX_DMA_MCBSP2_RX },
87 #if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP34XX)
88         { OMAP24XX_DMA_MCBSP3_TX, OMAP24XX_DMA_MCBSP3_RX },
89         { OMAP24XX_DMA_MCBSP4_TX, OMAP24XX_DMA_MCBSP4_RX },
90         { OMAP24XX_DMA_MCBSP5_TX, OMAP24XX_DMA_MCBSP5_RX },
91 #endif
92 };
93 #else
94 static const int omap24xx_dma_reqs[][2] = {};
95 #endif
96
97 #if defined(CONFIG_ARCH_OMAP2420)
98 static const unsigned long omap2420_mcbsp_port[][2] = {
99         { OMAP24XX_MCBSP1_BASE + OMAP_MCBSP_REG_DXR1,
100           OMAP24XX_MCBSP1_BASE + OMAP_MCBSP_REG_DRR1 },
101         { OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DXR1,
102           OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DRR1 },
103 };
104 #else
105 static const unsigned long omap2420_mcbsp_port[][2] = {};
106 #endif
107
108 #if defined(CONFIG_ARCH_OMAP2430)
109 static const unsigned long omap2430_mcbsp_port[][2] = {
110         { OMAP24XX_MCBSP1_BASE + OMAP_MCBSP_REG_DXR,
111           OMAP24XX_MCBSP1_BASE + OMAP_MCBSP_REG_DRR },
112         { OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DXR,
113           OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DRR },
114         { OMAP2430_MCBSP3_BASE + OMAP_MCBSP_REG_DXR,
115           OMAP2430_MCBSP3_BASE + OMAP_MCBSP_REG_DRR },
116         { OMAP2430_MCBSP4_BASE + OMAP_MCBSP_REG_DXR,
117           OMAP2430_MCBSP4_BASE + OMAP_MCBSP_REG_DRR },
118         { OMAP2430_MCBSP5_BASE + OMAP_MCBSP_REG_DXR,
119           OMAP2430_MCBSP5_BASE + OMAP_MCBSP_REG_DRR },
120 };
121 #else
122 static const unsigned long omap2430_mcbsp_port[][2] = {};
123 #endif
124
125 #if defined(CONFIG_ARCH_OMAP34XX)
126 static const unsigned long omap34xx_mcbsp_port[][2] = {
127         { OMAP34XX_MCBSP1_BASE + OMAP_MCBSP_REG_DXR,
128           OMAP34XX_MCBSP1_BASE + OMAP_MCBSP_REG_DRR },
129         { OMAP34XX_MCBSP2_BASE + OMAP_MCBSP_REG_DXR,
130           OMAP34XX_MCBSP2_BASE + OMAP_MCBSP_REG_DRR },
131         { OMAP34XX_MCBSP3_BASE + OMAP_MCBSP_REG_DXR,
132           OMAP34XX_MCBSP3_BASE + OMAP_MCBSP_REG_DRR },
133         { OMAP34XX_MCBSP4_BASE + OMAP_MCBSP_REG_DXR,
134           OMAP34XX_MCBSP4_BASE + OMAP_MCBSP_REG_DRR },
135         { OMAP34XX_MCBSP5_BASE + OMAP_MCBSP_REG_DXR,
136           OMAP34XX_MCBSP5_BASE + OMAP_MCBSP_REG_DRR },
137 };
138 #else
139 static const unsigned long omap34xx_mcbsp_port[][2] = {};
140 #endif
141
142 static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream,
143                                   struct snd_soc_dai *dai)
144 {
145         struct snd_soc_pcm_runtime *rtd = substream->private_data;
146         struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
147         struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
148         int err = 0;
149
150         if (cpu_is_omap343x() && mcbsp_data->bus_id == 1) {
151                 /*
152                  * McBSP2 in OMAP3 has 1024 * 32-bit internal audio buffer.
153                  * Set constraint for minimum buffer size to the same than FIFO
154                  * size in order to avoid underruns in playback startup because
155                  * HW is keeping the DMA request active until FIFO is filled.
156                  */
157                 snd_pcm_hw_constraint_minmax(substream->runtime,
158                         SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 4096, UINT_MAX);
159         }
160
161         if (!cpu_dai->active)
162                 err = omap_mcbsp_request(mcbsp_data->bus_id);
163
164         return err;
165 }
166
167 static void omap_mcbsp_dai_shutdown(struct snd_pcm_substream *substream,
168                                     struct snd_soc_dai *dai)
169 {
170         struct snd_soc_pcm_runtime *rtd = substream->private_data;
171         struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
172         struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
173
174         if (!cpu_dai->active) {
175                 omap_mcbsp_free(mcbsp_data->bus_id);
176                 mcbsp_data->configured = 0;
177         }
178 }
179
180 static int omap_mcbsp_dai_trigger(struct snd_pcm_substream *substream, int cmd,
181                                   struct snd_soc_dai *dai)
182 {
183         struct snd_soc_pcm_runtime *rtd = substream->private_data;
184         struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
185         struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
186         int err = 0;
187
188         switch (cmd) {
189         case SNDRV_PCM_TRIGGER_START:
190         case SNDRV_PCM_TRIGGER_RESUME:
191         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
192                 if (!mcbsp_data->active++)
193                         omap_mcbsp_start(mcbsp_data->bus_id);
194                 break;
195
196         case SNDRV_PCM_TRIGGER_STOP:
197         case SNDRV_PCM_TRIGGER_SUSPEND:
198         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
199                 if (!--mcbsp_data->active)
200                         omap_mcbsp_stop(mcbsp_data->bus_id);
201                 break;
202         default:
203                 err = -EINVAL;
204         }
205
206         return err;
207 }
208
209 static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
210                                     struct snd_pcm_hw_params *params,
211                                     struct snd_soc_dai *dai)
212 {
213         struct snd_soc_pcm_runtime *rtd = substream->private_data;
214         struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
215         struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
216         struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
217         int dma, bus_id = mcbsp_data->bus_id, id = cpu_dai->id;
218         int wlen, channels;
219         unsigned long port;
220
221         if (cpu_class_is_omap1()) {
222                 dma = omap1_dma_reqs[bus_id][substream->stream];
223                 port = omap1_mcbsp_port[bus_id][substream->stream];
224         } else if (cpu_is_omap2420()) {
225                 dma = omap24xx_dma_reqs[bus_id][substream->stream];
226                 port = omap2420_mcbsp_port[bus_id][substream->stream];
227         } else if (cpu_is_omap2430()) {
228                 dma = omap24xx_dma_reqs[bus_id][substream->stream];
229                 port = omap2430_mcbsp_port[bus_id][substream->stream];
230         } else if (cpu_is_omap343x()) {
231                 dma = omap24xx_dma_reqs[bus_id][substream->stream];
232                 port = omap34xx_mcbsp_port[bus_id][substream->stream];
233         } else {
234                 return -ENODEV;
235         }
236         omap_mcbsp_dai_dma_params[id][substream->stream].name =
237                 substream->stream ? "Audio Capture" : "Audio Playback";
238         omap_mcbsp_dai_dma_params[id][substream->stream].dma_req = dma;
239         omap_mcbsp_dai_dma_params[id][substream->stream].port_addr = port;
240         cpu_dai->dma_data = &omap_mcbsp_dai_dma_params[id][substream->stream];
241
242         if (mcbsp_data->configured) {
243                 /* McBSP already configured by another stream */
244                 return 0;
245         }
246
247         channels = params_channels(params);
248         switch (channels) {
249         case 2:
250                 /* Use dual-phase frames */
251                 regs->rcr2      |= RPHASE;
252                 regs->xcr2      |= XPHASE;
253         case 1:
254                 /* Set 1 word per (McBSP) frame */
255                 regs->rcr2      |= RFRLEN2(1 - 1);
256                 regs->rcr1      |= RFRLEN1(1 - 1);
257                 regs->xcr2      |= XFRLEN2(1 - 1);
258                 regs->xcr1      |= XFRLEN1(1 - 1);
259                 break;
260         default:
261                 /* Unsupported number of channels */
262                 return -EINVAL;
263         }
264
265         switch (params_format(params)) {
266         case SNDRV_PCM_FORMAT_S16_LE:
267                 /* Set word lengths */
268                 wlen = 16;
269                 regs->rcr2      |= RWDLEN2(OMAP_MCBSP_WORD_16);
270                 regs->rcr1      |= RWDLEN1(OMAP_MCBSP_WORD_16);
271                 regs->xcr2      |= XWDLEN2(OMAP_MCBSP_WORD_16);
272                 regs->xcr1      |= XWDLEN1(OMAP_MCBSP_WORD_16);
273                 break;
274         default:
275                 /* Unsupported PCM format */
276                 return -EINVAL;
277         }
278
279         /* Set FS period and length in terms of bit clock periods */
280         switch (mcbsp_data->fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
281         case SND_SOC_DAIFMT_I2S:
282                 regs->srgr2     |= FPER(wlen * 2 - 1);
283                 regs->srgr1     |= FWID(wlen - 1);
284                 break;
285         case SND_SOC_DAIFMT_DSP_B:
286                 regs->srgr2     |= FPER(wlen * channels - 1);
287                 regs->srgr1     |= FWID(0);
288                 break;
289         }
290
291         omap_mcbsp_config(bus_id, &mcbsp_data->regs);
292         mcbsp_data->configured = 1;
293
294         return 0;
295 }
296
297 /*
298  * This must be called before _set_clkdiv and _set_sysclk since McBSP register
299  * cache is initialized here
300  */
301 static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
302                                       unsigned int fmt)
303 {
304         struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
305         struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
306         unsigned int temp_fmt = fmt;
307
308         if (mcbsp_data->configured)
309                 return 0;
310
311         mcbsp_data->fmt = fmt;
312         memset(regs, 0, sizeof(*regs));
313         /* Generic McBSP register settings */
314         regs->spcr2     |= XINTM(3) | FREE;
315         regs->spcr1     |= RINTM(3);
316         regs->rcr2      |= RFIG;
317         regs->xcr2      |= XFIG;
318         if (cpu_is_omap2430() || cpu_is_omap34xx()) {
319                 regs->xccr = DXENDLY(1) | XDMAEN;
320                 regs->rccr = RFULL_CYCLE | RDMAEN;
321         }
322
323         switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
324         case SND_SOC_DAIFMT_I2S:
325                 /* 1-bit data delay */
326                 regs->rcr2      |= RDATDLY(1);
327                 regs->xcr2      |= XDATDLY(1);
328                 break;
329         case SND_SOC_DAIFMT_DSP_B:
330                 /* 0-bit data delay */
331                 regs->rcr2      |= RDATDLY(0);
332                 regs->xcr2      |= XDATDLY(0);
333                 /* Invert FS polarity configuration */
334                 temp_fmt ^= SND_SOC_DAIFMT_NB_IF;
335                 break;
336         default:
337                 /* Unsupported data format */
338                 return -EINVAL;
339         }
340
341         switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
342         case SND_SOC_DAIFMT_CBS_CFS:
343                 /* McBSP master. Set FS and bit clocks as outputs */
344                 regs->pcr0      |= FSXM | FSRM |
345                                    CLKXM | CLKRM;
346                 /* Sample rate generator drives the FS */
347                 regs->srgr2     |= FSGM;
348                 break;
349         case SND_SOC_DAIFMT_CBM_CFM:
350                 /* McBSP slave */
351                 break;
352         default:
353                 /* Unsupported master/slave configuration */
354                 return -EINVAL;
355         }
356
357         /* Set bit clock (CLKX/CLKR) and FS polarities */
358         switch (temp_fmt & SND_SOC_DAIFMT_INV_MASK) {
359         case SND_SOC_DAIFMT_NB_NF:
360                 /*
361                  * Normal BCLK + FS.
362                  * FS active low. TX data driven on falling edge of bit clock
363                  * and RX data sampled on rising edge of bit clock.
364                  */
365                 regs->pcr0      |= FSXP | FSRP |
366                                    CLKXP | CLKRP;
367                 break;
368         case SND_SOC_DAIFMT_NB_IF:
369                 regs->pcr0      |= CLKXP | CLKRP;
370                 break;
371         case SND_SOC_DAIFMT_IB_NF:
372                 regs->pcr0      |= FSXP | FSRP;
373                 break;
374         case SND_SOC_DAIFMT_IB_IF:
375                 break;
376         default:
377                 return -EINVAL;
378         }
379
380         return 0;
381 }
382
383 static int omap_mcbsp_dai_set_clkdiv(struct snd_soc_dai *cpu_dai,
384                                      int div_id, int div)
385 {
386         struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
387         struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
388
389         if (div_id != OMAP_MCBSP_CLKGDV)
390                 return -ENODEV;
391
392         regs->srgr1     |= CLKGDV(div - 1);
393
394         return 0;
395 }
396
397 static int omap_mcbsp_dai_set_clks_src(struct omap_mcbsp_data *mcbsp_data,
398                                        int clk_id)
399 {
400         int sel_bit;
401         u16 reg, reg_devconf1 = OMAP243X_CONTROL_DEVCONF1;
402
403         if (cpu_class_is_omap1()) {
404                 /* OMAP1's can use only external source clock */
405                 if (unlikely(clk_id == OMAP_MCBSP_SYSCLK_CLKS_FCLK))
406                         return -EINVAL;
407                 else
408                         return 0;
409         }
410
411         if (cpu_is_omap2420() && mcbsp_data->bus_id > 1)
412                 return -EINVAL;
413
414         if (cpu_is_omap343x())
415                 reg_devconf1 = OMAP343X_CONTROL_DEVCONF1;
416
417         switch (mcbsp_data->bus_id) {
418         case 0:
419                 reg = OMAP2_CONTROL_DEVCONF0;
420                 sel_bit = 2;
421                 break;
422         case 1:
423                 reg = OMAP2_CONTROL_DEVCONF0;
424                 sel_bit = 6;
425                 break;
426         case 2:
427                 reg = reg_devconf1;
428                 sel_bit = 0;
429                 break;
430         case 3:
431                 reg = reg_devconf1;
432                 sel_bit = 2;
433                 break;
434         case 4:
435                 reg = reg_devconf1;
436                 sel_bit = 4;
437                 break;
438         default:
439                 return -EINVAL;
440         }
441
442         if (clk_id == OMAP_MCBSP_SYSCLK_CLKS_FCLK)
443                 omap_ctrl_writel(omap_ctrl_readl(reg) & ~(1 << sel_bit), reg);
444         else
445                 omap_ctrl_writel(omap_ctrl_readl(reg) | (1 << sel_bit), reg);
446
447         return 0;
448 }
449
450 static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
451                                          int clk_id, unsigned int freq,
452                                          int dir)
453 {
454         struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
455         struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
456         int err = 0;
457
458         switch (clk_id) {
459         case OMAP_MCBSP_SYSCLK_CLK:
460                 regs->srgr2     |= CLKSM;
461                 break;
462         case OMAP_MCBSP_SYSCLK_CLKS_FCLK:
463         case OMAP_MCBSP_SYSCLK_CLKS_EXT:
464                 err = omap_mcbsp_dai_set_clks_src(mcbsp_data, clk_id);
465                 break;
466
467         case OMAP_MCBSP_SYSCLK_CLKX_EXT:
468                 regs->srgr2     |= CLKSM;
469         case OMAP_MCBSP_SYSCLK_CLKR_EXT:
470                 regs->pcr0      |= SCLKME;
471                 break;
472         default:
473                 err = -ENODEV;
474         }
475
476         return err;
477 }
478
479 static struct snd_soc_dai_ops omap_mcbsp_dai_ops = {
480         .startup        = omap_mcbsp_dai_startup,
481         .shutdown       = omap_mcbsp_dai_shutdown,
482         .trigger        = omap_mcbsp_dai_trigger,
483         .hw_params      = omap_mcbsp_dai_hw_params,
484         .set_fmt        = omap_mcbsp_dai_set_dai_fmt,
485         .set_clkdiv     = omap_mcbsp_dai_set_clkdiv,
486         .set_sysclk     = omap_mcbsp_dai_set_dai_sysclk,
487 };
488
489 #define OMAP_MCBSP_DAI_BUILDER(link_id)                         \
490 {                                                               \
491         .name = "omap-mcbsp-dai-"#link_id,                      \
492         .id = (link_id),                                        \
493         .playback = {                                           \
494                 .channels_min = 1,                              \
495                 .channels_max = 2,                              \
496                 .rates = OMAP_MCBSP_RATES,                      \
497                 .formats = SNDRV_PCM_FMTBIT_S16_LE,             \
498         },                                                      \
499         .capture = {                                            \
500                 .channels_min = 1,                              \
501                 .channels_max = 2,                              \
502                 .rates = OMAP_MCBSP_RATES,                      \
503                 .formats = SNDRV_PCM_FMTBIT_S16_LE,             \
504         },                                                      \
505         .ops = &omap_mcbsp_dai_ops,                             \
506         .private_data = &mcbsp_data[(link_id)].bus_id,          \
507 }
508
509 struct snd_soc_dai omap_mcbsp_dai[] = {
510         OMAP_MCBSP_DAI_BUILDER(0),
511         OMAP_MCBSP_DAI_BUILDER(1),
512 #if NUM_LINKS >= 3
513         OMAP_MCBSP_DAI_BUILDER(2),
514 #endif
515 #if NUM_LINKS == 5
516         OMAP_MCBSP_DAI_BUILDER(3),
517         OMAP_MCBSP_DAI_BUILDER(4),
518 #endif
519 };
520
521 EXPORT_SYMBOL_GPL(omap_mcbsp_dai);
522
523 static int __init snd_omap_mcbsp_init(void)
524 {
525         return snd_soc_register_dais(omap_mcbsp_dai,
526                                      ARRAY_SIZE(omap_mcbsp_dai));
527 }
528 module_init(snd_omap_mcbsp_init);
529
530 static void __exit snd_omap_mcbsp_exit(void)
531 {
532         snd_soc_unregister_dais(omap_mcbsp_dai, ARRAY_SIZE(omap_mcbsp_dai));
533 }
534 module_exit(snd_omap_mcbsp_exit);
535
536 MODULE_AUTHOR("Jarkko Nikula <jhnikula@gmail.com>");
537 MODULE_DESCRIPTION("OMAP I2S SoC Interface");
538 MODULE_LICENSE("GPL");