MIPS: Alchemy: change dbdma to accept physical memory addresses
[pandora-kernel.git] / sound / soc / au1x / dbdma2.c
1 /*
2  * Au12x0/Au1550 PSC ALSA ASoC audio support.
3  *
4  * (c) 2007-2008 MSC Vertriebsges.m.b.H.,
5  *      Manuel Lauss <manuel.lauss@gmail.com>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2 as
9  * published by the Free Software Foundation.
10  *
11  * DMA glue for Au1x-PSC audio.
12  *
13  * NOTE: all of these drivers can only work with a SINGLE instance
14  *       of a PSC. Multiple independent audio devices are impossible
15  *       with ASoC v1.
16  */
17
18
19 #include <linux/module.h>
20 #include <linux/init.h>
21 #include <linux/platform_device.h>
22 #include <linux/slab.h>
23 #include <linux/dma-mapping.h>
24
25 #include <sound/core.h>
26 #include <sound/pcm.h>
27 #include <sound/pcm_params.h>
28 #include <sound/soc.h>
29
30 #include <asm/mach-au1x00/au1000.h>
31 #include <asm/mach-au1x00/au1xxx_dbdma.h>
32 #include <asm/mach-au1x00/au1xxx_psc.h>
33
34 #include "psc.h"
35
36 /*#define PCM_DEBUG*/
37
38 #define MSG(x...)       printk(KERN_INFO "au1xpsc_pcm: " x)
39 #ifdef PCM_DEBUG
40 #define DBG             MSG
41 #else
42 #define DBG(x...)       do {} while (0)
43 #endif
44
45 struct au1xpsc_audio_dmadata {
46         /* DDMA control data */
47         unsigned int ddma_id;           /* DDMA direction ID for this PSC */
48         u32 ddma_chan;                  /* DDMA context */
49
50         /* PCM context (for irq handlers) */
51         struct snd_pcm_substream *substream;
52         unsigned long curr_period;      /* current segment DDMA is working on */
53         unsigned long q_period;         /* queue period(s) */
54         dma_addr_t dma_area;            /* address of queued DMA area */
55         dma_addr_t dma_area_s;          /* start address of DMA area */
56         unsigned long pos;              /* current byte position being played */
57         unsigned long periods;          /* number of SG segments in total */
58         unsigned long period_bytes;     /* size in bytes of one SG segment */
59
60         /* runtime data */
61         int msbits;
62 };
63
64 /* instance data. There can be only one, MacLeod!!!! */
65 static struct au1xpsc_audio_dmadata *au1xpsc_audio_pcmdma[2];
66
67 /*
68  * These settings are somewhat okay, at least on my machine audio plays
69  * almost skip-free. Especially the 64kB buffer seems to help a LOT.
70  */
71 #define AU1XPSC_PERIOD_MIN_BYTES        1024
72 #define AU1XPSC_BUFFER_MIN_BYTES        65536
73
74 #define AU1XPSC_PCM_FMTS                                        \
75         (SNDRV_PCM_FMTBIT_S8     | SNDRV_PCM_FMTBIT_U8 |        \
76          SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |    \
77          SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_U16_BE |    \
78          SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE |    \
79          SNDRV_PCM_FMTBIT_U32_LE | SNDRV_PCM_FMTBIT_U32_BE |    \
80          0)
81
82 /* PCM hardware DMA capabilities - platform specific */
83 static const struct snd_pcm_hardware au1xpsc_pcm_hardware = {
84         .info             = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
85                             SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BATCH,
86         .formats          = AU1XPSC_PCM_FMTS,
87         .period_bytes_min = AU1XPSC_PERIOD_MIN_BYTES,
88         .period_bytes_max = 4096 * 1024 - 1,
89         .periods_min      = 2,
90         .periods_max      = 4096,       /* 2 to as-much-as-you-like */
91         .buffer_bytes_max = 4096 * 1024 - 1,
92         .fifo_size        = 16,         /* fifo entries of AC97/I2S PSC */
93 };
94
95 static void au1x_pcm_queue_tx(struct au1xpsc_audio_dmadata *cd)
96 {
97         au1xxx_dbdma_put_source(cd->ddma_chan, cd->dma_area,
98                                 cd->period_bytes, DDMA_FLAGS_IE);
99
100         /* update next-to-queue period */
101         ++cd->q_period;
102         cd->dma_area += cd->period_bytes;
103         if (cd->q_period >= cd->periods) {
104                 cd->q_period = 0;
105                 cd->dma_area = cd->dma_area_s;
106         }
107 }
108
109 static void au1x_pcm_queue_rx(struct au1xpsc_audio_dmadata *cd)
110 {
111         au1xxx_dbdma_put_dest(cd->ddma_chan, cd->dma_area,
112                               cd->period_bytes, DDMA_FLAGS_IE);
113
114         /* update next-to-queue period */
115         ++cd->q_period;
116         cd->dma_area += cd->period_bytes;
117         if (cd->q_period >= cd->periods) {
118                 cd->q_period = 0;
119                 cd->dma_area = cd->dma_area_s;
120         }
121 }
122
123 static void au1x_pcm_dmatx_cb(int irq, void *dev_id)
124 {
125         struct au1xpsc_audio_dmadata *cd = dev_id;
126
127         cd->pos += cd->period_bytes;
128         if (++cd->curr_period >= cd->periods) {
129                 cd->pos = 0;
130                 cd->curr_period = 0;
131         }
132         snd_pcm_period_elapsed(cd->substream);
133         au1x_pcm_queue_tx(cd);
134 }
135
136 static void au1x_pcm_dmarx_cb(int irq, void *dev_id)
137 {
138         struct au1xpsc_audio_dmadata *cd = dev_id;
139
140         cd->pos += cd->period_bytes;
141         if (++cd->curr_period >= cd->periods) {
142                 cd->pos = 0;
143                 cd->curr_period = 0;
144         }
145         snd_pcm_period_elapsed(cd->substream);
146         au1x_pcm_queue_rx(cd);
147 }
148
149 static void au1x_pcm_dbdma_free(struct au1xpsc_audio_dmadata *pcd)
150 {
151         if (pcd->ddma_chan) {
152                 au1xxx_dbdma_stop(pcd->ddma_chan);
153                 au1xxx_dbdma_reset(pcd->ddma_chan);
154                 au1xxx_dbdma_chan_free(pcd->ddma_chan);
155                 pcd->ddma_chan = 0;
156                 pcd->msbits = 0;
157         }
158 }
159
160 /* in case of missing DMA ring or changed TX-source / RX-dest bit widths,
161  * allocate (or reallocate) a 2-descriptor DMA ring with bit depth according
162  * to ALSA-supplied sample depth.  This is due to limitations in the dbdma api
163  * (cannot adjust source/dest widths of already allocated descriptor ring).
164  */
165 static int au1x_pcm_dbdma_realloc(struct au1xpsc_audio_dmadata *pcd,
166                                  int stype, int msbits)
167 {
168         /* DMA only in 8/16/32 bit widths */
169         if (msbits == 24)
170                 msbits = 32;
171
172         /* check current config: correct bits and descriptors allocated? */
173         if ((pcd->ddma_chan) && (msbits == pcd->msbits))
174                 goto out;       /* all ok! */
175
176         au1x_pcm_dbdma_free(pcd);
177
178         if (stype == PCM_RX)
179                 pcd->ddma_chan = au1xxx_dbdma_chan_alloc(pcd->ddma_id,
180                                         DSCR_CMD0_ALWAYS,
181                                         au1x_pcm_dmarx_cb, (void *)pcd);
182         else
183                 pcd->ddma_chan = au1xxx_dbdma_chan_alloc(DSCR_CMD0_ALWAYS,
184                                         pcd->ddma_id,
185                                         au1x_pcm_dmatx_cb, (void *)pcd);
186
187         if (!pcd->ddma_chan)
188                 return -ENOMEM;
189
190         au1xxx_dbdma_set_devwidth(pcd->ddma_chan, msbits);
191         au1xxx_dbdma_ring_alloc(pcd->ddma_chan, 2);
192
193         pcd->msbits = msbits;
194
195         au1xxx_dbdma_stop(pcd->ddma_chan);
196         au1xxx_dbdma_reset(pcd->ddma_chan);
197
198 out:
199         return 0;
200 }
201
202 static int au1xpsc_pcm_hw_params(struct snd_pcm_substream *substream,
203                                  struct snd_pcm_hw_params *params)
204 {
205         struct snd_pcm_runtime *runtime = substream->runtime;
206         struct au1xpsc_audio_dmadata *pcd;
207         int stype, ret;
208
209         ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
210         if (ret < 0)
211                 goto out;
212
213         stype = SUBSTREAM_TYPE(substream);
214         pcd = au1xpsc_audio_pcmdma[stype];
215
216         DBG("runtime->dma_area = 0x%08lx dma_addr_t = 0x%08lx dma_size = %d "
217             "runtime->min_align %d\n",
218                 (unsigned long)runtime->dma_area,
219                 (unsigned long)runtime->dma_addr, runtime->dma_bytes,
220                 runtime->min_align);
221
222         DBG("bits %d  frags %d  frag_bytes %d  is_rx %d\n", params->msbits,
223                 params_periods(params), params_period_bytes(params), stype);
224
225         ret = au1x_pcm_dbdma_realloc(pcd, stype, params->msbits);
226         if (ret) {
227                 MSG("DDMA channel (re)alloc failed!\n");
228                 goto out;
229         }
230
231         pcd->substream = substream;
232         pcd->period_bytes = params_period_bytes(params);
233         pcd->periods = params_periods(params);
234         pcd->dma_area_s = pcd->dma_area = runtime->dma_addr;
235         pcd->q_period = 0;
236         pcd->curr_period = 0;
237         pcd->pos = 0;
238
239         ret = 0;
240 out:
241         return ret;
242 }
243
244 static int au1xpsc_pcm_hw_free(struct snd_pcm_substream *substream)
245 {
246         snd_pcm_lib_free_pages(substream);
247         return 0;
248 }
249
250 static int au1xpsc_pcm_prepare(struct snd_pcm_substream *substream)
251 {
252         struct au1xpsc_audio_dmadata *pcd =
253                         au1xpsc_audio_pcmdma[SUBSTREAM_TYPE(substream)];
254
255         au1xxx_dbdma_reset(pcd->ddma_chan);
256
257         if (SUBSTREAM_TYPE(substream) == PCM_RX) {
258                 au1x_pcm_queue_rx(pcd);
259                 au1x_pcm_queue_rx(pcd);
260         } else {
261                 au1x_pcm_queue_tx(pcd);
262                 au1x_pcm_queue_tx(pcd);
263         }
264
265         return 0;
266 }
267
268 static int au1xpsc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
269 {
270         u32 c = au1xpsc_audio_pcmdma[SUBSTREAM_TYPE(substream)]->ddma_chan;
271
272         switch (cmd) {
273         case SNDRV_PCM_TRIGGER_START:
274         case SNDRV_PCM_TRIGGER_RESUME:
275                 au1xxx_dbdma_start(c);
276                 break;
277         case SNDRV_PCM_TRIGGER_STOP:
278         case SNDRV_PCM_TRIGGER_SUSPEND:
279                 au1xxx_dbdma_stop(c);
280                 break;
281         default:
282                 return -EINVAL;
283         }
284         return 0;
285 }
286
287 static snd_pcm_uframes_t
288 au1xpsc_pcm_pointer(struct snd_pcm_substream *substream)
289 {
290         return bytes_to_frames(substream->runtime,
291                 au1xpsc_audio_pcmdma[SUBSTREAM_TYPE(substream)]->pos);
292 }
293
294 static int au1xpsc_pcm_open(struct snd_pcm_substream *substream)
295 {
296         snd_soc_set_runtime_hwparams(substream, &au1xpsc_pcm_hardware);
297         return 0;
298 }
299
300 static int au1xpsc_pcm_close(struct snd_pcm_substream *substream)
301 {
302         au1x_pcm_dbdma_free(au1xpsc_audio_pcmdma[SUBSTREAM_TYPE(substream)]);
303         return 0;
304 }
305
306 static struct snd_pcm_ops au1xpsc_pcm_ops = {
307         .open           = au1xpsc_pcm_open,
308         .close          = au1xpsc_pcm_close,
309         .ioctl          = snd_pcm_lib_ioctl,
310         .hw_params      = au1xpsc_pcm_hw_params,
311         .hw_free        = au1xpsc_pcm_hw_free,
312         .prepare        = au1xpsc_pcm_prepare,
313         .trigger        = au1xpsc_pcm_trigger,
314         .pointer        = au1xpsc_pcm_pointer,
315 };
316
317 static void au1xpsc_pcm_free_dma_buffers(struct snd_pcm *pcm)
318 {
319         snd_pcm_lib_preallocate_free_for_all(pcm);
320 }
321
322 static int au1xpsc_pcm_new(struct snd_card *card,
323                            struct snd_soc_dai *dai,
324                            struct snd_pcm *pcm)
325 {
326         snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
327                 card->dev, AU1XPSC_BUFFER_MIN_BYTES, (4096 * 1024) - 1);
328
329         return 0;
330 }
331
332 static int au1xpsc_pcm_probe(struct platform_device *pdev)
333 {
334         if (!au1xpsc_audio_pcmdma[PCM_TX] || !au1xpsc_audio_pcmdma[PCM_RX])
335                 return -ENODEV;
336
337         return 0;
338 }
339
340 static int au1xpsc_pcm_remove(struct platform_device *pdev)
341 {
342         return 0;
343 }
344
345 /* au1xpsc audio platform */
346 struct snd_soc_platform au1xpsc_soc_platform = {
347         .name           = "au1xpsc-pcm-dbdma",
348         .probe          = au1xpsc_pcm_probe,
349         .remove         = au1xpsc_pcm_remove,
350         .pcm_ops        = &au1xpsc_pcm_ops,
351         .pcm_new        = au1xpsc_pcm_new,
352         .pcm_free       = au1xpsc_pcm_free_dma_buffers,
353 };
354 EXPORT_SYMBOL_GPL(au1xpsc_soc_platform);
355
356 static int __devinit au1xpsc_pcm_drvprobe(struct platform_device *pdev)
357 {
358         struct resource *r;
359         int ret;
360
361         if (au1xpsc_audio_pcmdma[PCM_TX] || au1xpsc_audio_pcmdma[PCM_RX])
362                 return -EBUSY;
363
364         /* TX DMA */
365         au1xpsc_audio_pcmdma[PCM_TX]
366                 = kzalloc(sizeof(struct au1xpsc_audio_dmadata), GFP_KERNEL);
367         if (!au1xpsc_audio_pcmdma[PCM_TX])
368                 return -ENOMEM;
369
370         r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
371         if (!r) {
372                 ret = -ENODEV;
373                 goto out1;
374         }
375         (au1xpsc_audio_pcmdma[PCM_TX])->ddma_id = r->start;
376
377         /* RX DMA */
378         au1xpsc_audio_pcmdma[PCM_RX]
379                 = kzalloc(sizeof(struct au1xpsc_audio_dmadata), GFP_KERNEL);
380         if (!au1xpsc_audio_pcmdma[PCM_RX])
381                 return -ENOMEM;
382
383         r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
384         if (!r) {
385                 ret = -ENODEV;
386                 goto out2;
387         }
388         (au1xpsc_audio_pcmdma[PCM_RX])->ddma_id = r->start;
389
390         ret = snd_soc_register_platform(&au1xpsc_soc_platform);
391         if (!ret)
392                 return ret;
393
394 out2:
395         kfree(au1xpsc_audio_pcmdma[PCM_RX]);
396         au1xpsc_audio_pcmdma[PCM_RX] = NULL;
397 out1:
398         kfree(au1xpsc_audio_pcmdma[PCM_TX]);
399         au1xpsc_audio_pcmdma[PCM_TX] = NULL;
400         return ret;
401 }
402
403 static int __devexit au1xpsc_pcm_drvremove(struct platform_device *pdev)
404 {
405         int i;
406
407         snd_soc_unregister_platform(&au1xpsc_soc_platform);
408
409         for (i = 0; i < 2; i++) {
410                 if (au1xpsc_audio_pcmdma[i]) {
411                         au1x_pcm_dbdma_free(au1xpsc_audio_pcmdma[i]);
412                         kfree(au1xpsc_audio_pcmdma[i]);
413                         au1xpsc_audio_pcmdma[i] = NULL;
414                 }
415         }
416
417         return 0;
418 }
419
420 static struct platform_driver au1xpsc_pcm_driver = {
421         .driver = {
422                 .name   = "au1xpsc-pcm",
423                 .owner  = THIS_MODULE,
424         },
425         .probe          = au1xpsc_pcm_drvprobe,
426         .remove         = __devexit_p(au1xpsc_pcm_drvremove),
427 };
428
429 static int __init au1xpsc_audio_dbdma_load(void)
430 {
431         au1xpsc_audio_pcmdma[PCM_TX] = NULL;
432         au1xpsc_audio_pcmdma[PCM_RX] = NULL;
433         return platform_driver_register(&au1xpsc_pcm_driver);
434 }
435
436 static void __exit au1xpsc_audio_dbdma_unload(void)
437 {
438         platform_driver_unregister(&au1xpsc_pcm_driver);
439 }
440
441 module_init(au1xpsc_audio_dbdma_load);
442 module_exit(au1xpsc_audio_dbdma_unload);
443
444
445 struct platform_device *au1xpsc_pcm_add(struct platform_device *pdev)
446 {
447         struct resource *res, *r;
448         struct platform_device *pd;
449         int id[2];
450         int ret;
451
452         r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
453         if (!r)
454                 return NULL;
455         id[0] = r->start;
456
457         r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
458         if (!r)
459                 return NULL;
460         id[1] = r->start;
461
462         res = kzalloc(sizeof(struct resource) * 2, GFP_KERNEL);
463         if (!res)
464                 return NULL;
465
466         res[0].start = res[0].end = id[0];
467         res[1].start = res[1].end = id[1];
468         res[0].flags = res[1].flags = IORESOURCE_DMA;
469
470         pd = platform_device_alloc("au1xpsc-pcm", -1);
471         if (!pd)
472                 goto out;
473
474         pd->resource = res;
475         pd->num_resources = 2;
476
477         ret = platform_device_add(pd);
478         if (!ret)
479                 return pd;
480
481         platform_device_put(pd);
482 out:
483         kfree(res);
484         return NULL;
485 }
486 EXPORT_SYMBOL_GPL(au1xpsc_pcm_add);
487
488 void au1xpsc_pcm_destroy(struct platform_device *dmapd)
489 {
490         if (dmapd)
491                 platform_device_unregister(dmapd);
492 }
493 EXPORT_SYMBOL_GPL(au1xpsc_pcm_destroy);
494
495 MODULE_LICENSE("GPL");
496 MODULE_DESCRIPTION("Au12x0/Au1550 PSC Audio DMA driver");
497 MODULE_AUTHOR("Manuel Lauss");