ASoC: Fix WM8991 checkpatch warnings
[linux-2.6-asoc.git] / sound / soc / pxa / pxa2xx-ssp.c
1 /*
2  * pxa2xx-ssp.c  --  ALSA Soc Audio Layer
3  *
4  * Copyright 2005 Wolfson Microelectronics PLC.
5  * Author: Liam Girdwood
6  *         liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
7  *
8  *  This program is free software; you can redistribute  it and/or modify it
9  *  under  the terms of  the GNU General  Public License as published by the
10  *  Free Software Foundation;  either version 2 of the  License, or (at your
11  *  option) any later version.
12  *
13  *  Revision history
14  *    12th Aug 2005   Initial version.
15  *
16  * TODO:
17  *  o Test network mode for > 16bit sample size
18  */
19
20 #include <linux/init.h>
21 #include <linux/module.h>
22 #include <linux/platform_device.h>
23 #include <linux/clk.h>
24 #include <linux/io.h>
25
26 #include <sound/core.h>
27 #include <sound/pcm.h>
28 #include <sound/initval.h>
29 #include <sound/pcm_params.h>
30 #include <sound/soc.h>
31
32 #include <asm/hardware.h>
33 #include <asm/arch/pxa-regs.h>
34 #include <asm/arch/regs-ssp.h>
35 #include <asm/arch/audio.h>
36 #include <asm/arch/ssp.h>
37
38 #include "pxa2xx-pcm.h"
39 #include "pxa2xx-ssp.h"
40
41 /*
42  * SSP audio private data
43  */
44 struct ssp_priv {
45         unsigned int sysclk;
46 };
47
48 static struct ssp_priv ssp_clk[3];
49 static struct ssp_dev ssp[3];
50 #ifdef CONFIG_PM
51 static struct ssp_state ssp_state[3];
52 #endif
53
54 #define PXA2xx_SSP1_BASE        0x41000000
55 #define PXA27x_SSP2_BASE        0x41700000
56 #define PXA27x_SSP3_BASE        0x41900000
57
58 static struct pxa2xx_pcm_dma_params pxa2xx_ssp1_pcm_mono_out = {
59         .name                   = "SSP1 PCM Mono out",
60         .dev_addr               = PXA2xx_SSP1_BASE + SSDR,
61         .drcmr                  = &DRCMRTXSSDR,
62         .dcmd                   = DCMD_INCSRCADDR | DCMD_FLOWTRG |
63                                   DCMD_BURST16 | DCMD_WIDTH2,
64 };
65
66 static struct pxa2xx_pcm_dma_params pxa2xx_ssp1_pcm_mono_in = {
67         .name                   = "SSP1 PCM Mono in",
68         .dev_addr               = PXA2xx_SSP1_BASE + SSDR,
69         .drcmr                  = &DRCMRRXSSDR,
70         .dcmd                   = DCMD_INCTRGADDR | DCMD_FLOWSRC |
71                                   DCMD_BURST16 | DCMD_WIDTH2,
72 };
73
74 static struct pxa2xx_pcm_dma_params pxa2xx_ssp1_pcm_stereo_out = {
75         .name                   = "SSP1 PCM Stereo out",
76         .dev_addr               = PXA2xx_SSP1_BASE + SSDR,
77         .drcmr                  = &DRCMRTXSSDR,
78         .dcmd                   = DCMD_INCSRCADDR | DCMD_FLOWTRG |
79                                   DCMD_BURST16 | DCMD_WIDTH4,
80 };
81
82 static struct pxa2xx_pcm_dma_params pxa2xx_ssp1_pcm_stereo_in = {
83         .name                   = "SSP1 PCM Stereo in",
84         .dev_addr               = PXA2xx_SSP1_BASE + SSDR,
85         .drcmr                  = &DRCMRRXSSDR,
86         .dcmd                   = DCMD_INCTRGADDR | DCMD_FLOWSRC |
87                                   DCMD_BURST16 | DCMD_WIDTH4,
88 };
89
90 static struct pxa2xx_pcm_dma_params pxa2xx_ssp2_pcm_mono_out = {
91         .name                   = "SSP2 PCM Mono out",
92         .dev_addr               = PXA27x_SSP2_BASE + SSDR,
93         .drcmr                  = &DRCMRTXSS2DR,
94         .dcmd                   = DCMD_INCSRCADDR | DCMD_FLOWTRG |
95                                   DCMD_BURST16 | DCMD_WIDTH2,
96 };
97
98 static struct pxa2xx_pcm_dma_params pxa2xx_ssp2_pcm_mono_in = {
99         .name                   = "SSP2 PCM Mono in",
100         .dev_addr               = PXA27x_SSP2_BASE + SSDR,
101         .drcmr                  = &DRCMRRXSS2DR,
102         .dcmd                   = DCMD_INCTRGADDR | DCMD_FLOWSRC |
103                                   DCMD_BURST16 | DCMD_WIDTH2,
104 };
105
106 static struct pxa2xx_pcm_dma_params pxa2xx_ssp2_pcm_stereo_out = {
107         .name                   = "SSP2 PCM Stereo out",
108         .dev_addr               = PXA27x_SSP2_BASE + SSDR,
109         .drcmr                  = &DRCMRTXSS2DR,
110         .dcmd                   = DCMD_INCSRCADDR | DCMD_FLOWTRG |
111                                   DCMD_BURST16 | DCMD_WIDTH4,
112 };
113
114 static struct pxa2xx_pcm_dma_params pxa2xx_ssp2_pcm_stereo_in = {
115         .name                   = "SSP2 PCM Stereo in",
116         .dev_addr               = PXA27x_SSP2_BASE + SSDR,
117         .drcmr                  = &DRCMRRXSS2DR,
118         .dcmd                   = DCMD_INCTRGADDR | DCMD_FLOWSRC |
119                                   DCMD_BURST16 | DCMD_WIDTH4,
120 };
121
122 static struct pxa2xx_pcm_dma_params pxa2xx_ssp3_pcm_mono_out = {
123         .name                   = "SSP3 PCM Mono out",
124         .dev_addr               = PXA27x_SSP3_BASE + SSDR,
125         .drcmr                  = &DRCMRTXSS3DR,
126         .dcmd                   = DCMD_INCSRCADDR | DCMD_FLOWTRG |
127                                   DCMD_BURST16 | DCMD_WIDTH2,
128 };
129
130 static struct pxa2xx_pcm_dma_params pxa2xx_ssp3_pcm_mono_in = {
131         .name                   = "SSP3 PCM Mono in",
132         .dev_addr               = PXA27x_SSP3_BASE + SSDR,
133         .drcmr                  = &DRCMRRXSS3DR,
134         .dcmd                   = DCMD_INCTRGADDR | DCMD_FLOWSRC |
135                                   DCMD_BURST16 | DCMD_WIDTH2,
136 };
137
138 static struct pxa2xx_pcm_dma_params pxa2xx_ssp3_pcm_stereo_out = {
139         .name                   = "SSP3 PCM Stereo out",
140         .dev_addr               = PXA27x_SSP3_BASE + SSDR,
141         .drcmr                  = &DRCMRTXSS3DR,
142         .dcmd                   = DCMD_INCSRCADDR | DCMD_FLOWTRG |
143                                   DCMD_BURST16 | DCMD_WIDTH4,
144 };
145
146 static struct pxa2xx_pcm_dma_params pxa2xx_ssp3_pcm_stereo_in = {
147         .name                   = "SSP3 PCM Stereo in",
148         .dev_addr               = PXA27x_SSP3_BASE + SSDR,
149         .drcmr                  = &DRCMRRXSS3DR,
150         .dcmd                   = DCMD_INCTRGADDR | DCMD_FLOWSRC |
151                                   DCMD_BURST16 | DCMD_WIDTH4,
152 };
153
154 static struct pxa2xx_pcm_dma_params *ssp_dma_params[3][4] = {
155         {&pxa2xx_ssp1_pcm_mono_out, &pxa2xx_ssp1_pcm_mono_in,
156         &pxa2xx_ssp1_pcm_stereo_out, &pxa2xx_ssp1_pcm_stereo_in,},
157         {&pxa2xx_ssp2_pcm_mono_out, &pxa2xx_ssp2_pcm_mono_in,
158         &pxa2xx_ssp2_pcm_stereo_out, &pxa2xx_ssp2_pcm_stereo_in,},
159         {&pxa2xx_ssp3_pcm_mono_out, &pxa2xx_ssp3_pcm_mono_in,
160         &pxa2xx_ssp3_pcm_stereo_out, &pxa2xx_ssp3_pcm_stereo_in,},
161 };
162
163 static int pxa2xx_ssp_startup(struct snd_pcm_substream *substream)
164 {
165         struct snd_soc_pcm_runtime *rtd = substream->private_data;
166         struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
167         int ret = 0;
168
169         if (!rtd->dai->cpu_dai->active) {
170                 ret = ssp_init(&ssp[cpu_dai->id], cpu_dai->id + 1,
171                         SSP_NO_IRQ);
172                 if (ret < 0)
173                         return ret;
174                 ssp_disable(&ssp[cpu_dai->id]);
175         }
176         return ret;
177 }
178
179 static void pxa2xx_ssp_shutdown(struct snd_pcm_substream *substream)
180 {
181         struct snd_soc_pcm_runtime *rtd = substream->private_data;
182         struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
183
184         if (!cpu_dai->active) {
185                 ssp_disable(&ssp[cpu_dai->id]);
186                 ssp_exit(&ssp[cpu_dai->id]);
187         }
188 }
189
190 #ifdef CONFIG_PM
191
192 static int pxa2xx_ssp_suspend(struct platform_device *pdev,
193         struct snd_soc_cpu_dai *dai)
194 {
195         if (!dai->active)
196                 return 0;
197
198         ssp_save_state(&ssp[dai->id], &ssp_state[dai->id]);
199         clk_disable(ssp[dai->id].ssp->clk);
200         return 0;
201 }
202
203 static int pxa2xx_ssp_resume(struct platform_device *pdev,
204         struct snd_soc_cpu_dai *dai)
205 {
206         if (!dai->active)
207                 return 0;
208
209         clk_enable(ssp[dai->id].ssp->clk);
210         ssp_restore_state(&ssp[dai->id], &ssp_state[dai->id]);
211         ssp_enable(&ssp[dai->id]);
212
213         return 0;
214 }
215
216 #else
217 #define pxa2xx_ssp_suspend      NULL
218 #define pxa2xx_ssp_resume       NULL
219 #endif
220
221 /**
222  * ssp_set_clkdiv - set SSP clock divider
223  * @div: serial clock rate divider
224  */
225 void ssp_set_scr(struct ssp_dev *dev, u32 div)
226 {
227         struct ssp_device *ssp = dev->ssp;
228         u32 sscr0 = __raw_readl(ssp->mmio_base + SSCR0) & ~SSCR0_SCR;
229
230         __raw_writel(sscr0 | SSCR0_SerClkDiv(div), ssp->mmio_base + SSCR0);
231 }
232
233 /*
234  * Set the SSP ports SYSCLK.
235  */
236 static int pxa2xx_ssp_set_dai_sysclk(struct snd_soc_cpu_dai *cpu_dai,
237         int clk_id, unsigned int freq, int dir)
238 {
239         void __iomem *mmio_base = ssp[cpu_dai->id].ssp->mmio_base;
240         int val;
241
242         u32 sscr0 = __raw_readl(mmio_base + SSCR0) &
243                 ~(SSCR0_ECS |  SSCR0_NCS | SSCR0_MOD | SSCR0_ADC);
244
245         pr_debug("pxa2xx_ssp_set_dai_sysclk id: %d, clk_id %d, freq %d",
246                 cpu_dai->id, clk_id, freq);
247
248         switch (clk_id) {
249         case PXA2XX_SSP_CLK_NET_PLL:
250                 sscr0 |= SSCR0_MOD;
251         case PXA2XX_SSP_CLK_PLL:
252                 /* Internal PLL is fixed on pxa25x and pxa27x */
253                 if (cpu_is_pxa25x())
254                         ssp_clk[cpu_dai->id].sysclk = 1843200;
255                 else
256                         ssp_clk[cpu_dai->id].sysclk = 13000000;
257                 break;
258         case PXA2XX_SSP_CLK_EXT:
259                 ssp_clk[cpu_dai->id].sysclk = freq;
260                 sscr0 |= SSCR0_ECS;
261                 break;
262         case PXA2XX_SSP_CLK_NET:
263                 ssp_clk[cpu_dai->id].sysclk = freq;
264                 sscr0 |= SSCR0_NCS | SSCR0_MOD;
265                 break;
266         case PXA2XX_SSP_CLK_AUDIO:
267                 ssp_clk[cpu_dai->id].sysclk = 0;
268                 ssp_set_scr(&ssp[cpu_dai->id], 1);
269                 sscr0 |= SSCR0_ADC;
270                 break;
271         default:
272                 return -ENODEV;
273         }
274
275         /* the SSP CKEN clock must be disabled when changing SSP clock mode */
276         clk_disable(ssp[cpu_dai->id].ssp->clk);
277         val = __raw_readl(mmio_base + SSCR0) | sscr0;
278         __raw_writel(val, mmio_base + SSCR0);
279         clk_enable(ssp[cpu_dai->id].ssp->clk);
280         return 0;
281 }
282
283 /*
284  * Set the SSP clock dividers.
285  */
286 static int pxa2xx_ssp_set_dai_clkdiv(struct snd_soc_cpu_dai *cpu_dai,
287         int div_id, int div)
288 {
289         void __iomem *mmio_base = ssp[cpu_dai->id].ssp->mmio_base;
290         int val;
291
292         switch (div_id) {
293         case PXA2XX_SSP_AUDIO_DIV_ACDS:
294                 val = (__raw_readl(mmio_base + SSACD) & ~0x7) | SSACD_ACDS(div);
295                 __raw_writel(val, mmio_base + SSACD);
296                 break;
297         case PXA2XX_SSP_AUDIO_DIV_SCDB:
298                 val = __raw_readl(mmio_base + SSACD) & ~0x8;
299                 if (div == PXA2XX_SSP_CLK_SCDB_1)
300                         val |= SSACD_SCDB;
301                 __raw_writel(val, mmio_base + SSACD);
302                 break;
303         case PXA2XX_SSP_DIV_SCR:
304                 ssp_set_scr(&ssp[cpu_dai->id], div);
305                 break;
306         default:
307                 return -ENODEV;
308         }
309
310         return 0;
311 }
312
313 /*
314  * Configure the PLL frequency pxa27x and (afaik - pxa320 only)
315  */
316 static int pxa2xx_ssp_set_dai_pll(struct snd_soc_cpu_dai *cpu_dai,
317         int pll_id, unsigned int freq_in, unsigned int freq_out)
318 {
319         void __iomem *mmio_base = ssp[cpu_dai->id].ssp->mmio_base;
320         u32 ssacd;
321
322         ssacd = __raw_readl(mmio_base + SSACD) & ~0x70;
323         switch (freq_out) {
324         case 5622000:
325                 break;
326         case 11345000:
327                 ssacd |= (0x1 << 4);
328                 break;
329         case 12235000:
330                 ssacd |= (0x2 << 4);
331                 break;
332         case 14857000:
333                 ssacd |= (0x3 << 4);
334                 break;
335         case 32842000:
336                 ssacd |= (0x4 << 4);
337                 break;
338         case 48000000:
339                 ssacd |= (0x5 << 4);
340                 break;
341         }
342         __raw_writel(ssacd, mmio_base + SSACD);
343         return 0;
344 }
345
346 /*
347  * Set the active slots in TDM/Network mode
348  */
349 static int pxa2xx_ssp_set_dai_tdm_slot(struct snd_soc_cpu_dai *cpu_dai,
350         unsigned int mask, int slots)
351 {
352         void __iomem *mmio_base = ssp[cpu_dai->id].ssp->mmio_base;
353         u32 sscr0;
354
355         sscr0 = __raw_readl(mmio_base + SSCR0) & ~SSCR0_SlotsPerFrm(7);
356
357         /* set number of active slots */
358         sscr0 |= SSCR0_SlotsPerFrm(slots);
359         __raw_writel(sscr0, mmio_base + SSCR0);
360
361         /* set active slot mask */
362         __raw_writel(mask, mmio_base + SSTSA);
363         __raw_writel(mask, mmio_base + SSRSA);
364         return 0;
365 }
366
367 /*
368  * Tristate the SSP DAI lines
369  */
370 static int pxa2xx_ssp_set_dai_tristate(struct snd_soc_cpu_dai *cpu_dai,
371         int tristate)
372 {
373         void __iomem *mmio_base = ssp[cpu_dai->id].ssp->mmio_base;
374         u32 sscr1;
375
376         sscr1 = __raw_readl(mmio_base + SSCR1);
377         if (tristate)
378                 sscr1 &= ~SSCR1_TTE;
379         else
380                 sscr1 |= SSCR1_TTE;
381         __raw_writel(sscr1, mmio_base + SSCR1);
382
383         return 0;
384 }
385
386 /*
387  * Set up the SSP DAI format.
388  * The SSP Port must be inactive before calling this function as the
389  * physical interface format is changed.
390  */
391 static int pxa2xx_ssp_set_dai_fmt(struct snd_soc_cpu_dai *cpu_dai,
392                 unsigned int fmt)
393 {
394         void __iomem *mmio_base = ssp[cpu_dai->id].ssp->mmio_base;
395         int val;
396
397         /* reset port settings */
398         __raw_writel(0, mmio_base + SSCR0);
399         __raw_writel(0, mmio_base + SSCR1);
400         __raw_writel(0, mmio_base + SSPSP);
401
402         /* NOTE: I2S emulation is still very much work in progress here */
403
404         /* FIXME: this is what wince uses for msb */
405         if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_MSB) {
406                 __raw_writel(SSCR0_EDSS | SSCR0_TISSP | SSCR0_DataSize(16),
407                                 mmio_base + SSCR0);
408                 goto master;
409         }
410
411         /* check for I2S emulation mode - handle it separately  */
412         if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S) {
413                 /* 8.4.11 */
414
415                 /* Only SSCR0[NCS] or SSCR0[ECS] bit fields settings are optional */
416                 __raw_writel(SSCR0_EDSS | SSCR0_PSP | SSCR0_DataSize(16),
417                                 mmio_base + SSCR0);
418
419                 /* set FIFO thresholds */
420                 __raw_writel(SSCR1_RxTresh(14) | SSCR1_TxTresh(1),
421                                 mmio_base + SSCR1);
422
423                 /* normal: */
424                 /* all bit fields must be cleared except: FSRT = 1 and
425                  * SFRMWDTH = 16, DMYSTART=0,1) */
426                 __raw_writel(SSPSP_FSRT | SSPSP_SFRMWDTH(16) | SSPSP_DMYSTRT(0),
427                                 mmio_base + SSPSP);
428                 goto master;
429         }
430
431         val = __raw_readl(mmio_base + SSCR0) | SSCR0_PSP;
432         __raw_writel(val, mmio_base + SSCR0);
433         __raw_writel(SSCR1_RxTresh(14) | SSCR1_TxTresh(1) |
434                         SSCR1_TRAIL | SSCR1_RWOT,
435                         mmio_base + SSCR1);
436
437 master:
438         val = __raw_readl(mmio_base + SSCR1);
439         switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
440         case SND_SOC_DAIFMT_CBM_CFM:
441                 val |= (SSCR1_SCLKDIR | SSCR1_SFRMDIR);
442                 break;
443         case SND_SOC_DAIFMT_CBM_CFS:
444                 val |= SSCR1_SCLKDIR;
445                 break;
446         case SND_SOC_DAIFMT_CBS_CFM:
447                 val |= SSCR1_SFRMDIR;
448                 break;
449         case SND_SOC_DAIFMT_CBS_CFS:
450                 break;
451         default:
452                 return -EINVAL;
453         }
454         __raw_writel(val, mmio_base + SSCR1);
455
456         switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
457         case SND_SOC_DAIFMT_NB_NF:
458                 val = __raw_readl(mmio_base + SSPSP) | SSPSP_SFRMP | SSPSP_FSRT;
459                 __raw_writel(val, mmio_base + SSPSP);
460                 break;
461         case SND_SOC_DAIFMT_IB_IF:
462                 break;
463         default:
464                 return -EINVAL;
465         }
466
467         val = __raw_readl(mmio_base + SSPSP);
468         switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
469         case SND_SOC_DAIFMT_DSP_A:
470                 val |= SSPSP_DMYSTRT(1);
471         case SND_SOC_DAIFMT_DSP_B:
472                 val |= SSPSP_SCMODE(2);
473                 break;
474         case SND_SOC_DAIFMT_I2S:
475         case SND_SOC_DAIFMT_MSB:
476                 /* handled above */
477                 break;
478         default:
479                 return -EINVAL;
480         }
481         __raw_writel(val, mmio_base + SSPSP);
482
483         return 0;
484 }
485
486 /*
487  * Set the SSP audio DMA parameters and sample size.
488  * Can be called multiple times by oss emulation.
489  */
490 static int pxa2xx_ssp_hw_params(struct snd_pcm_substream *substream,
491                                 struct snd_pcm_hw_params *params)
492 {
493         struct snd_soc_pcm_runtime *rtd = substream->private_data;
494         struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
495         int dma = 0, chn = params_channels(params);
496         void __iomem *mmio_base = ssp[cpu_dai->id].ssp->mmio_base;
497         u32 sscr0;
498
499         /* select correct DMA params */
500         if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
501                 dma = 1; /* capture DMA offset is 1,3 */
502         if (chn == 2)
503                 dma += 2; /* stereo DMA offset is 2, mono is 0 */
504         cpu_dai->dma_data = ssp_dma_params[cpu_dai->id][dma];
505
506         pr_debug("pxa2xx_ssp_hw_params: dma %d", dma);
507
508         /* we can only change the settings if the port is not in use */
509         if (__raw_readl(mmio_base + SSCR0) & SSCR0_SSE)
510                 return 0;
511
512         /* clear selected SSP bits */
513         sscr0 = __raw_readl(mmio_base + SSCR0) & ~(SSCR0_DSS | SSCR0_EDSS);
514         __raw_writel(sscr0, mmio_base + SSCR0);
515
516         /* bit size */
517         sscr0 = __raw_readl(mmio_base + SSCR0);
518         switch (params_format(params)) {
519         case SNDRV_PCM_FORMAT_S16_LE:
520                 sscr0 |= SSCR0_DataSize(16);
521                 break;
522         case SNDRV_PCM_FORMAT_S24_LE:
523                 sscr0 |= (SSCR0_EDSS | SSCR0_DataSize(8));
524                 /* we must be in network mode (2 slots) for 24 bit stereo */
525                 break;
526         case SNDRV_PCM_FORMAT_S32_LE:
527                 sscr0 |= (SSCR0_EDSS | SSCR0_DataSize(16));
528                 /* we must be in network mode (2 slots) for 32 bit stereo */
529                 break;
530         }
531         __raw_writel(sscr0, mmio_base + SSCR0);
532
533         pr_debug("SSCR0 0x%08x SSCR1 0x%08x SSTO 0x%08x SSPSP 0x%08x SSSR 0x%08x SSACD 0x%08x",
534                 __raw_readl(mmio_base + SSCR0), __raw_readl(mmio_base + SSCR1),
535                 __raw_readl(mmio_base + SSTO), __raw_readl(mmio_base + SSPSP),
536                 __raw_readl(mmio_base + SSSR), __raw_readl(mmio_base + SSACD));
537
538         return 0;
539 }
540
541 static int pxa2xx_ssp_trigger(struct snd_pcm_substream *substream, int cmd)
542 {
543         struct snd_soc_pcm_runtime *rtd = substream->private_data;
544         struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
545         int ret = 0;
546         void __iomem *mmio_base = ssp[cpu_dai->id].ssp->mmio_base;
547         int val;
548
549         switch (cmd) {
550         case SNDRV_PCM_TRIGGER_RESUME:
551                 ssp_enable(&ssp[cpu_dai->id]);
552                 break;
553         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
554                 val = __raw_readl(mmio_base + SSCR1);
555                 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
556                         val |= SSCR1_TSRE;
557                 else
558                         val |= SSCR1_RSRE;
559                 __raw_writel(val, mmio_base + SSCR1);
560                 /* SSSR_P(port) |= SSSR_P(port); */
561                 val = __raw_readl(mmio_base + SSSR);
562                 __raw_writel(val, mmio_base + SSSR);
563                 break;
564         case SNDRV_PCM_TRIGGER_START:
565                 val = __raw_readl(mmio_base + SSCR1);
566                 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
567                         val |= SSCR1_TSRE;
568                 else
569                         val |= SSCR1_RSRE;
570                 __raw_writel(val, mmio_base + SSCR1);
571                 ssp_enable(&ssp[cpu_dai->id]);
572                 break;
573         case SNDRV_PCM_TRIGGER_STOP:
574                 val = __raw_readl(mmio_base + SSCR1);
575                 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
576                         val &= ~SSCR1_TSRE;
577                 else
578                         val &= ~SSCR1_RSRE;
579                 __raw_writel(val, mmio_base + SSCR1);
580                 break;
581         case SNDRV_PCM_TRIGGER_SUSPEND:
582                 ssp_disable(&ssp[cpu_dai->id]);
583                 break;
584         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
585                 val = __raw_readl(mmio_base + SSCR1);
586                 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
587                         val &= ~SSCR1_TSRE;
588                 else
589                         val &= ~SSCR1_RSRE;
590                 __raw_writel(val, mmio_base + SSCR1);
591                 break;
592
593         default:
594                 ret = -EINVAL;
595         }
596
597         pr_debug("SSCR0 0x%08x SSCR1 0x%08x SSTO 0x%08x SSPSP 0x%08x SSSR 0x%08x",
598                 __raw_readl(mmio_base + SSCR0), __raw_readl(mmio_base + SSCR1),
599                 __raw_readl(mmio_base + SSTO), __raw_readl(mmio_base + SSPSP),
600                 __raw_readl(mmio_base + SSSR));
601
602         return ret;
603 }
604
605 #define PXA2XX_SSP_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
606                 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \
607                 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
608
609 #define PXA2XX_SSP_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
610         SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
611
612 struct snd_soc_cpu_dai pxa_ssp_dai[] = {
613         {       .name = "pxa2xx-ssp1",
614                 .id = 0,
615                 .type = SND_SOC_DAI_PCM,
616                 .suspend = pxa2xx_ssp_suspend,
617                 .resume = pxa2xx_ssp_resume,
618                 .playback = {
619                         .channels_min = 1,
620                         .channels_max = 2,
621                         .rates = PXA2XX_SSP_RATES,
622                         .formats = PXA2XX_SSP_FORMATS,},
623                 .capture = {
624                         .channels_min = 1,
625                         .channels_max = 2,
626                         .rates = PXA2XX_SSP_RATES,
627                         .formats = PXA2XX_SSP_FORMATS,},
628                 .ops = {
629                         .startup = pxa2xx_ssp_startup,
630                         .shutdown = pxa2xx_ssp_shutdown,
631                         .trigger = pxa2xx_ssp_trigger,
632                         .hw_params = pxa2xx_ssp_hw_params,},
633                 .dai_ops = {
634                         .set_sysclk = pxa2xx_ssp_set_dai_sysclk,
635                         .set_clkdiv = pxa2xx_ssp_set_dai_clkdiv,
636                         .set_pll = pxa2xx_ssp_set_dai_pll,
637                         .set_fmt = pxa2xx_ssp_set_dai_fmt,
638                         .set_tdm_slot = pxa2xx_ssp_set_dai_tdm_slot,
639                         .set_tristate = pxa2xx_ssp_set_dai_tristate,
640                 },
641         },
642         {       .name = "pxa2xx-ssp2",
643                 .id = 1,
644                 .type = SND_SOC_DAI_PCM,
645                 .suspend = pxa2xx_ssp_suspend,
646                 .resume = pxa2xx_ssp_resume,
647                 .playback = {
648                         .channels_min = 1,
649                         .channels_max = 2,
650                         .rates = PXA2XX_SSP_RATES,
651                         .formats = PXA2XX_SSP_FORMATS,},
652                 .capture = {
653                         .channels_min = 1,
654                         .channels_max = 2,
655                         .rates = PXA2XX_SSP_RATES,
656                         .formats = PXA2XX_SSP_FORMATS,},
657                 .ops = {
658                         .startup = pxa2xx_ssp_startup,
659                         .shutdown = pxa2xx_ssp_shutdown,
660                         .trigger = pxa2xx_ssp_trigger,
661                         .hw_params = pxa2xx_ssp_hw_params,},
662                 .dai_ops = {
663                         .set_sysclk = pxa2xx_ssp_set_dai_sysclk,
664                         .set_clkdiv = pxa2xx_ssp_set_dai_clkdiv,
665                         .set_pll = pxa2xx_ssp_set_dai_pll,
666                         .set_fmt = pxa2xx_ssp_set_dai_fmt,
667                         .set_tdm_slot = pxa2xx_ssp_set_dai_tdm_slot,
668                         .set_tristate = pxa2xx_ssp_set_dai_tristate,
669                 },
670         },
671         {       .name = "pxa2xx-ssp3",
672                 .id = 2,
673                 .type = SND_SOC_DAI_PCM,
674                 .suspend = pxa2xx_ssp_suspend,
675                 .resume = pxa2xx_ssp_resume,
676                 .playback = {
677                         .channels_min = 1,
678                         .channels_max = 2,
679                         .rates = PXA2XX_SSP_RATES,
680                         .formats = PXA2XX_SSP_FORMATS,},
681                 .capture = {
682                         .channels_min = 1,
683                         .channels_max = 2,
684                         .rates = PXA2XX_SSP_RATES,
685                         .formats = PXA2XX_SSP_FORMATS,},
686                 .ops = {
687                         .startup = pxa2xx_ssp_startup,
688                         .shutdown = pxa2xx_ssp_shutdown,
689                         .trigger = pxa2xx_ssp_trigger,
690                         .hw_params = pxa2xx_ssp_hw_params,},
691                 .dai_ops = {
692                         .set_sysclk = pxa2xx_ssp_set_dai_sysclk,
693                         .set_clkdiv = pxa2xx_ssp_set_dai_clkdiv,
694                         .set_pll = pxa2xx_ssp_set_dai_pll,
695                         .set_fmt = pxa2xx_ssp_set_dai_fmt,
696                         .set_tdm_slot = pxa2xx_ssp_set_dai_tdm_slot,
697                         .set_tristate = pxa2xx_ssp_set_dai_tristate,
698                 },
699         },
700 };
701 EXPORT_SYMBOL_GPL(pxa_ssp_dai);
702
703 /* Module information */
704 MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com");
705 MODULE_DESCRIPTION("pxa2xx SSP/PCM SoC Interface");
706 MODULE_LICENSE("GPL");