Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/sound/soc/pxa/pxa2xx-pcm.c
10817 views
1
/*
2
* linux/sound/arm/pxa2xx-pcm.c -- ALSA PCM interface for the Intel PXA2xx chip
3
*
4
* Author: Nicolas Pitre
5
* Created: Nov 30, 2004
6
* Copyright: (C) 2004 MontaVista Software, Inc.
7
*
8
* This program is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License version 2 as
10
* published by the Free Software Foundation.
11
*/
12
13
#include <linux/dma-mapping.h>
14
15
#include <sound/core.h>
16
#include <sound/soc.h>
17
#include <sound/pxa2xx-lib.h>
18
19
#include "../../arm/pxa2xx-pcm.h"
20
21
static int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
22
struct snd_pcm_hw_params *params)
23
{
24
struct snd_pcm_runtime *runtime = substream->runtime;
25
struct pxa2xx_runtime_data *prtd = runtime->private_data;
26
struct snd_soc_pcm_runtime *rtd = substream->private_data;
27
struct pxa2xx_pcm_dma_params *dma;
28
int ret;
29
30
dma = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
31
32
/* return if this is a bufferless transfer e.g.
33
* codec <--> BT codec or GSM modem -- lg FIXME */
34
if (!dma)
35
return 0;
36
37
/* this may get called several times by oss emulation
38
* with different params */
39
if (prtd->params == NULL) {
40
prtd->params = dma;
41
ret = pxa_request_dma(prtd->params->name, DMA_PRIO_LOW,
42
pxa2xx_pcm_dma_irq, substream);
43
if (ret < 0)
44
return ret;
45
prtd->dma_ch = ret;
46
} else if (prtd->params != dma) {
47
pxa_free_dma(prtd->dma_ch);
48
prtd->params = dma;
49
ret = pxa_request_dma(prtd->params->name, DMA_PRIO_LOW,
50
pxa2xx_pcm_dma_irq, substream);
51
if (ret < 0)
52
return ret;
53
prtd->dma_ch = ret;
54
}
55
56
return __pxa2xx_pcm_hw_params(substream, params);
57
}
58
59
static int pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream)
60
{
61
struct pxa2xx_runtime_data *prtd = substream->runtime->private_data;
62
63
__pxa2xx_pcm_hw_free(substream);
64
65
if (prtd->dma_ch >= 0) {
66
pxa_free_dma(prtd->dma_ch);
67
prtd->dma_ch = -1;
68
prtd->params = NULL;
69
}
70
71
return 0;
72
}
73
74
static struct snd_pcm_ops pxa2xx_pcm_ops = {
75
.open = __pxa2xx_pcm_open,
76
.close = __pxa2xx_pcm_close,
77
.ioctl = snd_pcm_lib_ioctl,
78
.hw_params = pxa2xx_pcm_hw_params,
79
.hw_free = pxa2xx_pcm_hw_free,
80
.prepare = __pxa2xx_pcm_prepare,
81
.trigger = pxa2xx_pcm_trigger,
82
.pointer = pxa2xx_pcm_pointer,
83
.mmap = pxa2xx_pcm_mmap,
84
};
85
86
static u64 pxa2xx_pcm_dmamask = DMA_BIT_MASK(32);
87
88
static int pxa2xx_soc_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
89
struct snd_pcm *pcm)
90
{
91
int ret = 0;
92
93
if (!card->dev->dma_mask)
94
card->dev->dma_mask = &pxa2xx_pcm_dmamask;
95
if (!card->dev->coherent_dma_mask)
96
card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
97
98
if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
99
ret = pxa2xx_pcm_preallocate_dma_buffer(pcm,
100
SNDRV_PCM_STREAM_PLAYBACK);
101
if (ret)
102
goto out;
103
}
104
105
if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
106
ret = pxa2xx_pcm_preallocate_dma_buffer(pcm,
107
SNDRV_PCM_STREAM_CAPTURE);
108
if (ret)
109
goto out;
110
}
111
out:
112
return ret;
113
}
114
115
static struct snd_soc_platform_driver pxa2xx_soc_platform = {
116
.ops = &pxa2xx_pcm_ops,
117
.pcm_new = pxa2xx_soc_pcm_new,
118
.pcm_free = pxa2xx_pcm_free_dma_buffers,
119
};
120
121
static int __devinit pxa2xx_soc_platform_probe(struct platform_device *pdev)
122
{
123
return snd_soc_register_platform(&pdev->dev, &pxa2xx_soc_platform);
124
}
125
126
static int __devexit pxa2xx_soc_platform_remove(struct platform_device *pdev)
127
{
128
snd_soc_unregister_platform(&pdev->dev);
129
return 0;
130
}
131
132
static struct platform_driver pxa_pcm_driver = {
133
.driver = {
134
.name = "pxa-pcm-audio",
135
.owner = THIS_MODULE,
136
},
137
138
.probe = pxa2xx_soc_platform_probe,
139
.remove = __devexit_p(pxa2xx_soc_platform_remove),
140
};
141
142
static int __init snd_pxa_pcm_init(void)
143
{
144
return platform_driver_register(&pxa_pcm_driver);
145
}
146
module_init(snd_pxa_pcm_init);
147
148
static void __exit snd_pxa_pcm_exit(void)
149
{
150
platform_driver_unregister(&pxa_pcm_driver);
151
}
152
module_exit(snd_pxa_pcm_exit);
153
154
MODULE_AUTHOR("Nicolas Pitre");
155
MODULE_DESCRIPTION("Intel PXA2xx PCM DMA module");
156
MODULE_LICENSE("GPL");
157
158