~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/soc/davinci/davinci-pcm.c

Version: ~ [ linux-5.10-rc1 ] ~ [ linux-5.9.1 ] ~ [ linux-5.8.16 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.72 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.152 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.202 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.240 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.240 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.85 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 
 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
 31 static 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
 43 static 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 
 64 static 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 
 83 static 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  * How ping/pong works....
104  *
105  * Playback:
106  * ram_params - copys 2*ping_size from start of SDRAM to iram,
107  *      links to ram_link2
108  * ram_link2 - copys rest of SDRAM to iram in ping_size units,
109  *      links to ram_link
110  * ram_link - copys entire SDRAM to iram in ping_size uints,
111  *      links to self
112  *
113  * asp_params - same as asp_link[0]
114  * asp_link[0] - copys from lower half of iram to asp port
115  *      links to asp_link[1], triggers iram copy event on completion
116  * asp_link[1] - copys from upper half of iram to asp port
117  *      links to asp_link[0], triggers iram copy event on completion
118  *      triggers interrupt only needed to let upper SOC levels update position
119  *      in stream on completion
120  *
121  * When playback is started:
122  *      ram_params started
123  *      asp_params started
124  *
125  * Capture:
126  * ram_params - same as ram_link,
127  *      links to ram_link
128  * ram_link - same as playback
129  *      links to self
130  *
131  * asp_params - same as playback
132  * asp_link[0] - same as playback
133  * asp_link[1] - same as playback
134  *
135  * When capture is started:
136  *      asp_params started
137  */
138 struct davinci_runtime_data {
139         spinlock_t lock;
140         int period;             /* current DMA period */
141         int asp_channel;        /* Master DMA channel */
142         int asp_link[2];        /* asp parameter link channel, ping/pong */
143         struct davinci_pcm_dma_params *params;  /* DMA 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 
151 static 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 
161 static 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  * Not used with ping/pong
169  */
170 static 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 = 4;
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,
227                                                 fifo_level,
228                                                 count, fifo_level,
229                                                 ABSYNC);
230 }
231 
232 static void davinci_pcm_dma_irq(unsigned link, u16 ch_status, void *data)
233 {
234         struct snd_pcm_substream *substream = data;
235         struct davinci_runtime_data *prtd = substream->runtime->private_data;
236 
237         print_buf_info(prtd->ram_channel, "i ram_channel");
238         pr_debug("davinci_pcm: link=%d, status=0x%x\n", link, ch_status);
239 
240         if (unlikely(ch_status != DMA_COMPLETE))
241                 return;
242 
243         if (snd_pcm_running(substream)) {
244                 spin_lock(&prtd->lock);
245                 if (prtd->ram_channel < 0) {
246                         /* No ping/pong must fix up link dma data*/
247                         davinci_pcm_enqueue_dma(substream);
248                 }
249                 davinci_pcm_period_elapsed(substream);
250                 spin_unlock(&prtd->lock);
251                 snd_pcm_period_elapsed(substream);
252         }
253 }
254 
255 #ifdef CONFIG_GENERIC_ALLOCATOR
256 static int allocate_sram(struct snd_pcm_substream *substream,
257                 struct gen_pool *sram_pool, unsigned size,
258                 struct snd_pcm_hardware *ppcm)
259 {
260         struct snd_dma_buffer *buf = &substream->dma_buffer;
261         struct snd_dma_buffer *iram_dma = NULL;
262         dma_addr_t iram_phys = 0;
263         void *iram_virt = NULL;
264 
265         if (buf->private_data || !size)
266                 return 0;
267 
268         ppcm->period_bytes_max = size;
269         iram_virt = (void *)gen_pool_alloc(sram_pool, size);
270         if (!iram_virt)
271                 goto exit1;
272         iram_phys = gen_pool_virt_to_phys(sram_pool, (unsigned)iram_virt);
273         iram_dma = kzalloc(sizeof(*iram_dma), GFP_KERNEL);
274         if (!iram_dma)
275                 goto exit2;
276         iram_dma->area = iram_virt;
277         iram_dma->addr = iram_phys;
278         memset(iram_dma->area, 0, size);
279         iram_dma->bytes = size;
280         buf->private_data = iram_dma;
281         return 0;
282 exit2:
283         if (iram_virt)
284                 gen_pool_free(sram_pool, (unsigned)iram_virt, size);
285 exit1:
286         return -ENOMEM;
287 }
288 
289 static void davinci_free_sram(struct snd_pcm_substream *substream,
290                               struct snd_dma_buffer *iram_dma)
291 {
292         struct davinci_runtime_data *prtd = substream->runtime->private_data;
293         struct gen_pool *sram_pool = prtd->params->sram_pool;
294 
295         gen_pool_free(sram_pool, (unsigned) iram_dma->area, iram_dma->bytes);
296 }
297 #else
298 static int allocate_sram(struct snd_pcm_substream *substream,
299                 struct gen_pool *sram_pool, unsigned size,
300                 struct snd_pcm_hardware *ppcm)
301 {
302         return 0;
303 }
304 
305 static void davinci_free_sram(struct snd_pcm_substream *substream,
306                               struct snd_dma_buffer *iram_dma)
307 {
308 }
309 #endif
310 
311 /*
312  * Only used with ping/pong.
313  * This is called after runtime->dma_addr, period_bytes and data_type are valid
314  */
315 static int ping_pong_dma_setup(struct snd_pcm_substream *substream)
316 {
317         unsigned short ram_src_cidx, ram_dst_cidx;
318         struct snd_pcm_runtime *runtime = substream->runtime;
319         struct davinci_runtime_data *prtd = runtime->private_data;
320         struct snd_dma_buffer *iram_dma =
321                 (struct snd_dma_buffer *)substream->dma_buffer.private_data;
322         struct davinci_pcm_dma_params *params = prtd->params;
323         unsigned int data_type = params->data_type;
324         unsigned int acnt = params->acnt;
325         /* divide by 2 for ping/pong */
326         unsigned int ping_size = snd_pcm_lib_period_bytes(substream) >> 1;
327         unsigned int fifo_level = prtd->params->fifo_level;
328         unsigned int count;
329         if ((data_type == 0) || (data_type > 4)) {
330                 printk(KERN_ERR "%s: data_type=%i\n", __func__, data_type);
331                 return -EINVAL;
332         }
333         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
334                 dma_addr_t asp_src_pong = iram_dma->addr + ping_size;
335                 ram_src_cidx = ping_size;
336                 ram_dst_cidx = -ping_size;
337                 edma_set_src(prtd->asp_link[1], asp_src_pong, INCR, W8BIT);
338 
339                 edma_set_src_index(prtd->asp_link[0], data_type,
340                                 data_type * fifo_level);
341                 edma_set_src_index(prtd->asp_link[1], data_type,
342                                 data_type * fifo_level);
343 
344                 edma_set_src(prtd->ram_link, runtime->dma_addr, INCR, W32BIT);
345         } else {
346                 dma_addr_t asp_dst_pong = iram_dma->addr + ping_size;
347                 ram_src_cidx = -ping_size;
348                 ram_dst_cidx = ping_size;
349                 edma_set_dest(prtd->asp_link[1], asp_dst_pong, INCR, W8BIT);
350 
351                 edma_set_dest_index(prtd->asp_link[0], data_type,
352                                 data_type * fifo_level);
353                 edma_set_dest_index(prtd->asp_link[1], data_type,
354                                 data_type * fifo_level);
355 
356                 edma_set_dest(prtd->ram_link, runtime->dma_addr, INCR, W32BIT);
357         }
358 
359         if (!fifo_level) {
360                 count = ping_size / data_type;
361                 edma_set_transfer_params(prtd->asp_link[0], acnt, count,
362                                 1, 0, ASYNC);
363                 edma_set_transfer_params(prtd->asp_link[1], acnt, count,
364                                 1, 0, ASYNC);
365         } else {
366                 count = ping_size / (data_type * fifo_level);
367                 edma_set_transfer_params(prtd->asp_link[0], acnt, fifo_level,
368                                 count, fifo_level, ABSYNC);
369                 edma_set_transfer_params(prtd->asp_link[1], acnt, fifo_level,
370                                 count, fifo_level, ABSYNC);
371         }
372 
373         edma_set_src_index(prtd->ram_link, ping_size, ram_src_cidx);
374         edma_set_dest_index(prtd->ram_link, ping_size, ram_dst_cidx);
375         edma_set_transfer_params(prtd->ram_link, ping_size, 2,
376                         runtime->periods, 2, ASYNC);
377 
378         /* init master params */
379         edma_read_slot(prtd->asp_link[0], &prtd->asp_params);
380         edma_read_slot(prtd->ram_link, &prtd->ram_params);
381         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
382                 struct edmacc_param p_ram;
383                 /* Copy entire iram buffer before playback started */
384                 prtd->ram_params.a_b_cnt = (1 << 16) | (ping_size << 1);
385                 /* 0 dst_bidx */
386                 prtd->ram_params.src_dst_bidx = (ping_size << 1);
387                 /* 0 dst_cidx */
388                 prtd->ram_params.src_dst_cidx = (ping_size << 1);
389                 prtd->ram_params.ccnt = 1;
390 
391                 /* Skip 1st period */
392                 edma_read_slot(prtd->ram_link, &p_ram);
393                 p_ram.src += (ping_size << 1);
394                 p_ram.ccnt -= 1;
395                 edma_write_slot(prtd->ram_link2, &p_ram);
396                 /*
397                  * When 1st started, ram -> iram dma channel will fill the
398                  * entire iram.  Then, whenever a ping/pong asp buffer finishes,
399                  * 1/2 iram will be filled.
400                  */
401                 prtd->ram_params.link_bcntrld =
402                         EDMA_CHAN_SLOT(prtd->ram_link2) << 5;
403         }
404         return 0;
405 }
406 
407 /* 1 asp tx or rx channel using 2 parameter channels
408  * 1 ram to/from iram channel using 1 parameter channel
409  *
410  * Playback
411  * ram copy channel kicks off first,
412  * 1st ram copy of entire iram buffer completion kicks off asp channel
413  * asp tcc always kicks off ram copy of 1/2 iram buffer
414  *
415  * Record
416  * asp channel starts, tcc kicks off ram copy
417  */
418 static int request_ping_pong(struct snd_pcm_substream *substream,
419                 struct davinci_runtime_data *prtd,
420                 struct snd_dma_buffer *iram_dma)
421 {
422         dma_addr_t asp_src_ping;
423         dma_addr_t asp_dst_ping;
424         int ret;
425         struct davinci_pcm_dma_params *params = prtd->params;
426 
427         /* Request ram master channel */
428         ret = prtd->ram_channel = edma_alloc_channel(EDMA_CHANNEL_ANY,
429                                   davinci_pcm_dma_irq, substream,
430                                   prtd->params->ram_chan_q);
431         if (ret < 0)
432                 goto exit1;
433 
434         /* Request ram link channel */
435         ret = prtd->ram_link = edma_alloc_slot(
436                         EDMA_CTLR(prtd->ram_channel), EDMA_SLOT_ANY);
437         if (ret < 0)
438                 goto exit2;
439 
440         ret = prtd->asp_link[1] = edma_alloc_slot(
441                         EDMA_CTLR(prtd->asp_channel), EDMA_SLOT_ANY);
442         if (ret < 0)
443                 goto exit3;
444 
445         prtd->ram_link2 = -1;
446         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
447                 ret = prtd->ram_link2 = edma_alloc_slot(
448                         EDMA_CTLR(prtd->ram_channel), EDMA_SLOT_ANY);
449                 if (ret < 0)
450                         goto exit4;
451         }
452         /* circle ping-pong buffers */
453         edma_link(prtd->asp_link[0], prtd->asp_link[1]);
454         edma_link(prtd->asp_link[1], prtd->asp_link[0]);
455         /* circle ram buffers */
456         edma_link(prtd->ram_link, prtd->ram_link);
457 
458         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
459                 asp_src_ping = iram_dma->addr;
460                 asp_dst_ping = params->dma_addr;        /* fifo */
461         } else {
462                 asp_src_ping = params->dma_addr;        /* fifo */
463                 asp_dst_ping = iram_dma->addr;
464         }
465         /* ping */
466         edma_set_src(prtd->asp_link[0], asp_src_ping, INCR, W16BIT);
467         edma_set_dest(prtd->asp_link[0], asp_dst_ping, INCR, W16BIT);
468         edma_set_src_index(prtd->asp_link[0], 0, 0);
469         edma_set_dest_index(prtd->asp_link[0], 0, 0);
470 
471         edma_read_slot(prtd->asp_link[0], &prtd->asp_params);
472         prtd->asp_params.opt &= ~(TCCMODE | EDMA_TCC(0x3f) | TCINTEN);
473         prtd->asp_params.opt |= TCCHEN |
474                 EDMA_TCC(prtd->ram_channel & 0x3f);
475         edma_write_slot(prtd->asp_link[0], &prtd->asp_params);
476 
477         /* pong */
478         edma_set_src(prtd->asp_link[1], asp_src_ping, INCR, W16BIT);
479         edma_set_dest(prtd->asp_link[1], asp_dst_ping, INCR, W16BIT);
480         edma_set_src_index(prtd->asp_link[1], 0, 0);
481         edma_set_dest_index(prtd->asp_link[1], 0, 0);
482 
483         edma_read_slot(prtd->asp_link[1], &prtd->asp_params);
484         prtd->asp_params.opt &= ~(TCCMODE | EDMA_TCC(0x3f));
485         /* interrupt after every pong completion */
486         prtd->asp_params.opt |= TCINTEN | TCCHEN |
487                 EDMA_TCC(prtd->ram_channel & 0x3f);
488         edma_write_slot(prtd->asp_link[1], &prtd->asp_params);
489 
490         /* ram */
491         edma_set_src(prtd->ram_link, iram_dma->addr, INCR, W32BIT);
492         edma_set_dest(prtd->ram_link, iram_dma->addr, INCR, W32BIT);
493         pr_debug("%s: audio dma channels/slots in use for ram:%u %u %u,"
494                 "for asp:%u %u %u\n", __func__,
495                 prtd->ram_channel, prtd->ram_link, prtd->ram_link2,
496                 prtd->asp_channel, prtd->asp_link[0],
497                 prtd->asp_link[1]);
498         return 0;
499 exit4:
500         edma_free_channel(prtd->asp_link[1]);
501         prtd->asp_link[1] = -1;
502 exit3:
503         edma_free_channel(prtd->ram_link);
504         prtd->ram_link = -1;
505 exit2:
506         edma_free_channel(prtd->ram_channel);
507         prtd->ram_channel = -1;
508 exit1:
509         return ret;
510 }
511 
512 static int davinci_pcm_dma_request(struct snd_pcm_substream *substream)
513 {
514         struct snd_dma_buffer *iram_dma;
515         struct davinci_runtime_data *prtd = substream->runtime->private_data;
516         struct davinci_pcm_dma_params *params = prtd->params;
517         int ret;
518 
519         if (!params)
520                 return -ENODEV;
521 
522         /* Request asp master DMA channel */
523         ret = prtd->asp_channel = edma_alloc_channel(params->channel,
524                         davinci_pcm_dma_irq, substream,
525                         prtd->params->asp_chan_q);
526         if (ret < 0)
527                 goto exit1;
528 
529         /* Request asp link channels */
530         ret = prtd->asp_link[0] = edma_alloc_slot(
531                         EDMA_CTLR(prtd->asp_channel), EDMA_SLOT_ANY);
532         if (ret < 0)
533                 goto exit2;
534 
535         iram_dma = (struct snd_dma_buffer *)substream->dma_buffer.private_data;
536         if (iram_dma) {
537                 if (request_ping_pong(substream, prtd, iram_dma) == 0)
538                         return 0;
539                 printk(KERN_WARNING "%s: dma channel allocation failed,"
540                                 "not using sram\n", __func__);
541         }
542 
543         /* Issue transfer completion IRQ when the channel completes a
544          * transfer, then always reload from the same slot (by a kind
545          * of loopback link).  The completion IRQ handler will update
546          * the reload slot with a new buffer.
547          *
548          * REVISIT save p_ram here after setting up everything except
549          * the buffer and its length (ccnt) ... use it as a template
550          * so davinci_pcm_enqueue_dma() takes less time in IRQ.
551          */
552         edma_read_slot(prtd->asp_link[0], &prtd->asp_params);
553         prtd->asp_params.opt |= TCINTEN |
554                 EDMA_TCC(EDMA_CHAN_SLOT(prtd->asp_channel));
555         prtd->asp_params.link_bcntrld = EDMA_CHAN_SLOT(prtd->asp_link[0]) << 5;
556         edma_write_slot(prtd->asp_link[0], &prtd->asp_params);
557         return 0;
558 exit2:
559         edma_free_channel(prtd->asp_channel);
560         prtd->asp_channel = -1;
561 exit1:
562         return ret;
563 }
564 
565 static int davinci_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
566 {
567         struct davinci_runtime_data *prtd = substream->runtime->private_data;
568         int ret = 0;
569 
570         spin_lock(&prtd->lock);
571 
572         switch (cmd) {
573         case SNDRV_PCM_TRIGGER_START:
574                 edma_start(prtd->asp_channel);
575                 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
576                     prtd->ram_channel >= 0) {
577                         /* copy 1st iram buffer */
578                         edma_start(prtd->ram_channel);
579                 }
580                 break;
581         case SNDRV_PCM_TRIGGER_RESUME:
582         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
583                 edma_resume(prtd->asp_channel);
584                 break;
585         case SNDRV_PCM_TRIGGER_STOP:
586         case SNDRV_PCM_TRIGGER_SUSPEND:
587         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
588                 edma_pause(prtd->asp_channel);
589                 break;
590         default:
591                 ret = -EINVAL;
592                 break;
593         }
594 
595         spin_unlock(&prtd->lock);
596 
597         return ret;
598 }
599 
600 static int davinci_pcm_prepare(struct snd_pcm_substream *substream)
601 {
602         struct davinci_runtime_data *prtd = substream->runtime->private_data;
603 
604         davinci_pcm_period_reset(substream);
605         if (prtd->ram_channel >= 0) {
606                 int ret = ping_pong_dma_setup(substream);
607                 if (ret < 0)
608                         return ret;
609 
610                 edma_write_slot(prtd->ram_channel, &prtd->ram_params);
611                 edma_write_slot(prtd->asp_channel, &prtd->asp_params);
612 
613                 print_buf_info(prtd->ram_channel, "ram_channel");
614                 print_buf_info(prtd->ram_link, "ram_link");
615                 print_buf_info(prtd->ram_link2, "ram_link2");
616                 print_buf_info(prtd->asp_channel, "asp_channel");
617                 print_buf_info(prtd->asp_link[0], "asp_link[0]");
618                 print_buf_info(prtd->asp_link[1], "asp_link[1]");
619 
620                 /*
621                  * There is a phase offset of 2 periods between the position
622                  * used by dma setup and the position reported in the pointer
623                  * function.
624                  *
625                  * The phase offset, when not using ping-pong buffers, is due to
626                  * the two consecutive calls to davinci_pcm_enqueue_dma() below.
627                  *
628                  * Whereas here, with ping-pong buffers, the phase is due to
629                  * there being an entire buffer transfer complete before the
630                  * first dma completion event triggers davinci_pcm_dma_irq().
631                  */
632                 davinci_pcm_period_elapsed(substream);
633                 davinci_pcm_period_elapsed(substream);
634 
635                 return 0;
636         }
637         davinci_pcm_enqueue_dma(substream);
638         davinci_pcm_period_elapsed(substream);
639 
640         /* Copy self-linked parameter RAM entry into master channel */
641         edma_read_slot(prtd->asp_link[0], &prtd->asp_params);
642         edma_write_slot(prtd->asp_channel, &prtd->asp_params);
643         davinci_pcm_enqueue_dma(substream);
644         davinci_pcm_period_elapsed(substream);
645 
646         return 0;
647 }
648 
649 static snd_pcm_uframes_t
650 davinci_pcm_pointer(struct snd_pcm_substream *substream)
651 {
652         struct snd_pcm_runtime *runtime = substream->runtime;
653         struct davinci_runtime_data *prtd = runtime->private_data;
654         unsigned int offset;
655         int asp_count;
656         unsigned int period_size = snd_pcm_lib_period_bytes(substream);
657 
658         /*
659          * There is a phase offset of 2 periods between the position used by dma
660          * setup and the position reported in the pointer function. Either +2 in
661          * the dma setup or -2 here in the pointer function (with wrapping,
662          * both) accounts for this offset -- choose the latter since it makes
663          * the first-time setup clearer.
664          */
665         spin_lock(&prtd->lock);
666         asp_count = prtd->period - 2;
667         spin_unlock(&prtd->lock);
668 
669         if (asp_count < 0)
670                 asp_count += runtime->periods;
671         asp_count *= period_size;
672 
673         offset = bytes_to_frames(runtime, asp_count);
674         if (offset >= runtime->buffer_size)
675                 offset = 0;
676 
677         return offset;
678 }
679 
680 static int davinci_pcm_open(struct snd_pcm_substream *substream)
681 {
682         struct snd_pcm_runtime *runtime = substream->runtime;
683         struct davinci_runtime_data *prtd;
684         struct snd_pcm_hardware *ppcm;
685         int ret = 0;
686         struct snd_soc_pcm_runtime *rtd = substream->private_data;
687         struct davinci_pcm_dma_params *pa;
688         struct davinci_pcm_dma_params *params;
689 
690         pa = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
691         if (!pa)
692                 return -ENODEV;
693         params = &pa[substream->stream];
694 
695         ppcm = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
696                         &pcm_hardware_playback : &pcm_hardware_capture;
697         allocate_sram(substream, params->sram_pool, params->sram_size, ppcm);
698         snd_soc_set_runtime_hwparams(substream, ppcm);
699         /* ensure that buffer size is a multiple of period size */
700         ret = snd_pcm_hw_constraint_integer(runtime,
701                                                 SNDRV_PCM_HW_PARAM_PERIODS);
702         if (ret < 0)
703                 return ret;
704 
705         prtd = kzalloc(sizeof(struct davinci_runtime_data), GFP_KERNEL);
706         if (prtd == NULL)
707                 return -ENOMEM;
708 
709         spin_lock_init(&prtd->lock);
710         prtd->params = params;
711         prtd->asp_channel = -1;
712         prtd->asp_link[0] = prtd->asp_link[1] = -1;
713         prtd->ram_channel = -1;
714         prtd->ram_link = -1;
715         prtd->ram_link2 = -1;
716 
717         runtime->private_data = prtd;
718 
719         ret = davinci_pcm_dma_request(substream);
720         if (ret) {
721                 printk(KERN_ERR "davinci_pcm: Failed to get dma channels\n");
722                 kfree(prtd);
723         }
724 
725         return ret;
726 }
727 
728 static int davinci_pcm_close(struct snd_pcm_substream *substream)
729 {
730         struct snd_pcm_runtime *runtime = substream->runtime;
731         struct davinci_runtime_data *prtd = runtime->private_data;
732 
733         if (prtd->ram_channel >= 0)
734                 edma_stop(prtd->ram_channel);
735         if (prtd->asp_channel >= 0)
736                 edma_stop(prtd->asp_channel);
737         if (prtd->asp_link[0] >= 0)
738                 edma_unlink(prtd->asp_link[0]);
739         if (prtd->asp_link[1] >= 0)
740                 edma_unlink(prtd->asp_link[1]);
741         if (prtd->ram_link >= 0)
742                 edma_unlink(prtd->ram_link);
743 
744         if (prtd->asp_link[0] >= 0)
745                 edma_free_slot(prtd->asp_link[0]);
746         if (prtd->asp_link[1] >= 0)
747                 edma_free_slot(prtd->asp_link[1]);
748         if (prtd->asp_channel >= 0)
749                 edma_free_channel(prtd->asp_channel);
750         if (prtd->ram_link >= 0)
751                 edma_free_slot(prtd->ram_link);
752         if (prtd->ram_link2 >= 0)
753                 edma_free_slot(prtd->ram_link2);
754         if (prtd->ram_channel >= 0)
755                 edma_free_channel(prtd->ram_channel);
756 
757         kfree(prtd);
758 
759         return 0;
760 }
761 
762 static int davinci_pcm_hw_params(struct snd_pcm_substream *substream,
763                                  struct snd_pcm_hw_params *hw_params)
764 {
765         return snd_pcm_lib_malloc_pages(substream,
766                                         params_buffer_bytes(hw_params));
767 }
768 
769 static int davinci_pcm_hw_free(struct snd_pcm_substream *substream)
770 {
771         return snd_pcm_lib_free_pages(substream);
772 }
773 
774 static int davinci_pcm_mmap(struct snd_pcm_substream *substream,
775                             struct vm_area_struct *vma)
776 {
777         struct snd_pcm_runtime *runtime = substream->runtime;
778 
779         return dma_mmap_writecombine(substream->pcm->card->dev, vma,
780                                      runtime->dma_area,
781                                      runtime->dma_addr,
782                                      runtime->dma_bytes);
783 }
784 
785 static struct snd_pcm_ops davinci_pcm_ops = {
786         .open =         davinci_pcm_open,
787         .close =        davinci_pcm_close,
788         .ioctl =        snd_pcm_lib_ioctl,
789         .hw_params =    davinci_pcm_hw_params,
790         .hw_free =      davinci_pcm_hw_free,
791         .prepare =      davinci_pcm_prepare,
792         .trigger =      davinci_pcm_trigger,
793         .pointer =      davinci_pcm_pointer,
794         .mmap =         davinci_pcm_mmap,
795 };
796 
797 static int davinci_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream,
798                 size_t size)
799 {
800         struct snd_pcm_substream *substream = pcm->streams[stream].substream;
801         struct snd_dma_buffer *buf = &substream->dma_buffer;
802 
803         buf->dev.type = SNDRV_DMA_TYPE_DEV;
804         buf->dev.dev = pcm->card->dev;
805         buf->private_data = NULL;
806         buf->area = dma_alloc_writecombine(pcm->card->dev, size,
807                                            &buf->addr, GFP_KERNEL);
808 
809         pr_debug("davinci_pcm: preallocate_dma_buffer: area=%p, addr=%p, "
810                 "size=%d\n", (void *) buf->area, (void *) buf->addr, size);
811 
812         if (!buf->area)
813                 return -ENOMEM;
814 
815         buf->bytes = size;
816         return 0;
817 }
818 
819 static void davinci_pcm_free(struct snd_pcm *pcm)
820 {
821         struct snd_pcm_substream *substream;
822         struct snd_dma_buffer *buf;
823         int stream;
824 
825         for (stream = 0; stream < 2; stream++) {
826                 struct snd_dma_buffer *iram_dma;
827                 substream = pcm->streams[stream].substream;
828                 if (!substream)
829                         continue;
830 
831                 buf = &substream->dma_buffer;
832                 if (!buf->area)
833                         continue;
834 
835                 dma_free_writecombine(pcm->card->dev, buf->bytes,
836                                       buf->area, buf->addr);
837                 buf->area = NULL;
838                 iram_dma = buf->private_data;
839                 if (iram_dma) {
840                         davinci_free_sram(substream, iram_dma);
841                         kfree(iram_dma);
842                 }
843         }
844 }
845 
846 static u64 davinci_pcm_dmamask = DMA_BIT_MASK(32);
847 
848 static int davinci_pcm_new(struct snd_soc_pcm_runtime *rtd)
849 {
850         struct snd_card *card = rtd->card->snd_card;
851         struct snd_pcm *pcm = rtd->pcm;
852         int ret;
853 
854         if (!card->dev->dma_mask)
855                 card->dev->dma_mask = &davinci_pcm_dmamask;
856         if (!card->dev->coherent_dma_mask)
857                 card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
858 
859         if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
860                 ret = davinci_pcm_preallocate_dma_buffer(pcm,
861                         SNDRV_PCM_STREAM_PLAYBACK,
862                         pcm_hardware_playback.buffer_bytes_max);
863                 if (ret)
864                         return ret;
865         }
866 
867         if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
868                 ret = davinci_pcm_preallocate_dma_buffer(pcm,
869                         SNDRV_PCM_STREAM_CAPTURE,
870                         pcm_hardware_capture.buffer_bytes_max);
871                 if (ret)
872                         return ret;
873         }
874 
875         return 0;
876 }
877 
878 static struct snd_soc_platform_driver davinci_soc_platform = {
879         .ops =          &davinci_pcm_ops,
880         .pcm_new =      davinci_pcm_new,
881         .pcm_free =     davinci_pcm_free,
882 };
883 
884 int davinci_soc_platform_register(struct device *dev)
885 {
886         return snd_soc_register_platform(dev, &davinci_soc_platform);
887 }
888 EXPORT_SYMBOL_GPL(davinci_soc_platform_register);
889 
890 void davinci_soc_platform_unregister(struct device *dev)
891 {
892         snd_soc_unregister_platform(dev);
893 }
894 EXPORT_SYMBOL_GPL(davinci_soc_platform_unregister);
895 
896 MODULE_AUTHOR("Vladimir Barinov");
897 MODULE_DESCRIPTION("TI DAVINCI PCM DMA module");
898 MODULE_LICENSE("GPL");
899 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp