2 * ALSA PCM interface for the TI DAVINCI processor
4 * Author: Vladimir Barinov, <vbarinov@ru.mvista.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>
18 #include <sound/core.h>
19 #include <sound/pcm.h>
20 #include <sound/pcm_params.h>
21 #include <sound/soc.h>
25 #include "davinci-pcm.h"
27 #define DAVINCI_PCM_DEBUG 0
29 #define DPRINTK(x...) printk(KERN_DEBUG x)
34 static struct snd_pcm_hardware davinci_pcm_hardware
= {
35 .info
= (SNDRV_PCM_INFO_INTERLEAVED
| SNDRV_PCM_INFO_BLOCK_TRANSFER
|
36 SNDRV_PCM_INFO_MMAP
| SNDRV_PCM_INFO_MMAP_VALID
|
37 SNDRV_PCM_INFO_PAUSE
),
38 .formats
= (SNDRV_PCM_FMTBIT_S16_LE
),
39 .rates
= (SNDRV_PCM_RATE_8000
| SNDRV_PCM_RATE_16000
|
40 SNDRV_PCM_RATE_22050
| SNDRV_PCM_RATE_32000
|
41 SNDRV_PCM_RATE_44100
| SNDRV_PCM_RATE_48000
|
42 SNDRV_PCM_RATE_88200
| SNDRV_PCM_RATE_96000
|
48 .buffer_bytes_max
= 128 * 1024,
49 .period_bytes_min
= 32,
50 .period_bytes_max
= 8 * 1024,
56 struct davinci_runtime_data
{
58 int period
; /* current DMA period */
59 int master_lch
; /* Master DMA channel */
60 int slave_lch
; /* Slave DMA channel */
61 struct davinci_pcm_dma_params
*params
; /* DMA params */
64 static void davinci_pcm_enqueue_dma(struct snd_pcm_substream
*substream
)
66 struct davinci_runtime_data
*prtd
= substream
->runtime
->private_data
;
67 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
68 int lch
= prtd
->slave_lch
;
69 unsigned int period_size
;
70 unsigned int dma_offset
;
73 unsigned short src_bidx
, dst_bidx
;
74 unsigned int data_type
;
77 period_size
= snd_pcm_lib_period_bytes(substream
);
78 dma_offset
= prtd
->period
* period_size
;
79 dma_pos
= runtime
->dma_addr
+ dma_offset
;
81 DPRINTK("audio_set_dma_params_play channel = %d dma_ptr = %x "
82 "period_size=%x\n", lch
, dma_pos
, period_size
);
84 data_type
= prtd
->params
->data_type
;
85 count
= period_size
/ data_type
;
87 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
) {
89 dst
= prtd
->params
->dma_addr
;
93 src
= prtd
->params
->dma_addr
;
99 davinci_set_dma_src_params(lch
, src
, INCR
, W8BIT
);
100 davinci_set_dma_dest_params(lch
, dst
, INCR
, W8BIT
);
101 davinci_set_dma_src_index(lch
, src_bidx
, 0);
102 davinci_set_dma_dest_index(lch
, dst_bidx
, 0);
103 davinci_set_dma_transfer_params(lch
, data_type
, count
, 1, 0, ASYNC
);
106 if (unlikely(prtd
->period
>= runtime
->periods
))
110 static void davinci_pcm_dma_irq(int lch
, u16 ch_status
, void *data
)
112 struct snd_pcm_substream
*substream
= data
;
113 struct davinci_runtime_data
*prtd
= substream
->runtime
->private_data
;
115 DPRINTK("lch=%d, status=0x%x\n", lch
, ch_status
);
117 if (unlikely(ch_status
!= DMA_COMPLETE
))
120 if (snd_pcm_running(substream
)) {
121 snd_pcm_period_elapsed(substream
);
123 spin_lock(&prtd
->lock
);
124 davinci_pcm_enqueue_dma(substream
);
125 spin_unlock(&prtd
->lock
);
129 static int davinci_pcm_dma_request(struct snd_pcm_substream
*substream
)
131 struct davinci_runtime_data
*prtd
= substream
->runtime
->private_data
;
132 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
133 struct davinci_pcm_dma_params
*dma_data
= rtd
->dai
->cpu_dai
->dma_data
;
140 prtd
->params
= dma_data
;
142 /* Request master DMA channel */
143 ret
= davinci_request_dma(prtd
->params
->channel
, prtd
->params
->name
,
144 davinci_pcm_dma_irq
, substream
,
145 &prtd
->master_lch
, &tcc
, EVENTQ_0
);
149 /* Request slave DMA channel */
150 ret
= davinci_request_dma(PARAM_ANY
, "Link",
151 NULL
, NULL
, &prtd
->slave_lch
, &tcc
, EVENTQ_0
);
153 davinci_free_dma(prtd
->master_lch
);
157 /* Link slave DMA channel in loopback */
158 davinci_dma_link_lch(prtd
->slave_lch
, prtd
->slave_lch
);
163 static int davinci_pcm_trigger(struct snd_pcm_substream
*substream
, int cmd
)
165 struct davinci_runtime_data
*prtd
= substream
->runtime
->private_data
;
168 spin_lock(&prtd
->lock
);
171 case SNDRV_PCM_TRIGGER_START
:
172 case SNDRV_PCM_TRIGGER_RESUME
:
173 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
174 davinci_start_dma(prtd
->master_lch
);
176 case SNDRV_PCM_TRIGGER_STOP
:
177 case SNDRV_PCM_TRIGGER_SUSPEND
:
178 case SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
179 davinci_stop_dma(prtd
->master_lch
);
186 spin_unlock(&prtd
->lock
);
191 static int davinci_pcm_prepare(struct snd_pcm_substream
*substream
)
193 struct davinci_runtime_data
*prtd
= substream
->runtime
->private_data
;
194 struct paramentry_descriptor temp
;
197 davinci_pcm_enqueue_dma(substream
);
199 /* Get slave channel dma params for master channel startup */
200 davinci_get_dma_params(prtd
->slave_lch
, &temp
);
201 davinci_set_dma_params(prtd
->master_lch
, &temp
);
206 static snd_pcm_uframes_t
207 davinci_pcm_pointer(struct snd_pcm_substream
*substream
)
209 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
210 struct davinci_runtime_data
*prtd
= runtime
->private_data
;
215 spin_lock(&prtd
->lock
);
217 davinci_dma_getposition(prtd
->master_lch
, &src
, &dst
);
218 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
)
219 count
= src
- runtime
->dma_addr
;
221 count
= dst
- runtime
->dma_addr
;;
223 spin_unlock(&prtd
->lock
);
225 offset
= bytes_to_frames(runtime
, count
);
226 if (offset
>= runtime
->buffer_size
)
232 static int davinci_pcm_open(struct snd_pcm_substream
*substream
)
234 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
235 struct davinci_runtime_data
*prtd
;
238 snd_soc_set_runtime_hwparams(substream
, &davinci_pcm_hardware
);
240 prtd
= kzalloc(sizeof(struct davinci_runtime_data
), GFP_KERNEL
);
244 spin_lock_init(&prtd
->lock
);
246 runtime
->private_data
= prtd
;
248 ret
= davinci_pcm_dma_request(substream
);
250 printk(KERN_ERR
"davinci_pcm: Failed to get dma channels\n");
257 static int davinci_pcm_close(struct snd_pcm_substream
*substream
)
259 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
260 struct davinci_runtime_data
*prtd
= runtime
->private_data
;
262 davinci_dma_unlink_lch(prtd
->slave_lch
, prtd
->slave_lch
);
264 davinci_free_dma(prtd
->slave_lch
);
265 davinci_free_dma(prtd
->master_lch
);
272 static int davinci_pcm_hw_params(struct snd_pcm_substream
*substream
,
273 struct snd_pcm_hw_params
*hw_params
)
275 return snd_pcm_lib_malloc_pages(substream
,
276 params_buffer_bytes(hw_params
));
279 static int davinci_pcm_hw_free(struct snd_pcm_substream
*substream
)
281 return snd_pcm_lib_free_pages(substream
);
284 static int davinci_pcm_mmap(struct snd_pcm_substream
*substream
,
285 struct vm_area_struct
*vma
)
287 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
289 return dma_mmap_writecombine(substream
->pcm
->card
->dev
, vma
,
295 struct snd_pcm_ops davinci_pcm_ops
= {
296 .open
= davinci_pcm_open
,
297 .close
= davinci_pcm_close
,
298 .ioctl
= snd_pcm_lib_ioctl
,
299 .hw_params
= davinci_pcm_hw_params
,
300 .hw_free
= davinci_pcm_hw_free
,
301 .prepare
= davinci_pcm_prepare
,
302 .trigger
= davinci_pcm_trigger
,
303 .pointer
= davinci_pcm_pointer
,
304 .mmap
= davinci_pcm_mmap
,
307 static int davinci_pcm_preallocate_dma_buffer(struct snd_pcm
*pcm
, int stream
)
309 struct snd_pcm_substream
*substream
= pcm
->streams
[stream
].substream
;
310 struct snd_dma_buffer
*buf
= &substream
->dma_buffer
;
311 size_t size
= davinci_pcm_hardware
.buffer_bytes_max
;
313 buf
->dev
.type
= SNDRV_DMA_TYPE_DEV
;
314 buf
->dev
.dev
= pcm
->card
->dev
;
315 buf
->private_data
= NULL
;
316 buf
->area
= dma_alloc_writecombine(pcm
->card
->dev
, size
,
317 &buf
->addr
, GFP_KERNEL
);
319 DPRINTK("preallocate_dma_buffer: area=%p, addr=%p, size=%d\n",
320 (void *) buf
->area
, (void *) buf
->addr
, size
);
329 static void davinci_pcm_free(struct snd_pcm
*pcm
)
331 struct snd_pcm_substream
*substream
;
332 struct snd_dma_buffer
*buf
;
335 for (stream
= 0; stream
< 2; stream
++) {
336 substream
= pcm
->streams
[stream
].substream
;
340 buf
= &substream
->dma_buffer
;
344 dma_free_writecombine(pcm
->card
->dev
, buf
->bytes
,
345 buf
->area
, buf
->addr
);
350 static u64 davinci_pcm_dmamask
= 0xffffffff;
352 static int davinci_pcm_new(struct snd_card
*card
,
353 struct snd_soc_codec_dai
*dai
, struct snd_pcm
*pcm
)
357 if (!card
->dev
->dma_mask
)
358 card
->dev
->dma_mask
= &davinci_pcm_dmamask
;
359 if (!card
->dev
->coherent_dma_mask
)
360 card
->dev
->coherent_dma_mask
= 0xffffffff;
362 if (dai
->playback
.channels_min
) {
363 ret
= davinci_pcm_preallocate_dma_buffer(pcm
,
364 SNDRV_PCM_STREAM_PLAYBACK
);
369 if (dai
->capture
.channels_min
) {
370 ret
= davinci_pcm_preallocate_dma_buffer(pcm
,
371 SNDRV_PCM_STREAM_CAPTURE
);
379 struct snd_soc_platform davinci_soc_platform
= {
380 .name
= "davinci-audio",
381 .pcm_ops
= &davinci_pcm_ops
,
382 .pcm_new
= davinci_pcm_new
,
383 .pcm_free
= davinci_pcm_free
,
385 EXPORT_SYMBOL_GPL(davinci_soc_platform
);
387 MODULE_AUTHOR("Vladimir Barinov");
388 MODULE_DESCRIPTION("TI DAVINCI PCM DMA module");
389 MODULE_LICENSE("GPL");