]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - sound/soc/pxa/pxa2xx-i2s.c
39d19212f6d3c3fb5a3bfe4cb828d5294c25a82a
[linux-2.6-omap-h63xx.git] / sound / soc / pxa / pxa2xx-i2s.c
1 /*
2  * pxa2xx-i2s.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
14 #include <linux/init.h>
15 #include <linux/module.h>
16 #include <linux/device.h>
17 #include <linux/delay.h>
18 #include <linux/clk.h>
19 #include <linux/platform_device.h>
20 #include <sound/core.h>
21 #include <sound/pcm.h>
22 #include <sound/initval.h>
23 #include <sound/soc.h>
24 #include <sound/pxa2xx-lib.h>
25
26 #include <mach/hardware.h>
27 #include <mach/pxa-regs.h>
28 #include <mach/pxa2xx-gpio.h>
29 #include <mach/audio.h>
30
31 #include "pxa2xx-pcm.h"
32 #include "pxa2xx-i2s.h"
33
34 struct pxa2xx_gpio {
35         u32 sys;
36         u32     rx;
37         u32 tx;
38         u32 clk;
39         u32 frm;
40 };
41
42
43 struct pxa_i2s_port {
44         u32 sadiv;
45         u32 sacr0;
46         u32 sacr1;
47         u32 saimr;
48         int master;
49         u32 fmt;
50 };
51 static struct pxa_i2s_port pxa_i2s;
52 static struct clk *clk_i2s;
53
54 static struct pxa2xx_pcm_dma_params pxa2xx_i2s_pcm_stereo_out = {
55         .name                   = "I2S PCM Stereo out",
56         .dev_addr               = __PREG(SADR),
57         .drcmr                  = &DRCMRTXSADR,
58         .dcmd                   = DCMD_INCSRCADDR | DCMD_FLOWTRG |
59                                   DCMD_BURST32 | DCMD_WIDTH4,
60 };
61
62 static struct pxa2xx_pcm_dma_params pxa2xx_i2s_pcm_stereo_in = {
63         .name                   = "I2S PCM Stereo in",
64         .dev_addr               = __PREG(SADR),
65         .drcmr                  = &DRCMRRXSADR,
66         .dcmd                   = DCMD_INCTRGADDR | DCMD_FLOWSRC |
67                                   DCMD_BURST32 | DCMD_WIDTH4,
68 };
69
70 static struct pxa2xx_gpio gpio_bus[] = {
71         { /* I2S SoC Slave */
72                 .rx = GPIO29_SDATA_IN_I2S_MD,
73                 .tx = GPIO30_SDATA_OUT_I2S_MD,
74                 .clk = GPIO28_BITCLK_IN_I2S_MD,
75                 .frm = GPIO31_SYNC_I2S_MD,
76         },
77         { /* I2S SoC Master */
78                 .rx = GPIO29_SDATA_IN_I2S_MD,
79                 .tx = GPIO30_SDATA_OUT_I2S_MD,
80                 .clk = GPIO28_BITCLK_OUT_I2S_MD,
81                 .frm = GPIO31_SYNC_I2S_MD,
82         },
83 };
84
85 static int pxa2xx_i2s_startup(struct snd_pcm_substream *substream)
86 {
87         struct snd_soc_pcm_runtime *rtd = substream->private_data;
88         struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
89
90         if (IS_ERR(clk_i2s))
91                 return PTR_ERR(clk_i2s);
92
93         if (!cpu_dai->active) {
94                 SACR0 |= SACR0_RST;
95                 SACR0 = 0;
96         }
97
98         return 0;
99 }
100
101 /* wait for I2S controller to be ready */
102 static int pxa_i2s_wait(void)
103 {
104         int i;
105
106         /* flush the Rx FIFO */
107         for(i = 0; i < 16; i++)
108                 SADR;
109         return 0;
110 }
111
112 static int pxa2xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
113                 unsigned int fmt)
114 {
115         /* interface format */
116         switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
117         case SND_SOC_DAIFMT_I2S:
118                 pxa_i2s.fmt = 0;
119                 break;
120         case SND_SOC_DAIFMT_LEFT_J:
121                 pxa_i2s.fmt = SACR1_AMSL;
122                 break;
123         }
124
125         switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
126         case SND_SOC_DAIFMT_CBS_CFS:
127                 pxa_i2s.master = 1;
128                 break;
129         case SND_SOC_DAIFMT_CBM_CFS:
130                 pxa_i2s.master = 0;
131                 break;
132         default:
133                 break;
134         }
135         return 0;
136 }
137
138 static int pxa2xx_i2s_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
139                 int clk_id, unsigned int freq, int dir)
140 {
141         if (clk_id != PXA2XX_I2S_SYSCLK)
142                 return -ENODEV;
143
144         if (pxa_i2s.master && dir == SND_SOC_CLOCK_OUT)
145                 pxa_gpio_mode(gpio_bus[pxa_i2s.master].sys);
146
147         return 0;
148 }
149
150 static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream,
151                                 struct snd_pcm_hw_params *params)
152 {
153         struct snd_soc_pcm_runtime *rtd = substream->private_data;
154         struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
155
156         pxa_gpio_mode(gpio_bus[pxa_i2s.master].rx);
157         pxa_gpio_mode(gpio_bus[pxa_i2s.master].tx);
158         pxa_gpio_mode(gpio_bus[pxa_i2s.master].frm);
159         pxa_gpio_mode(gpio_bus[pxa_i2s.master].clk);
160         BUG_ON(IS_ERR(clk_i2s));
161         clk_enable(clk_i2s);
162         pxa_i2s_wait();
163
164         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
165                 cpu_dai->dma_data = &pxa2xx_i2s_pcm_stereo_out;
166         else
167                 cpu_dai->dma_data = &pxa2xx_i2s_pcm_stereo_in;
168
169         /* is port used by another stream */
170         if (!(SACR0 & SACR0_ENB)) {
171
172                 SACR0 = 0;
173                 SACR1 = 0;
174                 if (pxa_i2s.master)
175                         SACR0 |= SACR0_BCKD;
176
177                 SACR0 |= SACR0_RFTH(14) | SACR0_TFTH(1);
178                 SACR1 |= pxa_i2s.fmt;
179         }
180         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
181                 SAIMR |= SAIMR_TFS;
182         else
183                 SAIMR |= SAIMR_RFS;
184
185         switch (params_rate(params)) {
186         case 8000:
187                 SADIV = 0x48;
188                 break;
189         case 11025:
190                 SADIV = 0x34;
191                 break;
192         case 16000:
193                 SADIV = 0x24;
194                 break;
195         case 22050:
196                 SADIV = 0x1a;
197                 break;
198         case 44100:
199                 SADIV = 0xd;
200                 break;
201         case 48000:
202                 SADIV = 0xc;
203                 break;
204         case 96000: /* not in manual and possibly slightly inaccurate */
205                 SADIV = 0x6;
206                 break;
207         }
208
209         return 0;
210 }
211
212 static int pxa2xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd)
213 {
214         int ret = 0;
215
216         switch (cmd) {
217         case SNDRV_PCM_TRIGGER_START:
218                 SACR0 |= SACR0_ENB;
219                 break;
220         case SNDRV_PCM_TRIGGER_RESUME:
221         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
222         case SNDRV_PCM_TRIGGER_STOP:
223         case SNDRV_PCM_TRIGGER_SUSPEND:
224         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
225                 break;
226         default:
227                 ret = -EINVAL;
228         }
229
230         return ret;
231 }
232
233 static void pxa2xx_i2s_shutdown(struct snd_pcm_substream *substream)
234 {
235         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
236                 SACR1 |= SACR1_DRPL;
237                 SAIMR &= ~SAIMR_TFS;
238         } else {
239                 SACR1 |= SACR1_DREC;
240                 SAIMR &= ~SAIMR_RFS;
241         }
242
243         if (SACR1 & (SACR1_DREC | SACR1_DRPL)) {
244                 SACR0 &= ~SACR0_ENB;
245                 pxa_i2s_wait();
246                 clk_disable(clk_i2s);
247         }
248
249         clk_put(clk_i2s);
250 }
251
252 #ifdef CONFIG_PM
253 static int pxa2xx_i2s_suspend(struct platform_device *dev,
254         struct snd_soc_dai *dai)
255 {
256         if (!dai->active)
257                 return 0;
258
259         /* store registers */
260         pxa_i2s.sacr0 = SACR0;
261         pxa_i2s.sacr1 = SACR1;
262         pxa_i2s.saimr = SAIMR;
263         pxa_i2s.sadiv = SADIV;
264
265         /* deactivate link */
266         SACR0 &= ~SACR0_ENB;
267         pxa_i2s_wait();
268         return 0;
269 }
270
271 static int pxa2xx_i2s_resume(struct platform_device *pdev,
272         struct snd_soc_dai *dai)
273 {
274         if (!dai->active)
275                 return 0;
276
277         pxa_i2s_wait();
278
279         SACR0 = pxa_i2s.sacr0 &= ~SACR0_ENB;
280         SACR1 = pxa_i2s.sacr1;
281         SAIMR = pxa_i2s.saimr;
282         SADIV = pxa_i2s.sadiv;
283         SACR0 |= SACR0_ENB;
284
285         return 0;
286 }
287
288 #else
289 #define pxa2xx_i2s_suspend      NULL
290 #define pxa2xx_i2s_resume       NULL
291 #endif
292
293 #define PXA2XX_I2S_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
294                 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \
295                 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000)
296
297 struct snd_soc_dai pxa_i2s_dai = {
298         .name = "pxa2xx-i2s",
299         .id = 0,
300         .type = SND_SOC_DAI_I2S,
301         .suspend = pxa2xx_i2s_suspend,
302         .resume = pxa2xx_i2s_resume,
303         .playback = {
304                 .channels_min = 2,
305                 .channels_max = 2,
306                 .rates = PXA2XX_I2S_RATES,
307                 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
308         .capture = {
309                 .channels_min = 2,
310                 .channels_max = 2,
311                 .rates = PXA2XX_I2S_RATES,
312                 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
313         .ops = {
314                 .startup = pxa2xx_i2s_startup,
315                 .shutdown = pxa2xx_i2s_shutdown,
316                 .trigger = pxa2xx_i2s_trigger,
317                 .hw_params = pxa2xx_i2s_hw_params,},
318         .dai_ops = {
319                 .set_fmt = pxa2xx_i2s_set_dai_fmt,
320                 .set_sysclk = pxa2xx_i2s_set_dai_sysclk,
321         },
322 };
323
324 EXPORT_SYMBOL_GPL(pxa_i2s_dai);
325
326 static int pxa2xx_i2s_probe(struct platform_device *dev)
327 {
328         clk_i2s = clk_get(&dev->dev, "I2SCLK");
329         return IS_ERR(clk_i2s) ? PTR_ERR(clk_i2s) : 0;
330 }
331
332 static int __devexit pxa2xx_i2s_remove(struct platform_device *dev)
333 {
334         clk_put(clk_i2s);
335         clk_i2s = ERR_PTR(-ENOENT);
336         return 0;
337 }
338
339 static struct platform_driver pxa2xx_i2s_driver = {
340         .probe = pxa2xx_i2s_probe,
341         .remove = __devexit_p(pxa2xx_i2s_remove),
342
343         .driver = {
344                 .name = "pxa2xx-i2s",
345                 .owner = THIS_MODULE,
346         },
347 };
348
349 static int __init pxa2xx_i2s_init(void)
350 {
351         if (cpu_is_pxa27x())
352                 gpio_bus[1].sys = GPIO113_I2S_SYSCLK_MD;
353         else
354                 gpio_bus[1].sys = GPIO32_SYSCLK_I2S_MD;
355
356         clk_i2s = ERR_PTR(-ENOENT);
357         return platform_driver_register(&pxa2xx_i2s_driver);
358 }
359
360 static void __exit pxa2xx_i2s_exit(void)
361 {
362         platform_driver_unregister(&pxa2xx_i2s_driver);
363 }
364
365 module_init(pxa2xx_i2s_init);
366 module_exit(pxa2xx_i2s_exit);
367
368 /* Module information */
369 MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com");
370 MODULE_DESCRIPTION("pxa2xx I2S SoC Interface");
371 MODULE_LICENSE("GPL");