davinci-pcm.c
001     /** 
002       * ALSA PCM interface for the TI DAVINCI processor 
003       * 
004       * Author:      Vladimir Barinov, <vbarinov@embeddedalley.com> 
005       * Copyright:   (C) 2007 MontaVista Software, Inc., <source@mvista.com> 
006       * added SRAM ping/pong (C) 2008 Troy Kisky <troy.kisky@boundarydevices.com> 
007       * 
008       * This program is free software; you can redistribute it and/or modify 
009       * it under the terms of the GNU General Public License version 2 as 
010       * published by the Free Software Foundation. 
011       */ 
012      
013     #include <linux/module.h> 
014     #include <linux/init.h> 
015     #include <linux/platform_device.h> 
016     #include <linux/slab.h> 
017     #include <linux/dma-mapping.h> 
018     #include <linux/kernel.h> 
019      
020     #include <sound/core.h> 
021     #include <sound/pcm.h> 
022     #include <sound/pcm_params.h> 
023     #include <sound/soc.h> 
024      
025     #include <asm/dma.h> 
026     #include <mach/edma.h> 
027     #include <mach/sram.h> 
028      
029     #include "davinci-pcm.h" 
030      
031     #ifdef DEBUG 
032     static void print_buf_info( int slot, char *name) 
033     { 
034          struct edmacc_param p; 
035          if (slot < 0) 
036              return ; 
037          edma_read_slot(slot, &p); 
038          printk(KERN_DEBUG "%s: 0x%x, opt=%x, src=%x, a_b_cnt=%x dst=%x\n" , 
039                  name, slot, p.opt, p.src, p.a_b_cnt, p.dst); 
040          printk(KERN_DEBUG "    src_dst_bidx=%x link_bcntrld=%x src_dst_cidx=%x ccnt=%x\n" , 
041                  p.src_dst_bidx, p.link_bcntrld, p.src_dst_cidx, p.ccnt); 
042     } 
043     #else 
044     static void print_buf_info( int slot, char *name) 
045     { 
046     } 
047     #endif 
048      
049     static struct snd_pcm_hardware pcm_hardware_playback = { 
050          .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | 
051               SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | 
052               SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME), 
053          .formats = (SNDRV_PCM_FMTBIT_S16_LE), 
054          .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | 
055                SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | 
056                SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | 
057                SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | 
058                SNDRV_PCM_RATE_KNOT), 
059          .rate_min = 8000, 
060          .rate_max = 96000, 
061          .channels_min = 2, 
062          .channels_max = 2, 
063          .buffer_bytes_max = 128 * 1024, 
064          .period_bytes_min = 32, 
065          .period_bytes_max = 8 * 1024, 
066          .periods_min = 16, 
067          .periods_max = 255, 
068          .fifo_size = 0, 
069     }; 
070      
071     static struct snd_pcm_hardware pcm_hardware_capture = { 
072          .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | 
073               SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | 
074               SNDRV_PCM_INFO_PAUSE), 
075          .formats = (SNDRV_PCM_FMTBIT_S16_LE), 
076          .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | 
077                SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | 
078                SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | 
079                SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | 
080                SNDRV_PCM_RATE_KNOT), 
081          .rate_min = 8000, 
082          .rate_max = 96000, 
083          .channels_min = 2, 
084          .channels_max = 2, 
085          .buffer_bytes_max = 128 * 1024, 
086          .period_bytes_min = 32, 
087          .period_bytes_max = 8 * 1024, 
088          .periods_min = 16, 
089          .periods_max = 255, 
090          .fifo_size = 0, 
091     }; 
092      
093     /** 
094       * How ping/pong works.... 
095       * 
096       * Playback: 
097       * ram_params - copys 2*ping_size from start of SDRAM to iram, 
098       *  links to ram_link2 
099       * ram_link2 - copys rest of SDRAM to iram in ping_size units, 
100       *  links to ram_link 
101       * ram_link - copys entire SDRAM to iram in ping_size uints, 
102       *  links to self 
103       * 
104       * asp_params - same as asp_link[0] 
105       * asp_link[0] - copys from lower half of iram to asp port 
106       *  links to asp_link[1], triggers iram copy event on completion 
107       * asp_link[1] - copys from upper half of iram to asp port 
108       *  links to asp_link[0], triggers iram copy event on completion 
109       *  triggers interrupt only needed to let upper SOC levels update position 
110       *  in stream on completion 
111       * 
112       * When playback is started: 
113       *  ram_params started 
114       *  asp_params started 
115       * 
116       * Capture: 
117       * ram_params - same as ram_link, 
118       *  links to ram_link 
119       * ram_link - same as playback 
120       *  links to self 
121       * 
122       * asp_params - same as playback 
123       * asp_link[0] - same as playback 
124       * asp_link[1] - same as playback 
125       * 
126       * When capture is started: 
127       *  asp_params started 
128       */ 
129     struct davinci_runtime_data { 
130          spinlock_t lock; 
131          int period;     /** current DMA period */ 
132          int asp_channel;    /** Master DMA channel */ 
133          int asp_link[2];    /** asp parameter link channel, ping/pong */ 
134          struct davinci_pcm_dma_params *params;  /** DMA params */ 
135          int ram_channel; 
136          int ram_link; 
137          int ram_link2; 
138          struct edmacc_param asp_params; 
139          struct edmacc_param ram_params; 
140     }; 
141      
142     /** 
143       * Not used with ping/pong 
144       */ 
145     static void davinci_pcm_enqueue_dma( struct snd_pcm_substream *substream) 
146     { 
147          struct davinci_runtime_data *prtd = substream->runtime->private_data; 
148          struct snd_pcm_runtime *runtime = substream->runtime; 
149          int link = prtd->asp_link[0]; 
150          unsigned int period_size; 
151          unsigned int dma_offset; 
152          dma_addr_t dma_pos; 
153          dma_addr_t src, dst; 
154          unsigned short src_bidx, dst_bidx; 
155          unsigned short src_cidx, dst_cidx; 
156          unsigned int data_type; 
157          unsigned short acnt; 
158          unsigned int count; 
159          unsigned int fifo_level; 
160      
161          period_size = snd_pcm_lib_period_bytes(substream); 
162          dma_offset = prtd->period * period_size; 
163          dma_pos = runtime->dma_addr + dma_offset; 
164          fifo_level = prtd->params->fifo_level; 
165      
166          pr_debug( "davinci_pcm: audio_set_dma_params_play channel = %d " 
167              "dma_ptr = %x period_size=%x\n" , link, dma_pos, period_size); 
168      
169          data_type = prtd->params->data_type; 
170          count = period_size / data_type; 
171          if (fifo_level) 
172              count /= fifo_level; 
173      
174          if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 
175              src = dma_pos; 
176              dst = prtd->params->dma_addr; 
177              src_bidx = data_type; 
178              dst_bidx = 0; 
179              src_cidx = data_type * fifo_level; 
180              dst_cidx = 0; 
181          } else { 
182              src = prtd->params->dma_addr; 
183              dst = dma_pos; 
184              src_bidx = 0; 
185              dst_bidx = data_type; 
186              src_cidx = 0; 
187              dst_cidx = data_type * fifo_level; 
188          } 
189      
190          acnt = prtd->params->acnt; 
191          edma_set_src(link, src, INCR, W8BIT); 
192          edma_set_dest(link, dst, INCR, W8BIT); 
193      
194          edma_set_src_index(link, src_bidx, src_cidx); 
195          edma_set_dest_index(link, dst_bidx, dst_cidx); 
196      
197          if (!fifo_level) 
198              edma_set_transfer_params(link, acnt, count, 1, 0, ASYNC); 
199          else 
200              edma_set_transfer_params(link, acnt, fifo_level, count, 
201                                  fifo_level, ABSYNC); 
202      
203          prtd->period++; 
204          if (unlikely(prtd->period >= runtime->periods)) 
205              prtd->period = 0; 
206     } 
207      
208     static void davinci_pcm_dma_irq(unsigned link, u16 ch_status, void *data) 
209     { 
210          struct snd_pcm_substream *substream = data; 
211          struct davinci_runtime_data *prtd = substream->runtime->private_data; 
212      
213          print_buf_info(prtd->ram_channel, "i ram_channel" ); 
214          pr_debug( "davinci_pcm: link=%d, status=0x%x\n" , link, ch_status); 
215      
216          if (unlikely(ch_status != DMA_COMPLETE)) 
217              return ; 
218      
219          if (snd_pcm_running(substream)) { 
220              if (prtd->ram_channel < 0) { 
221                  /** No ping/pong must fix up link dma data*/ 
222                  spin_lock(&prtd->lock); 
223                  davinci_pcm_enqueue_dma(substream); 
224                  spin_unlock(&prtd->lock); 
225              } 
226              snd_pcm_period_elapsed(substream); 
227          } 
228     } 
229      
230     static int allocate_sram( struct snd_pcm_substream *substream, 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 = sram_alloc(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              sram_free(iram_virt, size); 
257     exit1: 
258          return -ENOMEM; 
259     } 
260      
261     /** 
262       * Only used with ping/pong. 
263       * This is called after runtime->dma_addr, period_bytes and data_type are valid 
264       */ 
265     static int ping_pong_dma_setup( struct snd_pcm_substream *substream) 
266     { 
267          unsigned short ram_src_cidx, ram_dst_cidx; 
268          struct snd_pcm_runtime *runtime = substream->runtime; 
269          struct davinci_runtime_data *prtd = runtime->private_data; 
270          struct snd_dma_buffer *iram_dma = 
271              ( struct snd_dma_buffer *)substream->dma_buffer.private_data; 
272          struct davinci_pcm_dma_params *params = prtd->params; 
273          unsigned int data_type = params->data_type; 
274          unsigned int acnt = params->acnt; 
275          /** divide by 2 for ping/pong */ 
276          unsigned int ping_size = snd_pcm_lib_period_bytes(substream) >> 1; 
277          int link = prtd->asp_link[1]; 
278          unsigned int fifo_level = prtd->params->fifo_level; 
279          unsigned int count; 
280          if ((data_type == 0) || (data_type > 4)) { 
281              printk(KERN_ERR "%s: data_type=%i\n" , __func__, data_type); 
282              return -EINVAL; 
283          } 
284          if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 
285              dma_addr_t asp_src_pong = iram_dma->addr + ping_size; 
286              ram_src_cidx = ping_size; 
287              ram_dst_cidx = -ping_size; 
288              edma_set_src(link, asp_src_pong, INCR, W8BIT); 
289      
290              link = prtd->asp_link[0]; 
291              edma_set_src_index(link, data_type, data_type * fifo_level); 
292              link = prtd->asp_link[1]; 
293              edma_set_src_index(link, data_type, data_type * fifo_level); 
294      
295              link = prtd->ram_link; 
296              edma_set_src(link, runtime->dma_addr, INCR, W32BIT); 
297          } else { 
298              dma_addr_t asp_dst_pong = iram_dma->addr + ping_size; 
299              ram_src_cidx = -ping_size; 
300              ram_dst_cidx = ping_size; 
301              edma_set_dest(link, asp_dst_pong, INCR, W8BIT); 
302      
303              link = prtd->asp_link[0]; 
304              edma_set_dest_index(link, data_type, data_type * fifo_level); 
305              link = prtd->asp_link[1]; 
306              edma_set_dest_index(link, data_type, data_type * fifo_level); 
307      
308              link = prtd->ram_link; 
309              edma_set_dest(link, runtime->dma_addr, INCR, W32BIT); 
310          } 
311      
312          if (!fifo_level) { 
313              count = ping_size / data_type; 
314              edma_set_transfer_params(prtd->asp_link[0], acnt, count, 
315                      1, 0, ASYNC); 
316              edma_set_transfer_params(prtd->asp_link[1], acnt, count, 
317                      1, 0, ASYNC); 
318          } else { 
319              count = ping_size / (data_type * fifo_level); 
320              edma_set_transfer_params(prtd->asp_link[0], acnt, fifo_level, 
321                      count, fifo_level, ABSYNC); 
322              edma_set_transfer_params(prtd->asp_link[1], acnt, fifo_level, 
323                      count, fifo_level, ABSYNC); 
324          } 
325      
326          link = prtd->ram_link; 
327          edma_set_src_index(link, ping_size, ram_src_cidx); 
328          edma_set_dest_index(link, ping_size, ram_dst_cidx); 
329          edma_set_transfer_params(link, ping_size, 2, 
330                  runtime->periods, 2, ASYNC); 
331      
332          /** init master params */ 
333          edma_read_slot(prtd->asp_link[0], &prtd->asp_params); 
334          edma_read_slot(prtd->ram_link, &prtd->ram_params); 
335          if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 
336              struct edmacc_param p_ram; 
337              /** Copy entire iram buffer before playback started */ 
338              prtd->ram_params.a_b_cnt = (1 << 16) | (ping_size << 1); 
339              /** 0 dst_bidx */ 
340              prtd->ram_params.src_dst_bidx = (ping_size << 1); 
341              /** 0 dst_cidx */ 
342              prtd->ram_params.src_dst_cidx = (ping_size << 1); 
343              prtd->ram_params.ccnt = 1; 
344      
345              /** Skip 1st period */ 
346              edma_read_slot(prtd->ram_link, &p_ram); 
347              p_ram.src += (ping_size << 1); 
348              p_ram.ccnt -= 1; 
349              edma_write_slot(prtd->ram_link2, &p_ram); 
350              /** 
351               * When 1st started, ram -> iram dma channel will fill the 
352               * entire iram.  Then, whenever a ping/pong asp buffer finishes, 
353               * 1/2 iram will be filled. 
354               */ 
355              prtd->ram_params.link_bcntrld = 
356                  EDMA_CHAN_SLOT(prtd->ram_link2) << 5; 
357          } 
358          return 0; 
359     } 
360      
361     /** 1 asp tx or rx channel using 2 parameter channels 
362       * 1 ram to/from iram channel using 1 parameter channel 
363       * 
364       * Playback 
365       * ram copy channel kicks off first, 
366       * 1st ram copy of entire iram buffer completion kicks off asp channel 
367       * asp tcc always kicks off ram copy of 1/2 iram buffer 
368       * 
369       * Record 
370       * asp channel starts, tcc kicks off ram copy 
371       */ 
372     static int request_ping_pong( struct snd_pcm_substream *substream, 
373              struct davinci_runtime_data *prtd, 
374              struct snd_dma_buffer *iram_dma) 
375     { 
376          dma_addr_t asp_src_ping; 
377          dma_addr_t asp_dst_ping; 
378          int link; 
379          struct davinci_pcm_dma_params *params = prtd->params; 
380      
381          /** Request ram master channel */ 
382          link = prtd->ram_channel = edma_alloc_channel(EDMA_CHANNEL_ANY, 
383                        davinci_pcm_dma_irq, substream, 
384                        prtd->params->ram_chan_q); 
385          if (link < 0) 
386              goto exit1; 
387      
388          /** Request ram link channel */ 
389          link = prtd->ram_link = edma_alloc_slot( 
390                  EDMA_CTLR(prtd->ram_channel), EDMA_SLOT_ANY); 
391          if (link < 0) 
392              goto exit2; 
393      
394          link = prtd->asp_link[1] = edma_alloc_slot( 
395                  EDMA_CTLR(prtd->asp_channel), EDMA_SLOT_ANY); 
396          if (link < 0) 
397              goto exit3; 
398      
399          prtd->ram_link2 = -1; 
400          if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 
401              link = prtd->ram_link2 = edma_alloc_slot( 
402                  EDMA_CTLR(prtd->ram_channel), EDMA_SLOT_ANY); 
403              if (link < 0) 
404                  goto exit4; 
405          } 
406          /** circle ping-pong buffers */ 
407          edma_link(prtd->asp_link[0], prtd->asp_link[1]); 
408          edma_link(prtd->asp_link[1], prtd->asp_link[0]); 
409          /** circle ram buffers */ 
410          edma_link(prtd->ram_link, prtd->ram_link); 
411      
412          if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 
413              asp_src_ping = iram_dma->addr; 
414              asp_dst_ping = params->dma_addr; /** fifo */ 
415          } else { 
416              asp_src_ping = params->dma_addr; /** fifo */ 
417              asp_dst_ping = iram_dma->addr; 
418          } 
419          /** ping */ 
420          link = prtd->asp_link[0]; 
421          edma_set_src(link, asp_src_ping, INCR, W16BIT); 
422          edma_set_dest(link, asp_dst_ping, INCR, W16BIT); 
423          edma_set_src_index(link, 0, 0); 
424          edma_set_dest_index(link, 0, 0); 
425      
426          edma_read_slot(link, &prtd->asp_params); 
427          prtd->asp_params.opt &= ~(TCCMODE | EDMA_TCC(0x3f) | TCINTEN); 
428          prtd->asp_params.opt |= TCCHEN | EDMA_TCC(prtd->ram_channel & 0x3f); 
429          edma_write_slot(link, &prtd->asp_params); 
430      
431          /** pong */ 
432          link = prtd->asp_link[1]; 
433          edma_set_src(link, asp_src_ping, INCR, W16BIT); 
434          edma_set_dest(link, asp_dst_ping, INCR, W16BIT); 
435          edma_set_src_index(link, 0, 0); 
436          edma_set_dest_index(link, 0, 0); 
437      
438          edma_read_slot(link, &prtd->asp_params); 
439          prtd->asp_params.opt &= ~(TCCMODE | EDMA_TCC(0x3f)); 
440          /** interrupt after every pong completion */ 
441          prtd->asp_params.opt |= TCINTEN | TCCHEN | 
442              EDMA_TCC(EDMA_CHAN_SLOT(prtd->ram_channel)); 
443          edma_write_slot(link, &prtd->asp_params); 
444      
445          /** ram */ 
446          link = prtd->ram_link; 
447          edma_set_src(link, iram_dma->addr, INCR, W32BIT); 
448          edma_set_dest(link, iram_dma->addr, INCR, W32BIT); 
449          pr_debug( "%s: audio dma channels/slots in use for ram:%u %u %u," 
450              "for asp:%u %u %u\n" , __func__, 
451              prtd->ram_channel, prtd->ram_link, prtd->ram_link2, 
452              prtd->asp_channel, prtd->asp_link[0], 
453              prtd->asp_link[1]); 
454          return 0; 
455     exit4: 
456          edma_free_channel(prtd->asp_link[1]); 
457          prtd->asp_link[1] = -1; 
458     exit3: 
459          edma_free_channel(prtd->ram_link); 
460          prtd->ram_link = -1; 
461     exit2: 
462          edma_free_channel(prtd->ram_channel); 
463          prtd->ram_channel = -1; 
464     exit1: 
465          return link; 
466     } 
467      
468     static int davinci_pcm_dma_request( struct snd_pcm_substream *substream) 
469     { 
470          struct snd_dma_buffer *iram_dma; 
471          struct davinci_runtime_data *prtd = substream->runtime->private_data; 
472          struct davinci_pcm_dma_params *params = prtd->params; 
473          int link; 
474      
475          if (!params) 
476              return -ENODEV; 
477      
478          /** Request asp master DMA channel */ 
479          link = prtd->asp_channel = edma_alloc_channel(params->channel, 
480                  davinci_pcm_dma_irq, substream, 
481                  prtd->params->asp_chan_q); 
482          if (link < 0) 
483              goto exit1; 
484      
485          /** Request asp link channels */ 
486          link = prtd->asp_link[0] = edma_alloc_slot( 
487                  EDMA_CTLR(prtd->asp_channel), EDMA_SLOT_ANY); 
488          if (link < 0) 
489              goto exit2; 
490      
491          iram_dma = ( struct snd_dma_buffer *)substream->dma_buffer.private_data; 
492          if (iram_dma) { 
493              if (request_ping_pong(substream, prtd, iram_dma) == 0) 
494                  return 0; 
495              printk(KERN_WARNING "%s: dma channel allocation failed," 
496                      "not using sram\n" , __func__); 
497          } 
498      
499          /** Issue transfer completion IRQ when the channel completes a 
500           * transfer, then always reload from the same slot (by a kind 
501           * of loopback link).  The completion IRQ handler will update 
502           * the reload slot with a new buffer. 
503           * 
504           * REVISIT save p_ram here after setting up everything except 
505           * the buffer and its length (ccnt) ... use it as a template 
506           * so davinci_pcm_enqueue_dma() takes less time in IRQ. 
507           */ 
508          edma_read_slot(link, &prtd->asp_params); 
509          prtd->asp_params.opt |= TCINTEN | 
510              EDMA_TCC(EDMA_CHAN_SLOT(prtd->asp_channel)); 
511          prtd->asp_params.link_bcntrld = EDMA_CHAN_SLOT(link) << 5; 
512          edma_write_slot(link, &prtd->asp_params); 
513          return 0; 
514     exit2: 
515          edma_free_channel(prtd->asp_channel); 
516          prtd->asp_channel = -1; 
517     exit1: 
518          return link; 
519     } 
520      
521     static int davinci_pcm_trigger( struct snd_pcm_substream *substream, int cmd) 
522     { 
523          struct davinci_runtime_data *prtd = substream->runtime->private_data; 
524          int ret = 0; 
525      
526          spin_lock(&prtd->lock); 
527      
528          switch (cmd) { 
529          case SNDRV_PCM_TRIGGER_START: 
530          case SNDRV_PCM_TRIGGER_RESUME: 
531          case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 
532              edma_resume(prtd->asp_channel); 
533              break ; 
534          case SNDRV_PCM_TRIGGER_STOP: 
535          case SNDRV_PCM_TRIGGER_SUSPEND: 
536          case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 
537              edma_pause(prtd->asp_channel); 
538              break ; 
539          default : 
540              ret = -EINVAL; 
541              break ; 
542          } 
543      
544          spin_unlock(&prtd->lock); 
545      
546          return ret; 
547     } 
548      
549     static int davinci_pcm_prepare( struct snd_pcm_substream *substream) 
550     { 
551          struct davinci_runtime_data *prtd = substream->runtime->private_data; 
552      
553          if (prtd->ram_channel >= 0) { 
554              int ret = ping_pong_dma_setup(substream); 
555              if (ret < 0) 
556                  return ret; 
557      
558              edma_write_slot(prtd->ram_channel, &prtd->ram_params); 
559              edma_write_slot(prtd->asp_channel, &prtd->asp_params); 
560      
561              print_buf_info(prtd->ram_channel, "ram_channel" ); 
562              print_buf_info(prtd->ram_link, "ram_link" ); 
563              print_buf_info(prtd->ram_link2, "ram_link2" ); 
564              print_buf_info(prtd->asp_channel, "asp_channel" ); 
565              print_buf_info(prtd->asp_link[0], "asp_link[0]" ); 
566              print_buf_info(prtd->asp_link[1], "asp_link[1]" ); 
567      
568              if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 
569                  /** copy 1st iram buffer */ 
570                  edma_start(prtd->ram_channel); 
571              } 
572              edma_start(prtd->asp_channel); 
573              return 0; 
574          } 
575          prtd->period = 0; 
576          davinci_pcm_enqueue_dma(substream); 
577      
578          /** Copy self-linked parameter RAM entry into master channel */ 
579          edma_read_slot(prtd->asp_link[0], &prtd->asp_params); 
580          edma_write_slot(prtd->asp_channel, &prtd->asp_params); 
581          davinci_pcm_enqueue_dma(substream); 
582          edma_start(prtd->asp_channel); 
583      
584          return 0; 
585     } 
586      
587     static snd_pcm_uframes_t 
588     davinci_pcm_pointer( struct snd_pcm_substream *substream) 
589     { 
590          struct snd_pcm_runtime *runtime = substream->runtime; 
591          struct davinci_runtime_data *prtd = runtime->private_data; 
592          unsigned int offset; 
593          int asp_count; 
594          dma_addr_t asp_src, asp_dst; 
595      
596          spin_lock(&prtd->lock); 
597          if (prtd->ram_channel >= 0) { 
598              int ram_count; 
599              int mod_ram; 
600              dma_addr_t ram_src, ram_dst; 
601              unsigned int period_size = snd_pcm_lib_period_bytes(substream); 
602              if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 
603                  /** reading ram before asp should be safe 
604                   * as long as the asp transfers less than a ping size 
605                   * of bytes between the 2 reads 
606                   */ 
607                  edma_get_position(prtd->ram_channel, 
608                          &ram_src, &ram_dst); 
609                  edma_get_position(prtd->asp_channel, 
610                          &asp_src, &asp_dst); 
611                  asp_count = asp_src - prtd->asp_params.src; 
612                  ram_count = ram_src - prtd->ram_params.src; 
613                  mod_ram = ram_count % period_size; 
614                  mod_ram -= asp_count; 
615                  if (mod_ram < 0) 
616                      mod_ram += period_size; 
617                  else if (mod_ram == 0) { 
618                      if (snd_pcm_running(substream)) 
619                          mod_ram += period_size; 
620                  } 
621                  ram_count -= mod_ram; 
622                  if (ram_count < 0) 
623                      ram_count += period_size * runtime->periods; 
624              } else { 
625                  edma_get_position(prtd->ram_channel, 
626                          &ram_src, &ram_dst); 
627                  ram_count = ram_dst - prtd->ram_params.dst; 
628              } 
629              asp_count = ram_count; 
630          } else { 
631              edma_get_position(prtd->asp_channel, &asp_src, &asp_dst); 
632              if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 
633                  asp_count = asp_src - runtime->dma_addr; 
634              else 
635                  asp_count = asp_dst - runtime->dma_addr; 
636          } 
637          spin_unlock(&prtd->lock); 
638      
639          offset = bytes_to_frames(runtime, asp_count); 
640          if (offset >= runtime->buffer_size) 
641              offset = 0; 
642      
643          return offset; 
644     } 
645      
646     static int davinci_pcm_open( struct snd_pcm_substream *substream) 
647     { 
648          struct snd_pcm_runtime *runtime = substream->runtime; 
649          struct davinci_runtime_data *prtd; 
650          struct snd_pcm_hardware *ppcm; 
651          int ret = 0; 
652          struct snd_soc_pcm_runtime *rtd = substream->private_data; 
653          struct davinci_pcm_dma_params *pa; 
654          struct davinci_pcm_dma_params *params; 
655      
656          pa = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); 
657          if (!pa) 
658              return -ENODEV; 
659          params = &pa[substream->stream]; 
660      
661          ppcm = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? 
662                  &pcm_hardware_playback : &pcm_hardware_capture; 
663          allocate_sram(substream, params->sram_size, ppcm); 
664          snd_soc_set_runtime_hwparams(substream, ppcm); 
665          /** ensure that buffer size is a multiple of period size */ 
666          ret = snd_pcm_hw_constraint_integer(runtime, 
667                              SNDRV_PCM_HW_PARAM_PERIODS); 
668          if (ret < 0) 
669              return ret; 
670      
671          prtd = kzalloc( sizeof ( struct davinci_runtime_data), GFP_KERNEL); 
672          if (prtd == NULL) 
673              return -ENOMEM; 
674      
675          spin_lock_init(&prtd->lock); 
676          prtd->params = params; 
677          prtd->asp_channel = -1; 
678          prtd->asp_link[0] = prtd->asp_link[1] = -1; 
679          prtd->ram_channel = -1; 
680          prtd->ram_link = -1; 
681          prtd->ram_link2 = -1; 
682      
683          runtime->private_data = prtd; 
684      
685          ret = davinci_pcm_dma_request(substream); 
686          if (ret) { 
687              printk(KERN_ERR "davinci_pcm: Failed to get dma channels\n" ); 
688              kfree(prtd); 
689          } 
690      
691          return ret; 
692     } 
693      
694     static int davinci_pcm_close( struct snd_pcm_substream *substream) 
695     { 
696          struct snd_pcm_runtime *runtime = substream->runtime; 
697          struct davinci_runtime_data *prtd = runtime->private_data; 
698      
699          if (prtd->ram_channel >= 0) 
700              edma_stop(prtd->ram_channel); 
701          if (prtd->asp_channel >= 0) 
702              edma_stop(prtd->asp_channel); 
703          if (prtd->asp_link[0] >= 0) 
704              edma_unlink(prtd->asp_link[0]); 
705          if (prtd->asp_link[1] >= 0) 
706              edma_unlink(prtd->asp_link[1]); 
707          if (prtd->ram_link >= 0) 
708              edma_unlink(prtd->ram_link); 
709      
710          if (prtd->asp_link[0] >= 0) 
711              edma_free_slot(prtd->asp_link[0]); 
712          if (prtd->asp_link[1] >= 0) 
713              edma_free_slot(prtd->asp_link[1]); 
714          if (prtd->asp_channel >= 0) 
715              edma_free_channel(prtd->asp_channel); 
716          if (prtd->ram_link >= 0) 
717              edma_free_slot(prtd->ram_link); 
718          if (prtd->ram_link2 >= 0) 
719              edma_free_slot(prtd->ram_link2); 
720          if (prtd->ram_channel >= 0) 
721              edma_free_channel(prtd->ram_channel); 
722      
723          kfree(prtd); 
724      
725          return 0; 
726     } 
727      
728     static int davinci_pcm_hw_params( struct snd_pcm_substream *substream, 
729                       struct snd_pcm_hw_params *hw_params) 
730     { 
731          return snd_pcm_lib_malloc_pages(substream, 
732                          params_buffer_bytes(hw_params)); 
733     } 
734      
735     static int davinci_pcm_hw_free( struct snd_pcm_substream *substream) 
736     { 
737          return snd_pcm_lib_free_pages(substream); 
738     } 
739      
740     static int davinci_pcm_mmap( struct snd_pcm_substream *substream, 
741                      struct vm_area_struct *vma) 
742     { 
743          struct snd_pcm_runtime *runtime = substream->runtime; 
744      
745          return dma_mmap_writecombine(substream->pcm->card->dev, vma, 
746                           runtime->dma_area, 
747                           runtime->dma_addr, 
748                           runtime->dma_bytes); 
749     } 
750      
751     static struct snd_pcm_ops davinci_pcm_ops = { 
752          .open =     davinci_pcm_open, 
753          .close =    davinci_pcm_close, 
754          .ioctl =    snd_pcm_lib_ioctl, 
755          .hw_params =    davinci_pcm_hw_params, 
756          .hw_free =  davinci_pcm_hw_free, 
757          .prepare =  davinci_pcm_prepare, 
758          .trigger =  davinci_pcm_trigger, 
759          .pointer =  davinci_pcm_pointer, 
760          .mmap =     davinci_pcm_mmap, 
761     }; 
762      
763     static int davinci_pcm_preallocate_dma_buffer( struct snd_pcm *pcm, int stream, 
764              size_t size) 
765     { 
766          struct snd_pcm_substream *substream = pcm->streams[stream].substream; 
767          struct snd_dma_buffer *buf = &substream->dma_buffer; 
768      
769          buf->dev.type = SNDRV_DMA_TYPE_DEV; 
770          buf->dev.dev = pcm->card->dev; 
771          buf->private_data = NULL; 
772          buf->area = dma_alloc_writecombine(pcm->card->dev, size, 
773                             &buf->addr, GFP_KERNEL); 
774      
775          pr_debug( "davinci_pcm: preallocate_dma_buffer: area=%p, addr=%p, " 
776              "size=%d\n" , ( void *) buf->area, ( void *) buf->addr, size); 
777      
778          if (!buf->area) 
779              return -ENOMEM; 
780      
781          buf->bytes = size; 
782          return 0; 
783     } 
784      
785     static void davinci_pcm_free( struct snd_pcm *pcm) 
786     { 
787          struct snd_pcm_substream *substream; 
788          struct snd_dma_buffer *buf; 
789          int stream; 
790      
791          for (stream = 0; stream < 2; stream++) { 
792              struct snd_dma_buffer *iram_dma; 
793              substream = pcm->streams[stream].substream; 
794              if (!substream) 
795                  continue ; 
796      
797              buf = &substream->dma_buffer; 
798              if (!buf->area) 
799                  continue ; 
800      
801              dma_free_writecombine(pcm->card->dev, buf->bytes, 
802                            buf->area, buf->addr); 
803              buf->area = NULL; 
804              iram_dma = buf->private_data; 
805              if (iram_dma) { 
806                  sram_free(iram_dma->area, iram_dma->bytes); 
807                  kfree(iram_dma); 
808              } 
809          } 
810     } 
811      
812     static u64 davinci_pcm_dmamask = 0xffffffff; 
813      
814     static int davinci_pcm_new( struct snd_card *card, 
815                     struct snd_soc_dai *dai, struct snd_pcm *pcm) 
816     { 
817          int ret; 
818      
819          if (!card->dev->dma_mask) 
820              card->dev->dma_mask = &davinci_pcm_dmamask; 
821          if (!card->dev->coherent_dma_mask) 
822              card->dev->coherent_dma_mask = 0xffffffff; 
823      
824          if (dai->playback.channels_min) { 
825              ret = davinci_pcm_preallocate_dma_buffer(pcm, 
826                  SNDRV_PCM_STREAM_PLAYBACK, 
827                  pcm_hardware_playback.buffer_bytes_max); 
828              if (ret) 
829                  return ret; 
830          } 
831      
832          if (dai->capture.channels_min) { 
833              ret = davinci_pcm_preallocate_dma_buffer(pcm, 
834                  SNDRV_PCM_STREAM_CAPTURE, 
835                  pcm_hardware_capture.buffer_bytes_max); 
836              if (ret) 
837                  return ret; 
838          } 
839      
840          return 0; 
841     } 
842      
843     struct snd_soc_platform davinci_soc_platform = { 
844          .name =     "davinci-audio" , 
845          .pcm_ops =  &davinci_pcm_ops, 
846          .pcm_new =  davinci_pcm_new, 
847          .pcm_free =     davinci_pcm_free, 
848     }; 
849     EXPORT_SYMBOL_GPL(davinci_soc_platform); 
850      
851     static int __init davinci_soc_platform_init( void ) 
852     { 
853          return snd_soc_register_platform(&davinci_soc_platform); 
854     } 
855     module_init(davinci_soc_platform_init); 
856      
857     static void __exit davinci_soc_platform_exit( void ) 
858     { 
859          snd_soc_unregister_platform(&davinci_soc_platform); 
860     } 
861     module_exit(davinci_soc_platform_exit); 
862      
863     MODULE_AUTHOR( "Vladimir Barinov" ); 
864     MODULE_DESCRIPTION( "TI DAVINCI PCM DMA module" ); 
865     MODULE_LICENSE( "GPL" );
没有评论:
发表评论