2 * mx1_mx2-pcm.c -- ALSA SoC interface for Freescale i.MX1x, i.MX2x CPUs
4 * Copyright 2009 Vista Silicon S.L.
5 * Author: Javier Martin
6 * javier.martin@vista-silicon.com
8 * Based on mxc-pcm.c by Liam Girdwood.
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
17 #include <linux/module.h>
18 #include <linux/init.h>
19 #include <linux/platform_device.h>
20 #include <linux/slab.h>
21 #include <linux/dma-mapping.h>
22 #include <sound/core.h>
23 #include <sound/pcm.h>
24 #include <sound/pcm_params.h>
25 #include <sound/soc.h>
27 #include <mach/hardware.h>
28 #include <mach/dma-mx1-mx2.h>
30 #include "mx1_mx2-pcm.h"
33 static const struct snd_pcm_hardware mx1_mx2_pcm_hardware
= {
34 .info
= (SNDRV_PCM_INFO_INTERLEAVED
|
35 SNDRV_PCM_INFO_BLOCK_TRANSFER
|
37 SNDRV_PCM_INFO_MMAP_VALID
),
38 .formats
= SNDRV_PCM_FMTBIT_S16_LE
,
39 .buffer_bytes_max
= 32 * 1024,
40 .period_bytes_min
= 64,
41 .period_bytes_max
= 8 * 1024,
47 struct mx1_mx2_runtime_data
{
54 struct mx1_mx2_pcm_dma_params
*dma_params
;
59 * This function stops the current dma transfer for playback
60 * and clears the dma pointers.
62 * @param substream pointer to the structure of the current stream.
65 static int audio_stop_dma(struct snd_pcm_substream
*substream
)
67 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
68 struct mx1_mx2_runtime_data
*prtd
= runtime
->private_data
;
71 spin_lock_irqsave(&prtd
->dma_lock
, flags
);
73 pr_debug("%s\n", __func__
);
79 /* this stops the dma channel and clears the buffer ptrs */
81 imx_dma_disable(prtd
->dma_ch
);
83 spin_unlock_irqrestore(&prtd
->dma_lock
, flags
);
89 * This function is called whenever a new audio block needs to be
90 * transferred to the codec. The function receives the address and the size
91 * of the new block and start a new DMA transfer.
93 * @param substream pointer to the structure of the current stream.
96 static int dma_new_period(struct snd_pcm_substream
*substream
)
98 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
99 struct mx1_mx2_runtime_data
*prtd
= runtime
->private_data
;
100 unsigned int dma_size
;
104 unsigned int dev_addr
;
107 dma_size
= frames_to_bytes(runtime
, runtime
->period_size
);
108 offset
= dma_size
* prtd
->period
;
110 pr_debug("%s: period (%d) out of (%d)\n", __func__
,
113 pr_debug("period_size %d frames\n offset %d bytes\n",
114 (unsigned int)runtime
->period_size
,
116 pr_debug("dma_size %d bytes\n", dma_size
);
118 snd_BUG_ON(dma_size
> mx1_mx2_pcm_hardware
.period_bytes_max
);
120 mem_addr
= (dma_addr_t
)(runtime
->dma_addr
+ offset
);
121 dev_addr
= prtd
->dma_params
->per_address
;
122 pr_debug("%s: mem_addr is %x\n dev_addr is %x\n",
123 __func__
, mem_addr
, dev_addr
);
125 ret
= imx_dma_setup_single(prtd
->dma_ch
, mem_addr
,
127 prtd
->dma_params
->transfer_type
);
129 printk(KERN_ERR
"Error %d configuring DMA\n", ret
);
132 imx_dma_enable(prtd
->dma_ch
);
134 pr_debug("%s: transfer enabled\nmem_addr = %x\n",
135 __func__
, (unsigned int) mem_addr
);
136 pr_debug("dev_addr = %x\ndma_size = %d\n",
137 (unsigned int) dev_addr
, dma_size
);
139 prtd
->tx_spin
= 1; /* FGA little trick to retrieve DMA pos */
141 prtd
->period
%= runtime
->periods
;
148 * This is a callback which will be called
149 * when a TX transfer finishes. The call occurs
150 * in interrupt context.
152 * @param dat pointer to the structure of the current stream.
155 static void audio_dma_irq(int channel
, void *data
)
157 struct snd_pcm_substream
*substream
;
158 struct snd_pcm_runtime
*runtime
;
159 struct mx1_mx2_runtime_data
*prtd
;
160 unsigned int dma_size
;
161 unsigned int previous_period
;
165 runtime
= substream
->runtime
;
166 prtd
= runtime
->private_data
;
167 previous_period
= prtd
->periods
;
168 dma_size
= frames_to_bytes(runtime
, runtime
->period_size
);
169 offset
= dma_size
* previous_period
;
173 prtd
->periods
%= runtime
->periods
;
175 pr_debug("%s: irq per %d offset %x\n", __func__
, prtd
->periods
, offset
);
178 * If we are getting a callback for an active stream then we inform
179 * the PCM middle layer we've finished a period
182 snd_pcm_period_elapsed(substream
);
185 * Trig next DMA transfer
187 dma_new_period(substream
);
191 * This function configures the hardware to allow audio
192 * playback operations. It is called by ALSA framework.
194 * @param substream pointer to the structure of the current stream.
196 * @return 0 on success, -1 otherwise.
199 snd_mx1_mx2_prepare(struct snd_pcm_substream
*substream
)
201 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
202 struct mx1_mx2_runtime_data
*prtd
= runtime
->private_data
;
210 static int mx1_mx2_pcm_hw_params(struct snd_pcm_substream
*substream
,
211 struct snd_pcm_hw_params
*hw_params
)
213 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
216 ret
= snd_pcm_lib_malloc_pages(substream
,
217 params_buffer_bytes(hw_params
));
219 printk(KERN_ERR
"%s: Error %d failed to malloc pcm pages \n",
224 pr_debug("%s: snd_imx1_mx2_audio_hw_params runtime->dma_addr 0x(%x)\n",
225 __func__
, (unsigned int)runtime
->dma_addr
);
226 pr_debug("%s: snd_imx1_mx2_audio_hw_params runtime->dma_area 0x(%x)\n",
227 __func__
, (unsigned int)runtime
->dma_area
);
228 pr_debug("%s: snd_imx1_mx2_audio_hw_params runtime->dma_bytes 0x(%x)\n",
229 __func__
, (unsigned int)runtime
->dma_bytes
);
234 static int mx1_mx2_pcm_hw_free(struct snd_pcm_substream
*substream
)
236 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
237 struct mx1_mx2_runtime_data
*prtd
= runtime
->private_data
;
239 imx_dma_free(prtd
->dma_ch
);
241 snd_pcm_lib_free_pages(substream
);
246 static int mx1_mx2_pcm_trigger(struct snd_pcm_substream
*substream
, int cmd
)
248 struct mx1_mx2_runtime_data
*prtd
= substream
->runtime
->private_data
;
252 case SNDRV_PCM_TRIGGER_START
:
254 /* requested stream startup */
256 pr_debug("%s: starting dma_new_period\n", __func__
);
257 ret
= dma_new_period(substream
);
259 case SNDRV_PCM_TRIGGER_STOP
:
260 /* requested stream shutdown */
261 pr_debug("%s: stopping dma transfer\n", __func__
);
262 ret
= audio_stop_dma(substream
);
272 static snd_pcm_uframes_t
273 mx1_mx2_pcm_pointer(struct snd_pcm_substream
*substream
)
275 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
276 struct mx1_mx2_runtime_data
*prtd
= runtime
->private_data
;
277 unsigned int offset
= 0;
279 /* tx_spin value is used here to check if a transfer is active */
281 offset
= (runtime
->period_size
* (prtd
->periods
)) +
282 (runtime
->period_size
>> 1);
283 if (offset
>= runtime
->buffer_size
)
284 offset
= runtime
->period_size
>> 1;
286 offset
= (runtime
->period_size
* (prtd
->periods
));
287 if (offset
>= runtime
->buffer_size
)
290 pr_debug("%s: pointer offset %x\n", __func__
, offset
);
295 static int mx1_mx2_pcm_open(struct snd_pcm_substream
*substream
)
297 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
298 struct mx1_mx2_runtime_data
*prtd
;
299 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
300 struct mx1_mx2_pcm_dma_params
*dma_data
= rtd
->dai
->cpu_dai
->dma_data
;
303 snd_soc_set_runtime_hwparams(substream
, &mx1_mx2_pcm_hardware
);
305 ret
= snd_pcm_hw_constraint_integer(runtime
,
306 SNDRV_PCM_HW_PARAM_PERIODS
);
310 prtd
= kzalloc(sizeof(struct mx1_mx2_runtime_data
), GFP_KERNEL
);
316 runtime
->private_data
= prtd
;
321 prtd
->dma_params
= dma_data
;
323 pr_debug("%s: Requesting dma channel (%s)\n", __func__
,
324 prtd
->dma_params
->name
);
325 prtd
->dma_ch
= imx_dma_request_by_prio(prtd
->dma_params
->name
,
327 if (prtd
->dma_ch
< 0) {
328 printk(KERN_ERR
"Error %d requesting dma channel\n", ret
);
331 imx_dma_config_burstlen(prtd
->dma_ch
,
332 prtd
->dma_params
->watermark_level
);
334 ret
= imx_dma_config_channel(prtd
->dma_ch
,
335 prtd
->dma_params
->per_config
,
336 prtd
->dma_params
->mem_config
,
337 prtd
->dma_params
->event_id
, 0);
340 pr_debug(KERN_ERR
"Error %d configuring dma channel %d\n",
345 pr_debug("%s: Setting tx dma callback function\n", __func__
);
346 ret
= imx_dma_setup_handlers(prtd
->dma_ch
,
350 printk(KERN_ERR
"Error %d setting dma callback function\n", ret
);
359 static int mx1_mx2_pcm_close(struct snd_pcm_substream
*substream
)
361 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
362 struct mx1_mx2_runtime_data
*prtd
= runtime
->private_data
;
369 static int mx1_mx2_pcm_mmap(struct snd_pcm_substream
*substream
,
370 struct vm_area_struct
*vma
)
372 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
373 return dma_mmap_writecombine(substream
->pcm
->card
->dev
, vma
,
379 static struct snd_pcm_ops mx1_mx2_pcm_ops
= {
380 .open
= mx1_mx2_pcm_open
,
381 .close
= mx1_mx2_pcm_close
,
382 .ioctl
= snd_pcm_lib_ioctl
,
383 .hw_params
= mx1_mx2_pcm_hw_params
,
384 .hw_free
= mx1_mx2_pcm_hw_free
,
385 .prepare
= snd_mx1_mx2_prepare
,
386 .trigger
= mx1_mx2_pcm_trigger
,
387 .pointer
= mx1_mx2_pcm_pointer
,
388 .mmap
= mx1_mx2_pcm_mmap
,
391 static u64 mx1_mx2_pcm_dmamask
= 0xffffffff;
393 static int mx1_mx2_pcm_preallocate_dma_buffer(struct snd_pcm
*pcm
, int stream
)
395 struct snd_pcm_substream
*substream
= pcm
->streams
[stream
].substream
;
396 struct snd_dma_buffer
*buf
= &substream
->dma_buffer
;
397 size_t size
= mx1_mx2_pcm_hardware
.buffer_bytes_max
;
398 buf
->dev
.type
= SNDRV_DMA_TYPE_DEV
;
399 buf
->dev
.dev
= pcm
->card
->dev
;
400 buf
->private_data
= NULL
;
402 /* Reserve uncached-buffered memory area for DMA */
403 buf
->area
= dma_alloc_writecombine(pcm
->card
->dev
, size
,
404 &buf
->addr
, GFP_KERNEL
);
406 pr_debug("%s: preallocate_dma_buffer: area=%p, addr=%p, size=%d\n",
407 __func__
, (void *) buf
->area
, (void *) buf
->addr
, size
);
416 static void mx1_mx2_pcm_free_dma_buffers(struct snd_pcm
*pcm
)
418 struct snd_pcm_substream
*substream
;
419 struct snd_dma_buffer
*buf
;
422 for (stream
= 0; stream
< 2; stream
++) {
423 substream
= pcm
->streams
[stream
].substream
;
427 buf
= &substream
->dma_buffer
;
431 dma_free_writecombine(pcm
->card
->dev
, buf
->bytes
,
432 buf
->area
, buf
->addr
);
437 static int mx1_mx2_pcm_new(struct snd_card
*card
, struct snd_soc_dai
*dai
,
442 if (!card
->dev
->dma_mask
)
443 card
->dev
->dma_mask
= &mx1_mx2_pcm_dmamask
;
444 if (!card
->dev
->coherent_dma_mask
)
445 card
->dev
->coherent_dma_mask
= 0xffffffff;
447 if (dai
->playback
.channels_min
) {
448 ret
= mx1_mx2_pcm_preallocate_dma_buffer(pcm
,
449 SNDRV_PCM_STREAM_PLAYBACK
);
450 pr_debug("%s: preallocate playback buffer\n", __func__
);
455 if (dai
->capture
.channels_min
) {
456 ret
= mx1_mx2_pcm_preallocate_dma_buffer(pcm
,
457 SNDRV_PCM_STREAM_CAPTURE
);
458 pr_debug("%s: preallocate capture buffer\n", __func__
);
466 struct snd_soc_platform mx1_mx2_soc_platform
= {
467 .name
= "mx1_mx2-audio",
468 .pcm_ops
= &mx1_mx2_pcm_ops
,
469 .pcm_new
= mx1_mx2_pcm_new
,
470 .pcm_free
= mx1_mx2_pcm_free_dma_buffers
,
472 EXPORT_SYMBOL_GPL(mx1_mx2_soc_platform
);
474 static int __init
mx1_mx2_soc_platform_init(void)
476 return snd_soc_register_platform(&mx1_mx2_soc_platform
);
478 module_init(mx1_mx2_soc_platform_init
);
480 static void __exit
mx1_mx2_soc_platform_exit(void)
482 snd_soc_unregister_platform(&mx1_mx2_soc_platform
);
484 module_exit(mx1_mx2_soc_platform_exit
);
486 MODULE_AUTHOR("Javier Martin, javier.martin@vista-silicon.com");
487 MODULE_DESCRIPTION("Freescale i.MX2x, i.MX1x PCM DMA module");
488 MODULE_LICENSE("GPL");