aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/spear
diff options
context:
space:
mode:
authorLars-Peter Clausen <lars@metafoo.de>2013-04-20 13:29:07 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2013-05-12 14:01:41 -0400
commit52c102e534fd46a25aacab37bbaaa593929a2ca1 (patch)
tree174d9e238c18a2bda9f6753c639224d80a198579 /sound/soc/spear
parent46fdd8b11d4ab58af126344dcbc0bd565174db16 (diff)
ASoC: spear: Use generic dmaengine PCM
Use the generic dmaengine PCM driver instead of a custom implementation. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/spear')
-rw-r--r--sound/soc/spear/spear_pcm.c152
1 files changed, 15 insertions, 137 deletions
diff --git a/sound/soc/spear/spear_pcm.c b/sound/soc/spear/spear_pcm.c
index 2fbd4899d8ef..4707f2b862c3 100644
--- a/sound/soc/spear/spear_pcm.c
+++ b/sound/soc/spear/spear_pcm.c
@@ -13,19 +13,13 @@
13 13
14#include <linux/module.h> 14#include <linux/module.h>
15#include <linux/dmaengine.h> 15#include <linux/dmaengine.h>
16#include <linux/dma-mapping.h>
17#include <linux/init.h>
18#include <linux/platform_device.h> 16#include <linux/platform_device.h>
19#include <linux/scatterlist.h>
20#include <linux/slab.h>
21#include <sound/core.h>
22#include <sound/dmaengine_pcm.h> 17#include <sound/dmaengine_pcm.h>
23#include <sound/pcm.h> 18#include <sound/pcm.h>
24#include <sound/pcm_params.h>
25#include <sound/soc.h> 19#include <sound/soc.h>
26#include <sound/spear_dma.h> 20#include <sound/spear_dma.h>
27 21
28static struct snd_pcm_hardware spear_pcm_hardware = { 22static const struct snd_pcm_hardware spear_pcm_hardware = {
29 .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | 23 .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
30 SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | 24 SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
31 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME), 25 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
@@ -37,149 +31,33 @@ static struct snd_pcm_hardware spear_pcm_hardware = {
37 .fifo_size = 0, /* fifo size in bytes */ 31 .fifo_size = 0, /* fifo size in bytes */
38}; 32};
39 33
40static int spear_pcm_hw_params(struct snd_pcm_substream *substream, 34static struct dma_chan *spear_pcm_request_chan(struct snd_soc_pcm_runtime *rtd,
41 struct snd_pcm_hw_params *params) 35 struct snd_pcm_substream *substream)
42{ 36{
43 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); 37 struct spear_dma_data *dma_data;
44 38
45 return 0; 39 dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
46}
47
48static int spear_pcm_hw_free(struct snd_pcm_substream *substream)
49{
50 snd_pcm_set_runtime_buffer(substream, NULL);
51
52 return 0;
53}
54
55static int spear_pcm_open(struct snd_pcm_substream *substream)
56{
57 struct snd_soc_pcm_runtime *rtd = substream->private_data;
58
59 struct spear_dma_data *dma_data = (struct spear_dma_data *)
60 snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
61 int ret;
62
63 ret = snd_soc_set_runtime_hwparams(substream, &spear_pcm_hardware);
64 if (ret)
65 return ret;
66 40
67 return snd_dmaengine_pcm_open_request_chan(substream, dma_data->filter, 41 return snd_dmaengine_pcm_request_channel(dma_data->filter, dma_data);
68 dma_data);
69} 42}
70 43
71static int spear_pcm_mmap(struct snd_pcm_substream *substream, 44static const struct snd_dmaengine_pcm_config spear_dmaengine_pcm_config = {
72 struct vm_area_struct *vma) 45 .pcm_hardware = &spear_pcm_hardware,
73{ 46 .compat_request_channel = spear_pcm_request_chan,
74 struct snd_pcm_runtime *runtime = substream->runtime; 47 .prealloc_buffer_size = 16 * 1024,
75
76 return dma_mmap_writecombine(substream->pcm->card->dev, vma,
77 runtime->dma_area, runtime->dma_addr,
78 runtime->dma_bytes);
79}
80
81static struct snd_pcm_ops spear_pcm_ops = {
82 .open = spear_pcm_open,
83 .close = snd_dmaengine_pcm_close_release_chan,
84 .ioctl = snd_pcm_lib_ioctl,
85 .hw_params = spear_pcm_hw_params,
86 .hw_free = spear_pcm_hw_free,
87 .trigger = snd_dmaengine_pcm_trigger,
88 .pointer = snd_dmaengine_pcm_pointer,
89 .mmap = spear_pcm_mmap,
90};
91
92static int
93spear_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream,
94 size_t size)
95{
96 struct snd_pcm_substream *substream = pcm->streams[stream].substream;
97 struct snd_dma_buffer *buf = &substream->dma_buffer;
98
99 buf->dev.type = SNDRV_DMA_TYPE_DEV;
100 buf->dev.dev = pcm->card->dev;
101 buf->private_data = NULL;
102
103 buf->area = dma_alloc_writecombine(pcm->card->dev, size,
104 &buf->addr, GFP_KERNEL);
105 if (!buf->area)
106 return -ENOMEM;
107
108 dev_info(buf->dev.dev,
109 " preallocate_dma_buffer: area=%p, addr=%p, size=%d\n",
110 (void *)buf->area, (void *)buf->addr, size);
111
112 buf->bytes = size;
113 return 0;
114}
115
116static void spear_pcm_free(struct snd_pcm *pcm)
117{
118 struct snd_pcm_substream *substream;
119 struct snd_dma_buffer *buf;
120 int stream;
121
122 for (stream = 0; stream < 2; stream++) {
123 substream = pcm->streams[stream].substream;
124 if (!substream)
125 continue;
126
127 buf = &substream->dma_buffer;
128 if (!buf || !buf->area)
129 continue;
130
131 dma_free_writecombine(pcm->card->dev, buf->bytes,
132 buf->area, buf->addr);
133 buf->area = NULL;
134 }
135}
136
137static u64 spear_pcm_dmamask = DMA_BIT_MASK(32);
138
139static int spear_pcm_new(struct snd_soc_pcm_runtime *rtd)
140{
141 struct snd_card *card = rtd->card->snd_card;
142 int ret;
143
144 if (!card->dev->dma_mask)
145 card->dev->dma_mask = &spear_pcm_dmamask;
146 if (!card->dev->coherent_dma_mask)
147 card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
148
149 if (rtd->cpu_dai->driver->playback.channels_min) {
150 ret = spear_pcm_preallocate_dma_buffer(rtd->pcm,
151 SNDRV_PCM_STREAM_PLAYBACK,
152 spear_pcm_hardware.buffer_bytes_max);
153 if (ret)
154 return ret;
155 }
156
157 if (rtd->cpu_dai->driver->capture.channels_min) {
158 ret = spear_pcm_preallocate_dma_buffer(rtd->pcm,
159 SNDRV_PCM_STREAM_CAPTURE,
160 spear_pcm_hardware.buffer_bytes_max);
161 if (ret)
162 return ret;
163 }
164
165 return 0;
166}
167
168static struct snd_soc_platform_driver spear_soc_platform = {
169 .ops = &spear_pcm_ops,
170 .pcm_new = spear_pcm_new,
171 .pcm_free = spear_pcm_free,
172}; 48};
173 49
174static int spear_soc_platform_probe(struct platform_device *pdev) 50static int spear_soc_platform_probe(struct platform_device *pdev)
175{ 51{
176 return snd_soc_register_platform(&pdev->dev, &spear_soc_platform); 52 return snd_dmaengine_pcm_register(&pdev->dev,
53 &spear_dmaengine_pcm_config,
54 SND_DMAENGINE_PCM_FLAG_NO_DT |
55 SND_DMAENGINE_PCM_FLAG_COMPAT);
177} 56}
178 57
179static int spear_soc_platform_remove(struct platform_device *pdev) 58static int spear_soc_platform_remove(struct platform_device *pdev)
180{ 59{
181 snd_soc_unregister_platform(&pdev->dev); 60 snd_dmaengine_pcm_unregister(&pdev->dev);
182
183 return 0; 61 return 0;
184} 62}
185 63