2 * ALSA PCM interface for the TI DAVINCI processor
4 * Author: Vladimir Barinov, <vbarinov@embeddedalley.com>
5 * Copyright: (C) 2007 MontaVista Software, Inc., <source@mvista.com>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
12 #include <linux/module.h>
13 #include <linux/init.h>
14 #include <linux/platform_device.h>
15 #include <linux/slab.h>
16 #include <linux/dma-mapping.h>
17 #include <linux/kernel.h>
19 #include <sound/core.h>
20 #include <sound/pcm.h>
21 #include <sound/pcm_params.h>
22 #include <sound/soc.h>
26 #include "davinci-pcm.h"
28 static struct snd_pcm_hardware davinci_pcm_hardware = {
29 .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
30 SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
31 SNDRV_PCM_INFO_PAUSE),
32 .formats = (SNDRV_PCM_FMTBIT_S16_LE),
33 .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
34 SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 |
35 SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
36 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
42 .buffer_bytes_max = 128 * 1024,
43 .period_bytes_min = 32,
44 .period_bytes_max = 8 * 1024,
50 struct davinci_runtime_data {
52 int period; /* current DMA period */
53 int master_lch; /* Master DMA channel */
54 int slave_lch; /* Slave DMA channel */
55 struct davinci_pcm_dma_params *params; /* DMA params */
58 static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream)
60 struct davinci_runtime_data *prtd = substream->runtime->private_data;
61 struct snd_pcm_runtime *runtime = substream->runtime;
62 int lch = prtd->slave_lch;
63 unsigned int period_size;
64 unsigned int dma_offset;
67 unsigned short src_bidx, dst_bidx;
68 unsigned int data_type;
71 period_size = snd_pcm_lib_period_bytes(substream);
72 dma_offset = prtd->period * period_size;
73 dma_pos = runtime->dma_addr + dma_offset;
75 pr_debug("davinci_pcm: audio_set_dma_params_play channel = %d "
76 "dma_ptr = %x period_size=%x\n", lch, dma_pos, period_size);
78 data_type = prtd->params->data_type;
79 count = period_size / data_type;
81 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
83 dst = prtd->params->dma_addr;
87 src = prtd->params->dma_addr;
93 davinci_set_dma_src_params(lch, src, INCR, W8BIT);
94 davinci_set_dma_dest_params(lch, dst, INCR, W8BIT);
95 davinci_set_dma_src_index(lch, src_bidx, 0);
96 davinci_set_dma_dest_index(lch, dst_bidx, 0);
97 davinci_set_dma_transfer_params(lch, data_type, count, 1, 0, ASYNC);
100 if (unlikely(prtd->period >= runtime->periods))
104 static void davinci_pcm_dma_irq(int lch, u16 ch_status, void *data)
106 struct snd_pcm_substream *substream = data;
107 struct davinci_runtime_data *prtd = substream->runtime->private_data;
109 pr_debug("davinci_pcm: lch=%d, status=0x%x\n", lch, ch_status);
111 if (unlikely(ch_status != DMA_COMPLETE))
114 if (snd_pcm_running(substream)) {
115 snd_pcm_period_elapsed(substream);
117 spin_lock(&prtd->lock);
118 davinci_pcm_enqueue_dma(substream);
119 spin_unlock(&prtd->lock);
123 static int davinci_pcm_dma_request(struct snd_pcm_substream *substream)
125 struct davinci_runtime_data *prtd = substream->runtime->private_data;
126 struct snd_soc_pcm_runtime *rtd = substream->private_data;
127 struct davinci_pcm_dma_params *dma_data = rtd->dai->cpu_dai->dma_data;
134 prtd->params = dma_data;
136 /* Request master DMA channel */
137 ret = davinci_request_dma(prtd->params->channel, prtd->params->name,
138 davinci_pcm_dma_irq, substream,
139 &prtd->master_lch, &tcc, EVENTQ_0);
143 /* Request slave DMA channel */
144 ret = davinci_request_dma(PARAM_ANY, "Link",
145 NULL, NULL, &prtd->slave_lch, &tcc, EVENTQ_0);
147 davinci_free_dma(prtd->master_lch);
151 /* Link slave DMA channel in loopback */
152 davinci_dma_link_lch(prtd->slave_lch, prtd->slave_lch);
157 static int davinci_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
159 struct davinci_runtime_data *prtd = substream->runtime->private_data;
162 spin_lock(&prtd->lock);
165 case SNDRV_PCM_TRIGGER_START:
166 case SNDRV_PCM_TRIGGER_RESUME:
167 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
168 davinci_start_dma(prtd->master_lch);
170 case SNDRV_PCM_TRIGGER_STOP:
171 case SNDRV_PCM_TRIGGER_SUSPEND:
172 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
173 davinci_stop_dma(prtd->master_lch);
180 spin_unlock(&prtd->lock);
185 static int davinci_pcm_prepare(struct snd_pcm_substream *substream)
187 struct davinci_runtime_data *prtd = substream->runtime->private_data;
188 struct paramentry_descriptor temp;
191 davinci_pcm_enqueue_dma(substream);
193 /* Get slave channel dma params for master channel startup */
194 davinci_get_dma_params(prtd->slave_lch, &temp);
195 davinci_set_dma_params(prtd->master_lch, &temp);
200 static snd_pcm_uframes_t
201 davinci_pcm_pointer(struct snd_pcm_substream *substream)
203 struct snd_pcm_runtime *runtime = substream->runtime;
204 struct davinci_runtime_data *prtd = runtime->private_data;
209 spin_lock(&prtd->lock);
211 davinci_dma_getposition(prtd->master_lch, &src, &dst);
212 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
213 count = src - runtime->dma_addr;
215 count = dst - runtime->dma_addr;
217 spin_unlock(&prtd->lock);
219 offset = bytes_to_frames(runtime, count);
220 if (offset >= runtime->buffer_size)
226 static int davinci_pcm_open(struct snd_pcm_substream *substream)
228 struct snd_pcm_runtime *runtime = substream->runtime;
229 struct davinci_runtime_data *prtd;
232 snd_soc_set_runtime_hwparams(substream, &davinci_pcm_hardware);
234 prtd = kzalloc(sizeof(struct davinci_runtime_data), GFP_KERNEL);
238 spin_lock_init(&prtd->lock);
240 runtime->private_data = prtd;
242 ret = davinci_pcm_dma_request(substream);
244 printk(KERN_ERR "davinci_pcm: Failed to get dma channels\n");
251 static int davinci_pcm_close(struct snd_pcm_substream *substream)
253 struct snd_pcm_runtime *runtime = substream->runtime;
254 struct davinci_runtime_data *prtd = runtime->private_data;
256 davinci_dma_unlink_lch(prtd->slave_lch, prtd->slave_lch);
258 davinci_free_dma(prtd->slave_lch);
259 davinci_free_dma(prtd->master_lch);
266 static int davinci_pcm_hw_params(struct snd_pcm_substream *substream,
267 struct snd_pcm_hw_params *hw_params)
269 return snd_pcm_lib_malloc_pages(substream,
270 params_buffer_bytes(hw_params));
273 static int davinci_pcm_hw_free(struct snd_pcm_substream *substream)
275 return snd_pcm_lib_free_pages(substream);
278 static int davinci_pcm_mmap(struct snd_pcm_substream *substream,
279 struct vm_area_struct *vma)
281 struct snd_pcm_runtime *runtime = substream->runtime;
283 return dma_mmap_writecombine(substream->pcm->card->dev, vma,
289 static struct snd_pcm_ops davinci_pcm_ops = {
290 .open = davinci_pcm_open,
291 .close = davinci_pcm_close,
292 .ioctl = snd_pcm_lib_ioctl,
293 .hw_params = davinci_pcm_hw_params,
294 .hw_free = davinci_pcm_hw_free,
295 .prepare = davinci_pcm_prepare,
296 .trigger = davinci_pcm_trigger,
297 .pointer = davinci_pcm_pointer,
298 .mmap = davinci_pcm_mmap,
301 static int davinci_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
303 struct snd_pcm_substream *substream = pcm->streams[stream].substream;
304 struct snd_dma_buffer *buf = &substream->dma_buffer;
305 size_t size = davinci_pcm_hardware.buffer_bytes_max;
307 buf->dev.type = SNDRV_DMA_TYPE_DEV;
308 buf->dev.dev = pcm->card->dev;
309 buf->private_data = NULL;
310 buf->area = dma_alloc_writecombine(pcm->card->dev, size,
311 &buf->addr, GFP_KERNEL);
313 pr_debug("davinci_pcm: preallocate_dma_buffer: area=%p, addr=%p, "
314 "size=%d\n", (void *) buf->area, (void *) buf->addr, size);
323 static void davinci_pcm_free(struct snd_pcm *pcm)
325 struct snd_pcm_substream *substream;
326 struct snd_dma_buffer *buf;
329 for (stream = 0; stream < 2; stream++) {
330 substream = pcm->streams[stream].substream;
334 buf = &substream->dma_buffer;
338 dma_free_writecombine(pcm->card->dev, buf->bytes,
339 buf->area, buf->addr);
344 static u64 davinci_pcm_dmamask = 0xffffffff;
346 static int davinci_pcm_new(struct snd_card *card,
347 struct snd_soc_dai *dai, struct snd_pcm *pcm)
351 if (!card->dev->dma_mask)
352 card->dev->dma_mask = &davinci_pcm_dmamask;
353 if (!card->dev->coherent_dma_mask)
354 card->dev->coherent_dma_mask = 0xffffffff;
356 if (dai->playback.channels_min) {
357 ret = davinci_pcm_preallocate_dma_buffer(pcm,
358 SNDRV_PCM_STREAM_PLAYBACK);
363 if (dai->capture.channels_min) {
364 ret = davinci_pcm_preallocate_dma_buffer(pcm,
365 SNDRV_PCM_STREAM_CAPTURE);
373 struct snd_soc_platform davinci_soc_platform = {
374 .name = "davinci-audio",
375 .pcm_ops = &davinci_pcm_ops,
376 .pcm_new = davinci_pcm_new,
377 .pcm_free = davinci_pcm_free,
379 EXPORT_SYMBOL_GPL(davinci_soc_platform);
381 static int __init davinci_soc_platform_init(void)
383 return snd_soc_register_platform(&davinci_soc_platform);
385 module_init(davinci_soc_platform_init);
387 static void __exit davinci_soc_platform_exit(void)
389 snd_soc_unregister_platform(&davinci_soc_platform);
391 module_exit(davinci_soc_platform_exit);
393 MODULE_AUTHOR("Vladimir Barinov");
394 MODULE_DESCRIPTION("TI DAVINCI PCM DMA module");
395 MODULE_LICENSE("GPL");