OMAP: McBSP: Add 32-bit mode support
[linux-2.6.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 <plat/control.h>
35 #include <plat/dma.h>
36 #include <plat/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 #define OMAP_MCBSP_SOC_SINGLE_S16_EXT(xname, xmin, xmax, \
43         xhandler_get, xhandler_put) \
44 {       .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
45         .info = omap_mcbsp_st_info_volsw, \
46         .get = xhandler_get, .put = xhandler_put, \
47         .private_value = (unsigned long) &(struct soc_mixer_control) \
48         {.min = xmin, .max = xmax} }
49
50 struct omap_mcbsp_data {
51         unsigned int                    bus_id;
52         struct omap_mcbsp_reg_cfg       regs;
53         unsigned int                    fmt;
54         /*
55          * Flags indicating is the bus already activated and configured by
56          * another substream
57          */
58         int                             active;
59         int                             configured;
60         unsigned int                    in_freq;
61         int                             clk_div;
62 };
63
64 #define to_mcbsp(priv)  container_of((priv), struct omap_mcbsp_data, bus_id)
65
66 static struct omap_mcbsp_data mcbsp_data[NUM_LINKS];
67
68 /*
69  * Stream DMA parameters. DMA request line and port address are set runtime
70  * since they are different between OMAP1 and later OMAPs
71  */
72 static struct omap_pcm_dma_data omap_mcbsp_dai_dma_params[NUM_LINKS][2];
73
74 #if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX)
75 static const int omap1_dma_reqs[][2] = {
76         { OMAP_DMA_MCBSP1_TX, OMAP_DMA_MCBSP1_RX },
77         { OMAP_DMA_MCBSP2_TX, OMAP_DMA_MCBSP2_RX },
78         { OMAP_DMA_MCBSP3_TX, OMAP_DMA_MCBSP3_RX },
79 };
80 static const unsigned long omap1_mcbsp_port[][2] = {
81         { OMAP1510_MCBSP1_BASE + OMAP_MCBSP_REG_DXR1,
82           OMAP1510_MCBSP1_BASE + OMAP_MCBSP_REG_DRR1 },
83         { OMAP1510_MCBSP2_BASE + OMAP_MCBSP_REG_DXR1,
84           OMAP1510_MCBSP2_BASE + OMAP_MCBSP_REG_DRR1 },
85         { OMAP1510_MCBSP3_BASE + OMAP_MCBSP_REG_DXR1,
86           OMAP1510_MCBSP3_BASE + OMAP_MCBSP_REG_DRR1 },
87 };
88 #else
89 static const int omap1_dma_reqs[][2] = {};
90 static const unsigned long omap1_mcbsp_port[][2] = {};
91 #endif
92
93 #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
94 static const int omap24xx_dma_reqs[][2] = {
95         { OMAP24XX_DMA_MCBSP1_TX, OMAP24XX_DMA_MCBSP1_RX },
96         { OMAP24XX_DMA_MCBSP2_TX, OMAP24XX_DMA_MCBSP2_RX },
97 #if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3)
98         { OMAP24XX_DMA_MCBSP3_TX, OMAP24XX_DMA_MCBSP3_RX },
99         { OMAP24XX_DMA_MCBSP4_TX, OMAP24XX_DMA_MCBSP4_RX },
100         { OMAP24XX_DMA_MCBSP5_TX, OMAP24XX_DMA_MCBSP5_RX },
101 #endif
102 };
103 #else
104 static const int omap24xx_dma_reqs[][2] = {};
105 #endif
106
107 #if defined(CONFIG_ARCH_OMAP2420)
108 static const unsigned long omap2420_mcbsp_port[][2] = {
109         { OMAP24XX_MCBSP1_BASE + OMAP_MCBSP_REG_DXR1,
110           OMAP24XX_MCBSP1_BASE + OMAP_MCBSP_REG_DRR1 },
111         { OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DXR1,
112           OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DRR1 },
113 };
114 #else
115 static const unsigned long omap2420_mcbsp_port[][2] = {};
116 #endif
117
118 #if defined(CONFIG_ARCH_OMAP2430)
119 static const unsigned long omap2430_mcbsp_port[][2] = {
120         { OMAP24XX_MCBSP1_BASE + OMAP_MCBSP_REG_DXR,
121           OMAP24XX_MCBSP1_BASE + OMAP_MCBSP_REG_DRR },
122         { OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DXR,
123           OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DRR },
124         { OMAP2430_MCBSP3_BASE + OMAP_MCBSP_REG_DXR,
125           OMAP2430_MCBSP3_BASE + OMAP_MCBSP_REG_DRR },
126         { OMAP2430_MCBSP4_BASE + OMAP_MCBSP_REG_DXR,
127           OMAP2430_MCBSP4_BASE + OMAP_MCBSP_REG_DRR },
128         { OMAP2430_MCBSP5_BASE + OMAP_MCBSP_REG_DXR,
129           OMAP2430_MCBSP5_BASE + OMAP_MCBSP_REG_DRR },
130 };
131 #else
132 static const unsigned long omap2430_mcbsp_port[][2] = {};
133 #endif
134
135 #if defined(CONFIG_ARCH_OMAP3)
136 static const unsigned long omap34xx_mcbsp_port[][2] = {
137         { OMAP34XX_MCBSP1_BASE + OMAP_MCBSP_REG_DXR,
138           OMAP34XX_MCBSP1_BASE + OMAP_MCBSP_REG_DRR },
139         { OMAP34XX_MCBSP2_BASE + OMAP_MCBSP_REG_DXR,
140           OMAP34XX_MCBSP2_BASE + OMAP_MCBSP_REG_DRR },
141         { OMAP34XX_MCBSP3_BASE + OMAP_MCBSP_REG_DXR,
142           OMAP34XX_MCBSP3_BASE + OMAP_MCBSP_REG_DRR },
143         { OMAP34XX_MCBSP4_BASE + OMAP_MCBSP_REG_DXR,
144           OMAP34XX_MCBSP4_BASE + OMAP_MCBSP_REG_DRR },
145         { OMAP34XX_MCBSP5_BASE + OMAP_MCBSP_REG_DXR,
146           OMAP34XX_MCBSP5_BASE + OMAP_MCBSP_REG_DRR },
147 };
148 #else
149 static const unsigned long omap34xx_mcbsp_port[][2] = {};
150 #endif
151
152 static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream)
153 {
154         struct snd_soc_pcm_runtime *rtd = substream->private_data;
155         struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
156         struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
157         int dma_op_mode = omap_mcbsp_get_dma_op_mode(mcbsp_data->bus_id);
158         int samples;
159
160         /* TODO: Currently, MODE_ELEMENT == MODE_FRAME */
161         if (dma_op_mode == MCBSP_DMA_MODE_THRESHOLD)
162                 samples = snd_pcm_lib_period_bytes(substream) >> 1;
163         else
164                 samples = 1;
165
166         /* Configure McBSP internal buffer usage */
167         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
168                 omap_mcbsp_set_tx_threshold(mcbsp_data->bus_id, samples - 1);
169         else
170                 omap_mcbsp_set_rx_threshold(mcbsp_data->bus_id, samples - 1);
171 }
172
173 static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream,
174                                   struct snd_soc_dai *dai)
175 {
176         struct snd_soc_pcm_runtime *rtd = substream->private_data;
177         struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
178         struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
179         int bus_id = mcbsp_data->bus_id;
180         int err = 0;
181
182         if (!cpu_dai->active)
183                 err = omap_mcbsp_request(bus_id);
184
185         if (cpu_is_omap343x()) {
186                 int dma_op_mode = omap_mcbsp_get_dma_op_mode(bus_id);
187                 int max_period;
188
189                 /*
190                  * McBSP2 in OMAP3 has 1024 * 32-bit internal audio buffer.
191                  * Set constraint for minimum buffer size to the same than FIFO
192                  * size in order to avoid underruns in playback startup because
193                  * HW is keeping the DMA request active until FIFO is filled.
194                  */
195                 if (bus_id == 1)
196                         snd_pcm_hw_constraint_minmax(substream->runtime,
197                                         SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
198                                         4096, UINT_MAX);
199
200                 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
201                         max_period = omap_mcbsp_get_max_tx_threshold(bus_id);
202                 else
203                         max_period = omap_mcbsp_get_max_rx_threshold(bus_id);
204
205                 max_period++;
206                 max_period <<= 1;
207
208                 if (dma_op_mode == MCBSP_DMA_MODE_THRESHOLD)
209                         snd_pcm_hw_constraint_minmax(substream->runtime,
210                                                 SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
211                                                 32, max_period);
212         }
213
214         return err;
215 }
216
217 static void omap_mcbsp_dai_shutdown(struct snd_pcm_substream *substream,
218                                     struct snd_soc_dai *dai)
219 {
220         struct snd_soc_pcm_runtime *rtd = substream->private_data;
221         struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
222         struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
223
224         if (!cpu_dai->active) {
225                 omap_mcbsp_free(mcbsp_data->bus_id);
226                 mcbsp_data->configured = 0;
227         }
228 }
229
230 static int omap_mcbsp_dai_trigger(struct snd_pcm_substream *substream, int cmd,
231                                   struct snd_soc_dai *dai)
232 {
233         struct snd_soc_pcm_runtime *rtd = substream->private_data;
234         struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
235         struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
236         int err = 0, play = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
237
238         switch (cmd) {
239         case SNDRV_PCM_TRIGGER_START:
240         case SNDRV_PCM_TRIGGER_RESUME:
241         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
242                 mcbsp_data->active++;
243                 omap_mcbsp_start(mcbsp_data->bus_id, play, !play);
244                 break;
245
246         case SNDRV_PCM_TRIGGER_STOP:
247         case SNDRV_PCM_TRIGGER_SUSPEND:
248         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
249                 omap_mcbsp_stop(mcbsp_data->bus_id, play, !play);
250                 mcbsp_data->active--;
251                 break;
252         default:
253                 err = -EINVAL;
254         }
255
256         return err;
257 }
258
259 static snd_pcm_sframes_t omap_mcbsp_dai_delay(
260                         struct snd_pcm_substream *substream,
261                         struct snd_soc_dai *dai)
262 {
263         struct snd_soc_pcm_runtime *rtd = substream->private_data;
264         struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
265         struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
266         u16 fifo_use;
267         snd_pcm_sframes_t delay;
268
269         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
270                 fifo_use = omap_mcbsp_get_tx_delay(mcbsp_data->bus_id);
271         else
272                 fifo_use = omap_mcbsp_get_rx_delay(mcbsp_data->bus_id);
273
274         /*
275          * Divide the used locations with the channel count to get the
276          * FIFO usage in samples (don't care about partial samples in the
277          * buffer).
278          */
279         delay = fifo_use / substream->runtime->channels;
280
281         return delay;
282 }
283
284 static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
285                                     struct snd_pcm_hw_params *params,
286                                     struct snd_soc_dai *dai)
287 {
288         struct snd_soc_pcm_runtime *rtd = substream->private_data;
289         struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
290         struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
291         struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
292         int dma, bus_id = mcbsp_data->bus_id, id = cpu_dai->id;
293         int wlen, channels, wpf, sync_mode = OMAP_DMA_SYNC_ELEMENT;
294         unsigned long port;
295         unsigned int format, div, framesize, master;
296
297         if (cpu_class_is_omap1()) {
298                 dma = omap1_dma_reqs[bus_id][substream->stream];
299                 port = omap1_mcbsp_port[bus_id][substream->stream];
300         } else if (cpu_is_omap2420()) {
301                 dma = omap24xx_dma_reqs[bus_id][substream->stream];
302                 port = omap2420_mcbsp_port[bus_id][substream->stream];
303         } else if (cpu_is_omap2430()) {
304                 dma = omap24xx_dma_reqs[bus_id][substream->stream];
305                 port = omap2430_mcbsp_port[bus_id][substream->stream];
306         } else if (cpu_is_omap343x()) {
307                 dma = omap24xx_dma_reqs[bus_id][substream->stream];
308                 port = omap34xx_mcbsp_port[bus_id][substream->stream];
309                 omap_mcbsp_dai_dma_params[id][substream->stream].set_threshold =
310                                                 omap_mcbsp_set_threshold;
311                 /* TODO: Currently, MODE_ELEMENT == MODE_FRAME */
312                 if (omap_mcbsp_get_dma_op_mode(bus_id) ==
313                                                 MCBSP_DMA_MODE_THRESHOLD)
314                         sync_mode = OMAP_DMA_SYNC_FRAME;
315         } else {
316                 return -ENODEV;
317         }
318         omap_mcbsp_dai_dma_params[id][substream->stream].name =
319                 substream->stream ? "Audio Capture" : "Audio Playback";
320         omap_mcbsp_dai_dma_params[id][substream->stream].dma_req = dma;
321         omap_mcbsp_dai_dma_params[id][substream->stream].port_addr = port;
322         omap_mcbsp_dai_dma_params[id][substream->stream].sync_mode = sync_mode;
323         switch (params_format(params)) {
324         case SNDRV_PCM_FORMAT_S16_LE:
325                 omap_mcbsp_dai_dma_params[id][substream->stream].data_type =
326                          OMAP_DMA_DATA_TYPE_S16;
327                 break;
328         case SNDRV_PCM_FORMAT_S32_LE:
329                 omap_mcbsp_dai_dma_params[id][substream->stream].data_type =
330                          OMAP_DMA_DATA_TYPE_S32;
331                 break;
332         default:
333                 return -EINVAL;
334         }
335
336         snd_soc_dai_set_dma_data(cpu_dai, substream,
337                 &omap_mcbsp_dai_dma_params[id][substream->stream]);
338
339         if (mcbsp_data->configured) {
340                 /* McBSP already configured by another stream */
341                 return 0;
342         }
343
344         format = mcbsp_data->fmt & SND_SOC_DAIFMT_FORMAT_MASK;
345         wpf = channels = params_channels(params);
346         if (channels == 2 && (format == SND_SOC_DAIFMT_I2S ||
347                               format == SND_SOC_DAIFMT_LEFT_J)) {
348                 /* Use dual-phase frames */
349                 regs->rcr2      |= RPHASE;
350                 regs->xcr2      |= XPHASE;
351                 /* Set 1 word per (McBSP) frame for phase1 and phase2 */
352                 wpf--;
353                 regs->rcr2      |= RFRLEN2(wpf - 1);
354                 regs->xcr2      |= XFRLEN2(wpf - 1);
355         }
356
357         regs->rcr1      |= RFRLEN1(wpf - 1);
358         regs->xcr1      |= XFRLEN1(wpf - 1);
359
360         switch (params_format(params)) {
361         case SNDRV_PCM_FORMAT_S16_LE:
362                 /* Set word lengths */
363                 wlen = 16;
364                 regs->rcr2      |= RWDLEN2(OMAP_MCBSP_WORD_16);
365                 regs->rcr1      |= RWDLEN1(OMAP_MCBSP_WORD_16);
366                 regs->xcr2      |= XWDLEN2(OMAP_MCBSP_WORD_16);
367                 regs->xcr1      |= XWDLEN1(OMAP_MCBSP_WORD_16);
368                 break;
369         case SNDRV_PCM_FORMAT_S32_LE:
370                 /* Set word lengths */
371                 wlen = 32;
372                 regs->rcr2      |= RWDLEN2(OMAP_MCBSP_WORD_32);
373                 regs->rcr1      |= RWDLEN1(OMAP_MCBSP_WORD_32);
374                 regs->xcr2      |= XWDLEN2(OMAP_MCBSP_WORD_32);
375                 regs->xcr1      |= XWDLEN1(OMAP_MCBSP_WORD_32);
376                 break;
377         default:
378                 /* Unsupported PCM format */
379                 return -EINVAL;
380         }
381
382         /* In McBSP master modes, FRAME (i.e. sample rate) is generated
383          * by _counting_ BCLKs. Calculate frame size in BCLKs */
384         master = mcbsp_data->fmt & SND_SOC_DAIFMT_MASTER_MASK;
385         if (master ==   SND_SOC_DAIFMT_CBS_CFS) {
386                 div = mcbsp_data->clk_div ? mcbsp_data->clk_div : 1;
387                 framesize = (mcbsp_data->in_freq / div) / params_rate(params);
388
389                 if (framesize < wlen * channels) {
390                         printk(KERN_ERR "%s: not enough bandwidth for desired rate and "
391                                         "channels\n", __func__);
392                         return -EINVAL;
393                 }
394         } else
395                 framesize = wlen * channels;
396
397         /* Set FS period and length in terms of bit clock periods */
398         switch (format) {
399         case SND_SOC_DAIFMT_I2S:
400         case SND_SOC_DAIFMT_LEFT_J:
401                 regs->srgr2     |= FPER(framesize - 1);
402                 regs->srgr1     |= FWID((framesize >> 1) - 1);
403                 break;
404         case SND_SOC_DAIFMT_DSP_A:
405         case SND_SOC_DAIFMT_DSP_B:
406                 regs->srgr2     |= FPER(framesize - 1);
407                 regs->srgr1     |= FWID(0);
408                 break;
409         }
410
411         omap_mcbsp_config(bus_id, &mcbsp_data->regs);
412         mcbsp_data->configured = 1;
413
414         return 0;
415 }
416
417 /*
418  * This must be called before _set_clkdiv and _set_sysclk since McBSP register
419  * cache is initialized here
420  */
421 static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
422                                       unsigned int fmt)
423 {
424         struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
425         struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
426         unsigned int temp_fmt = fmt;
427
428         if (mcbsp_data->configured)
429                 return 0;
430
431         mcbsp_data->fmt = fmt;
432         memset(regs, 0, sizeof(*regs));
433         /* Generic McBSP register settings */
434         regs->spcr2     |= XINTM(3) | FREE;
435         regs->spcr1     |= RINTM(3);
436         /* RFIG and XFIG are not defined in 34xx */
437         if (!cpu_is_omap34xx()) {
438                 regs->rcr2      |= RFIG;
439                 regs->xcr2      |= XFIG;
440         }
441         if (cpu_is_omap2430() || cpu_is_omap34xx()) {
442                 regs->xccr = DXENDLY(1) | XDMAEN | XDISABLE;
443                 regs->rccr = RFULL_CYCLE | RDMAEN | RDISABLE;
444         }
445
446         switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
447         case SND_SOC_DAIFMT_I2S:
448                 /* 1-bit data delay */
449                 regs->rcr2      |= RDATDLY(1);
450                 regs->xcr2      |= XDATDLY(1);
451                 break;
452         case SND_SOC_DAIFMT_LEFT_J:
453                 /* 0-bit data delay */
454                 regs->rcr2      |= RDATDLY(0);
455                 regs->xcr2      |= XDATDLY(0);
456                 regs->spcr1     |= RJUST(2);
457                 /* Invert FS polarity configuration */
458                 temp_fmt ^= SND_SOC_DAIFMT_NB_IF;
459                 break;
460         case SND_SOC_DAIFMT_DSP_A:
461                 /* 1-bit data delay */
462                 regs->rcr2      |= RDATDLY(1);
463                 regs->xcr2      |= XDATDLY(1);
464                 /* Invert FS polarity configuration */
465                 temp_fmt ^= SND_SOC_DAIFMT_NB_IF;
466                 break;
467         case SND_SOC_DAIFMT_DSP_B:
468                 /* 0-bit data delay */
469                 regs->rcr2      |= RDATDLY(0);
470                 regs->xcr2      |= XDATDLY(0);
471                 /* Invert FS polarity configuration */
472                 temp_fmt ^= SND_SOC_DAIFMT_NB_IF;
473                 break;
474         default:
475                 /* Unsupported data format */
476                 return -EINVAL;
477         }
478
479         switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
480         case SND_SOC_DAIFMT_CBS_CFS:
481                 /* McBSP master. Set FS and bit clocks as outputs */
482                 regs->pcr0      |= FSXM | FSRM |
483                                    CLKXM | CLKRM;
484                 /* Sample rate generator drives the FS */
485                 regs->srgr2     |= FSGM;
486                 break;
487         case SND_SOC_DAIFMT_CBM_CFM:
488                 /* McBSP slave */
489                 break;
490         default:
491                 /* Unsupported master/slave configuration */
492                 return -EINVAL;
493         }
494
495         /* Set bit clock (CLKX/CLKR) and FS polarities */
496         switch (temp_fmt & SND_SOC_DAIFMT_INV_MASK) {
497         case SND_SOC_DAIFMT_NB_NF:
498                 /*
499                  * Normal BCLK + FS.
500                  * FS active low. TX data driven on falling edge of bit clock
501                  * and RX data sampled on rising edge of bit clock.
502                  */
503                 regs->pcr0      |= FSXP | FSRP |
504                                    CLKXP | CLKRP;
505                 break;
506         case SND_SOC_DAIFMT_NB_IF:
507                 regs->pcr0      |= CLKXP | CLKRP;
508                 break;
509         case SND_SOC_DAIFMT_IB_NF:
510                 regs->pcr0      |= FSXP | FSRP;
511                 break;
512         case SND_SOC_DAIFMT_IB_IF:
513                 break;
514         default:
515                 return -EINVAL;
516         }
517
518         return 0;
519 }
520
521 static int omap_mcbsp_dai_set_clkdiv(struct snd_soc_dai *cpu_dai,
522                                      int div_id, int div)
523 {
524         struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
525         struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
526
527         if (div_id != OMAP_MCBSP_CLKGDV)
528                 return -ENODEV;
529
530         mcbsp_data->clk_div = div;
531         regs->srgr1     |= CLKGDV(div - 1);
532
533         return 0;
534 }
535
536 static int omap_mcbsp_dai_set_clks_src(struct omap_mcbsp_data *mcbsp_data,
537                                        int clk_id)
538 {
539         int sel_bit;
540         u16 reg, reg_devconf1 = OMAP243X_CONTROL_DEVCONF1;
541
542         if (cpu_class_is_omap1()) {
543                 /* OMAP1's can use only external source clock */
544                 if (unlikely(clk_id == OMAP_MCBSP_SYSCLK_CLKS_FCLK))
545                         return -EINVAL;
546                 else
547                         return 0;
548         }
549
550         if (cpu_is_omap2420() && mcbsp_data->bus_id > 1)
551                 return -EINVAL;
552
553         if (cpu_is_omap343x())
554                 reg_devconf1 = OMAP343X_CONTROL_DEVCONF1;
555
556         switch (mcbsp_data->bus_id) {
557         case 0:
558                 reg = OMAP2_CONTROL_DEVCONF0;
559                 sel_bit = 2;
560                 break;
561         case 1:
562                 reg = OMAP2_CONTROL_DEVCONF0;
563                 sel_bit = 6;
564                 break;
565         case 2:
566                 reg = reg_devconf1;
567                 sel_bit = 0;
568                 break;
569         case 3:
570                 reg = reg_devconf1;
571                 sel_bit = 2;
572                 break;
573         case 4:
574                 reg = reg_devconf1;
575                 sel_bit = 4;
576                 break;
577         default:
578                 return -EINVAL;
579         }
580
581         if (clk_id == OMAP_MCBSP_SYSCLK_CLKS_FCLK)
582                 omap_ctrl_writel(omap_ctrl_readl(reg) & ~(1 << sel_bit), reg);
583         else
584                 omap_ctrl_writel(omap_ctrl_readl(reg) | (1 << sel_bit), reg);
585
586         return 0;
587 }
588
589 static int omap_mcbsp_dai_set_rcvr_src(struct omap_mcbsp_data *mcbsp_data,
590                                        int clk_id)
591 {
592         int sel_bit, set = 0;
593         u16 reg = OMAP2_CONTROL_DEVCONF0;
594
595         if (cpu_class_is_omap1())
596                 return -EINVAL; /* TODO: Can this be implemented for OMAP1? */
597         if (mcbsp_data->bus_id != 0)
598                 return -EINVAL;
599
600         switch (clk_id) {
601         case OMAP_MCBSP_CLKR_SRC_CLKX:
602                 set = 1;
603         case OMAP_MCBSP_CLKR_SRC_CLKR:
604                 sel_bit = 3;
605                 break;
606         case OMAP_MCBSP_FSR_SRC_FSX:
607                 set = 1;
608         case OMAP_MCBSP_FSR_SRC_FSR:
609                 sel_bit = 4;
610                 break;
611         default:
612                 return -EINVAL;
613         }
614
615         if (set)
616                 omap_ctrl_writel(omap_ctrl_readl(reg) | (1 << sel_bit), reg);
617         else
618                 omap_ctrl_writel(omap_ctrl_readl(reg) & ~(1 << sel_bit), reg);
619
620         return 0;
621 }
622
623 static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
624                                          int clk_id, unsigned int freq,
625                                          int dir)
626 {
627         struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
628         struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
629         int err = 0;
630
631         mcbsp_data->in_freq = freq;
632
633         switch (clk_id) {
634         case OMAP_MCBSP_SYSCLK_CLK:
635                 regs->srgr2     |= CLKSM;
636                 break;
637         case OMAP_MCBSP_SYSCLK_CLKS_FCLK:
638         case OMAP_MCBSP_SYSCLK_CLKS_EXT:
639                 err = omap_mcbsp_dai_set_clks_src(mcbsp_data, clk_id);
640                 break;
641
642         case OMAP_MCBSP_SYSCLK_CLKX_EXT:
643                 regs->srgr2     |= CLKSM;
644         case OMAP_MCBSP_SYSCLK_CLKR_EXT:
645                 regs->pcr0      |= SCLKME;
646                 break;
647
648         case OMAP_MCBSP_CLKR_SRC_CLKR:
649         case OMAP_MCBSP_CLKR_SRC_CLKX:
650         case OMAP_MCBSP_FSR_SRC_FSR:
651         case OMAP_MCBSP_FSR_SRC_FSX:
652                 err = omap_mcbsp_dai_set_rcvr_src(mcbsp_data, clk_id);
653                 break;
654         default:
655                 err = -ENODEV;
656         }
657
658         return err;
659 }
660
661 static struct snd_soc_dai_ops omap_mcbsp_dai_ops = {
662         .startup        = omap_mcbsp_dai_startup,
663         .shutdown       = omap_mcbsp_dai_shutdown,
664         .trigger        = omap_mcbsp_dai_trigger,
665         .delay          = omap_mcbsp_dai_delay,
666         .hw_params      = omap_mcbsp_dai_hw_params,
667         .set_fmt        = omap_mcbsp_dai_set_dai_fmt,
668         .set_clkdiv     = omap_mcbsp_dai_set_clkdiv,
669         .set_sysclk     = omap_mcbsp_dai_set_dai_sysclk,
670 };
671
672 #define OMAP_MCBSP_DAI_BUILDER(link_id)                         \
673 {                                                               \
674         .name = "omap-mcbsp-dai-"#link_id,                      \
675         .id = (link_id),                                        \
676         .playback = {                                           \
677                 .channels_min = 1,                              \
678                 .channels_max = 16,                             \
679                 .rates = OMAP_MCBSP_RATES,                      \
680                 .formats = SNDRV_PCM_FMTBIT_S16_LE |            \
681                            SNDRV_PCM_FMTBIT_S32_LE,             \
682         },                                                      \
683         .capture = {                                            \
684                 .channels_min = 1,                              \
685                 .channels_max = 16,                             \
686                 .rates = OMAP_MCBSP_RATES,                      \
687                 .formats = SNDRV_PCM_FMTBIT_S16_LE |            \
688                            SNDRV_PCM_FMTBIT_S32_LE,             \
689         },                                                      \
690         .ops = &omap_mcbsp_dai_ops,                             \
691         .private_data = &mcbsp_data[(link_id)].bus_id,          \
692 }
693
694 struct snd_soc_dai omap_mcbsp_dai[] = {
695         OMAP_MCBSP_DAI_BUILDER(0),
696         OMAP_MCBSP_DAI_BUILDER(1),
697 #if NUM_LINKS >= 3
698         OMAP_MCBSP_DAI_BUILDER(2),
699 #endif
700 #if NUM_LINKS == 5
701         OMAP_MCBSP_DAI_BUILDER(3),
702         OMAP_MCBSP_DAI_BUILDER(4),
703 #endif
704 };
705
706 EXPORT_SYMBOL_GPL(omap_mcbsp_dai);
707
708 int omap_mcbsp_st_info_volsw(struct snd_kcontrol *kcontrol,
709                         struct snd_ctl_elem_info *uinfo)
710 {
711         struct soc_mixer_control *mc =
712                 (struct soc_mixer_control *)kcontrol->private_value;
713         int max = mc->max;
714         int min = mc->min;
715
716         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
717         uinfo->count = 1;
718         uinfo->value.integer.min = min;
719         uinfo->value.integer.max = max;
720         return 0;
721 }
722
723 #define OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(id, channel)                   \
724 static int                                                              \
725 omap_mcbsp##id##_set_st_ch##channel##_volume(struct snd_kcontrol *kc,   \
726                                         struct snd_ctl_elem_value *uc)  \
727 {                                                                       \
728         struct soc_mixer_control *mc =                                  \
729                 (struct soc_mixer_control *)kc->private_value;          \
730         int max = mc->max;                                              \
731         int min = mc->min;                                              \
732         int val = uc->value.integer.value[0];                           \
733                                                                         \
734         if (val < min || val > max)                                     \
735                 return -EINVAL;                                         \
736                                                                         \
737         /* OMAP McBSP implementation uses index values 0..4 */          \
738         return omap_st_set_chgain((id)-1, channel, val);                \
739 }
740
741 #define OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(id, channel)                   \
742 static int                                                              \
743 omap_mcbsp##id##_get_st_ch##channel##_volume(struct snd_kcontrol *kc,   \
744                                         struct snd_ctl_elem_value *uc)  \
745 {                                                                       \
746         s16 chgain;                                                     \
747                                                                         \
748         if (omap_st_get_chgain((id)-1, channel, &chgain))               \
749                 return -EAGAIN;                                         \
750                                                                         \
751         uc->value.integer.value[0] = chgain;                            \
752         return 0;                                                       \
753 }
754
755 OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(2, 0)
756 OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(2, 1)
757 OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(3, 0)
758 OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(3, 1)
759 OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(2, 0)
760 OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(2, 1)
761 OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(3, 0)
762 OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(3, 1)
763
764 static int omap_mcbsp_st_put_mode(struct snd_kcontrol *kcontrol,
765                                 struct snd_ctl_elem_value *ucontrol)
766 {
767         struct soc_mixer_control *mc =
768                 (struct soc_mixer_control *)kcontrol->private_value;
769         u8 value = ucontrol->value.integer.value[0];
770
771         if (value == omap_st_is_enabled(mc->reg))
772                 return 0;
773
774         if (value)
775                 omap_st_enable(mc->reg);
776         else
777                 omap_st_disable(mc->reg);
778
779         return 1;
780 }
781
782 static int omap_mcbsp_st_get_mode(struct snd_kcontrol *kcontrol,
783                                 struct snd_ctl_elem_value *ucontrol)
784 {
785         struct soc_mixer_control *mc =
786                 (struct soc_mixer_control *)kcontrol->private_value;
787
788         ucontrol->value.integer.value[0] = omap_st_is_enabled(mc->reg);
789         return 0;
790 }
791
792 static const struct snd_kcontrol_new omap_mcbsp2_st_controls[] = {
793         SOC_SINGLE_EXT("McBSP2 Sidetone Switch", 1, 0, 1, 0,
794                         omap_mcbsp_st_get_mode, omap_mcbsp_st_put_mode),
795         OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP2 Sidetone Channel 0 Volume",
796                                       -32768, 32767,
797                                       omap_mcbsp2_get_st_ch0_volume,
798                                       omap_mcbsp2_set_st_ch0_volume),
799         OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP2 Sidetone Channel 1 Volume",
800                                       -32768, 32767,
801                                       omap_mcbsp2_get_st_ch1_volume,
802                                       omap_mcbsp2_set_st_ch1_volume),
803 };
804
805 static const struct snd_kcontrol_new omap_mcbsp3_st_controls[] = {
806         SOC_SINGLE_EXT("McBSP3 Sidetone Switch", 2, 0, 1, 0,
807                         omap_mcbsp_st_get_mode, omap_mcbsp_st_put_mode),
808         OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP3 Sidetone Channel 0 Volume",
809                                       -32768, 32767,
810                                       omap_mcbsp3_get_st_ch0_volume,
811                                       omap_mcbsp3_set_st_ch0_volume),
812         OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP3 Sidetone Channel 1 Volume",
813                                       -32768, 32767,
814                                       omap_mcbsp3_get_st_ch1_volume,
815                                       omap_mcbsp3_set_st_ch1_volume),
816 };
817
818 int omap_mcbsp_st_add_controls(struct snd_soc_codec *codec, int mcbsp_id)
819 {
820         if (!cpu_is_omap34xx())
821                 return -ENODEV;
822
823         switch (mcbsp_id) {
824         case 1: /* McBSP 2 */
825                 return snd_soc_add_controls(codec, omap_mcbsp2_st_controls,
826                                         ARRAY_SIZE(omap_mcbsp2_st_controls));
827         case 2: /* McBSP 3 */
828                 return snd_soc_add_controls(codec, omap_mcbsp3_st_controls,
829                                         ARRAY_SIZE(omap_mcbsp3_st_controls));
830         default:
831                 break;
832         }
833
834         return -EINVAL;
835 }
836 EXPORT_SYMBOL_GPL(omap_mcbsp_st_add_controls);
837
838 static int __init snd_omap_mcbsp_init(void)
839 {
840         return snd_soc_register_dais(omap_mcbsp_dai,
841                                      ARRAY_SIZE(omap_mcbsp_dai));
842 }
843 module_init(snd_omap_mcbsp_init);
844
845 static void __exit snd_omap_mcbsp_exit(void)
846 {
847         snd_soc_unregister_dais(omap_mcbsp_dai, ARRAY_SIZE(omap_mcbsp_dai));
848 }
849 module_exit(snd_omap_mcbsp_exit);
850
851 MODULE_AUTHOR("Jarkko Nikula <jhnikula@gmail.com>");
852 MODULE_DESCRIPTION("OMAP I2S SoC Interface");
853 MODULE_LICENSE("GPL");