diff options
author | Peter Ujfalusi <peter.ujfalusi@ti.com> | 2015-03-03 09:45:21 -0500 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2015-03-04 12:26:28 -0500 |
commit | 4da4608c91308d0d15dd022074724446c15710dc (patch) | |
tree | 762999f7d1a8d23a109e75d9791671c6c6449b4f /sound/soc/davinci | |
parent | 9759e7ef53138c5ab46ea516ad08977eb5770393 (diff) |
ASoC: davinci: Remove unused davinci-pcm platform driver
All DAI drivers has been converted to use edma-pcm instead of davinci-pcm
and the driver can be removed from the tree.
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound/soc/davinci')
-rw-r--r-- | sound/soc/davinci/Makefile | 2 | ||||
-rw-r--r-- | sound/soc/davinci/davinci-pcm.c | 861 | ||||
-rw-r--r-- | sound/soc/davinci/davinci-pcm.h | 41 |
3 files changed, 0 insertions, 904 deletions
diff --git a/sound/soc/davinci/Makefile b/sound/soc/davinci/Makefile index 09bf2ba92d38..f883933c1a19 100644 --- a/sound/soc/davinci/Makefile +++ b/sound/soc/davinci/Makefile | |||
@@ -1,11 +1,9 @@ | |||
1 | # DAVINCI Platform Support | 1 | # DAVINCI Platform Support |
2 | snd-soc-davinci-objs := davinci-pcm.o | ||
3 | snd-soc-edma-objs := edma-pcm.o | 2 | snd-soc-edma-objs := edma-pcm.o |
4 | snd-soc-davinci-i2s-objs := davinci-i2s.o | 3 | snd-soc-davinci-i2s-objs := davinci-i2s.o |
5 | snd-soc-davinci-mcasp-objs:= davinci-mcasp.o | 4 | snd-soc-davinci-mcasp-objs:= davinci-mcasp.o |
6 | snd-soc-davinci-vcif-objs:= davinci-vcif.o | 5 | snd-soc-davinci-vcif-objs:= davinci-vcif.o |
7 | 6 | ||
8 | obj-$(CONFIG_SND_DAVINCI_SOC) += snd-soc-davinci.o | ||
9 | obj-$(CONFIG_SND_EDMA_SOC) += snd-soc-edma.o | 7 | obj-$(CONFIG_SND_EDMA_SOC) += snd-soc-edma.o |
10 | obj-$(CONFIG_SND_DAVINCI_SOC_I2S) += snd-soc-davinci-i2s.o | 8 | obj-$(CONFIG_SND_DAVINCI_SOC_I2S) += snd-soc-davinci-i2s.o |
11 | obj-$(CONFIG_SND_DAVINCI_SOC_MCASP) += snd-soc-davinci-mcasp.o | 9 | obj-$(CONFIG_SND_DAVINCI_SOC_MCASP) += snd-soc-davinci-mcasp.o |
diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c deleted file mode 100644 index 7809e9d935fc..000000000000 --- a/sound/soc/davinci/davinci-pcm.c +++ /dev/null | |||
@@ -1,861 +0,0 @@ | |||
1 | /* | ||
2 | * ALSA PCM interface for the TI DAVINCI processor | ||
3 | * | ||
4 | * Author: Vladimir Barinov, <vbarinov@embeddedalley.com> | ||
5 | * Copyright: (C) 2007 MontaVista Software, Inc., <source@mvista.com> | ||
6 | * added SRAM ping/pong (C) 2008 Troy Kisky <troy.kisky@boundarydevices.com> | ||
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/module.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include <linux/dma-mapping.h> | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/genalloc.h> | ||
20 | #include <linux/platform_data/edma.h> | ||
21 | |||
22 | #include <sound/core.h> | ||
23 | #include <sound/pcm.h> | ||
24 | #include <sound/pcm_params.h> | ||
25 | #include <sound/soc.h> | ||
26 | |||
27 | #include <asm/dma.h> | ||
28 | |||
29 | #include "davinci-pcm.h" | ||
30 | |||
31 | #ifdef DEBUG | ||
32 | static void print_buf_info(int slot, char *name) | ||
33 | { | ||
34 | struct edmacc_param p; | ||
35 | if (slot < 0) | ||
36 | return; | ||
37 | edma_read_slot(slot, &p); | ||
38 | printk(KERN_DEBUG "%s: 0x%x, opt=%x, src=%x, a_b_cnt=%x dst=%x\n", | ||
39 | name, slot, p.opt, p.src, p.a_b_cnt, p.dst); | ||
40 | printk(KERN_DEBUG " src_dst_bidx=%x link_bcntrld=%x src_dst_cidx=%x ccnt=%x\n", | ||
41 | p.src_dst_bidx, p.link_bcntrld, p.src_dst_cidx, p.ccnt); | ||
42 | } | ||
43 | #else | ||
44 | static void print_buf_info(int slot, char *name) | ||
45 | { | ||
46 | } | ||
47 | #endif | ||
48 | |||
49 | static struct snd_pcm_hardware pcm_hardware_playback = { | ||
50 | .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
51 | SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | | ||
52 | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME| | ||
53 | SNDRV_PCM_INFO_BATCH), | ||
54 | .buffer_bytes_max = 128 * 1024, | ||
55 | .period_bytes_min = 32, | ||
56 | .period_bytes_max = 8 * 1024, | ||
57 | .periods_min = 16, | ||
58 | .periods_max = 255, | ||
59 | .fifo_size = 0, | ||
60 | }; | ||
61 | |||
62 | static struct snd_pcm_hardware pcm_hardware_capture = { | ||
63 | .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
64 | SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | | ||
65 | SNDRV_PCM_INFO_PAUSE | | ||
66 | SNDRV_PCM_INFO_BATCH), | ||
67 | .buffer_bytes_max = 128 * 1024, | ||
68 | .period_bytes_min = 32, | ||
69 | .period_bytes_max = 8 * 1024, | ||
70 | .periods_min = 16, | ||
71 | .periods_max = 255, | ||
72 | .fifo_size = 0, | ||
73 | }; | ||
74 | |||
75 | /* | ||
76 | * How ping/pong works.... | ||
77 | * | ||
78 | * Playback: | ||
79 | * ram_params - copys 2*ping_size from start of SDRAM to iram, | ||
80 | * links to ram_link2 | ||
81 | * ram_link2 - copys rest of SDRAM to iram in ping_size units, | ||
82 | * links to ram_link | ||
83 | * ram_link - copys entire SDRAM to iram in ping_size uints, | ||
84 | * links to self | ||
85 | * | ||
86 | * asp_params - same as asp_link[0] | ||
87 | * asp_link[0] - copys from lower half of iram to asp port | ||
88 | * links to asp_link[1], triggers iram copy event on completion | ||
89 | * asp_link[1] - copys from upper half of iram to asp port | ||
90 | * links to asp_link[0], triggers iram copy event on completion | ||
91 | * triggers interrupt only needed to let upper SOC levels update position | ||
92 | * in stream on completion | ||
93 | * | ||
94 | * When playback is started: | ||
95 | * ram_params started | ||
96 | * asp_params started | ||
97 | * | ||
98 | * Capture: | ||
99 | * ram_params - same as ram_link, | ||
100 | * links to ram_link | ||
101 | * ram_link - same as playback | ||
102 | * links to self | ||
103 | * | ||
104 | * asp_params - same as playback | ||
105 | * asp_link[0] - same as playback | ||
106 | * asp_link[1] - same as playback | ||
107 | * | ||
108 | * When capture is started: | ||
109 | * asp_params started | ||
110 | */ | ||
111 | struct davinci_runtime_data { | ||
112 | spinlock_t lock; | ||
113 | int period; /* current DMA period */ | ||
114 | int asp_channel; /* Master DMA channel */ | ||
115 | int asp_link[2]; /* asp parameter link channel, ping/pong */ | ||
116 | struct davinci_pcm_dma_params *params; /* DMA params */ | ||
117 | int ram_channel; | ||
118 | int ram_link; | ||
119 | int ram_link2; | ||
120 | struct edmacc_param asp_params; | ||
121 | struct edmacc_param ram_params; | ||
122 | }; | ||
123 | |||
124 | static void davinci_pcm_period_elapsed(struct snd_pcm_substream *substream) | ||
125 | { | ||
126 | struct davinci_runtime_data *prtd = substream->runtime->private_data; | ||
127 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
128 | |||
129 | prtd->period++; | ||
130 | if (unlikely(prtd->period >= runtime->periods)) | ||
131 | prtd->period = 0; | ||
132 | } | ||
133 | |||
134 | static void davinci_pcm_period_reset(struct snd_pcm_substream *substream) | ||
135 | { | ||
136 | struct davinci_runtime_data *prtd = substream->runtime->private_data; | ||
137 | |||
138 | prtd->period = 0; | ||
139 | } | ||
140 | /* | ||
141 | * Not used with ping/pong | ||
142 | */ | ||
143 | static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream) | ||
144 | { | ||
145 | struct davinci_runtime_data *prtd = substream->runtime->private_data; | ||
146 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
147 | unsigned int period_size; | ||
148 | unsigned int dma_offset; | ||
149 | dma_addr_t dma_pos; | ||
150 | dma_addr_t src, dst; | ||
151 | unsigned short src_bidx, dst_bidx; | ||
152 | unsigned short src_cidx, dst_cidx; | ||
153 | unsigned int data_type; | ||
154 | unsigned short acnt; | ||
155 | unsigned int count; | ||
156 | unsigned int fifo_level; | ||
157 | |||
158 | period_size = snd_pcm_lib_period_bytes(substream); | ||
159 | dma_offset = prtd->period * period_size; | ||
160 | dma_pos = runtime->dma_addr + dma_offset; | ||
161 | fifo_level = prtd->params->fifo_level; | ||
162 | |||
163 | pr_debug("davinci_pcm: audio_set_dma_params_play channel = %d " | ||
164 | "dma_ptr = %x period_size=%x\n", prtd->asp_link[0], dma_pos, | ||
165 | period_size); | ||
166 | |||
167 | data_type = prtd->params->data_type; | ||
168 | count = period_size / data_type; | ||
169 | if (fifo_level) | ||
170 | count /= fifo_level; | ||
171 | |||
172 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
173 | src = dma_pos; | ||
174 | dst = prtd->params->dma_addr; | ||
175 | src_bidx = data_type; | ||
176 | dst_bidx = 4; | ||
177 | src_cidx = data_type * fifo_level; | ||
178 | dst_cidx = 0; | ||
179 | } else { | ||
180 | src = prtd->params->dma_addr; | ||
181 | dst = dma_pos; | ||
182 | src_bidx = 0; | ||
183 | dst_bidx = data_type; | ||
184 | src_cidx = 0; | ||
185 | dst_cidx = data_type * fifo_level; | ||
186 | } | ||
187 | |||
188 | acnt = prtd->params->acnt; | ||
189 | edma_set_src(prtd->asp_link[0], src, INCR, W8BIT); | ||
190 | edma_set_dest(prtd->asp_link[0], dst, INCR, W8BIT); | ||
191 | |||
192 | edma_set_src_index(prtd->asp_link[0], src_bidx, src_cidx); | ||
193 | edma_set_dest_index(prtd->asp_link[0], dst_bidx, dst_cidx); | ||
194 | |||
195 | if (!fifo_level) | ||
196 | edma_set_transfer_params(prtd->asp_link[0], acnt, count, 1, 0, | ||
197 | ASYNC); | ||
198 | else | ||
199 | edma_set_transfer_params(prtd->asp_link[0], acnt, | ||
200 | fifo_level, | ||
201 | count, fifo_level, | ||
202 | ABSYNC); | ||
203 | } | ||
204 | |||
205 | static void davinci_pcm_dma_irq(unsigned link, u16 ch_status, void *data) | ||
206 | { | ||
207 | struct snd_pcm_substream *substream = data; | ||
208 | struct davinci_runtime_data *prtd = substream->runtime->private_data; | ||
209 | |||
210 | print_buf_info(prtd->ram_channel, "i ram_channel"); | ||
211 | pr_debug("davinci_pcm: link=%d, status=0x%x\n", link, ch_status); | ||
212 | |||
213 | if (unlikely(ch_status != EDMA_DMA_COMPLETE)) | ||
214 | return; | ||
215 | |||
216 | if (snd_pcm_running(substream)) { | ||
217 | spin_lock(&prtd->lock); | ||
218 | if (prtd->ram_channel < 0) { | ||
219 | /* No ping/pong must fix up link dma data*/ | ||
220 | davinci_pcm_enqueue_dma(substream); | ||
221 | } | ||
222 | davinci_pcm_period_elapsed(substream); | ||
223 | spin_unlock(&prtd->lock); | ||
224 | snd_pcm_period_elapsed(substream); | ||
225 | } | ||
226 | } | ||
227 | |||
228 | #ifdef CONFIG_GENERIC_ALLOCATOR | ||
229 | static int allocate_sram(struct snd_pcm_substream *substream, | ||
230 | struct gen_pool *sram_pool, unsigned size, | ||
231 | struct snd_pcm_hardware *ppcm) | ||
232 | { | ||
233 | struct snd_dma_buffer *buf = &substream->dma_buffer; | ||
234 | struct snd_dma_buffer *iram_dma = NULL; | ||
235 | dma_addr_t iram_phys = 0; | ||
236 | void *iram_virt = NULL; | ||
237 | |||
238 | if (buf->private_data || !size) | ||
239 | return 0; | ||
240 | |||
241 | ppcm->period_bytes_max = size; | ||
242 | iram_virt = gen_pool_dma_alloc(sram_pool, size, &iram_phys); | ||
243 | if (!iram_virt) | ||
244 | goto exit1; | ||
245 | iram_dma = kzalloc(sizeof(*iram_dma), GFP_KERNEL); | ||
246 | if (!iram_dma) | ||
247 | goto exit2; | ||
248 | iram_dma->area = iram_virt; | ||
249 | iram_dma->addr = iram_phys; | ||
250 | memset(iram_dma->area, 0, size); | ||
251 | iram_dma->bytes = size; | ||
252 | buf->private_data = iram_dma; | ||
253 | return 0; | ||
254 | exit2: | ||
255 | if (iram_virt) | ||
256 | gen_pool_free(sram_pool, (unsigned)iram_virt, size); | ||
257 | exit1: | ||
258 | return -ENOMEM; | ||
259 | } | ||
260 | |||
261 | static void davinci_free_sram(struct snd_pcm_substream *substream, | ||
262 | struct snd_dma_buffer *iram_dma) | ||
263 | { | ||
264 | struct davinci_runtime_data *prtd = substream->runtime->private_data; | ||
265 | struct gen_pool *sram_pool = prtd->params->sram_pool; | ||
266 | |||
267 | gen_pool_free(sram_pool, (unsigned) iram_dma->area, iram_dma->bytes); | ||
268 | } | ||
269 | #else | ||
270 | static int allocate_sram(struct snd_pcm_substream *substream, | ||
271 | struct gen_pool *sram_pool, unsigned size, | ||
272 | struct snd_pcm_hardware *ppcm) | ||
273 | { | ||
274 | return 0; | ||
275 | } | ||
276 | |||
277 | static void davinci_free_sram(struct snd_pcm_substream *substream, | ||
278 | struct snd_dma_buffer *iram_dma) | ||
279 | { | ||
280 | } | ||
281 | #endif | ||
282 | |||
283 | /* | ||
284 | * Only used with ping/pong. | ||
285 | * This is called after runtime->dma_addr, period_bytes and data_type are valid | ||
286 | */ | ||
287 | static int ping_pong_dma_setup(struct snd_pcm_substream *substream) | ||
288 | { | ||
289 | unsigned short ram_src_cidx, ram_dst_cidx; | ||
290 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
291 | struct davinci_runtime_data *prtd = runtime->private_data; | ||
292 | struct snd_dma_buffer *iram_dma = | ||
293 | (struct snd_dma_buffer *)substream->dma_buffer.private_data; | ||
294 | struct davinci_pcm_dma_params *params = prtd->params; | ||
295 | unsigned int data_type = params->data_type; | ||
296 | unsigned int acnt = params->acnt; | ||
297 | /* divide by 2 for ping/pong */ | ||
298 | unsigned int ping_size = snd_pcm_lib_period_bytes(substream) >> 1; | ||
299 | unsigned int fifo_level = prtd->params->fifo_level; | ||
300 | unsigned int count; | ||
301 | if ((data_type == 0) || (data_type > 4)) { | ||
302 | printk(KERN_ERR "%s: data_type=%i\n", __func__, data_type); | ||
303 | return -EINVAL; | ||
304 | } | ||
305 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
306 | dma_addr_t asp_src_pong = iram_dma->addr + ping_size; | ||
307 | ram_src_cidx = ping_size; | ||
308 | ram_dst_cidx = -ping_size; | ||
309 | edma_set_src(prtd->asp_link[1], asp_src_pong, INCR, W8BIT); | ||
310 | |||
311 | edma_set_src_index(prtd->asp_link[0], data_type, | ||
312 | data_type * fifo_level); | ||
313 | edma_set_src_index(prtd->asp_link[1], data_type, | ||
314 | data_type * fifo_level); | ||
315 | |||
316 | edma_set_src(prtd->ram_link, runtime->dma_addr, INCR, W32BIT); | ||
317 | } else { | ||
318 | dma_addr_t asp_dst_pong = iram_dma->addr + ping_size; | ||
319 | ram_src_cidx = -ping_size; | ||
320 | ram_dst_cidx = ping_size; | ||
321 | edma_set_dest(prtd->asp_link[1], asp_dst_pong, INCR, W8BIT); | ||
322 | |||
323 | edma_set_dest_index(prtd->asp_link[0], data_type, | ||
324 | data_type * fifo_level); | ||
325 | edma_set_dest_index(prtd->asp_link[1], data_type, | ||
326 | data_type * fifo_level); | ||
327 | |||
328 | edma_set_dest(prtd->ram_link, runtime->dma_addr, INCR, W32BIT); | ||
329 | } | ||
330 | |||
331 | if (!fifo_level) { | ||
332 | count = ping_size / data_type; | ||
333 | edma_set_transfer_params(prtd->asp_link[0], acnt, count, | ||
334 | 1, 0, ASYNC); | ||
335 | edma_set_transfer_params(prtd->asp_link[1], acnt, count, | ||
336 | 1, 0, ASYNC); | ||
337 | } else { | ||
338 | count = ping_size / (data_type * fifo_level); | ||
339 | edma_set_transfer_params(prtd->asp_link[0], acnt, fifo_level, | ||
340 | count, fifo_level, ABSYNC); | ||
341 | edma_set_transfer_params(prtd->asp_link[1], acnt, fifo_level, | ||
342 | count, fifo_level, ABSYNC); | ||
343 | } | ||
344 | |||
345 | edma_set_src_index(prtd->ram_link, ping_size, ram_src_cidx); | ||
346 | edma_set_dest_index(prtd->ram_link, ping_size, ram_dst_cidx); | ||
347 | edma_set_transfer_params(prtd->ram_link, ping_size, 2, | ||
348 | runtime->periods, 2, ASYNC); | ||
349 | |||
350 | /* init master params */ | ||
351 | edma_read_slot(prtd->asp_link[0], &prtd->asp_params); | ||
352 | edma_read_slot(prtd->ram_link, &prtd->ram_params); | ||
353 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
354 | struct edmacc_param p_ram; | ||
355 | /* Copy entire iram buffer before playback started */ | ||
356 | prtd->ram_params.a_b_cnt = (1 << 16) | (ping_size << 1); | ||
357 | /* 0 dst_bidx */ | ||
358 | prtd->ram_params.src_dst_bidx = (ping_size << 1); | ||
359 | /* 0 dst_cidx */ | ||
360 | prtd->ram_params.src_dst_cidx = (ping_size << 1); | ||
361 | prtd->ram_params.ccnt = 1; | ||
362 | |||
363 | /* Skip 1st period */ | ||
364 | edma_read_slot(prtd->ram_link, &p_ram); | ||
365 | p_ram.src += (ping_size << 1); | ||
366 | p_ram.ccnt -= 1; | ||
367 | edma_write_slot(prtd->ram_link2, &p_ram); | ||
368 | /* | ||
369 | * When 1st started, ram -> iram dma channel will fill the | ||
370 | * entire iram. Then, whenever a ping/pong asp buffer finishes, | ||
371 | * 1/2 iram will be filled. | ||
372 | */ | ||
373 | prtd->ram_params.link_bcntrld = | ||
374 | EDMA_CHAN_SLOT(prtd->ram_link2) << 5; | ||
375 | } | ||
376 | return 0; | ||
377 | } | ||
378 | |||
379 | /* 1 asp tx or rx channel using 2 parameter channels | ||
380 | * 1 ram to/from iram channel using 1 parameter channel | ||
381 | * | ||
382 | * Playback | ||
383 | * ram copy channel kicks off first, | ||
384 | * 1st ram copy of entire iram buffer completion kicks off asp channel | ||
385 | * asp tcc always kicks off ram copy of 1/2 iram buffer | ||
386 | * | ||
387 | * Record | ||
388 | * asp channel starts, tcc kicks off ram copy | ||
389 | */ | ||
390 | static int request_ping_pong(struct snd_pcm_substream *substream, | ||
391 | struct davinci_runtime_data *prtd, | ||
392 | struct snd_dma_buffer *iram_dma) | ||
393 | { | ||
394 | dma_addr_t asp_src_ping; | ||
395 | dma_addr_t asp_dst_ping; | ||
396 | int ret; | ||
397 | struct davinci_pcm_dma_params *params = prtd->params; | ||
398 | |||
399 | /* Request ram master channel */ | ||
400 | ret = prtd->ram_channel = edma_alloc_channel(EDMA_CHANNEL_ANY, | ||
401 | davinci_pcm_dma_irq, substream, | ||
402 | prtd->params->ram_chan_q); | ||
403 | if (ret < 0) | ||
404 | goto exit1; | ||
405 | |||
406 | /* Request ram link channel */ | ||
407 | ret = prtd->ram_link = edma_alloc_slot( | ||
408 | EDMA_CTLR(prtd->ram_channel), EDMA_SLOT_ANY); | ||
409 | if (ret < 0) | ||
410 | goto exit2; | ||
411 | |||
412 | ret = prtd->asp_link[1] = edma_alloc_slot( | ||
413 | EDMA_CTLR(prtd->asp_channel), EDMA_SLOT_ANY); | ||
414 | if (ret < 0) | ||
415 | goto exit3; | ||
416 | |||
417 | prtd->ram_link2 = -1; | ||
418 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
419 | ret = prtd->ram_link2 = edma_alloc_slot( | ||
420 | EDMA_CTLR(prtd->ram_channel), EDMA_SLOT_ANY); | ||
421 | if (ret < 0) | ||
422 | goto exit4; | ||
423 | } | ||
424 | /* circle ping-pong buffers */ | ||
425 | edma_link(prtd->asp_link[0], prtd->asp_link[1]); | ||
426 | edma_link(prtd->asp_link[1], prtd->asp_link[0]); | ||
427 | /* circle ram buffers */ | ||
428 | edma_link(prtd->ram_link, prtd->ram_link); | ||
429 | |||
430 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
431 | asp_src_ping = iram_dma->addr; | ||
432 | asp_dst_ping = params->dma_addr; /* fifo */ | ||
433 | } else { | ||
434 | asp_src_ping = params->dma_addr; /* fifo */ | ||
435 | asp_dst_ping = iram_dma->addr; | ||
436 | } | ||
437 | /* ping */ | ||
438 | edma_set_src(prtd->asp_link[0], asp_src_ping, INCR, W16BIT); | ||
439 | edma_set_dest(prtd->asp_link[0], asp_dst_ping, INCR, W16BIT); | ||
440 | edma_set_src_index(prtd->asp_link[0], 0, 0); | ||
441 | edma_set_dest_index(prtd->asp_link[0], 0, 0); | ||
442 | |||
443 | edma_read_slot(prtd->asp_link[0], &prtd->asp_params); | ||
444 | prtd->asp_params.opt &= ~(TCCMODE | EDMA_TCC(0x3f) | TCINTEN); | ||
445 | prtd->asp_params.opt |= TCCHEN | | ||
446 | EDMA_TCC(prtd->ram_channel & 0x3f); | ||
447 | edma_write_slot(prtd->asp_link[0], &prtd->asp_params); | ||
448 | |||
449 | /* pong */ | ||
450 | edma_set_src(prtd->asp_link[1], asp_src_ping, INCR, W16BIT); | ||
451 | edma_set_dest(prtd->asp_link[1], asp_dst_ping, INCR, W16BIT); | ||
452 | edma_set_src_index(prtd->asp_link[1], 0, 0); | ||
453 | edma_set_dest_index(prtd->asp_link[1], 0, 0); | ||
454 | |||
455 | edma_read_slot(prtd->asp_link[1], &prtd->asp_params); | ||
456 | prtd->asp_params.opt &= ~(TCCMODE | EDMA_TCC(0x3f)); | ||
457 | /* interrupt after every pong completion */ | ||
458 | prtd->asp_params.opt |= TCINTEN | TCCHEN | | ||
459 | EDMA_TCC(prtd->ram_channel & 0x3f); | ||
460 | edma_write_slot(prtd->asp_link[1], &prtd->asp_params); | ||
461 | |||
462 | /* ram */ | ||
463 | edma_set_src(prtd->ram_link, iram_dma->addr, INCR, W32BIT); | ||
464 | edma_set_dest(prtd->ram_link, iram_dma->addr, INCR, W32BIT); | ||
465 | pr_debug("%s: audio dma channels/slots in use for ram:%u %u %u," | ||
466 | "for asp:%u %u %u\n", __func__, | ||
467 | prtd->ram_channel, prtd->ram_link, prtd->ram_link2, | ||
468 | prtd->asp_channel, prtd->asp_link[0], | ||
469 | prtd->asp_link[1]); | ||
470 | return 0; | ||
471 | exit4: | ||
472 | edma_free_channel(prtd->asp_link[1]); | ||
473 | prtd->asp_link[1] = -1; | ||
474 | exit3: | ||
475 | edma_free_channel(prtd->ram_link); | ||
476 | prtd->ram_link = -1; | ||
477 | exit2: | ||
478 | edma_free_channel(prtd->ram_channel); | ||
479 | prtd->ram_channel = -1; | ||
480 | exit1: | ||
481 | return ret; | ||
482 | } | ||
483 | |||
484 | static int davinci_pcm_dma_request(struct snd_pcm_substream *substream) | ||
485 | { | ||
486 | struct snd_dma_buffer *iram_dma; | ||
487 | struct davinci_runtime_data *prtd = substream->runtime->private_data; | ||
488 | struct davinci_pcm_dma_params *params = prtd->params; | ||
489 | int ret; | ||
490 | |||
491 | if (!params) | ||
492 | return -ENODEV; | ||
493 | |||
494 | /* Request asp master DMA channel */ | ||
495 | ret = prtd->asp_channel = edma_alloc_channel(params->channel, | ||
496 | davinci_pcm_dma_irq, substream, | ||
497 | prtd->params->asp_chan_q); | ||
498 | if (ret < 0) | ||
499 | goto exit1; | ||
500 | |||
501 | /* Request asp link channels */ | ||
502 | ret = prtd->asp_link[0] = edma_alloc_slot( | ||
503 | EDMA_CTLR(prtd->asp_channel), EDMA_SLOT_ANY); | ||
504 | if (ret < 0) | ||
505 | goto exit2; | ||
506 | |||
507 | iram_dma = (struct snd_dma_buffer *)substream->dma_buffer.private_data; | ||
508 | if (iram_dma) { | ||
509 | if (request_ping_pong(substream, prtd, iram_dma) == 0) | ||
510 | return 0; | ||
511 | printk(KERN_WARNING "%s: dma channel allocation failed," | ||
512 | "not using sram\n", __func__); | ||
513 | } | ||
514 | |||
515 | /* Issue transfer completion IRQ when the channel completes a | ||
516 | * transfer, then always reload from the same slot (by a kind | ||
517 | * of loopback link). The completion IRQ handler will update | ||
518 | * the reload slot with a new buffer. | ||
519 | * | ||
520 | * REVISIT save p_ram here after setting up everything except | ||
521 | * the buffer and its length (ccnt) ... use it as a template | ||
522 | * so davinci_pcm_enqueue_dma() takes less time in IRQ. | ||
523 | */ | ||
524 | edma_read_slot(prtd->asp_link[0], &prtd->asp_params); | ||
525 | prtd->asp_params.opt |= TCINTEN | | ||
526 | EDMA_TCC(EDMA_CHAN_SLOT(prtd->asp_channel)); | ||
527 | prtd->asp_params.link_bcntrld = EDMA_CHAN_SLOT(prtd->asp_link[0]) << 5; | ||
528 | edma_write_slot(prtd->asp_link[0], &prtd->asp_params); | ||
529 | return 0; | ||
530 | exit2: | ||
531 | edma_free_channel(prtd->asp_channel); | ||
532 | prtd->asp_channel = -1; | ||
533 | exit1: | ||
534 | return ret; | ||
535 | } | ||
536 | |||
537 | static int davinci_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | ||
538 | { | ||
539 | struct davinci_runtime_data *prtd = substream->runtime->private_data; | ||
540 | int ret = 0; | ||
541 | |||
542 | spin_lock(&prtd->lock); | ||
543 | |||
544 | switch (cmd) { | ||
545 | case SNDRV_PCM_TRIGGER_START: | ||
546 | edma_start(prtd->asp_channel); | ||
547 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && | ||
548 | prtd->ram_channel >= 0) { | ||
549 | /* copy 1st iram buffer */ | ||
550 | edma_start(prtd->ram_channel); | ||
551 | } | ||
552 | break; | ||
553 | case SNDRV_PCM_TRIGGER_RESUME: | ||
554 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
555 | edma_resume(prtd->asp_channel); | ||
556 | break; | ||
557 | case SNDRV_PCM_TRIGGER_STOP: | ||
558 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
559 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
560 | edma_pause(prtd->asp_channel); | ||
561 | break; | ||
562 | default: | ||
563 | ret = -EINVAL; | ||
564 | break; | ||
565 | } | ||
566 | |||
567 | spin_unlock(&prtd->lock); | ||
568 | |||
569 | return ret; | ||
570 | } | ||
571 | |||
572 | static int davinci_pcm_prepare(struct snd_pcm_substream *substream) | ||
573 | { | ||
574 | struct davinci_runtime_data *prtd = substream->runtime->private_data; | ||
575 | |||
576 | davinci_pcm_period_reset(substream); | ||
577 | if (prtd->ram_channel >= 0) { | ||
578 | int ret = ping_pong_dma_setup(substream); | ||
579 | if (ret < 0) | ||
580 | return ret; | ||
581 | |||
582 | edma_write_slot(prtd->ram_channel, &prtd->ram_params); | ||
583 | edma_write_slot(prtd->asp_channel, &prtd->asp_params); | ||
584 | |||
585 | print_buf_info(prtd->ram_channel, "ram_channel"); | ||
586 | print_buf_info(prtd->ram_link, "ram_link"); | ||
587 | print_buf_info(prtd->ram_link2, "ram_link2"); | ||
588 | print_buf_info(prtd->asp_channel, "asp_channel"); | ||
589 | print_buf_info(prtd->asp_link[0], "asp_link[0]"); | ||
590 | print_buf_info(prtd->asp_link[1], "asp_link[1]"); | ||
591 | |||
592 | /* | ||
593 | * There is a phase offset of 2 periods between the position | ||
594 | * used by dma setup and the position reported in the pointer | ||
595 | * function. | ||
596 | * | ||
597 | * The phase offset, when not using ping-pong buffers, is due to | ||
598 | * the two consecutive calls to davinci_pcm_enqueue_dma() below. | ||
599 | * | ||
600 | * Whereas here, with ping-pong buffers, the phase is due to | ||
601 | * there being an entire buffer transfer complete before the | ||
602 | * first dma completion event triggers davinci_pcm_dma_irq(). | ||
603 | */ | ||
604 | davinci_pcm_period_elapsed(substream); | ||
605 | davinci_pcm_period_elapsed(substream); | ||
606 | |||
607 | return 0; | ||
608 | } | ||
609 | davinci_pcm_enqueue_dma(substream); | ||
610 | davinci_pcm_period_elapsed(substream); | ||
611 | |||
612 | /* Copy self-linked parameter RAM entry into master channel */ | ||
613 | edma_read_slot(prtd->asp_link[0], &prtd->asp_params); | ||
614 | edma_write_slot(prtd->asp_channel, &prtd->asp_params); | ||
615 | davinci_pcm_enqueue_dma(substream); | ||
616 | davinci_pcm_period_elapsed(substream); | ||
617 | |||
618 | return 0; | ||
619 | } | ||
620 | |||
621 | static snd_pcm_uframes_t | ||
622 | davinci_pcm_pointer(struct snd_pcm_substream *substream) | ||
623 | { | ||
624 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
625 | struct davinci_runtime_data *prtd = runtime->private_data; | ||
626 | unsigned int offset; | ||
627 | int asp_count; | ||
628 | unsigned int period_size = snd_pcm_lib_period_bytes(substream); | ||
629 | |||
630 | /* | ||
631 | * There is a phase offset of 2 periods between the position used by dma | ||
632 | * setup and the position reported in the pointer function. Either +2 in | ||
633 | * the dma setup or -2 here in the pointer function (with wrapping, | ||
634 | * both) accounts for this offset -- choose the latter since it makes | ||
635 | * the first-time setup clearer. | ||
636 | */ | ||
637 | spin_lock(&prtd->lock); | ||
638 | asp_count = prtd->period - 2; | ||
639 | spin_unlock(&prtd->lock); | ||
640 | |||
641 | if (asp_count < 0) | ||
642 | asp_count += runtime->periods; | ||
643 | asp_count *= period_size; | ||
644 | |||
645 | offset = bytes_to_frames(runtime, asp_count); | ||
646 | if (offset >= runtime->buffer_size) | ||
647 | offset = 0; | ||
648 | |||
649 | return offset; | ||
650 | } | ||
651 | |||
652 | static int davinci_pcm_open(struct snd_pcm_substream *substream) | ||
653 | { | ||
654 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
655 | struct davinci_runtime_data *prtd; | ||
656 | struct snd_pcm_hardware *ppcm; | ||
657 | int ret = 0; | ||
658 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
659 | struct davinci_pcm_dma_params *pa; | ||
660 | struct davinci_pcm_dma_params *params; | ||
661 | |||
662 | pa = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | ||
663 | if (!pa) | ||
664 | return -ENODEV; | ||
665 | params = &pa[substream->stream]; | ||
666 | |||
667 | ppcm = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? | ||
668 | &pcm_hardware_playback : &pcm_hardware_capture; | ||
669 | allocate_sram(substream, params->sram_pool, params->sram_size, ppcm); | ||
670 | snd_soc_set_runtime_hwparams(substream, ppcm); | ||
671 | /* ensure that buffer size is a multiple of period size */ | ||
672 | ret = snd_pcm_hw_constraint_integer(runtime, | ||
673 | SNDRV_PCM_HW_PARAM_PERIODS); | ||
674 | if (ret < 0) | ||
675 | return ret; | ||
676 | |||
677 | prtd = kzalloc(sizeof(struct davinci_runtime_data), GFP_KERNEL); | ||
678 | if (prtd == NULL) | ||
679 | return -ENOMEM; | ||
680 | |||
681 | spin_lock_init(&prtd->lock); | ||
682 | prtd->params = params; | ||
683 | prtd->asp_channel = -1; | ||
684 | prtd->asp_link[0] = prtd->asp_link[1] = -1; | ||
685 | prtd->ram_channel = -1; | ||
686 | prtd->ram_link = -1; | ||
687 | prtd->ram_link2 = -1; | ||
688 | |||
689 | runtime->private_data = prtd; | ||
690 | |||
691 | ret = davinci_pcm_dma_request(substream); | ||
692 | if (ret) { | ||
693 | printk(KERN_ERR "davinci_pcm: Failed to get dma channels\n"); | ||
694 | kfree(prtd); | ||
695 | } | ||
696 | |||
697 | return ret; | ||
698 | } | ||
699 | |||
700 | static int davinci_pcm_close(struct snd_pcm_substream *substream) | ||
701 | { | ||
702 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
703 | struct davinci_runtime_data *prtd = runtime->private_data; | ||
704 | |||
705 | if (prtd->ram_channel >= 0) | ||
706 | edma_stop(prtd->ram_channel); | ||
707 | if (prtd->asp_channel >= 0) | ||
708 | edma_stop(prtd->asp_channel); | ||
709 | if (prtd->asp_link[0] >= 0) | ||
710 | edma_unlink(prtd->asp_link[0]); | ||
711 | if (prtd->asp_link[1] >= 0) | ||
712 | edma_unlink(prtd->asp_link[1]); | ||
713 | if (prtd->ram_link >= 0) | ||
714 | edma_unlink(prtd->ram_link); | ||
715 | |||
716 | if (prtd->asp_link[0] >= 0) | ||
717 | edma_free_slot(prtd->asp_link[0]); | ||
718 | if (prtd->asp_link[1] >= 0) | ||
719 | edma_free_slot(prtd->asp_link[1]); | ||
720 | if (prtd->asp_channel >= 0) | ||
721 | edma_free_channel(prtd->asp_channel); | ||
722 | if (prtd->ram_link >= 0) | ||
723 | edma_free_slot(prtd->ram_link); | ||
724 | if (prtd->ram_link2 >= 0) | ||
725 | edma_free_slot(prtd->ram_link2); | ||
726 | if (prtd->ram_channel >= 0) | ||
727 | edma_free_channel(prtd->ram_channel); | ||
728 | |||
729 | kfree(prtd); | ||
730 | |||
731 | return 0; | ||
732 | } | ||
733 | |||
734 | static int davinci_pcm_hw_params(struct snd_pcm_substream *substream, | ||
735 | struct snd_pcm_hw_params *hw_params) | ||
736 | { | ||
737 | return snd_pcm_lib_malloc_pages(substream, | ||
738 | params_buffer_bytes(hw_params)); | ||
739 | } | ||
740 | |||
741 | static int davinci_pcm_hw_free(struct snd_pcm_substream *substream) | ||
742 | { | ||
743 | return snd_pcm_lib_free_pages(substream); | ||
744 | } | ||
745 | |||
746 | static int davinci_pcm_mmap(struct snd_pcm_substream *substream, | ||
747 | struct vm_area_struct *vma) | ||
748 | { | ||
749 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
750 | |||
751 | return dma_mmap_writecombine(substream->pcm->card->dev, vma, | ||
752 | runtime->dma_area, | ||
753 | runtime->dma_addr, | ||
754 | runtime->dma_bytes); | ||
755 | } | ||
756 | |||
757 | static struct snd_pcm_ops davinci_pcm_ops = { | ||
758 | .open = davinci_pcm_open, | ||
759 | .close = davinci_pcm_close, | ||
760 | .ioctl = snd_pcm_lib_ioctl, | ||
761 | .hw_params = davinci_pcm_hw_params, | ||
762 | .hw_free = davinci_pcm_hw_free, | ||
763 | .prepare = davinci_pcm_prepare, | ||
764 | .trigger = davinci_pcm_trigger, | ||
765 | .pointer = davinci_pcm_pointer, | ||
766 | .mmap = davinci_pcm_mmap, | ||
767 | }; | ||
768 | |||
769 | static int davinci_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream, | ||
770 | size_t size) | ||
771 | { | ||
772 | struct snd_pcm_substream *substream = pcm->streams[stream].substream; | ||
773 | struct snd_dma_buffer *buf = &substream->dma_buffer; | ||
774 | |||
775 | buf->dev.type = SNDRV_DMA_TYPE_DEV; | ||
776 | buf->dev.dev = pcm->card->dev; | ||
777 | buf->private_data = NULL; | ||
778 | buf->area = dma_alloc_writecombine(pcm->card->dev, size, | ||
779 | &buf->addr, GFP_KERNEL); | ||
780 | |||
781 | pr_debug("davinci_pcm: preallocate_dma_buffer: area=%p, addr=%p, " | ||
782 | "size=%d\n", (void *) buf->area, (void *) buf->addr, size); | ||
783 | |||
784 | if (!buf->area) | ||
785 | return -ENOMEM; | ||
786 | |||
787 | buf->bytes = size; | ||
788 | return 0; | ||
789 | } | ||
790 | |||
791 | static void davinci_pcm_free(struct snd_pcm *pcm) | ||
792 | { | ||
793 | struct snd_pcm_substream *substream; | ||
794 | struct snd_dma_buffer *buf; | ||
795 | int stream; | ||
796 | |||
797 | for (stream = 0; stream < 2; stream++) { | ||
798 | struct snd_dma_buffer *iram_dma; | ||
799 | substream = pcm->streams[stream].substream; | ||
800 | if (!substream) | ||
801 | continue; | ||
802 | |||
803 | buf = &substream->dma_buffer; | ||
804 | if (!buf->area) | ||
805 | continue; | ||
806 | |||
807 | dma_free_writecombine(pcm->card->dev, buf->bytes, | ||
808 | buf->area, buf->addr); | ||
809 | buf->area = NULL; | ||
810 | iram_dma = buf->private_data; | ||
811 | if (iram_dma) { | ||
812 | davinci_free_sram(substream, iram_dma); | ||
813 | kfree(iram_dma); | ||
814 | } | ||
815 | } | ||
816 | } | ||
817 | |||
818 | static int davinci_pcm_new(struct snd_soc_pcm_runtime *rtd) | ||
819 | { | ||
820 | struct snd_card *card = rtd->card->snd_card; | ||
821 | struct snd_pcm *pcm = rtd->pcm; | ||
822 | int ret; | ||
823 | |||
824 | ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32)); | ||
825 | if (ret) | ||
826 | return ret; | ||
827 | |||
828 | if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { | ||
829 | ret = davinci_pcm_preallocate_dma_buffer(pcm, | ||
830 | SNDRV_PCM_STREAM_PLAYBACK, | ||
831 | pcm_hardware_playback.buffer_bytes_max); | ||
832 | if (ret) | ||
833 | return ret; | ||
834 | } | ||
835 | |||
836 | if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { | ||
837 | ret = davinci_pcm_preallocate_dma_buffer(pcm, | ||
838 | SNDRV_PCM_STREAM_CAPTURE, | ||
839 | pcm_hardware_capture.buffer_bytes_max); | ||
840 | if (ret) | ||
841 | return ret; | ||
842 | } | ||
843 | |||
844 | return 0; | ||
845 | } | ||
846 | |||
847 | static struct snd_soc_platform_driver davinci_soc_platform = { | ||
848 | .ops = &davinci_pcm_ops, | ||
849 | .pcm_new = davinci_pcm_new, | ||
850 | .pcm_free = davinci_pcm_free, | ||
851 | }; | ||
852 | |||
853 | int davinci_soc_platform_register(struct device *dev) | ||
854 | { | ||
855 | return devm_snd_soc_register_platform(dev, &davinci_soc_platform); | ||
856 | } | ||
857 | EXPORT_SYMBOL_GPL(davinci_soc_platform_register); | ||
858 | |||
859 | MODULE_AUTHOR("Vladimir Barinov"); | ||
860 | MODULE_DESCRIPTION("TI DAVINCI PCM DMA module"); | ||
861 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/davinci/davinci-pcm.h b/sound/soc/davinci/davinci-pcm.h deleted file mode 100644 index 0fe2346a9aa2..000000000000 --- a/sound/soc/davinci/davinci-pcm.h +++ /dev/null | |||
@@ -1,41 +0,0 @@ | |||
1 | /* | ||
2 | * ALSA PCM interface for the TI DAVINCI processor | ||
3 | * | ||
4 | * Author: Vladimir Barinov, <vbarinov@embeddedalley.com> | ||
5 | * Copyright: (C) 2007 MontaVista Software, Inc., <source@mvista.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 | |||
12 | #ifndef _DAVINCI_PCM_H | ||
13 | #define _DAVINCI_PCM_H | ||
14 | |||
15 | #include <linux/genalloc.h> | ||
16 | #include <linux/platform_data/davinci_asp.h> | ||
17 | #include <linux/platform_data/edma.h> | ||
18 | |||
19 | struct davinci_pcm_dma_params { | ||
20 | int channel; /* sync dma channel ID */ | ||
21 | unsigned short acnt; | ||
22 | dma_addr_t dma_addr; /* device physical address for DMA */ | ||
23 | unsigned sram_size; | ||
24 | struct gen_pool *sram_pool; /* SRAM gen_pool for ping pong */ | ||
25 | enum dma_event_q asp_chan_q; /* event queue number for ASP channel */ | ||
26 | enum dma_event_q ram_chan_q; /* event queue number for RAM channel */ | ||
27 | unsigned char data_type; /* xfer data type */ | ||
28 | unsigned char convert_mono_stereo; | ||
29 | unsigned int fifo_level; | ||
30 | }; | ||
31 | |||
32 | #if IS_ENABLED(CONFIG_SND_DAVINCI_SOC) | ||
33 | int davinci_soc_platform_register(struct device *dev); | ||
34 | #else | ||
35 | static inline int davinci_soc_platform_register(struct device *dev) | ||
36 | { | ||
37 | return 0; | ||
38 | } | ||
39 | #endif /* CONFIG_SND_DAVINCI_SOC */ | ||
40 | |||
41 | #endif | ||