Merge branch 'topic/oss' into for-linus
[pandora-kernel.git] / sound / soc / imx / mxc-ssi.c
1 /*
2  * mxc-ssi.c  --  SSI driver for Freescale IMX
3  *
4  * Copyright 2006 Wolfson Microelectronics PLC.
5  * Author: Liam Girdwood
6  *         liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
7  *
8  *  Based on mxc-alsa-mc13783 (C) 2006 Freescale.
9  *
10  *  This program is free software; you can redistribute  it and/or modify it
11  *  under  the terms of  the GNU General  Public License as published by the
12  *  Free Software Foundation;  either version 2 of the  License, or (at your
13  *  option) any later version.
14  *
15  * TODO:
16  *   Need to rework SSI register defs when new defs go into mainline.
17  *   Add support for TDM and FIFO 1.
18  *   Add support for i.mx3x DMA interface.
19  *
20  */
21
22
23 #include <linux/module.h>
24 #include <linux/init.h>
25 #include <linux/platform_device.h>
26 #include <linux/slab.h>
27 #include <linux/dma-mapping.h>
28 #include <linux/clk.h>
29 #include <sound/core.h>
30 #include <sound/pcm.h>
31 #include <sound/pcm_params.h>
32 #include <sound/soc.h>
33 #include <mach/dma-mx1-mx2.h>
34 #include <asm/mach-types.h>
35
36 #include "mxc-ssi.h"
37 #include "mx1_mx2-pcm.h"
38
39 #define SSI1_PORT       0
40 #define SSI2_PORT       1
41
42 static int ssi_active[2] = {0, 0};
43
44 /* DMA information for mx1_mx2 platforms */
45 static struct mx1_mx2_pcm_dma_params imx_ssi1_pcm_stereo_out0 = {
46         .name                   = "SSI1 PCM Stereo out 0",
47         .transfer_type = DMA_MODE_WRITE,
48         .per_address = SSI1_BASE_ADDR + STX0,
49         .event_id = DMA_REQ_SSI1_TX0,
50         .watermark_level = TXFIFO_WATERMARK,
51         .per_config = IMX_DMA_MEMSIZE_16 | IMX_DMA_TYPE_FIFO,
52         .mem_config = IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR,
53 };
54
55 static struct mx1_mx2_pcm_dma_params imx_ssi1_pcm_stereo_out1 = {
56         .name                   = "SSI1 PCM Stereo out 1",
57         .transfer_type = DMA_MODE_WRITE,
58         .per_address = SSI1_BASE_ADDR + STX1,
59         .event_id = DMA_REQ_SSI1_TX1,
60         .watermark_level = TXFIFO_WATERMARK,
61         .per_config = IMX_DMA_MEMSIZE_16 | IMX_DMA_TYPE_FIFO,
62         .mem_config = IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR,
63 };
64
65 static struct mx1_mx2_pcm_dma_params imx_ssi1_pcm_stereo_in0 = {
66         .name                   = "SSI1 PCM Stereo in 0",
67         .transfer_type = DMA_MODE_READ,
68         .per_address = SSI1_BASE_ADDR + SRX0,
69         .event_id = DMA_REQ_SSI1_RX0,
70         .watermark_level = RXFIFO_WATERMARK,
71         .per_config = IMX_DMA_MEMSIZE_16 | IMX_DMA_TYPE_FIFO,
72         .mem_config = IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR,
73 };
74
75 static struct mx1_mx2_pcm_dma_params imx_ssi1_pcm_stereo_in1 = {
76         .name                   = "SSI1 PCM Stereo in 1",
77         .transfer_type = DMA_MODE_READ,
78         .per_address = SSI1_BASE_ADDR + SRX1,
79         .event_id = DMA_REQ_SSI1_RX1,
80         .watermark_level = RXFIFO_WATERMARK,
81         .per_config = IMX_DMA_MEMSIZE_16 | IMX_DMA_TYPE_FIFO,
82         .mem_config = IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR,
83 };
84
85 static struct mx1_mx2_pcm_dma_params imx_ssi2_pcm_stereo_out0 = {
86         .name                   = "SSI2 PCM Stereo out 0",
87         .transfer_type = DMA_MODE_WRITE,
88         .per_address = SSI2_BASE_ADDR + STX0,
89         .event_id = DMA_REQ_SSI2_TX0,
90         .watermark_level = TXFIFO_WATERMARK,
91         .per_config = IMX_DMA_MEMSIZE_16 | IMX_DMA_TYPE_FIFO,
92         .mem_config = IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR,
93 };
94
95 static struct mx1_mx2_pcm_dma_params imx_ssi2_pcm_stereo_out1 = {
96         .name                   = "SSI2 PCM Stereo out 1",
97         .transfer_type = DMA_MODE_WRITE,
98         .per_address = SSI2_BASE_ADDR + STX1,
99         .event_id = DMA_REQ_SSI2_TX1,
100         .watermark_level = TXFIFO_WATERMARK,
101         .per_config = IMX_DMA_MEMSIZE_16 | IMX_DMA_TYPE_FIFO,
102         .mem_config = IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR,
103 };
104
105 static struct mx1_mx2_pcm_dma_params imx_ssi2_pcm_stereo_in0 = {
106         .name                   = "SSI2 PCM Stereo in 0",
107         .transfer_type = DMA_MODE_READ,
108         .per_address = SSI2_BASE_ADDR + SRX0,
109         .event_id = DMA_REQ_SSI2_RX0,
110         .watermark_level = RXFIFO_WATERMARK,
111         .per_config = IMX_DMA_MEMSIZE_16 | IMX_DMA_TYPE_FIFO,
112         .mem_config = IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR,
113 };
114
115 static struct mx1_mx2_pcm_dma_params imx_ssi2_pcm_stereo_in1 = {
116         .name                   = "SSI2 PCM Stereo in 1",
117         .transfer_type = DMA_MODE_READ,
118         .per_address = SSI2_BASE_ADDR + SRX1,
119         .event_id = DMA_REQ_SSI2_RX1,
120         .watermark_level = RXFIFO_WATERMARK,
121         .per_config = IMX_DMA_MEMSIZE_16 | IMX_DMA_TYPE_FIFO,
122         .mem_config = IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR,
123 };
124
125 static struct clk *ssi_clk0, *ssi_clk1;
126
127 int get_ssi_clk(int ssi, struct device *dev)
128 {
129         switch (ssi) {
130         case 0:
131                 ssi_clk0 = clk_get(dev, "ssi1");
132                 if (IS_ERR(ssi_clk0))
133                         return PTR_ERR(ssi_clk0);
134                 return 0;
135         case 1:
136                 ssi_clk1 = clk_get(dev, "ssi2");
137                 if (IS_ERR(ssi_clk1))
138                         return PTR_ERR(ssi_clk1);
139                 return 0;
140         default:
141                 return -EINVAL;
142         }
143 }
144 EXPORT_SYMBOL(get_ssi_clk);
145
146 void put_ssi_clk(int ssi)
147 {
148         switch (ssi) {
149         case 0:
150                 clk_put(ssi_clk0);
151                 ssi_clk0 = NULL;
152                 break;
153         case 1:
154                 clk_put(ssi_clk1);
155                 ssi_clk1 = NULL;
156                 break;
157         }
158 }
159 EXPORT_SYMBOL(put_ssi_clk);
160
161 /*
162  * SSI system clock configuration.
163  * Should only be called when port is inactive (i.e. SSIEN = 0).
164  */
165 static int imx_ssi_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
166         int clk_id, unsigned int freq, int dir)
167 {
168         u32 scr;
169
170         if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2) {
171                 scr = SSI1_SCR;
172                 pr_debug("%s: SCR for SSI1 is %x\n", __func__, scr);
173         } else {
174                 scr = SSI2_SCR;
175                 pr_debug("%s: SCR for SSI2 is %x\n", __func__, scr);
176         }
177
178         if (scr & SSI_SCR_SSIEN) {
179                 printk(KERN_WARNING "Warning ssi already enabled\n");
180                 return 0;
181         }
182
183         switch (clk_id) {
184         case IMX_SSP_SYS_CLK:
185                 if (dir == SND_SOC_CLOCK_OUT) {
186                         scr |= SSI_SCR_SYS_CLK_EN;
187                         pr_debug("%s: clk of is output\n", __func__);
188                 } else {
189                         scr &= ~SSI_SCR_SYS_CLK_EN;
190                         pr_debug("%s: clk of is input\n", __func__);
191                 }
192                 break;
193         default:
194                 return -EINVAL;
195         }
196
197         if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2) {
198                 pr_debug("%s: writeback of SSI1_SCR\n", __func__);
199                 SSI1_SCR = scr;
200         } else {
201                 pr_debug("%s: writeback of SSI2_SCR\n", __func__);
202                 SSI2_SCR = scr;
203         }
204
205         return 0;
206 }
207
208 /*
209  * SSI Clock dividers
210  * Should only be called when port is inactive (i.e. SSIEN = 0).
211  */
212 static int imx_ssi_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
213         int div_id, int div)
214 {
215         u32 stccr, srccr;
216
217         pr_debug("%s\n", __func__);
218         if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2) {
219                 if (SSI1_SCR & SSI_SCR_SSIEN)
220                         return 0;
221                 srccr = SSI1_STCCR;
222                 stccr = SSI1_STCCR;
223         } else {
224                 if (SSI2_SCR & SSI_SCR_SSIEN)
225                         return 0;
226                 srccr = SSI2_STCCR;
227                 stccr = SSI2_STCCR;
228         }
229
230         switch (div_id) {
231         case IMX_SSI_TX_DIV_2:
232                 stccr &= ~SSI_STCCR_DIV2;
233                 stccr |= div;
234                 break;
235         case IMX_SSI_TX_DIV_PSR:
236                 stccr &= ~SSI_STCCR_PSR;
237                 stccr |= div;
238                 break;
239         case IMX_SSI_TX_DIV_PM:
240                 stccr &= ~0xff;
241                 stccr |= SSI_STCCR_PM(div);
242                 break;
243         case IMX_SSI_RX_DIV_2:
244                 stccr &= ~SSI_STCCR_DIV2;
245                 stccr |= div;
246                 break;
247         case IMX_SSI_RX_DIV_PSR:
248                 stccr &= ~SSI_STCCR_PSR;
249                 stccr |= div;
250                 break;
251         case IMX_SSI_RX_DIV_PM:
252                 stccr &= ~0xff;
253                 stccr |= SSI_STCCR_PM(div);
254                 break;
255         default:
256                 return -EINVAL;
257         }
258
259         if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2) {
260                 SSI1_STCCR = stccr;
261                 SSI1_SRCCR = srccr;
262         } else {
263                 SSI2_STCCR = stccr;
264                 SSI2_SRCCR = srccr;
265         }
266         return 0;
267 }
268
269 /*
270  * SSI Network Mode or TDM slots configuration.
271  * Should only be called when port is inactive (i.e. SSIEN = 0).
272  */
273 static int imx_ssi_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai,
274         unsigned int mask, int slots)
275 {
276         u32 stmsk, srmsk, stccr;
277
278         if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2) {
279                 if (SSI1_SCR & SSI_SCR_SSIEN) {
280                         printk(KERN_WARNING "Warning ssi already enabled\n");
281                         return 0;
282                 }
283                 stccr = SSI1_STCCR;
284         } else {
285                 if (SSI2_SCR & SSI_SCR_SSIEN) {
286                         printk(KERN_WARNING "Warning ssi already enabled\n");
287                         return 0;
288                 }
289                 stccr = SSI2_STCCR;
290         }
291
292         stmsk = srmsk = mask;
293         stccr &= ~SSI_STCCR_DC_MASK;
294         stccr |= SSI_STCCR_DC(slots - 1);
295
296         if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2) {
297                 SSI1_STMSK = stmsk;
298                 SSI1_SRMSK = srmsk;
299                 SSI1_SRCCR = SSI1_STCCR = stccr;
300         } else {
301                 SSI2_STMSK = stmsk;
302                 SSI2_SRMSK = srmsk;
303                 SSI2_SRCCR = SSI2_STCCR = stccr;
304         }
305
306         return 0;
307 }
308
309 /*
310  * SSI DAI format configuration.
311  * Should only be called when port is inactive (i.e. SSIEN = 0).
312  * Note: We don't use the I2S modes but instead manually configure the
313  * SSI for I2S.
314  */
315 static int imx_ssi_set_dai_fmt(struct snd_soc_dai *cpu_dai,
316                 unsigned int fmt)
317 {
318         u32 stcr = 0, srcr = 0, scr;
319
320         /*
321          * This is done to avoid this function to modify
322          * previous set values in stcr
323          */
324         stcr = SSI1_STCR;
325
326         if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2)
327                 scr = SSI1_SCR & ~(SSI_SCR_SYN | SSI_SCR_NET);
328         else
329                 scr = SSI2_SCR & ~(SSI_SCR_SYN | SSI_SCR_NET);
330
331         if (scr & SSI_SCR_SSIEN) {
332                 printk(KERN_WARNING "Warning ssi already enabled\n");
333                 return 0;
334         }
335
336         /* DAI mode */
337         switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
338         case SND_SOC_DAIFMT_I2S:
339                 /* data on rising edge of bclk, frame low 1clk before data */
340                 stcr |= SSI_STCR_TFSI | SSI_STCR_TEFS | SSI_STCR_TXBIT0;
341                 srcr |= SSI_SRCR_RFSI | SSI_SRCR_REFS | SSI_SRCR_RXBIT0;
342                 break;
343         case SND_SOC_DAIFMT_LEFT_J:
344                 /* data on rising edge of bclk, frame high with data */
345                 stcr |= SSI_STCR_TXBIT0;
346                 srcr |= SSI_SRCR_RXBIT0;
347                 break;
348         case SND_SOC_DAIFMT_DSP_B:
349                 /* data on rising edge of bclk, frame high with data */
350                 stcr |= SSI_STCR_TFSL;
351                 srcr |= SSI_SRCR_RFSL;
352                 break;
353         case SND_SOC_DAIFMT_DSP_A:
354                 /* data on rising edge of bclk, frame high 1clk before data */
355                 stcr |= SSI_STCR_TFSL | SSI_STCR_TEFS;
356                 srcr |= SSI_SRCR_RFSL | SSI_SRCR_REFS;
357                 break;
358         }
359
360         /* DAI clock inversion */
361         switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
362         case SND_SOC_DAIFMT_IB_IF:
363                 stcr |= SSI_STCR_TFSI;
364                 stcr &= ~SSI_STCR_TSCKP;
365                 srcr |= SSI_SRCR_RFSI;
366                 srcr &= ~SSI_SRCR_RSCKP;
367                 break;
368         case SND_SOC_DAIFMT_IB_NF:
369                 stcr &= ~(SSI_STCR_TSCKP | SSI_STCR_TFSI);
370                 srcr &= ~(SSI_SRCR_RSCKP | SSI_SRCR_RFSI);
371                 break;
372         case SND_SOC_DAIFMT_NB_IF:
373                 stcr |= SSI_STCR_TFSI | SSI_STCR_TSCKP;
374                 srcr |= SSI_SRCR_RFSI | SSI_SRCR_RSCKP;
375                 break;
376         case SND_SOC_DAIFMT_NB_NF:
377                 stcr &= ~SSI_STCR_TFSI;
378                 stcr |= SSI_STCR_TSCKP;
379                 srcr &= ~SSI_SRCR_RFSI;
380                 srcr |= SSI_SRCR_RSCKP;
381                 break;
382         }
383
384         /* DAI clock master masks */
385         switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
386         case SND_SOC_DAIFMT_CBS_CFS:
387                 stcr |= SSI_STCR_TFDIR | SSI_STCR_TXDIR;
388                 srcr |= SSI_SRCR_RFDIR | SSI_SRCR_RXDIR;
389                 break;
390         case SND_SOC_DAIFMT_CBM_CFS:
391                 stcr |= SSI_STCR_TFDIR;
392                 srcr |= SSI_SRCR_RFDIR;
393                 break;
394         case SND_SOC_DAIFMT_CBS_CFM:
395                 stcr |= SSI_STCR_TXDIR;
396                 srcr |= SSI_SRCR_RXDIR;
397                 break;
398         }
399
400         /* sync */
401         if (!(fmt & SND_SOC_DAIFMT_ASYNC))
402                 scr |= SSI_SCR_SYN;
403
404         /* tdm - only for stereo atm */
405         if (fmt & SND_SOC_DAIFMT_TDM)
406                 scr |= SSI_SCR_NET;
407
408         if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2) {
409                 SSI1_STCR = stcr;
410                 SSI1_SRCR = srcr;
411                 SSI1_SCR = scr;
412         } else {
413                 SSI2_STCR = stcr;
414                 SSI2_SRCR = srcr;
415                 SSI2_SCR = scr;
416         }
417
418         return 0;
419 }
420
421 static int imx_ssi_startup(struct snd_pcm_substream *substream,
422                         struct snd_soc_dai *dai)
423 {
424         struct snd_soc_pcm_runtime *rtd = substream->private_data;
425         struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
426
427         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
428                 /* set up TX DMA params */
429                 switch (cpu_dai->id) {
430                 case IMX_DAI_SSI0:
431                         cpu_dai->dma_data = &imx_ssi1_pcm_stereo_out0;
432                         break;
433                 case IMX_DAI_SSI1:
434                         cpu_dai->dma_data = &imx_ssi1_pcm_stereo_out1;
435                         break;
436                 case IMX_DAI_SSI2:
437                         cpu_dai->dma_data = &imx_ssi2_pcm_stereo_out0;
438                         break;
439                 case IMX_DAI_SSI3:
440                         cpu_dai->dma_data = &imx_ssi2_pcm_stereo_out1;
441                 }
442                 pr_debug("%s: (playback)\n", __func__);
443         } else {
444                 /* set up RX DMA params */
445                 switch (cpu_dai->id) {
446                 case IMX_DAI_SSI0:
447                         cpu_dai->dma_data = &imx_ssi1_pcm_stereo_in0;
448                         break;
449                 case IMX_DAI_SSI1:
450                         cpu_dai->dma_data = &imx_ssi1_pcm_stereo_in1;
451                         break;
452                 case IMX_DAI_SSI2:
453                         cpu_dai->dma_data = &imx_ssi2_pcm_stereo_in0;
454                         break;
455                 case IMX_DAI_SSI3:
456                         cpu_dai->dma_data = &imx_ssi2_pcm_stereo_in1;
457                 }
458                 pr_debug("%s: (capture)\n", __func__);
459         }
460
461         /*
462          * we cant really change any SSI values after SSI is enabled
463          * need to fix in software for max flexibility - lrg
464          */
465         if (cpu_dai->active) {
466                 printk(KERN_WARNING "Warning ssi already enabled\n");
467                 return 0;
468         }
469
470         /* reset the SSI port - Sect 45.4.4 */
471         if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2) {
472
473                 if (!ssi_clk0)
474                         return -EINVAL;
475
476                 if (ssi_active[SSI1_PORT]++) {
477                         pr_debug("%s: exit before reset\n", __func__);
478                         return 0;
479                 }
480
481                 /* SSI1 Reset */
482                 SSI1_SCR = 0;
483
484                 SSI1_SFCSR = SSI_SFCSR_RFWM1(RXFIFO_WATERMARK) |
485                         SSI_SFCSR_RFWM0(RXFIFO_WATERMARK) |
486                         SSI_SFCSR_TFWM1(TXFIFO_WATERMARK) |
487                         SSI_SFCSR_TFWM0(TXFIFO_WATERMARK);
488         } else {
489
490                 if (!ssi_clk1)
491                         return -EINVAL;
492
493                 if (ssi_active[SSI2_PORT]++) {
494                         pr_debug("%s: exit before reset\n", __func__);
495                         return 0;
496                 }
497
498                 /* SSI2 Reset */
499                 SSI2_SCR = 0;
500
501                 SSI2_SFCSR = SSI_SFCSR_RFWM1(RXFIFO_WATERMARK) |
502                         SSI_SFCSR_RFWM0(RXFIFO_WATERMARK) |
503                         SSI_SFCSR_TFWM1(TXFIFO_WATERMARK) |
504                         SSI_SFCSR_TFWM0(TXFIFO_WATERMARK);
505         }
506
507         return 0;
508 }
509
510 int imx_ssi_hw_tx_params(struct snd_pcm_substream *substream,
511                                 struct snd_pcm_hw_params *params)
512 {
513         struct snd_soc_pcm_runtime *rtd = substream->private_data;
514         struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
515         u32 stccr, stcr, sier;
516
517         pr_debug("%s\n", __func__);
518
519         if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2) {
520                 stccr = SSI1_STCCR & ~SSI_STCCR_WL_MASK;
521                 stcr = SSI1_STCR;
522                 sier = SSI1_SIER;
523         } else {
524                 stccr = SSI2_STCCR & ~SSI_STCCR_WL_MASK;
525                 stcr = SSI2_STCR;
526                 sier = SSI2_SIER;
527         }
528
529         /* DAI data (word) size */
530         switch (params_format(params)) {
531         case SNDRV_PCM_FORMAT_S16_LE:
532                 stccr |= SSI_STCCR_WL(16);
533                 break;
534         case SNDRV_PCM_FORMAT_S20_3LE:
535                 stccr |= SSI_STCCR_WL(20);
536                 break;
537         case SNDRV_PCM_FORMAT_S24_LE:
538                 stccr |= SSI_STCCR_WL(24);
539                 break;
540         }
541
542         /* enable interrupts */
543         if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2)
544                 stcr |= SSI_STCR_TFEN0;
545         else
546                 stcr |= SSI_STCR_TFEN1;
547         sier |= SSI_SIER_TDMAE;
548
549         if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2) {
550                 SSI1_STCR = stcr;
551                 SSI1_STCCR = stccr;
552                 SSI1_SIER = sier;
553         } else {
554                 SSI2_STCR = stcr;
555                 SSI2_STCCR = stccr;
556                 SSI2_SIER = sier;
557         }
558
559         return 0;
560 }
561
562 int imx_ssi_hw_rx_params(struct snd_pcm_substream *substream,
563                                 struct snd_pcm_hw_params *params)
564 {
565         struct snd_soc_pcm_runtime *rtd = substream->private_data;
566         struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
567         u32 srccr, srcr, sier;
568
569         pr_debug("%s\n", __func__);
570
571         if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2) {
572                 srccr = SSI1_SRCCR & ~SSI_SRCCR_WL_MASK;
573                 srcr = SSI1_SRCR;
574                 sier = SSI1_SIER;
575         } else {
576                 srccr = SSI2_SRCCR & ~SSI_SRCCR_WL_MASK;
577                 srcr = SSI2_SRCR;
578                 sier = SSI2_SIER;
579         }
580
581         /* DAI data (word) size */
582         switch (params_format(params)) {
583         case SNDRV_PCM_FORMAT_S16_LE:
584                 srccr |= SSI_SRCCR_WL(16);
585                 break;
586         case SNDRV_PCM_FORMAT_S20_3LE:
587                 srccr |= SSI_SRCCR_WL(20);
588                 break;
589         case SNDRV_PCM_FORMAT_S24_LE:
590                 srccr |= SSI_SRCCR_WL(24);
591                 break;
592         }
593
594         /* enable interrupts */
595         if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2)
596                 srcr |= SSI_SRCR_RFEN0;
597         else
598                 srcr |= SSI_SRCR_RFEN1;
599         sier |= SSI_SIER_RDMAE;
600
601         if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2) {
602                 SSI1_SRCR = srcr;
603                 SSI1_SRCCR = srccr;
604                 SSI1_SIER = sier;
605         } else {
606                 SSI2_SRCR = srcr;
607                 SSI2_SRCCR = srccr;
608                 SSI2_SIER = sier;
609         }
610
611         return 0;
612 }
613
614 /*
615  * Should only be called when port is inactive (i.e. SSIEN = 0),
616  * although can be called multiple times by upper layers.
617  */
618 int imx_ssi_hw_params(struct snd_pcm_substream *substream,
619                                 struct snd_pcm_hw_params *params,
620                                 struct snd_soc_dai *dai)
621 {
622         struct snd_soc_pcm_runtime *rtd = substream->private_data;
623         struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
624
625         int ret;
626
627         /* cant change any parameters when SSI is running */
628         if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2) {
629                 if (SSI1_SCR & SSI_SCR_SSIEN) {
630                         printk(KERN_WARNING "Warning ssi already enabled\n");
631                         return 0;
632                 }
633         } else {
634                 if (SSI2_SCR & SSI_SCR_SSIEN) {
635                         printk(KERN_WARNING "Warning ssi already enabled\n");
636                         return 0;
637                 }
638         }
639
640         /*
641          * Configure both tx and rx params with the same settings. This is
642          * really a harware restriction because SSI must be disabled until
643          * we can change those values. If there is an active audio stream in
644          * one direction, enabling the other direction with different
645          * settings would mean disturbing the running one.
646          */
647         ret = imx_ssi_hw_tx_params(substream, params);
648         if (ret < 0)
649                 return ret;
650         return imx_ssi_hw_rx_params(substream, params);
651 }
652
653 int imx_ssi_prepare(struct snd_pcm_substream *substream,
654                         struct snd_soc_dai *dai)
655 {
656         struct snd_soc_pcm_runtime *rtd = substream->private_data;
657         struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
658         int ret;
659
660         pr_debug("%s\n", __func__);
661
662         /* Enable clks here to follow SSI recommended init sequence */
663         if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2) {
664                 ret = clk_enable(ssi_clk0);
665                 if (ret < 0)
666                         printk(KERN_ERR "Unable to enable ssi_clk0\n");
667         } else {
668                 ret = clk_enable(ssi_clk1);
669                 if (ret < 0)
670                         printk(KERN_ERR "Unable to enable ssi_clk1\n");
671         }
672
673         return 0;
674 }
675
676 static int imx_ssi_trigger(struct snd_pcm_substream *substream, int cmd,
677                         struct snd_soc_dai *dai)
678 {
679         struct snd_soc_pcm_runtime *rtd = substream->private_data;
680         struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
681         u32 scr;
682
683         if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2)
684                 scr = SSI1_SCR;
685         else
686                 scr = SSI2_SCR;
687
688         switch (cmd) {
689         case SNDRV_PCM_TRIGGER_START:
690         case SNDRV_PCM_TRIGGER_RESUME:
691         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
692                 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
693                         scr |= SSI_SCR_TE | SSI_SCR_SSIEN;
694                 else
695                         scr |= SSI_SCR_RE | SSI_SCR_SSIEN;
696                 break;
697         case SNDRV_PCM_TRIGGER_SUSPEND:
698         case SNDRV_PCM_TRIGGER_STOP:
699         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
700                 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
701                         scr &= ~SSI_SCR_TE;
702                 else
703                         scr &= ~SSI_SCR_RE;
704                 break;
705         default:
706                 return -EINVAL;
707         }
708
709         if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2)
710                 SSI1_SCR = scr;
711         else
712                 SSI2_SCR = scr;
713
714         return 0;
715 }
716
717 static void imx_ssi_shutdown(struct snd_pcm_substream *substream,
718                         struct snd_soc_dai *dai)
719 {
720         struct snd_soc_pcm_runtime *rtd = substream->private_data;
721         struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
722
723         /* shutdown SSI if neither Tx or Rx is active */
724         if (!cpu_dai->active) {
725
726                 if (cpu_dai->id == IMX_DAI_SSI0 ||
727                         cpu_dai->id == IMX_DAI_SSI2) {
728
729                         if (--ssi_active[SSI1_PORT] > 1)
730                                 return;
731
732                         SSI1_SCR = 0;
733                         clk_disable(ssi_clk0);
734                 } else {
735                         if (--ssi_active[SSI2_PORT])
736                                 return;
737                         SSI2_SCR = 0;
738                         clk_disable(ssi_clk1);
739                 }
740         }
741 }
742
743 #ifdef CONFIG_PM
744 static int imx_ssi_suspend(struct platform_device *dev,
745         struct snd_soc_dai *dai)
746 {
747         return 0;
748 }
749
750 static int imx_ssi_resume(struct platform_device *pdev,
751         struct snd_soc_dai *dai)
752 {
753         return 0;
754 }
755
756 #else
757 #define imx_ssi_suspend NULL
758 #define imx_ssi_resume  NULL
759 #endif
760
761 #define IMX_SSI_RATES \
762         (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | \
763         SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | \
764         SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
765         SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | \
766         SNDRV_PCM_RATE_96000)
767
768 #define IMX_SSI_BITS \
769         (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
770         SNDRV_PCM_FMTBIT_S24_LE)
771
772 static struct snd_soc_dai_ops imx_ssi_pcm_dai_ops = {
773         .startup = imx_ssi_startup,
774         .shutdown = imx_ssi_shutdown,
775         .trigger = imx_ssi_trigger,
776         .prepare = imx_ssi_prepare,
777         .hw_params = imx_ssi_hw_params,
778         .set_sysclk = imx_ssi_set_dai_sysclk,
779         .set_clkdiv = imx_ssi_set_dai_clkdiv,
780         .set_fmt = imx_ssi_set_dai_fmt,
781         .set_tdm_slot = imx_ssi_set_dai_tdm_slot,
782 };
783
784 struct snd_soc_dai imx_ssi_pcm_dai[] = {
785 {
786         .name = "imx-i2s-1-0",
787         .id = IMX_DAI_SSI0,
788         .suspend = imx_ssi_suspend,
789         .resume = imx_ssi_resume,
790         .playback = {
791                 .channels_min = 1,
792                 .channels_max = 2,
793                 .formats = IMX_SSI_BITS,
794                 .rates = IMX_SSI_RATES,},
795         .capture = {
796                 .channels_min = 1,
797                 .channels_max = 2,
798                 .formats = IMX_SSI_BITS,
799                 .rates = IMX_SSI_RATES,},
800         .ops = &imx_ssi_pcm_dai_ops,
801 },
802 {
803         .name = "imx-i2s-2-0",
804         .id = IMX_DAI_SSI1,
805         .playback = {
806                 .channels_min = 1,
807                 .channels_max = 2,
808                 .formats = IMX_SSI_BITS,
809                 .rates = IMX_SSI_RATES,},
810         .capture = {
811                 .channels_min = 1,
812                 .channels_max = 2,
813                 .formats = IMX_SSI_BITS,
814                 .rates = IMX_SSI_RATES,},
815         .ops = &imx_ssi_pcm_dai_ops,
816 },
817 {
818         .name = "imx-i2s-1-1",
819         .id = IMX_DAI_SSI2,
820         .suspend = imx_ssi_suspend,
821         .resume = imx_ssi_resume,
822         .playback = {
823                 .channels_min = 1,
824                 .channels_max = 2,
825                 .formats = IMX_SSI_BITS,
826                 .rates = IMX_SSI_RATES,},
827         .capture = {
828                 .channels_min = 1,
829                 .channels_max = 2,
830                 .formats = IMX_SSI_BITS,
831                 .rates = IMX_SSI_RATES,},
832         .ops = &imx_ssi_pcm_dai_ops,
833 },
834 {
835         .name = "imx-i2s-2-1",
836         .id = IMX_DAI_SSI3,
837         .playback = {
838                 .channels_min = 1,
839                 .channels_max = 2,
840                 .formats = IMX_SSI_BITS,
841                 .rates = IMX_SSI_RATES,},
842         .capture = {
843                 .channels_min = 1,
844                 .channels_max = 2,
845                 .formats = IMX_SSI_BITS,
846                 .rates = IMX_SSI_RATES,},
847         .ops = &imx_ssi_pcm_dai_ops,
848 },
849 };
850 EXPORT_SYMBOL_GPL(imx_ssi_pcm_dai);
851
852 static int __init imx_ssi_init(void)
853 {
854         return snd_soc_register_dais(imx_ssi_pcm_dai,
855                                 ARRAY_SIZE(imx_ssi_pcm_dai));
856 }
857
858 static void __exit imx_ssi_exit(void)
859 {
860         snd_soc_unregister_dais(imx_ssi_pcm_dai,
861                                 ARRAY_SIZE(imx_ssi_pcm_dai));
862 }
863
864 module_init(imx_ssi_init);
865 module_exit(imx_ssi_exit);
866 MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com");
867 MODULE_DESCRIPTION("i.MX ASoC I2S driver");
868 MODULE_LICENSE("GPL");