1 /* sound/soc/at32/at32-pcm.c
2 * ASoC PCM interface for Atmel AT32 SoC
4 * Copyright (C) 2008 Long Range Systems
5 * Geoffrey Wossum <gwossum@acm.org>
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.
11 * Note that this is basically a port of the sound/soc/at91-pcm.c to
12 * the AVR32 kernel. Thanks to Frank Mandarino for that code.
15 #include <linux/module.h>
16 #include <linux/init.h>
17 #include <linux/platform_device.h>
18 #include <linux/slab.h>
19 #include <linux/dma-mapping.h>
20 #include <linux/atmel_pdc.h>
22 #include <sound/core.h>
23 #include <sound/pcm.h>
24 #include <sound/pcm_params.h>
25 #include <sound/soc.h>
31 /*--------------------------------------------------------------------------*\
33 \*--------------------------------------------------------------------------*/
34 /* TODO: These values were taken from the AT91 platform driver, check
35 * them against real values for AT32
37 static const struct snd_pcm_hardware at32_pcm_hardware
= {
38 .info
= (SNDRV_PCM_INFO_MMAP
|
39 SNDRV_PCM_INFO_MMAP_VALID
|
40 SNDRV_PCM_INFO_INTERLEAVED
|
41 SNDRV_PCM_INFO_BLOCK_TRANSFER
|
42 SNDRV_PCM_INFO_PAUSE
),
44 .formats
= SNDRV_PCM_FMTBIT_S16
,
45 .period_bytes_min
= 32,
46 .period_bytes_max
= 8192, /* 512 frames * 16 bytes / frame */
49 .buffer_bytes_max
= 32 * 1024,
54 /*--------------------------------------------------------------------------*\
56 \*--------------------------------------------------------------------------*/
57 struct at32_runtime_data
{
58 struct at32_pcm_dma_params
*params
;
59 dma_addr_t dma_buffer
; /* physical address of DMA buffer */
60 dma_addr_t dma_buffer_end
; /* first address beyond DMA buffer */
63 dma_addr_t period_ptr
; /* physical address of next period */
64 int periods
; /* period index of period_ptr */
66 /* Save PDC registers (for power management) */
75 /*--------------------------------------------------------------------------*\
77 \*--------------------------------------------------------------------------*/
78 static int at32_pcm_preallocate_dma_buffer(struct snd_pcm
*pcm
, int stream
)
80 struct snd_pcm_substream
*substream
= pcm
->streams
[stream
].substream
;
81 struct snd_dma_buffer
*dmabuf
= &substream
->dma_buffer
;
82 size_t size
= at32_pcm_hardware
.buffer_bytes_max
;
84 dmabuf
->dev
.type
= SNDRV_DMA_TYPE_DEV
;
85 dmabuf
->dev
.dev
= pcm
->card
->dev
;
86 dmabuf
->private_data
= NULL
;
87 dmabuf
->area
= dma_alloc_coherent(pcm
->card
->dev
, size
,
88 &dmabuf
->addr
, GFP_KERNEL
);
89 pr_debug("at32_pcm: preallocate_dma_buffer: "
90 "area=%p, addr=%p, size=%ld\n",
91 (void *)dmabuf
->area
, (void *)dmabuf
->addr
, size
);
102 /*--------------------------------------------------------------------------*\
104 \*--------------------------------------------------------------------------*/
105 static void at32_pcm_dma_irq(u32 ssc_sr
, struct snd_pcm_substream
*substream
)
107 struct snd_pcm_runtime
*rtd
= substream
->runtime
;
108 struct at32_runtime_data
*prtd
= rtd
->private_data
;
109 struct at32_pcm_dma_params
*params
= prtd
->params
;
113 if (ssc_sr
& params
->mask
->ssc_endbuf
) {
114 pr_warning("at32-pcm: buffer %s on %s (SSC_SR=%#x, count=%d)\n",
115 substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
?
116 "underrun" : "overrun", params
->name
, ssc_sr
, count
);
118 /* re-start the PDC */
119 ssc_writex(params
->ssc
->regs
, ATMEL_PDC_PTCR
,
120 params
->mask
->pdc_disable
);
121 prtd
->period_ptr
+= prtd
->period_size
;
122 if (prtd
->period_ptr
>= prtd
->dma_buffer_end
)
123 prtd
->period_ptr
= prtd
->dma_buffer
;
126 ssc_writex(params
->ssc
->regs
, params
->pdc
->xpr
,
128 ssc_writex(params
->ssc
->regs
, params
->pdc
->xcr
,
129 prtd
->period_size
/ params
->pdc_xfer_size
);
130 ssc_writex(params
->ssc
->regs
, ATMEL_PDC_PTCR
,
131 params
->mask
->pdc_enable
);
135 if (ssc_sr
& params
->mask
->ssc_endx
) {
136 /* Load the PDC next pointer and counter registers */
137 prtd
->period_ptr
+= prtd
->period_size
;
138 if (prtd
->period_ptr
>= prtd
->dma_buffer_end
)
139 prtd
->period_ptr
= prtd
->dma_buffer
;
140 ssc_writex(params
->ssc
->regs
, params
->pdc
->xnpr
,
142 ssc_writex(params
->ssc
->regs
, params
->pdc
->xncr
,
143 prtd
->period_size
/ params
->pdc_xfer_size
);
147 snd_pcm_period_elapsed(substream
);
152 /*--------------------------------------------------------------------------*\
154 \*--------------------------------------------------------------------------*/
155 static int at32_pcm_hw_params(struct snd_pcm_substream
*substream
,
156 struct snd_pcm_hw_params
*params
)
158 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
159 struct at32_runtime_data
*prtd
= runtime
->private_data
;
160 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
162 /* this may get called several times by oss emulation
163 * with different params
165 snd_pcm_set_runtime_buffer(substream
, &substream
->dma_buffer
);
166 runtime
->dma_bytes
= params_buffer_bytes(params
);
168 prtd
->params
= rtd
->dai
->cpu_dai
->dma_data
;
169 prtd
->params
->dma_intr_handler
= at32_pcm_dma_irq
;
171 prtd
->dma_buffer
= runtime
->dma_addr
;
172 prtd
->dma_buffer_end
= runtime
->dma_addr
+ runtime
->dma_bytes
;
173 prtd
->period_size
= params_period_bytes(params
);
175 pr_debug("hw_params: DMA for %s initialized "
176 "(dma_bytes=%ld, period_size=%ld)\n",
177 prtd
->params
->name
, runtime
->dma_bytes
, prtd
->period_size
);
184 static int at32_pcm_hw_free(struct snd_pcm_substream
*substream
)
186 struct at32_runtime_data
*prtd
= substream
->runtime
->private_data
;
187 struct at32_pcm_dma_params
*params
= prtd
->params
;
189 if (params
!= NULL
) {
190 ssc_writex(params
->ssc
->regs
, SSC_PDC_PTCR
,
191 params
->mask
->pdc_disable
);
192 prtd
->params
->dma_intr_handler
= NULL
;
200 static int at32_pcm_prepare(struct snd_pcm_substream
*substream
)
202 struct at32_runtime_data
*prtd
= substream
->runtime
->private_data
;
203 struct at32_pcm_dma_params
*params
= prtd
->params
;
205 ssc_writex(params
->ssc
->regs
, SSC_IDR
,
206 params
->mask
->ssc_endx
| params
->mask
->ssc_endbuf
);
207 ssc_writex(params
->ssc
->regs
, ATMEL_PDC_PTCR
,
208 params
->mask
->pdc_disable
);
214 static int at32_pcm_trigger(struct snd_pcm_substream
*substream
, int cmd
)
216 struct snd_pcm_runtime
*rtd
= substream
->runtime
;
217 struct at32_runtime_data
*prtd
= rtd
->private_data
;
218 struct at32_pcm_dma_params
*params
= prtd
->params
;
221 pr_debug("at32_pcm_trigger: buffer_size = %ld, "
222 "dma_area = %p, dma_bytes = %ld\n",
223 rtd
->buffer_size
, rtd
->dma_area
, rtd
->dma_bytes
);
226 case SNDRV_PCM_TRIGGER_START
:
227 prtd
->period_ptr
= prtd
->dma_buffer
;
229 ssc_writex(params
->ssc
->regs
, params
->pdc
->xpr
,
231 ssc_writex(params
->ssc
->regs
, params
->pdc
->xcr
,
232 prtd
->period_size
/ params
->pdc_xfer_size
);
234 prtd
->period_ptr
+= prtd
->period_size
;
235 ssc_writex(params
->ssc
->regs
, params
->pdc
->xnpr
,
237 ssc_writex(params
->ssc
->regs
, params
->pdc
->xncr
,
238 prtd
->period_size
/ params
->pdc_xfer_size
);
240 pr_debug("trigger: period_ptr=%lx, xpr=%x, "
241 "xcr=%d, xnpr=%x, xncr=%d\n",
242 (unsigned long)prtd
->period_ptr
,
243 ssc_readx(params
->ssc
->regs
, params
->pdc
->xpr
),
244 ssc_readx(params
->ssc
->regs
, params
->pdc
->xcr
),
245 ssc_readx(params
->ssc
->regs
, params
->pdc
->xnpr
),
246 ssc_readx(params
->ssc
->regs
, params
->pdc
->xncr
));
248 ssc_writex(params
->ssc
->regs
, SSC_IER
,
249 params
->mask
->ssc_endx
| params
->mask
->ssc_endbuf
);
250 ssc_writex(params
->ssc
->regs
, SSC_PDC_PTCR
,
251 params
->mask
->pdc_enable
);
253 pr_debug("sr=%x, imr=%x\n",
254 ssc_readx(params
->ssc
->regs
, SSC_SR
),
255 ssc_readx(params
->ssc
->regs
, SSC_IER
));
256 break; /* SNDRV_PCM_TRIGGER_START */
260 case SNDRV_PCM_TRIGGER_STOP
:
261 case SNDRV_PCM_TRIGGER_SUSPEND
:
262 case SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
263 ssc_writex(params
->ssc
->regs
, ATMEL_PDC_PTCR
,
264 params
->mask
->pdc_disable
);
268 case SNDRV_PCM_TRIGGER_RESUME
:
269 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
270 ssc_writex(params
->ssc
->regs
, ATMEL_PDC_PTCR
,
271 params
->mask
->pdc_enable
);
283 static snd_pcm_uframes_t
at32_pcm_pointer(struct snd_pcm_substream
*substream
)
285 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
286 struct at32_runtime_data
*prtd
= runtime
->private_data
;
287 struct at32_pcm_dma_params
*params
= prtd
->params
;
291 ptr
= (dma_addr_t
) ssc_readx(params
->ssc
->regs
, params
->pdc
->xpr
);
292 x
= bytes_to_frames(runtime
, ptr
- prtd
->dma_buffer
);
294 if (x
== runtime
->buffer_size
)
302 static int at32_pcm_open(struct snd_pcm_substream
*substream
)
304 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
305 struct at32_runtime_data
*prtd
;
308 snd_soc_set_runtime_hwparams(substream
, &at32_pcm_hardware
);
310 /* ensure that buffer size is a multiple of period size */
311 ret
= snd_pcm_hw_constraint_integer(runtime
,
312 SNDRV_PCM_HW_PARAM_PERIODS
);
316 prtd
= kzalloc(sizeof(*prtd
), GFP_KERNEL
);
321 runtime
->private_data
= prtd
;
330 static int at32_pcm_close(struct snd_pcm_substream
*substream
)
332 struct at32_runtime_data
*prtd
= substream
->runtime
->private_data
;
339 static int at32_pcm_mmap(struct snd_pcm_substream
*substream
,
340 struct vm_area_struct
*vma
)
342 return remap_pfn_range(vma
, vma
->vm_start
,
343 substream
->dma_buffer
.addr
>> PAGE_SHIFT
,
344 vma
->vm_end
- vma
->vm_start
, vma
->vm_page_prot
);
349 static struct snd_pcm_ops at32_pcm_ops
= {
350 .open
= at32_pcm_open
,
351 .close
= at32_pcm_close
,
352 .ioctl
= snd_pcm_lib_ioctl
,
353 .hw_params
= at32_pcm_hw_params
,
354 .hw_free
= at32_pcm_hw_free
,
355 .prepare
= at32_pcm_prepare
,
356 .trigger
= at32_pcm_trigger
,
357 .pointer
= at32_pcm_pointer
,
358 .mmap
= at32_pcm_mmap
,
363 /*--------------------------------------------------------------------------*\
364 * ASoC platform driver
365 \*--------------------------------------------------------------------------*/
366 static u64 at32_pcm_dmamask
= 0xffffffff;
368 static int at32_pcm_new(struct snd_card
*card
,
369 struct snd_soc_dai
*dai
,
374 if (!card
->dev
->dma_mask
)
375 card
->dev
->dma_mask
= &at32_pcm_dmamask
;
376 if (!card
->dev
->coherent_dma_mask
)
377 card
->dev
->coherent_dma_mask
= 0xffffffff;
379 if (dai
->playback
.channels_min
) {
380 ret
= at32_pcm_preallocate_dma_buffer(
381 pcm
, SNDRV_PCM_STREAM_PLAYBACK
);
386 if (dai
->capture
.channels_min
) {
387 pr_debug("at32-pcm: Allocating PCM capture DMA buffer\n");
388 ret
= at32_pcm_preallocate_dma_buffer(
389 pcm
, SNDRV_PCM_STREAM_CAPTURE
);
401 static void at32_pcm_free_dma_buffers(struct snd_pcm
*pcm
)
403 struct snd_pcm_substream
*substream
;
404 struct snd_dma_buffer
*buf
;
407 for (stream
= 0; stream
< 2; stream
++) {
408 substream
= pcm
->streams
[stream
].substream
;
409 if (substream
== NULL
)
412 buf
= &substream
->dma_buffer
;
415 dma_free_coherent(pcm
->card
->dev
, buf
->bytes
,
416 buf
->area
, buf
->addr
);
424 static int at32_pcm_suspend(struct platform_device
*pdev
,
425 struct snd_soc_dai
*dai
)
427 struct snd_pcm_runtime
*runtime
= dai
->runtime
;
428 struct at32_runtime_data
*prtd
;
429 struct at32_pcm_dma_params
*params
;
433 prtd
= runtime
->private_data
;
434 params
= prtd
->params
;
436 /* Disable the PDC and save the PDC registers */
437 ssc_writex(params
->ssc
->regs
, ATMEL_PDC_PTCR
,
438 params
->mask
->pdc_disable
);
440 prtd
->pdc_xpr_save
= ssc_readx(params
->ssc
->regs
, params
->pdc
->xpr
);
441 prtd
->pdc_xcr_save
= ssc_readx(params
->ssc
->regs
, params
->pdc
->xcr
);
442 prtd
->pdc_xnpr_save
= ssc_readx(params
->ssc
->regs
, params
->pdc
->xnpr
);
443 prtd
->pdc_xncr_save
= ssc_readx(params
->ssc
->regs
, params
->pdc
->xncr
);
450 static int at32_pcm_resume(struct platform_device
*pdev
,
451 struct snd_soc_dai
*dai
)
453 struct snd_pcm_runtime
*runtime
= dai
->runtime
;
454 struct at32_runtime_data
*prtd
;
455 struct at32_pcm_dma_params
*params
;
459 prtd
= runtime
->private_data
;
460 params
= prtd
->params
;
462 /* Restore the PDC registers and enable the PDC */
463 ssc_writex(params
->ssc
->regs
, params
->pdc
->xpr
, prtd
->pdc_xpr_save
);
464 ssc_writex(params
->ssc
->regs
, params
->pdc
->xcr
, prtd
->pdc_xcr_save
);
465 ssc_writex(params
->ssc
->regs
, params
->pdc
->xnpr
, prtd
->pdc_xnpr_save
);
466 ssc_writex(params
->ssc
->regs
, params
->pdc
->xncr
, prtd
->pdc_xncr_save
);
468 ssc_writex(params
->ssc
->regs
, ATMEL_PDC_PTCR
, params
->mask
->pdc_enable
);
471 #else /* CONFIG_PM */
472 # define at32_pcm_suspend NULL
473 # define at32_pcm_resume NULL
474 #endif /* CONFIG_PM */
478 struct snd_soc_platform at32_soc_platform
= {
479 .name
= "at32-audio",
480 .pcm_ops
= &at32_pcm_ops
,
481 .pcm_new
= at32_pcm_new
,
482 .pcm_free
= at32_pcm_free_dma_buffers
,
483 .suspend
= at32_pcm_suspend
,
484 .resume
= at32_pcm_resume
,
486 EXPORT_SYMBOL_GPL(at32_soc_platform
);
490 MODULE_AUTHOR("Geoffrey Wossum <gwossum@acm.org>");
491 MODULE_DESCRIPTION("Atmel AT32 PCM module");
492 MODULE_LICENSE("GPL");