1
2
3
4
5
6
7
8
9
10
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
21#include <sound/core.h>
22#include <sound/pcm.h>
23#include <sound/pcm_params.h>
24#include <sound/soc.h>
25
26#include <asm/dma.h>
27
28#include "davinci-pcm.h"
29
30#ifdef DEBUG
31static void print_buf_info(int slot, char *name)
32{
33 struct edmacc_param p;
34 if (slot < 0)
35 return;
36 edma_read_slot(slot, &p);
37 printk(KERN_DEBUG "%s: 0x%x, opt=%x, src=%x, a_b_cnt=%x dst=%x\n",
38 name, slot, p.opt, p.src, p.a_b_cnt, p.dst);
39 printk(KERN_DEBUG " src_dst_bidx=%x link_bcntrld=%x src_dst_cidx=%x ccnt=%x\n",
40 p.src_dst_bidx, p.link_bcntrld, p.src_dst_cidx, p.ccnt);
41}
42#else
43static void print_buf_info(int slot, char *name)
44{
45}
46#endif
47
48#define DAVINCI_PCM_FMTBITS (\
49 SNDRV_PCM_FMTBIT_S8 |\
50 SNDRV_PCM_FMTBIT_U8 |\
51 SNDRV_PCM_FMTBIT_S16_LE |\
52 SNDRV_PCM_FMTBIT_S16_BE |\
53 SNDRV_PCM_FMTBIT_U16_LE |\
54 SNDRV_PCM_FMTBIT_U16_BE |\
55 SNDRV_PCM_FMTBIT_S24_LE |\
56 SNDRV_PCM_FMTBIT_S24_BE |\
57 SNDRV_PCM_FMTBIT_U24_LE |\
58 SNDRV_PCM_FMTBIT_U24_BE |\
59 SNDRV_PCM_FMTBIT_S32_LE |\
60 SNDRV_PCM_FMTBIT_S32_BE |\
61 SNDRV_PCM_FMTBIT_U32_LE |\
62 SNDRV_PCM_FMTBIT_U32_BE)
63
64static struct snd_pcm_hardware pcm_hardware_playback = {
65 .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
66 SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
67 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME|
68 SNDRV_PCM_INFO_BATCH),
69 .formats = DAVINCI_PCM_FMTBITS,
70 .rates = SNDRV_PCM_RATE_8000_192000 | SNDRV_PCM_RATE_KNOT,
71 .rate_min = 8000,
72 .rate_max = 192000,
73 .channels_min = 2,
74 .channels_max = 384,
75 .buffer_bytes_max = 128 * 1024,
76 .period_bytes_min = 32,
77 .period_bytes_max = 8 * 1024,
78 .periods_min = 16,
79 .periods_max = 255,
80 .fifo_size = 0,
81};
82
83static struct snd_pcm_hardware pcm_hardware_capture = {
84 .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
85 SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
86 SNDRV_PCM_INFO_PAUSE |
87 SNDRV_PCM_INFO_BATCH),
88 .formats = DAVINCI_PCM_FMTBITS,
89 .rates = SNDRV_PCM_RATE_8000_192000 | SNDRV_PCM_RATE_KNOT,
90 .rate_min = 8000,
91 .rate_max = 192000,
92 .channels_min = 2,
93 .channels_max = 384,
94 .buffer_bytes_max = 128 * 1024,
95 .period_bytes_min = 32,
96 .period_bytes_max = 8 * 1024,
97 .periods_min = 16,
98 .periods_max = 255,
99 .fifo_size = 0,
100};
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138struct davinci_runtime_data {
139 spinlock_t lock;
140 int period;
141 int asp_channel;
142 int asp_link[2];
143 struct davinci_pcm_dma_params *params;
144 int ram_channel;
145 int ram_link;
146 int ram_link2;
147 struct edmacc_param asp_params;
148 struct edmacc_param ram_params;
149};
150
151static void davinci_pcm_period_elapsed(struct snd_pcm_substream *substream)
152{
153 struct davinci_runtime_data *prtd = substream->runtime->private_data;
154 struct snd_pcm_runtime *runtime = substream->runtime;
155
156 prtd->period++;
157 if (unlikely(prtd->period >= runtime->periods))
158 prtd->period = 0;
159}
160
161static void davinci_pcm_period_reset(struct snd_pcm_substream *substream)
162{
163 struct davinci_runtime_data *prtd = substream->runtime->private_data;
164
165 prtd->period = 0;
166}
167
168
169
170static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream)
171{
172 struct davinci_runtime_data *prtd = substream->runtime->private_data;
173 struct snd_pcm_runtime *runtime = substream->runtime;
174 unsigned int period_size;
175 unsigned int dma_offset;
176 dma_addr_t dma_pos;
177 dma_addr_t src, dst;
178 unsigned short src_bidx, dst_bidx;
179 unsigned short src_cidx, dst_cidx;
180 unsigned int data_type;
181 unsigned short acnt;
182 unsigned int count;
183 unsigned int fifo_level;
184
185 period_size = snd_pcm_lib_period_bytes(substream);
186 dma_offset = prtd->period * period_size;
187 dma_pos = runtime->dma_addr + dma_offset;
188 fifo_level = prtd->params->fifo_level;
189
190 pr_debug("davinci_pcm: audio_set_dma_params_play channel = %d "
191 "dma_ptr = %x period_size=%x\n", prtd->asp_link[0], dma_pos,
192 period_size);
193
194 data_type = prtd->params->data_type;
195 count = period_size / data_type;
196 if (fifo_level)
197 count /= fifo_level;
198
199 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
200 src = dma_pos;
201 dst = prtd->params->dma_addr;
202 src_bidx = data_type;
203 dst_bidx = 0;
204 src_cidx = data_type * fifo_level;
205 dst_cidx = 0;
206 } else {
207 src = prtd->params->dma_addr;
208 dst = dma_pos;
209 src_bidx = 0;
210 dst_bidx = data_type;
211 src_cidx = 0;
212 dst_cidx = data_type * fifo_level;
213 }
214
215 acnt = prtd->params->acnt;
216 edma_set_src(prtd->asp_link[0], src, INCR, W8BIT);
217 edma_set_dest(prtd->asp_link[0], dst, INCR, W8BIT);
218
219 edma_set_src_index(prtd->asp_link[0], src_bidx, src_cidx);
220 edma_set_dest_index(prtd->asp_link[0], dst_bidx, dst_cidx);
221
222 if (!fifo_level)
223 edma_set_transfer_params(prtd->asp_link[0], acnt, count, 1, 0,
224 ASYNC);
225 else
226 edma_set_transfer_params(prtd->asp_link[0], acnt, fifo_level,
227 count, fifo_level,
228 ABSYNC);
229}
230
231static void davinci_pcm_dma_irq(unsigned link, u16 ch_status, void *data)
232{
233 struct snd_pcm_substream *substream = data;
234 struct davinci_runtime_data *prtd = substream->runtime->private_data;
235
236 print_buf_info(prtd->ram_channel, "i ram_channel");
237 pr_debug("davinci_pcm: link=%d, status=0x%x\n", link, ch_status);
238
239 if (unlikely(ch_status != DMA_COMPLETE))
240 return;
241
242 if (snd_pcm_running(substream)) {
243 spin_lock(&prtd->lock);
244 if (prtd->ram_channel < 0) {
245
246 davinci_pcm_enqueue_dma(substream);
247 }
248 davinci_pcm_period_elapsed(substream);
249 spin_unlock(&prtd->lock);
250 snd_pcm_period_elapsed(substream);
251 }
252}
253
254#ifdef CONFIG_GENERIC_ALLOCATOR
255static int allocate_sram(struct snd_pcm_substream *substream,
256 struct gen_pool *sram_pool, unsigned size,
257 struct snd_pcm_hardware *ppcm)
258{
259 struct snd_dma_buffer *buf = &substream->dma_buffer;
260 struct snd_dma_buffer *iram_dma = NULL;
261 dma_addr_t iram_phys = 0;
262 void *iram_virt = NULL;
263
264 if (buf->private_data || !size)
265 return 0;
266
267 ppcm->period_bytes_max = size;
268 iram_virt = (void *)gen_pool_alloc(sram_pool, size);
269 if (!iram_virt)
270 goto exit1;
271 iram_phys = gen_pool_virt_to_phys(sram_pool, (unsigned)iram_virt);
272 iram_dma = kzalloc(sizeof(*iram_dma), GFP_KERNEL);
273 if (!iram_dma)
274 goto exit2;
275 iram_dma->area = iram_virt;
276 iram_dma->addr = iram_phys;
277 memset(iram_dma->area, 0, size);
278 iram_dma->bytes = size;
279 buf->private_data = iram_dma;
280 return 0;
281exit2:
282 if (iram_virt)
283 gen_pool_free(sram_pool, (unsigned)iram_virt, size);
284exit1:
285 return -ENOMEM;
286}
287
288static void davinci_free_sram(struct snd_pcm_substream *substream,
289 struct snd_dma_buffer *iram_dma)
290{
291 struct davinci_runtime_data *prtd = substream->runtime->private_data;
292 struct gen_pool *sram_pool = prtd->params->sram_pool;
293
294 gen_pool_free(sram_pool, (unsigned) iram_dma->area, iram_dma->bytes);
295}
296#else
297static int allocate_sram(struct snd_pcm_substream *substream,
298 struct gen_pool *sram_pool, unsigned size,
299 struct snd_pcm_hardware *ppcm)
300{
301 return 0;
302}
303
304static void davinci_free_sram(struct snd_pcm_substream *substream,
305 struct snd_dma_buffer *iram_dma)
306{
307}
308#endif
309
310
311
312
313
314static int ping_pong_dma_setup(struct snd_pcm_substream *substream)
315{
316 unsigned short ram_src_cidx, ram_dst_cidx;
317 struct snd_pcm_runtime *runtime = substream->runtime;
318 struct davinci_runtime_data *prtd = runtime->private_data;
319 struct snd_dma_buffer *iram_dma =
320 (struct snd_dma_buffer *)substream->dma_buffer.private_data;
321 struct davinci_pcm_dma_params *params = prtd->params;
322 unsigned int data_type = params->data_type;
323 unsigned int acnt = params->acnt;
324
325 unsigned int ping_size = snd_pcm_lib_period_bytes(substream) >> 1;
326 unsigned int fifo_level = prtd->params->fifo_level;
327 unsigned int count;
328 if ((data_type == 0) || (data_type > 4)) {
329 printk(KERN_ERR "%s: data_type=%i\n", __func__, data_type);
330 return -EINVAL;
331 }
332 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
333 dma_addr_t asp_src_pong = iram_dma->addr + ping_size;
334 ram_src_cidx = ping_size;
335 ram_dst_cidx = -ping_size;
336 edma_set_src(prtd->asp_link[1], asp_src_pong, INCR, W8BIT);
337
338 edma_set_src_index(prtd->asp_link[0], data_type,
339 data_type * fifo_level);
340 edma_set_src_index(prtd->asp_link[1], data_type,
341 data_type * fifo_level);
342
343 edma_set_src(prtd->ram_link, runtime->dma_addr, INCR, W32BIT);
344 } else {
345 dma_addr_t asp_dst_pong = iram_dma->addr + ping_size;
346 ram_src_cidx = -ping_size;
347 ram_dst_cidx = ping_size;
348 edma_set_dest(prtd->asp_link[1], asp_dst_pong, INCR, W8BIT);
349
350 edma_set_dest_index(prtd->asp_link[0], data_type,
351 data_type * fifo_level);
352 edma_set_dest_index(prtd->asp_link[1], data_type,
353 data_type * fifo_level);
354
355 edma_set_dest(prtd->ram_link, runtime->dma_addr, INCR, W32BIT);
356 }
357
358 if (!fifo_level) {
359 count = ping_size / data_type;
360 edma_set_transfer_params(prtd->asp_link[0], acnt, count,
361 1, 0, ASYNC);
362 edma_set_transfer_params(prtd->asp_link[1], acnt, count,
363 1, 0, ASYNC);
364 } else {
365 count = ping_size / (data_type * fifo_level);
366 edma_set_transfer_params(prtd->asp_link[0], acnt, fifo_level,
367 count, fifo_level, ABSYNC);
368 edma_set_transfer_params(prtd->asp_link[1], acnt, fifo_level,
369 count, fifo_level, ABSYNC);
370 }
371
372 edma_set_src_index(prtd->ram_link, ping_size, ram_src_cidx);
373 edma_set_dest_index(prtd->ram_link, ping_size, ram_dst_cidx);
374 edma_set_transfer_params(prtd->ram_link, ping_size, 2,
375 runtime->periods, 2, ASYNC);
376
377
378 edma_read_slot(prtd->asp_link[0], &prtd->asp_params);
379 edma_read_slot(prtd->ram_link, &prtd->ram_params);
380 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
381 struct edmacc_param p_ram;
382
383 prtd->ram_params.a_b_cnt = (1 << 16) | (ping_size << 1);
384
385 prtd->ram_params.src_dst_bidx = (ping_size << 1);
386
387 prtd->ram_params.src_dst_cidx = (ping_size << 1);
388 prtd->ram_params.ccnt = 1;
389
390
391 edma_read_slot(prtd->ram_link, &p_ram);
392 p_ram.src += (ping_size << 1);
393 p_ram.ccnt -= 1;
394 edma_write_slot(prtd->ram_link2, &p_ram);
395
396
397
398
399
400 prtd->ram_params.link_bcntrld =
401 EDMA_CHAN_SLOT(prtd->ram_link2) << 5;
402 }
403 return 0;
404}
405
406
407
408
409
410
411
412
413
414
415
416
417static int request_ping_pong(struct snd_pcm_substream *substream,
418 struct davinci_runtime_data *prtd,
419 struct snd_dma_buffer *iram_dma)
420{
421 dma_addr_t asp_src_ping;
422 dma_addr_t asp_dst_ping;
423 int ret;
424 struct davinci_pcm_dma_params *params = prtd->params;
425
426
427 ret = prtd->ram_channel = edma_alloc_channel(EDMA_CHANNEL_ANY,
428 davinci_pcm_dma_irq, substream,
429 prtd->params->ram_chan_q);
430 if (ret < 0)
431 goto exit1;
432
433
434 ret = prtd->ram_link = edma_alloc_slot(
435 EDMA_CTLR(prtd->ram_channel), EDMA_SLOT_ANY);
436 if (ret < 0)
437 goto exit2;
438
439 ret = prtd->asp_link[1] = edma_alloc_slot(
440 EDMA_CTLR(prtd->asp_channel), EDMA_SLOT_ANY);
441 if (ret < 0)
442 goto exit3;
443
444 prtd->ram_link2 = -1;
445 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
446 ret = prtd->ram_link2 = edma_alloc_slot(
447 EDMA_CTLR(prtd->ram_channel), EDMA_SLOT_ANY);
448 if (ret < 0)
449 goto exit4;
450 }
451
452 edma_link(prtd->asp_link[0], prtd->asp_link[1]);
453 edma_link(prtd->asp_link[1], prtd->asp_link[0]);
454
455 edma_link(prtd->ram_link, prtd->ram_link);
456
457 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
458 asp_src_ping = iram_dma->addr;
459 asp_dst_ping = params->dma_addr;
460 } else {
461 asp_src_ping = params->dma_addr;
462 asp_dst_ping = iram_dma->addr;
463 }
464
465 edma_set_src(prtd->asp_link[0], asp_src_ping, INCR, W16BIT);
466 edma_set_dest(prtd->asp_link[0], asp_dst_ping, INCR, W16BIT);
467 edma_set_src_index(prtd->asp_link[0], 0, 0);
468 edma_set_dest_index(prtd->asp_link[0], 0, 0);
469
470 edma_read_slot(prtd->asp_link[0], &prtd->asp_params);
471 prtd->asp_params.opt &= ~(TCCMODE | EDMA_TCC(0x3f) | TCINTEN);
472 prtd->asp_params.opt |= TCCHEN |
473 EDMA_TCC(prtd->ram_channel & 0x3f);
474 edma_write_slot(prtd->asp_link[0], &prtd->asp_params);
475
476
477 edma_set_src(prtd->asp_link[1], asp_src_ping, INCR, W16BIT);
478 edma_set_dest(prtd->asp_link[1], asp_dst_ping, INCR, W16BIT);
479 edma_set_src_index(prtd->asp_link[1], 0, 0);
480 edma_set_dest_index(prtd->asp_link[1], 0, 0);
481
482 edma_read_slot(prtd->asp_link[1], &prtd->asp_params);
483 prtd->asp_params.opt &= ~(TCCMODE | EDMA_TCC(0x3f));
484
485 prtd->asp_params.opt |= TCINTEN | TCCHEN |
486 EDMA_TCC(prtd->ram_channel & 0x3f);
487 edma_write_slot(prtd->asp_link[1], &prtd->asp_params);
488
489
490 edma_set_src(prtd->ram_link, iram_dma->addr, INCR, W32BIT);
491 edma_set_dest(prtd->ram_link, iram_dma->addr, INCR, W32BIT);
492 pr_debug("%s: audio dma channels/slots in use for ram:%u %u %u,"
493 "for asp:%u %u %u\n", __func__,
494 prtd->ram_channel, prtd->ram_link, prtd->ram_link2,
495 prtd->asp_channel, prtd->asp_link[0],
496 prtd->asp_link[1]);
497 return 0;
498exit4:
499 edma_free_channel(prtd->asp_link[1]);
500 prtd->asp_link[1] = -1;
501exit3:
502 edma_free_channel(prtd->ram_link);
503 prtd->ram_link = -1;
504exit2:
505 edma_free_channel(prtd->ram_channel);
506 prtd->ram_channel = -1;
507exit1:
508 return ret;
509}
510
511static int davinci_pcm_dma_request(struct snd_pcm_substream *substream)
512{
513 struct snd_dma_buffer *iram_dma;
514 struct davinci_runtime_data *prtd = substream->runtime->private_data;
515 struct davinci_pcm_dma_params *params = prtd->params;
516 int ret;
517
518 if (!params)
519 return -ENODEV;
520
521
522 ret = prtd->asp_channel = edma_alloc_channel(params->channel,
523 davinci_pcm_dma_irq, substream,
524 prtd->params->asp_chan_q);
525 if (ret < 0)
526 goto exit1;
527
528
529 ret = prtd->asp_link[0] = edma_alloc_slot(
530 EDMA_CTLR(prtd->asp_channel), EDMA_SLOT_ANY);
531 if (ret < 0)
532 goto exit2;
533
534 iram_dma = (struct snd_dma_buffer *)substream->dma_buffer.private_data;
535 if (iram_dma) {
536 if (request_ping_pong(substream, prtd, iram_dma) == 0)
537 return 0;
538 printk(KERN_WARNING "%s: dma channel allocation failed,"
539 "not using sram\n", __func__);
540 }
541
542
543
544
545
546
547
548
549
550
551 edma_read_slot(prtd->asp_link[0], &prtd->asp_params);
552 prtd->asp_params.opt |= TCINTEN |
553 EDMA_TCC(EDMA_CHAN_SLOT(prtd->asp_channel));
554 prtd->asp_params.link_bcntrld = EDMA_CHAN_SLOT(prtd->asp_link[0]) << 5;
555 edma_write_slot(prtd->asp_link[0], &prtd->asp_params);
556 return 0;
557exit2:
558 edma_free_channel(prtd->asp_channel);
559 prtd->asp_channel = -1;
560exit1:
561 return ret;
562}
563
564static int davinci_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
565{
566 struct davinci_runtime_data *prtd = substream->runtime->private_data;
567 int ret = 0;
568
569 spin_lock(&prtd->lock);
570
571 switch (cmd) {
572 case SNDRV_PCM_TRIGGER_START:
573 edma_start(prtd->asp_channel);
574 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
575 prtd->ram_channel >= 0) {
576
577 edma_start(prtd->ram_channel);
578 }
579 break;
580 case SNDRV_PCM_TRIGGER_RESUME:
581 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
582 edma_resume(prtd->asp_channel);
583 break;
584 case SNDRV_PCM_TRIGGER_STOP:
585 case SNDRV_PCM_TRIGGER_SUSPEND:
586 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
587 edma_pause(prtd->asp_channel);
588 break;
589 default:
590 ret = -EINVAL;
591 break;
592 }
593
594 spin_unlock(&prtd->lock);
595
596 return ret;
597}
598
599static int davinci_pcm_prepare(struct snd_pcm_substream *substream)
600{
601 struct davinci_runtime_data *prtd = substream->runtime->private_data;
602
603 davinci_pcm_period_reset(substream);
604 if (prtd->ram_channel >= 0) {
605 int ret = ping_pong_dma_setup(substream);
606 if (ret < 0)
607 return ret;
608
609 edma_write_slot(prtd->ram_channel, &prtd->ram_params);
610 edma_write_slot(prtd->asp_channel, &prtd->asp_params);
611
612 print_buf_info(prtd->ram_channel, "ram_channel");
613 print_buf_info(prtd->ram_link, "ram_link");
614 print_buf_info(prtd->ram_link2, "ram_link2");
615 print_buf_info(prtd->asp_channel, "asp_channel");
616 print_buf_info(prtd->asp_link[0], "asp_link[0]");
617 print_buf_info(prtd->asp_link[1], "asp_link[1]");
618
619
620
621
622
623
624
625
626
627
628
629
630
631 davinci_pcm_period_elapsed(substream);
632 davinci_pcm_period_elapsed(substream);
633
634 return 0;
635 }
636 davinci_pcm_enqueue_dma(substream);
637 davinci_pcm_period_elapsed(substream);
638
639
640 edma_read_slot(prtd->asp_link[0], &prtd->asp_params);
641 edma_write_slot(prtd->asp_channel, &prtd->asp_params);
642 davinci_pcm_enqueue_dma(substream);
643 davinci_pcm_period_elapsed(substream);
644
645 return 0;
646}
647
648static snd_pcm_uframes_t
649davinci_pcm_pointer(struct snd_pcm_substream *substream)
650{
651 struct snd_pcm_runtime *runtime = substream->runtime;
652 struct davinci_runtime_data *prtd = runtime->private_data;
653 unsigned int offset;
654 int asp_count;
655 unsigned int period_size = snd_pcm_lib_period_bytes(substream);
656
657
658
659
660
661
662
663
664 spin_lock(&prtd->lock);
665 asp_count = prtd->period - 2;
666 spin_unlock(&prtd->lock);
667
668 if (asp_count < 0)
669 asp_count += runtime->periods;
670 asp_count *= period_size;
671
672 offset = bytes_to_frames(runtime, asp_count);
673 if (offset >= runtime->buffer_size)
674 offset = 0;
675
676 return offset;
677}
678
679static int davinci_pcm_open(struct snd_pcm_substream *substream)
680{
681 struct snd_pcm_runtime *runtime = substream->runtime;
682 struct davinci_runtime_data *prtd;
683 struct snd_pcm_hardware *ppcm;
684 int ret = 0;
685 struct snd_soc_pcm_runtime *rtd = substream->private_data;
686 struct davinci_pcm_dma_params *pa;
687 struct davinci_pcm_dma_params *params;
688
689 pa = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
690 if (!pa)
691 return -ENODEV;
692 params = &pa[substream->stream];
693
694 ppcm = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
695 &pcm_hardware_playback : &pcm_hardware_capture;
696 allocate_sram(substream, params->sram_pool, params->sram_size, ppcm);
697 snd_soc_set_runtime_hwparams(substream, ppcm);
698
699 ret = snd_pcm_hw_constraint_integer(runtime,
700 SNDRV_PCM_HW_PARAM_PERIODS);
701 if (ret < 0)
702 return ret;
703
704 prtd = kzalloc(sizeof(struct davinci_runtime_data), GFP_KERNEL);
705 if (prtd == NULL)
706 return -ENOMEM;
707
708 spin_lock_init(&prtd->lock);
709 prtd->params = params;
710 prtd->asp_channel = -1;
711 prtd->asp_link[0] = prtd->asp_link[1] = -1;
712 prtd->ram_channel = -1;
713 prtd->ram_link = -1;
714 prtd->ram_link2 = -1;
715
716 runtime->private_data = prtd;
717
718 ret = davinci_pcm_dma_request(substream);
719 if (ret) {
720 printk(KERN_ERR "davinci_pcm: Failed to get dma channels\n");
721 kfree(prtd);
722 }
723
724 return ret;
725}
726
727static int davinci_pcm_close(struct snd_pcm_substream *substream)
728{
729 struct snd_pcm_runtime *runtime = substream->runtime;
730 struct davinci_runtime_data *prtd = runtime->private_data;
731
732 if (prtd->ram_channel >= 0)
733 edma_stop(prtd->ram_channel);
734 if (prtd->asp_channel >= 0)
735 edma_stop(prtd->asp_channel);
736 if (prtd->asp_link[0] >= 0)
737 edma_unlink(prtd->asp_link[0]);
738 if (prtd->asp_link[1] >= 0)
739 edma_unlink(prtd->asp_link[1]);
740 if (prtd->ram_link >= 0)
741 edma_unlink(prtd->ram_link);
742
743 if (prtd->asp_link[0] >= 0)
744 edma_free_slot(prtd->asp_link[0]);
745 if (prtd->asp_link[1] >= 0)
746 edma_free_slot(prtd->asp_link[1]);
747 if (prtd->asp_channel >= 0)
748 edma_free_channel(prtd->asp_channel);
749 if (prtd->ram_link >= 0)
750 edma_free_slot(prtd->ram_link);
751 if (prtd->ram_link2 >= 0)
752 edma_free_slot(prtd->ram_link2);
753 if (prtd->ram_channel >= 0)
754 edma_free_channel(prtd->ram_channel);
755
756 kfree(prtd);
757
758 return 0;
759}
760
761static int davinci_pcm_hw_params(struct snd_pcm_substream *substream,
762 struct snd_pcm_hw_params *hw_params)
763{
764 return snd_pcm_lib_malloc_pages(substream,
765 params_buffer_bytes(hw_params));
766}
767
768static int davinci_pcm_hw_free(struct snd_pcm_substream *substream)
769{
770 return snd_pcm_lib_free_pages(substream);
771}
772
773static int davinci_pcm_mmap(struct snd_pcm_substream *substream,
774 struct vm_area_struct *vma)
775{
776 struct snd_pcm_runtime *runtime = substream->runtime;
777
778 return dma_mmap_writecombine(substream->pcm->card->dev, vma,
779 runtime->dma_area,
780 runtime->dma_addr,
781 runtime->dma_bytes);
782}
783
784static struct snd_pcm_ops davinci_pcm_ops = {
785 .open = davinci_pcm_open,
786 .close = davinci_pcm_close,
787 .ioctl = snd_pcm_lib_ioctl,
788 .hw_params = davinci_pcm_hw_params,
789 .hw_free = davinci_pcm_hw_free,
790 .prepare = davinci_pcm_prepare,
791 .trigger = davinci_pcm_trigger,
792 .pointer = davinci_pcm_pointer,
793 .mmap = davinci_pcm_mmap,
794};
795
796static int davinci_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream,
797 size_t size)
798{
799 struct snd_pcm_substream *substream = pcm->streams[stream].substream;
800 struct snd_dma_buffer *buf = &substream->dma_buffer;
801
802 buf->dev.type = SNDRV_DMA_TYPE_DEV;
803 buf->dev.dev = pcm->card->dev;
804 buf->private_data = NULL;
805 buf->area = dma_alloc_writecombine(pcm->card->dev, size,
806 &buf->addr, GFP_KERNEL);
807
808 pr_debug("davinci_pcm: preallocate_dma_buffer: area=%p, addr=%p, "
809 "size=%d\n", (void *) buf->area, (void *) buf->addr, size);
810
811 if (!buf->area)
812 return -ENOMEM;
813
814 buf->bytes = size;
815 return 0;
816}
817
818static void davinci_pcm_free(struct snd_pcm *pcm)
819{
820 struct snd_pcm_substream *substream;
821 struct snd_dma_buffer *buf;
822 int stream;
823
824 for (stream = 0; stream < 2; stream++) {
825 struct snd_dma_buffer *iram_dma;
826 substream = pcm->streams[stream].substream;
827 if (!substream)
828 continue;
829
830 buf = &substream->dma_buffer;
831 if (!buf->area)
832 continue;
833
834 dma_free_writecombine(pcm->card->dev, buf->bytes,
835 buf->area, buf->addr);
836 buf->area = NULL;
837 iram_dma = buf->private_data;
838 if (iram_dma) {
839 davinci_free_sram(substream, iram_dma);
840 kfree(iram_dma);
841 }
842 }
843}
844
845static u64 davinci_pcm_dmamask = DMA_BIT_MASK(32);
846
847static int davinci_pcm_new(struct snd_soc_pcm_runtime *rtd)
848{
849 struct snd_card *card = rtd->card->snd_card;
850 struct snd_pcm *pcm = rtd->pcm;
851 int ret;
852
853 if (!card->dev->dma_mask)
854 card->dev->dma_mask = &davinci_pcm_dmamask;
855 if (!card->dev->coherent_dma_mask)
856 card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
857
858 if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
859 ret = davinci_pcm_preallocate_dma_buffer(pcm,
860 SNDRV_PCM_STREAM_PLAYBACK,
861 pcm_hardware_playback.buffer_bytes_max);
862 if (ret)
863 return ret;
864 }
865
866 if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
867 ret = davinci_pcm_preallocate_dma_buffer(pcm,
868 SNDRV_PCM_STREAM_CAPTURE,
869 pcm_hardware_capture.buffer_bytes_max);
870 if (ret)
871 return ret;
872 }
873
874 return 0;
875}
876
877static struct snd_soc_platform_driver davinci_soc_platform = {
878 .ops = &davinci_pcm_ops,
879 .pcm_new = davinci_pcm_new,
880 .pcm_free = davinci_pcm_free,
881};
882
883int davinci_soc_platform_register(struct device *dev)
884{
885 return snd_soc_register_platform(dev, &davinci_soc_platform);
886}
887EXPORT_SYMBOL_GPL(davinci_soc_platform_register);
888
889void davinci_soc_platform_unregister(struct device *dev)
890{
891 snd_soc_unregister_platform(dev);
892}
893EXPORT_SYMBOL_GPL(davinci_soc_platform_unregister);
894
895MODULE_AUTHOR("Vladimir Barinov");
896MODULE_DESCRIPTION("TI DAVINCI PCM DMA module");
897MODULE_LICENSE("GPL");
898