aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/au1x/dbdma2.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/au1x/dbdma2.c')
-rw-r--r--sound/soc/au1x/dbdma2.c129
1 files changed, 102 insertions, 27 deletions
diff --git a/sound/soc/au1x/dbdma2.c b/sound/soc/au1x/dbdma2.c
index 594c6c5b7838..6d9f4c624949 100644
--- a/sound/soc/au1x/dbdma2.c
+++ b/sound/soc/au1x/dbdma2.c
@@ -2,7 +2,7 @@
2 * Au12x0/Au1550 PSC ALSA ASoC audio support. 2 * Au12x0/Au1550 PSC ALSA ASoC audio support.
3 * 3 *
4 * (c) 2007-2008 MSC Vertriebsges.m.b.H., 4 * (c) 2007-2008 MSC Vertriebsges.m.b.H.,
5 * Manuel Lauss <mano@roarinelk.homelinux.net> 5 * Manuel Lauss <manuel.lauss@gmail.com>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 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 8 * it under the terms of the GNU General Public License version 2 as
@@ -51,8 +51,8 @@ struct au1xpsc_audio_dmadata {
51 struct snd_pcm_substream *substream; 51 struct snd_pcm_substream *substream;
52 unsigned long curr_period; /* current segment DDMA is working on */ 52 unsigned long curr_period; /* current segment DDMA is working on */
53 unsigned long q_period; /* queue period(s) */ 53 unsigned long q_period; /* queue period(s) */
54 unsigned long dma_area; /* address of queued DMA area */ 54 dma_addr_t dma_area; /* address of queued DMA area */
55 unsigned long dma_area_s; /* start address of DMA area */ 55 dma_addr_t dma_area_s; /* start address of DMA area */
56 unsigned long pos; /* current byte position being played */ 56 unsigned long pos; /* current byte position being played */
57 unsigned long periods; /* number of SG segments in total */ 57 unsigned long periods; /* number of SG segments in total */
58 unsigned long period_bytes; /* size in bytes of one SG segment */ 58 unsigned long period_bytes; /* size in bytes of one SG segment */
@@ -94,8 +94,7 @@ static const struct snd_pcm_hardware au1xpsc_pcm_hardware = {
94 94
95static void au1x_pcm_queue_tx(struct au1xpsc_audio_dmadata *cd) 95static void au1x_pcm_queue_tx(struct au1xpsc_audio_dmadata *cd)
96{ 96{
97 au1xxx_dbdma_put_source_flags(cd->ddma_chan, 97 au1xxx_dbdma_put_source(cd->ddma_chan, cd->dma_area,
98 (void *)phys_to_virt(cd->dma_area),
99 cd->period_bytes, DDMA_FLAGS_IE); 98 cd->period_bytes, DDMA_FLAGS_IE);
100 99
101 /* update next-to-queue period */ 100 /* update next-to-queue period */
@@ -109,9 +108,8 @@ static void au1x_pcm_queue_tx(struct au1xpsc_audio_dmadata *cd)
109 108
110static void au1x_pcm_queue_rx(struct au1xpsc_audio_dmadata *cd) 109static void au1x_pcm_queue_rx(struct au1xpsc_audio_dmadata *cd)
111{ 110{
112 au1xxx_dbdma_put_dest_flags(cd->ddma_chan, 111 au1xxx_dbdma_put_dest(cd->ddma_chan, cd->dma_area,
113 (void *)phys_to_virt(cd->dma_area), 112 cd->period_bytes, DDMA_FLAGS_IE);
114 cd->period_bytes, DDMA_FLAGS_IE);
115 113
116 /* update next-to-queue period */ 114 /* update next-to-queue period */
117 ++cd->q_period; 115 ++cd->q_period;
@@ -233,7 +231,7 @@ static int au1xpsc_pcm_hw_params(struct snd_pcm_substream *substream,
233 pcd->substream = substream; 231 pcd->substream = substream;
234 pcd->period_bytes = params_period_bytes(params); 232 pcd->period_bytes = params_period_bytes(params);
235 pcd->periods = params_periods(params); 233 pcd->periods = params_periods(params);
236 pcd->dma_area_s = pcd->dma_area = (unsigned long)runtime->dma_addr; 234 pcd->dma_area_s = pcd->dma_area = runtime->dma_addr;
237 pcd->q_period = 0; 235 pcd->q_period = 0;
238 pcd->curr_period = 0; 236 pcd->curr_period = 0;
239 pcd->pos = 0; 237 pcd->pos = 0;
@@ -333,6 +331,30 @@ static int au1xpsc_pcm_new(struct snd_card *card,
333 331
334static int au1xpsc_pcm_probe(struct platform_device *pdev) 332static int au1xpsc_pcm_probe(struct platform_device *pdev)
335{ 333{
334 if (!au1xpsc_audio_pcmdma[PCM_TX] || !au1xpsc_audio_pcmdma[PCM_RX])
335 return -ENODEV;
336
337 return 0;
338}
339
340static int au1xpsc_pcm_remove(struct platform_device *pdev)
341{
342 return 0;
343}
344
345/* au1xpsc audio platform */
346struct 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};
354EXPORT_SYMBOL_GPL(au1xpsc_soc_platform);
355
356static int __devinit au1xpsc_pcm_drvprobe(struct platform_device *pdev)
357{
336 struct resource *r; 358 struct resource *r;
337 int ret; 359 int ret;
338 360
@@ -365,7 +387,9 @@ static int au1xpsc_pcm_probe(struct platform_device *pdev)
365 } 387 }
366 (au1xpsc_audio_pcmdma[PCM_RX])->ddma_id = r->start; 388 (au1xpsc_audio_pcmdma[PCM_RX])->ddma_id = r->start;
367 389
368 return 0; 390 ret = snd_soc_register_platform(&au1xpsc_soc_platform);
391 if (!ret)
392 return ret;
369 393
370out2: 394out2:
371 kfree(au1xpsc_audio_pcmdma[PCM_RX]); 395 kfree(au1xpsc_audio_pcmdma[PCM_RX]);
@@ -376,10 +400,12 @@ out1:
376 return ret; 400 return ret;
377} 401}
378 402
379static int au1xpsc_pcm_remove(struct platform_device *pdev) 403static int __devexit au1xpsc_pcm_drvremove(struct platform_device *pdev)
380{ 404{
381 int i; 405 int i;
382 406
407 snd_soc_unregister_platform(&au1xpsc_soc_platform);
408
383 for (i = 0; i < 2; i++) { 409 for (i = 0; i < 2; i++) {
384 if (au1xpsc_audio_pcmdma[i]) { 410 if (au1xpsc_audio_pcmdma[i]) {
385 au1x_pcm_dbdma_free(au1xpsc_audio_pcmdma[i]); 411 au1x_pcm_dbdma_free(au1xpsc_audio_pcmdma[i]);
@@ -391,32 +417,81 @@ static int au1xpsc_pcm_remove(struct platform_device *pdev)
391 return 0; 417 return 0;
392} 418}
393 419
394/* au1xpsc audio platform */ 420static struct platform_driver au1xpsc_pcm_driver = {
395struct snd_soc_platform au1xpsc_soc_platform = { 421 .driver = {
396 .name = "au1xpsc-pcm-dbdma", 422 .name = "au1xpsc-pcm",
397 .probe = au1xpsc_pcm_probe, 423 .owner = THIS_MODULE,
398 .remove = au1xpsc_pcm_remove, 424 },
399 .pcm_ops = &au1xpsc_pcm_ops, 425 .probe = au1xpsc_pcm_drvprobe,
400 .pcm_new = au1xpsc_pcm_new, 426 .remove = __devexit_p(au1xpsc_pcm_drvremove),
401 .pcm_free = au1xpsc_pcm_free_dma_buffers,
402}; 427};
403EXPORT_SYMBOL_GPL(au1xpsc_soc_platform);
404 428
405static int __init au1xpsc_audio_dbdma_init(void) 429static int __init au1xpsc_audio_dbdma_load(void)
406{ 430{
407 au1xpsc_audio_pcmdma[PCM_TX] = NULL; 431 au1xpsc_audio_pcmdma[PCM_TX] = NULL;
408 au1xpsc_audio_pcmdma[PCM_RX] = NULL; 432 au1xpsc_audio_pcmdma[PCM_RX] = NULL;
409 return snd_soc_register_platform(&au1xpsc_soc_platform); 433 return platform_driver_register(&au1xpsc_pcm_driver);
410} 434}
411 435
412static void __exit au1xpsc_audio_dbdma_exit(void) 436static void __exit au1xpsc_audio_dbdma_unload(void)
413{ 437{
414 snd_soc_unregister_platform(&au1xpsc_soc_platform); 438 platform_driver_unregister(&au1xpsc_pcm_driver);
439}
440
441module_init(au1xpsc_audio_dbdma_load);
442module_exit(au1xpsc_audio_dbdma_unload);
443
444
445struct 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);
482out:
483 kfree(res);
484 return NULL;
415} 485}
486EXPORT_SYMBOL_GPL(au1xpsc_pcm_add);
416 487
417module_init(au1xpsc_audio_dbdma_init); 488void au1xpsc_pcm_destroy(struct platform_device *dmapd)
418module_exit(au1xpsc_audio_dbdma_exit); 489{
490 if (dmapd)
491 platform_device_unregister(dmapd);
492}
493EXPORT_SYMBOL_GPL(au1xpsc_pcm_destroy);
419 494
420MODULE_LICENSE("GPL"); 495MODULE_LICENSE("GPL");
421MODULE_DESCRIPTION("Au12x0/Au1550 PSC Audio DMA driver"); 496MODULE_DESCRIPTION("Au12x0/Au1550 PSC Audio DMA driver");
422MODULE_AUTHOR("Manuel Lauss <mano@roarinelk.homelinux.net>"); 497MODULE_AUTHOR("Manuel Lauss");