2 * Au1000/Au1500/Au1100 Audio DMA support.
4 * (c) 2011 Manuel Lauss <manuel.lauss@googlemail.com>
6 * copied almost verbatim from the old ALSA driver, written by
7 * Charles Eidsness <charles@cooper-street.com>
10 #include <linux/module.h>
11 #include <linux/init.h>
12 #include <linux/platform_device.h>
13 #include <linux/slab.h>
14 #include <linux/dma-mapping.h>
15 #include <sound/core.h>
16 #include <sound/pcm.h>
17 #include <sound/pcm_params.h>
18 #include <sound/soc.h>
19 #include <asm/mach-au1x00/au1000.h>
20 #include <asm/mach-au1x00/au1000_dma.h>
24 #define ALCHEMY_PCM_FMTS \
25 (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 | \
26 SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | \
27 SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_U16_BE | \
28 SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE | \
29 SNDRV_PCM_FMTBIT_U32_LE | SNDRV_PCM_FMTBIT_U32_BE | \
34 u32 relative_end
; /* relative to start of buffer */
35 struct pcm_period
*next
;
39 struct snd_pcm_substream
*substream
;
41 struct pcm_period
*buffer
;
42 unsigned int period_size
;
46 struct alchemy_pcm_ctx
{
47 struct audio_stream stream
[2]; /* playback & capture */
50 static void au1000_release_dma_link(struct audio_stream
*stream
)
52 struct pcm_period
*pointer
;
53 struct pcm_period
*pointer_next
;
55 stream
->period_size
= 0;
57 pointer
= stream
->buffer
;
61 pointer_next
= pointer
->next
;
63 pointer
= pointer_next
;
64 } while (pointer
!= stream
->buffer
);
65 stream
->buffer
= NULL
;
68 static int au1000_setup_dma_link(struct audio_stream
*stream
,
69 unsigned int period_bytes
,
72 struct snd_pcm_substream
*substream
= stream
->substream
;
73 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
74 struct pcm_period
*pointer
;
75 unsigned long dma_start
;
78 dma_start
= virt_to_phys(runtime
->dma_area
);
80 if (stream
->period_size
== period_bytes
&&
81 stream
->periods
== periods
)
82 return 0; /* not changed */
84 au1000_release_dma_link(stream
);
86 stream
->period_size
= period_bytes
;
87 stream
->periods
= periods
;
89 stream
->buffer
= kmalloc(sizeof(struct pcm_period
), GFP_KERNEL
);
92 pointer
= stream
->buffer
;
93 for (i
= 0; i
< periods
; i
++) {
94 pointer
->start
= (u32
)(dma_start
+ (i
* period_bytes
));
95 pointer
->relative_end
= (u32
) (((i
+1) * period_bytes
) - 0x1);
96 if (i
< periods
- 1) {
97 pointer
->next
= kmalloc(sizeof(struct pcm_period
),
100 au1000_release_dma_link(stream
);
103 pointer
= pointer
->next
;
106 pointer
->next
= stream
->buffer
;
110 static void au1000_dma_stop(struct audio_stream
*stream
)
113 disable_dma(stream
->dma
);
116 static void au1000_dma_start(struct audio_stream
*stream
)
121 init_dma(stream
->dma
);
122 if (get_dma_active_buffer(stream
->dma
) == 0) {
123 clear_dma_done0(stream
->dma
);
124 set_dma_addr0(stream
->dma
, stream
->buffer
->start
);
125 set_dma_count0(stream
->dma
, stream
->period_size
>> 1);
126 set_dma_addr1(stream
->dma
, stream
->buffer
->next
->start
);
127 set_dma_count1(stream
->dma
, stream
->period_size
>> 1);
129 clear_dma_done1(stream
->dma
);
130 set_dma_addr1(stream
->dma
, stream
->buffer
->start
);
131 set_dma_count1(stream
->dma
, stream
->period_size
>> 1);
132 set_dma_addr0(stream
->dma
, stream
->buffer
->next
->start
);
133 set_dma_count0(stream
->dma
, stream
->period_size
>> 1);
135 enable_dma_buffers(stream
->dma
);
136 start_dma(stream
->dma
);
139 static irqreturn_t
au1000_dma_interrupt(int irq
, void *ptr
)
141 struct audio_stream
*stream
= (struct audio_stream
*)ptr
;
142 struct snd_pcm_substream
*substream
= stream
->substream
;
144 switch (get_dma_buffer_done(stream
->dma
)) {
146 stream
->buffer
= stream
->buffer
->next
;
147 clear_dma_done0(stream
->dma
);
148 set_dma_addr0(stream
->dma
, stream
->buffer
->next
->start
);
149 set_dma_count0(stream
->dma
, stream
->period_size
>> 1);
150 enable_dma_buffer0(stream
->dma
);
153 stream
->buffer
= stream
->buffer
->next
;
154 clear_dma_done1(stream
->dma
);
155 set_dma_addr1(stream
->dma
, stream
->buffer
->next
->start
);
156 set_dma_count1(stream
->dma
, stream
->period_size
>> 1);
157 enable_dma_buffer1(stream
->dma
);
159 case (DMA_D0
| DMA_D1
):
160 pr_debug("DMA %d missed interrupt.\n", stream
->dma
);
161 au1000_dma_stop(stream
);
162 au1000_dma_start(stream
);
164 case (~DMA_D0
& ~DMA_D1
):
165 pr_debug("DMA %d empty irq.\n", stream
->dma
);
167 snd_pcm_period_elapsed(substream
);
171 static const struct snd_pcm_hardware alchemy_pcm_hardware
= {
172 .info
= SNDRV_PCM_INFO_MMAP
| SNDRV_PCM_INFO_MMAP_VALID
|
173 SNDRV_PCM_INFO_INTERLEAVED
| SNDRV_PCM_INFO_BATCH
,
174 .formats
= ALCHEMY_PCM_FMTS
,
175 .rates
= SNDRV_PCM_RATE_8000_192000
,
176 .rate_min
= SNDRV_PCM_RATE_8000
,
177 .rate_max
= SNDRV_PCM_RATE_192000
,
180 .period_bytes_min
= 1024,
181 .period_bytes_max
= 16 * 1024 - 1,
184 .buffer_bytes_max
= 128 * 1024,
188 static inline struct alchemy_pcm_ctx
*ss_to_ctx(struct snd_pcm_substream
*ss
)
190 struct snd_soc_pcm_runtime
*rtd
= ss
->private_data
;
191 return snd_soc_platform_get_drvdata(rtd
->platform
);
194 static inline struct audio_stream
*ss_to_as(struct snd_pcm_substream
*ss
)
196 struct alchemy_pcm_ctx
*ctx
= ss_to_ctx(ss
);
197 return &(ctx
->stream
[ss
->stream
]);
200 static int alchemy_pcm_open(struct snd_pcm_substream
*substream
)
202 struct alchemy_pcm_ctx
*ctx
= ss_to_ctx(substream
);
203 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
204 int *dmaids
, s
= substream
->stream
;
207 dmaids
= snd_soc_dai_get_dma_data(rtd
->cpu_dai
, substream
);
209 return -ENODEV
; /* whoa, has ordering changed? */
212 name
= (s
== SNDRV_PCM_STREAM_PLAYBACK
) ? "audio-tx" : "audio-rx";
213 ctx
->stream
[s
].dma
= request_au1000_dma(dmaids
[s
], name
,
214 au1000_dma_interrupt
, 0,
216 set_dma_mode(ctx
->stream
[s
].dma
,
217 get_dma_mode(ctx
->stream
[s
].dma
) & ~DMA_NC
);
219 ctx
->stream
[s
].substream
= substream
;
220 ctx
->stream
[s
].buffer
= NULL
;
221 snd_soc_set_runtime_hwparams(substream
, &alchemy_pcm_hardware
);
226 static int alchemy_pcm_close(struct snd_pcm_substream
*substream
)
228 struct alchemy_pcm_ctx
*ctx
= ss_to_ctx(substream
);
229 int stype
= substream
->stream
;
231 ctx
->stream
[stype
].substream
= NULL
;
232 free_au1000_dma(ctx
->stream
[stype
].dma
);
237 static int alchemy_pcm_hw_params(struct snd_pcm_substream
*substream
,
238 struct snd_pcm_hw_params
*hw_params
)
240 struct audio_stream
*stream
= ss_to_as(substream
);
243 err
= snd_pcm_lib_malloc_pages(substream
,
244 params_buffer_bytes(hw_params
));
247 err
= au1000_setup_dma_link(stream
,
248 params_period_bytes(hw_params
),
249 params_periods(hw_params
));
251 snd_pcm_lib_free_pages(substream
);
256 static int alchemy_pcm_hw_free(struct snd_pcm_substream
*substream
)
258 struct audio_stream
*stream
= ss_to_as(substream
);
259 au1000_release_dma_link(stream
);
260 return snd_pcm_lib_free_pages(substream
);
263 static int alchemy_pcm_trigger(struct snd_pcm_substream
*substream
, int cmd
)
265 struct audio_stream
*stream
= ss_to_as(substream
);
269 case SNDRV_PCM_TRIGGER_START
:
270 au1000_dma_start(stream
);
272 case SNDRV_PCM_TRIGGER_STOP
:
273 au1000_dma_stop(stream
);
282 static snd_pcm_uframes_t
alchemy_pcm_pointer(struct snd_pcm_substream
*ss
)
284 struct audio_stream
*stream
= ss_to_as(ss
);
287 location
= get_dma_residue(stream
->dma
);
288 location
= stream
->buffer
->relative_end
- location
;
291 return bytes_to_frames(ss
->runtime
, location
);
294 static struct snd_pcm_ops alchemy_pcm_ops
= {
295 .open
= alchemy_pcm_open
,
296 .close
= alchemy_pcm_close
,
297 .ioctl
= snd_pcm_lib_ioctl
,
298 .hw_params
= alchemy_pcm_hw_params
,
299 .hw_free
= alchemy_pcm_hw_free
,
300 .trigger
= alchemy_pcm_trigger
,
301 .pointer
= alchemy_pcm_pointer
,
304 static void alchemy_pcm_free_dma_buffers(struct snd_pcm
*pcm
)
306 snd_pcm_lib_preallocate_free_for_all(pcm
);
309 static int alchemy_pcm_new(struct snd_soc_pcm_runtime
*rtd
)
311 struct snd_pcm
*pcm
= rtd
->pcm
;
313 snd_pcm_lib_preallocate_pages_for_all(pcm
, SNDRV_DMA_TYPE_CONTINUOUS
,
314 snd_dma_continuous_data(GFP_KERNEL
), 65536, (4096 * 1024) - 1);
319 static struct snd_soc_platform_driver alchemy_pcm_soc_platform
= {
320 .ops
= &alchemy_pcm_ops
,
321 .pcm_new
= alchemy_pcm_new
,
322 .pcm_free
= alchemy_pcm_free_dma_buffers
,
325 static int __devinit
alchemy_pcm_drvprobe(struct platform_device
*pdev
)
327 struct alchemy_pcm_ctx
*ctx
;
329 ctx
= devm_kzalloc(&pdev
->dev
, sizeof(*ctx
), GFP_KERNEL
);
333 platform_set_drvdata(pdev
, ctx
);
335 return snd_soc_register_platform(&pdev
->dev
, &alchemy_pcm_soc_platform
);
338 static int __devexit
alchemy_pcm_drvremove(struct platform_device
*pdev
)
340 snd_soc_unregister_platform(&pdev
->dev
);
345 static struct platform_driver alchemy_pcmdma_driver
= {
347 .name
= "alchemy-pcm-dma",
348 .owner
= THIS_MODULE
,
350 .probe
= alchemy_pcm_drvprobe
,
351 .remove
= __devexit_p(alchemy_pcm_drvremove
),
354 module_platform_driver(alchemy_pcmdma_driver
);
356 MODULE_LICENSE("GPL");
357 MODULE_DESCRIPTION("Au1000/Au1500/Au1100 Audio DMA driver");
358 MODULE_AUTHOR("Manuel Lauss");