diff options
author | Vasily Khoruzhick <anarsoul@gmail.com> | 2014-06-23 16:24:05 -0400 |
---|---|---|
committer | Mark Brown <broonie@linaro.org> | 2014-06-24 06:57:43 -0400 |
commit | ae602456e83c9242f752f8176ebe658e37d4f90d (patch) | |
tree | 5e70425753ad59c8aedc83e2ad58cfbd4482d61f | |
parent | 87b132bc0315fdfe7677449da1fb1ce12c5dda35 (diff) |
ASoC: samsung: drop support for legacy S3C24XX DMA API
Signed-off-by: Vasily Khoruzhick <anarsoul@gmail.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
-rw-r--r-- | sound/soc/samsung/Kconfig | 3 | ||||
-rw-r--r-- | sound/soc/samsung/Makefile | 2 | ||||
-rw-r--r-- | sound/soc/samsung/dma.c | 454 |
3 files changed, 0 insertions, 459 deletions
diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index e88e598fbe0c..3be49cd2e984 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig | |||
@@ -13,9 +13,6 @@ config SND_SOC_SAMSUNG | |||
13 | config SND_S3C_DMA | 13 | config SND_S3C_DMA |
14 | tristate | 14 | tristate |
15 | 15 | ||
16 | config SND_S3C_DMA_LEGACY | ||
17 | tristate | ||
18 | |||
19 | config SND_S3C24XX_I2S | 16 | config SND_S3C24XX_I2S |
20 | tristate | 17 | tristate |
21 | 18 | ||
diff --git a/sound/soc/samsung/Makefile b/sound/soc/samsung/Makefile index 6d0212ba571c..6469199acea5 100644 --- a/sound/soc/samsung/Makefile +++ b/sound/soc/samsung/Makefile | |||
@@ -1,6 +1,5 @@ | |||
1 | # S3c24XX Platform Support | 1 | # S3c24XX Platform Support |
2 | snd-soc-s3c-dma-objs := dmaengine.o | 2 | snd-soc-s3c-dma-objs := dmaengine.o |
3 | snd-soc-s3c-dma-legacy-objs := dma.o | ||
4 | snd-soc-idma-objs := idma.o | 3 | snd-soc-idma-objs := idma.o |
5 | snd-soc-s3c24xx-i2s-objs := s3c24xx-i2s.o | 4 | snd-soc-s3c24xx-i2s-objs := s3c24xx-i2s.o |
6 | snd-soc-s3c2412-i2s-objs := s3c2412-i2s.o | 5 | snd-soc-s3c2412-i2s-objs := s3c2412-i2s.o |
@@ -11,7 +10,6 @@ snd-soc-pcm-objs := pcm.o | |||
11 | snd-soc-i2s-objs := i2s.o | 10 | snd-soc-i2s-objs := i2s.o |
12 | 11 | ||
13 | obj-$(CONFIG_SND_S3C_DMA) += snd-soc-s3c-dma.o | 12 | obj-$(CONFIG_SND_S3C_DMA) += snd-soc-s3c-dma.o |
14 | obj-$(CONFIG_SND_S3C_DMA_LEGACY) += snd-soc-s3c-dma-legacy.o | ||
15 | obj-$(CONFIG_SND_S3C24XX_I2S) += snd-soc-s3c24xx-i2s.o | 13 | obj-$(CONFIG_SND_S3C24XX_I2S) += snd-soc-s3c24xx-i2s.o |
16 | obj-$(CONFIG_SND_SAMSUNG_AC97) += snd-soc-ac97.o | 14 | obj-$(CONFIG_SND_SAMSUNG_AC97) += snd-soc-ac97.o |
17 | obj-$(CONFIG_SND_S3C2412_SOC_I2S) += snd-soc-s3c2412-i2s.o | 15 | obj-$(CONFIG_SND_S3C2412_SOC_I2S) += snd-soc-s3c2412-i2s.o |
diff --git a/sound/soc/samsung/dma.c b/sound/soc/samsung/dma.c deleted file mode 100644 index d9dc7bcc0336..000000000000 --- a/sound/soc/samsung/dma.c +++ /dev/null | |||
@@ -1,454 +0,0 @@ | |||
1 | /* | ||
2 | * dma.c -- ALSA Soc Audio Layer | ||
3 | * | ||
4 | * (c) 2006 Wolfson Microelectronics PLC. | ||
5 | * Graeme Gregory graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com | ||
6 | * | ||
7 | * Copyright 2004-2005 Simtec Electronics | ||
8 | * http://armlinux.simtec.co.uk/ | ||
9 | * Ben Dooks <ben@simtec.co.uk> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License as published by the | ||
13 | * Free Software Foundation; either version 2 of the License, or (at your | ||
14 | * option) any later version. | ||
15 | */ | ||
16 | |||
17 | #include <linux/slab.h> | ||
18 | #include <linux/dma-mapping.h> | ||
19 | #include <linux/module.h> | ||
20 | |||
21 | #include <sound/soc.h> | ||
22 | #include <sound/pcm_params.h> | ||
23 | |||
24 | #include <asm/dma.h> | ||
25 | #include <mach/hardware.h> | ||
26 | #include <mach/dma.h> | ||
27 | |||
28 | #include "dma.h" | ||
29 | |||
30 | #define ST_RUNNING (1<<0) | ||
31 | #define ST_OPENED (1<<1) | ||
32 | |||
33 | static const struct snd_pcm_hardware dma_hardware = { | ||
34 | .info = SNDRV_PCM_INFO_INTERLEAVED | | ||
35 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
36 | SNDRV_PCM_INFO_MMAP | | ||
37 | SNDRV_PCM_INFO_MMAP_VALID, | ||
38 | .buffer_bytes_max = 128*1024, | ||
39 | .period_bytes_min = PAGE_SIZE, | ||
40 | .period_bytes_max = PAGE_SIZE*2, | ||
41 | .periods_min = 2, | ||
42 | .periods_max = 128, | ||
43 | .fifo_size = 32, | ||
44 | }; | ||
45 | |||
46 | struct runtime_data { | ||
47 | spinlock_t lock; | ||
48 | int state; | ||
49 | unsigned int dma_loaded; | ||
50 | unsigned int dma_period; | ||
51 | dma_addr_t dma_start; | ||
52 | dma_addr_t dma_pos; | ||
53 | dma_addr_t dma_end; | ||
54 | struct s3c_dma_params *params; | ||
55 | }; | ||
56 | |||
57 | static void audio_buffdone(void *data); | ||
58 | |||
59 | /* dma_enqueue | ||
60 | * | ||
61 | * place a dma buffer onto the queue for the dma system | ||
62 | * to handle. | ||
63 | */ | ||
64 | static void dma_enqueue(struct snd_pcm_substream *substream) | ||
65 | { | ||
66 | struct runtime_data *prtd = substream->runtime->private_data; | ||
67 | dma_addr_t pos = prtd->dma_pos; | ||
68 | unsigned int limit; | ||
69 | struct samsung_dma_prep dma_info; | ||
70 | |||
71 | pr_debug("Entered %s\n", __func__); | ||
72 | |||
73 | limit = (prtd->dma_end - prtd->dma_start) / prtd->dma_period; | ||
74 | |||
75 | pr_debug("%s: loaded %d, limit %d\n", | ||
76 | __func__, prtd->dma_loaded, limit); | ||
77 | |||
78 | dma_info.cap = (samsung_dma_has_circular() ? DMA_CYCLIC : DMA_SLAVE); | ||
79 | dma_info.direction = | ||
80 | (substream->stream == SNDRV_PCM_STREAM_PLAYBACK | ||
81 | ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM); | ||
82 | dma_info.fp = audio_buffdone; | ||
83 | dma_info.fp_param = substream; | ||
84 | dma_info.period = prtd->dma_period; | ||
85 | dma_info.len = prtd->dma_period*limit; | ||
86 | |||
87 | if (dma_info.cap == DMA_CYCLIC) { | ||
88 | dma_info.buf = pos; | ||
89 | prtd->params->ops->prepare(prtd->params->ch, &dma_info); | ||
90 | prtd->dma_loaded += limit; | ||
91 | return; | ||
92 | } | ||
93 | |||
94 | while (prtd->dma_loaded < limit) { | ||
95 | pr_debug("dma_loaded: %d\n", prtd->dma_loaded); | ||
96 | |||
97 | if ((pos + dma_info.period) > prtd->dma_end) { | ||
98 | dma_info.period = prtd->dma_end - pos; | ||
99 | pr_debug("%s: corrected dma len %ld\n", | ||
100 | __func__, dma_info.period); | ||
101 | } | ||
102 | |||
103 | dma_info.buf = pos; | ||
104 | prtd->params->ops->prepare(prtd->params->ch, &dma_info); | ||
105 | |||
106 | prtd->dma_loaded++; | ||
107 | pos += prtd->dma_period; | ||
108 | if (pos >= prtd->dma_end) | ||
109 | pos = prtd->dma_start; | ||
110 | } | ||
111 | |||
112 | prtd->dma_pos = pos; | ||
113 | } | ||
114 | |||
115 | static void audio_buffdone(void *data) | ||
116 | { | ||
117 | struct snd_pcm_substream *substream = data; | ||
118 | struct runtime_data *prtd = substream->runtime->private_data; | ||
119 | |||
120 | pr_debug("Entered %s\n", __func__); | ||
121 | |||
122 | if (prtd->state & ST_RUNNING) { | ||
123 | prtd->dma_pos += prtd->dma_period; | ||
124 | if (prtd->dma_pos >= prtd->dma_end) | ||
125 | prtd->dma_pos = prtd->dma_start; | ||
126 | |||
127 | if (substream) | ||
128 | snd_pcm_period_elapsed(substream); | ||
129 | |||
130 | spin_lock(&prtd->lock); | ||
131 | if (!samsung_dma_has_circular()) { | ||
132 | prtd->dma_loaded--; | ||
133 | dma_enqueue(substream); | ||
134 | } | ||
135 | spin_unlock(&prtd->lock); | ||
136 | } | ||
137 | } | ||
138 | |||
139 | static int dma_hw_params(struct snd_pcm_substream *substream, | ||
140 | struct snd_pcm_hw_params *params) | ||
141 | { | ||
142 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
143 | struct runtime_data *prtd = runtime->private_data; | ||
144 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
145 | unsigned long totbytes = params_buffer_bytes(params); | ||
146 | struct s3c_dma_params *dma = | ||
147 | snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | ||
148 | struct samsung_dma_req req; | ||
149 | struct samsung_dma_config config; | ||
150 | |||
151 | pr_debug("Entered %s\n", __func__); | ||
152 | |||
153 | /* return if this is a bufferless transfer e.g. | ||
154 | * codec <--> BT codec or GSM modem -- lg FIXME */ | ||
155 | if (!dma) | ||
156 | return 0; | ||
157 | |||
158 | /* this may get called several times by oss emulation | ||
159 | * with different params -HW */ | ||
160 | if (prtd->params == NULL) { | ||
161 | /* prepare DMA */ | ||
162 | prtd->params = dma; | ||
163 | |||
164 | pr_debug("params %p, client %p, channel %d\n", prtd->params, | ||
165 | prtd->params->client, prtd->params->channel); | ||
166 | |||
167 | prtd->params->ops = samsung_dma_get_ops(); | ||
168 | |||
169 | req.cap = (samsung_dma_has_circular() ? | ||
170 | DMA_CYCLIC : DMA_SLAVE); | ||
171 | req.client = prtd->params->client; | ||
172 | config.direction = | ||
173 | (substream->stream == SNDRV_PCM_STREAM_PLAYBACK | ||
174 | ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM); | ||
175 | config.width = prtd->params->dma_size; | ||
176 | config.fifo = prtd->params->dma_addr; | ||
177 | prtd->params->ch = prtd->params->ops->request( | ||
178 | prtd->params->channel, &req, rtd->cpu_dai->dev, | ||
179 | prtd->params->ch_name); | ||
180 | if (!prtd->params->ch) { | ||
181 | pr_err("Failed to allocate DMA channel\n"); | ||
182 | return -ENXIO; | ||
183 | } | ||
184 | prtd->params->ops->config(prtd->params->ch, &config); | ||
185 | } | ||
186 | |||
187 | snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); | ||
188 | |||
189 | runtime->dma_bytes = totbytes; | ||
190 | |||
191 | spin_lock_irq(&prtd->lock); | ||
192 | prtd->dma_loaded = 0; | ||
193 | prtd->dma_period = params_period_bytes(params); | ||
194 | prtd->dma_start = runtime->dma_addr; | ||
195 | prtd->dma_pos = prtd->dma_start; | ||
196 | prtd->dma_end = prtd->dma_start + totbytes; | ||
197 | spin_unlock_irq(&prtd->lock); | ||
198 | |||
199 | return 0; | ||
200 | } | ||
201 | |||
202 | static int dma_hw_free(struct snd_pcm_substream *substream) | ||
203 | { | ||
204 | struct runtime_data *prtd = substream->runtime->private_data; | ||
205 | |||
206 | pr_debug("Entered %s\n", __func__); | ||
207 | |||
208 | snd_pcm_set_runtime_buffer(substream, NULL); | ||
209 | |||
210 | if (prtd->params) { | ||
211 | prtd->params->ops->flush(prtd->params->ch); | ||
212 | prtd->params->ops->release(prtd->params->ch, | ||
213 | prtd->params->client); | ||
214 | prtd->params = NULL; | ||
215 | } | ||
216 | |||
217 | return 0; | ||
218 | } | ||
219 | |||
220 | static int dma_prepare(struct snd_pcm_substream *substream) | ||
221 | { | ||
222 | struct runtime_data *prtd = substream->runtime->private_data; | ||
223 | int ret = 0; | ||
224 | |||
225 | pr_debug("Entered %s\n", __func__); | ||
226 | |||
227 | /* return if this is a bufferless transfer e.g. | ||
228 | * codec <--> BT codec or GSM modem -- lg FIXME */ | ||
229 | if (!prtd->params) | ||
230 | return 0; | ||
231 | |||
232 | /* flush the DMA channel */ | ||
233 | prtd->params->ops->flush(prtd->params->ch); | ||
234 | |||
235 | prtd->dma_loaded = 0; | ||
236 | prtd->dma_pos = prtd->dma_start; | ||
237 | |||
238 | /* enqueue dma buffers */ | ||
239 | dma_enqueue(substream); | ||
240 | |||
241 | return ret; | ||
242 | } | ||
243 | |||
244 | static int dma_trigger(struct snd_pcm_substream *substream, int cmd) | ||
245 | { | ||
246 | struct runtime_data *prtd = substream->runtime->private_data; | ||
247 | int ret = 0; | ||
248 | |||
249 | pr_debug("Entered %s\n", __func__); | ||
250 | |||
251 | spin_lock(&prtd->lock); | ||
252 | |||
253 | switch (cmd) { | ||
254 | case SNDRV_PCM_TRIGGER_START: | ||
255 | prtd->state |= ST_RUNNING; | ||
256 | prtd->params->ops->trigger(prtd->params->ch); | ||
257 | break; | ||
258 | |||
259 | case SNDRV_PCM_TRIGGER_STOP: | ||
260 | prtd->state &= ~ST_RUNNING; | ||
261 | prtd->params->ops->stop(prtd->params->ch); | ||
262 | break; | ||
263 | |||
264 | default: | ||
265 | ret = -EINVAL; | ||
266 | break; | ||
267 | } | ||
268 | |||
269 | spin_unlock(&prtd->lock); | ||
270 | |||
271 | return ret; | ||
272 | } | ||
273 | |||
274 | static snd_pcm_uframes_t | ||
275 | dma_pointer(struct snd_pcm_substream *substream) | ||
276 | { | ||
277 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
278 | struct runtime_data *prtd = runtime->private_data; | ||
279 | unsigned long res; | ||
280 | |||
281 | pr_debug("Entered %s\n", __func__); | ||
282 | |||
283 | res = prtd->dma_pos - prtd->dma_start; | ||
284 | |||
285 | pr_debug("Pointer offset: %lu\n", res); | ||
286 | |||
287 | /* we seem to be getting the odd error from the pcm library due | ||
288 | * to out-of-bounds pointers. this is maybe due to the dma engine | ||
289 | * not having loaded the new values for the channel before being | ||
290 | * called... (todo - fix ) | ||
291 | */ | ||
292 | |||
293 | if (res >= snd_pcm_lib_buffer_bytes(substream)) { | ||
294 | if (res == snd_pcm_lib_buffer_bytes(substream)) | ||
295 | res = 0; | ||
296 | } | ||
297 | |||
298 | return bytes_to_frames(substream->runtime, res); | ||
299 | } | ||
300 | |||
301 | static int dma_open(struct snd_pcm_substream *substream) | ||
302 | { | ||
303 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
304 | struct runtime_data *prtd; | ||
305 | |||
306 | pr_debug("Entered %s\n", __func__); | ||
307 | |||
308 | snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); | ||
309 | snd_soc_set_runtime_hwparams(substream, &dma_hardware); | ||
310 | |||
311 | prtd = kzalloc(sizeof(struct runtime_data), GFP_KERNEL); | ||
312 | if (prtd == NULL) | ||
313 | return -ENOMEM; | ||
314 | |||
315 | spin_lock_init(&prtd->lock); | ||
316 | |||
317 | runtime->private_data = prtd; | ||
318 | return 0; | ||
319 | } | ||
320 | |||
321 | static int dma_close(struct snd_pcm_substream *substream) | ||
322 | { | ||
323 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
324 | struct runtime_data *prtd = runtime->private_data; | ||
325 | |||
326 | pr_debug("Entered %s\n", __func__); | ||
327 | |||
328 | if (!prtd) | ||
329 | pr_debug("dma_close called with prtd == NULL\n"); | ||
330 | |||
331 | kfree(prtd); | ||
332 | |||
333 | return 0; | ||
334 | } | ||
335 | |||
336 | static int dma_mmap(struct snd_pcm_substream *substream, | ||
337 | struct vm_area_struct *vma) | ||
338 | { | ||
339 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
340 | |||
341 | pr_debug("Entered %s\n", __func__); | ||
342 | |||
343 | return dma_mmap_writecombine(substream->pcm->card->dev, vma, | ||
344 | runtime->dma_area, | ||
345 | runtime->dma_addr, | ||
346 | runtime->dma_bytes); | ||
347 | } | ||
348 | |||
349 | static struct snd_pcm_ops dma_ops = { | ||
350 | .open = dma_open, | ||
351 | .close = dma_close, | ||
352 | .ioctl = snd_pcm_lib_ioctl, | ||
353 | .hw_params = dma_hw_params, | ||
354 | .hw_free = dma_hw_free, | ||
355 | .prepare = dma_prepare, | ||
356 | .trigger = dma_trigger, | ||
357 | .pointer = dma_pointer, | ||
358 | .mmap = dma_mmap, | ||
359 | }; | ||
360 | |||
361 | static int preallocate_dma_buffer(struct snd_pcm *pcm, int stream) | ||
362 | { | ||
363 | struct snd_pcm_substream *substream = pcm->streams[stream].substream; | ||
364 | struct snd_dma_buffer *buf = &substream->dma_buffer; | ||
365 | size_t size = dma_hardware.buffer_bytes_max; | ||
366 | |||
367 | pr_debug("Entered %s\n", __func__); | ||
368 | |||
369 | buf->dev.type = SNDRV_DMA_TYPE_DEV; | ||
370 | buf->dev.dev = pcm->card->dev; | ||
371 | buf->private_data = NULL; | ||
372 | buf->area = dma_alloc_writecombine(pcm->card->dev, size, | ||
373 | &buf->addr, GFP_KERNEL); | ||
374 | if (!buf->area) | ||
375 | return -ENOMEM; | ||
376 | buf->bytes = size; | ||
377 | return 0; | ||
378 | } | ||
379 | |||
380 | static void dma_free_dma_buffers(struct snd_pcm *pcm) | ||
381 | { | ||
382 | struct snd_pcm_substream *substream; | ||
383 | struct snd_dma_buffer *buf; | ||
384 | int stream; | ||
385 | |||
386 | pr_debug("Entered %s\n", __func__); | ||
387 | |||
388 | for (stream = 0; stream < 2; stream++) { | ||
389 | substream = pcm->streams[stream].substream; | ||
390 | if (!substream) | ||
391 | continue; | ||
392 | |||
393 | buf = &substream->dma_buffer; | ||
394 | if (!buf->area) | ||
395 | continue; | ||
396 | |||
397 | dma_free_writecombine(pcm->card->dev, buf->bytes, | ||
398 | buf->area, buf->addr); | ||
399 | buf->area = NULL; | ||
400 | } | ||
401 | } | ||
402 | |||
403 | static int dma_new(struct snd_soc_pcm_runtime *rtd) | ||
404 | { | ||
405 | struct snd_card *card = rtd->card->snd_card; | ||
406 | struct snd_pcm *pcm = rtd->pcm; | ||
407 | int ret; | ||
408 | |||
409 | pr_debug("Entered %s\n", __func__); | ||
410 | |||
411 | ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32)); | ||
412 | if (ret) | ||
413 | return ret; | ||
414 | |||
415 | if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { | ||
416 | ret = preallocate_dma_buffer(pcm, | ||
417 | SNDRV_PCM_STREAM_PLAYBACK); | ||
418 | if (ret) | ||
419 | goto out; | ||
420 | } | ||
421 | |||
422 | if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { | ||
423 | ret = preallocate_dma_buffer(pcm, | ||
424 | SNDRV_PCM_STREAM_CAPTURE); | ||
425 | if (ret) | ||
426 | goto out; | ||
427 | } | ||
428 | out: | ||
429 | return ret; | ||
430 | } | ||
431 | |||
432 | static struct snd_soc_platform_driver samsung_asoc_platform = { | ||
433 | .ops = &dma_ops, | ||
434 | .pcm_new = dma_new, | ||
435 | .pcm_free = dma_free_dma_buffers, | ||
436 | }; | ||
437 | |||
438 | void samsung_asoc_init_dma_data(struct snd_soc_dai *dai, | ||
439 | struct s3c_dma_params *playback, | ||
440 | struct s3c_dma_params *capture) | ||
441 | { | ||
442 | snd_soc_dai_init_dma_data(dai, playback, capture); | ||
443 | } | ||
444 | EXPORT_SYMBOL_GPL(samsung_asoc_init_dma_data); | ||
445 | |||
446 | int samsung_asoc_dma_platform_register(struct device *dev) | ||
447 | { | ||
448 | return devm_snd_soc_register_platform(dev, &samsung_asoc_platform); | ||
449 | } | ||
450 | EXPORT_SYMBOL_GPL(samsung_asoc_dma_platform_register); | ||
451 | |||
452 | MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); | ||
453 | MODULE_DESCRIPTION("Samsung ASoC DMA Driver"); | ||
454 | MODULE_LICENSE("GPL"); | ||