2 * Generic TXx9 ACLC platform driver
4 * Copyright (C) 2009 Atsushi Nemoto
6 * Based on RBTX49xx patch from CELF patch archive.
7 * (C) Copyright TOSHIBA CORPORATION 2004-2006
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
14 #include <linux/module.h>
15 #include <linux/init.h>
16 #include <linux/platform_device.h>
17 #include <linux/scatterlist.h>
18 #include <linux/slab.h>
19 #include <sound/core.h>
20 #include <sound/pcm.h>
21 #include <sound/pcm_params.h>
22 #include <sound/soc.h>
25 static const struct snd_pcm_hardware txx9aclc_pcm_hardware
= {
27 * REVISIT: SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID
28 * needs more works for noncoherent MIPS.
30 .info
= SNDRV_PCM_INFO_INTERLEAVED
|
31 SNDRV_PCM_INFO_BATCH
|
34 .formats
= SNDRV_PCM_FMTBIT_S16_BE
,
36 .formats
= SNDRV_PCM_FMTBIT_S16_LE
,
38 .period_bytes_min
= 1024,
39 .period_bytes_max
= 8 * 1024,
42 .buffer_bytes_max
= 32 * 1024,
45 static int txx9aclc_pcm_hw_params(struct snd_pcm_substream
*substream
,
46 struct snd_pcm_hw_params
*params
)
48 struct snd_soc_pcm_runtime
*rtd
= snd_pcm_substream_chip(substream
);
49 struct snd_soc_device
*socdev
= rtd
->socdev
;
50 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
51 struct txx9aclc_dmadata
*dmadata
= runtime
->private_data
;
54 ret
= snd_pcm_lib_malloc_pages(substream
, params_buffer_bytes(params
));
59 "runtime->dma_area = %#lx dma_addr = %#lx dma_bytes = %zd "
60 "runtime->min_align %ld\n",
61 (unsigned long)runtime
->dma_area
,
62 (unsigned long)runtime
->dma_addr
, runtime
->dma_bytes
,
65 "periods %d period_bytes %d stream %d\n",
66 params_periods(params
), params_period_bytes(params
),
69 dmadata
->substream
= substream
;
74 static int txx9aclc_pcm_hw_free(struct snd_pcm_substream
*substream
)
76 return snd_pcm_lib_free_pages(substream
);
79 static int txx9aclc_pcm_prepare(struct snd_pcm_substream
*substream
)
81 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
82 struct txx9aclc_dmadata
*dmadata
= runtime
->private_data
;
84 dmadata
->dma_addr
= runtime
->dma_addr
;
85 dmadata
->buffer_bytes
= snd_pcm_lib_buffer_bytes(substream
);
86 dmadata
->period_bytes
= snd_pcm_lib_period_bytes(substream
);
88 if (dmadata
->buffer_bytes
== dmadata
->period_bytes
) {
89 dmadata
->frag_bytes
= dmadata
->period_bytes
>> 1;
92 dmadata
->frag_bytes
= dmadata
->period_bytes
;
93 dmadata
->frags
= dmadata
->buffer_bytes
/ dmadata
->period_bytes
;
95 dmadata
->frag_count
= 0;
100 static void txx9aclc_dma_complete(void *arg
)
102 struct txx9aclc_dmadata
*dmadata
= arg
;
105 /* dma completion handler cannot submit new operations */
106 spin_lock_irqsave(&dmadata
->dma_lock
, flags
);
107 if (dmadata
->frag_count
>= 0) {
109 BUG_ON(dmadata
->dmacount
< 0);
110 tasklet_schedule(&dmadata
->tasklet
);
112 spin_unlock_irqrestore(&dmadata
->dma_lock
, flags
);
115 static struct dma_async_tx_descriptor
*
116 txx9aclc_dma_submit(struct txx9aclc_dmadata
*dmadata
, dma_addr_t buf_dma_addr
)
118 struct dma_chan
*chan
= dmadata
->dma_chan
;
119 struct dma_async_tx_descriptor
*desc
;
120 struct scatterlist sg
;
122 sg_init_table(&sg
, 1);
123 sg_set_page(&sg
, pfn_to_page(PFN_DOWN(buf_dma_addr
)),
124 dmadata
->frag_bytes
, buf_dma_addr
& (PAGE_SIZE
- 1));
125 sg_dma_address(&sg
) = buf_dma_addr
;
126 desc
= chan
->device
->device_prep_slave_sg(chan
, &sg
, 1,
127 dmadata
->substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
?
128 DMA_TO_DEVICE
: DMA_FROM_DEVICE
,
129 DMA_PREP_INTERRUPT
| DMA_CTRL_ACK
);
131 dev_err(&chan
->dev
->device
, "cannot prepare slave dma\n");
134 desc
->callback
= txx9aclc_dma_complete
;
135 desc
->callback_param
= dmadata
;
136 desc
->tx_submit(desc
);
140 #define NR_DMA_CHAIN 2
142 static void txx9aclc_dma_tasklet(unsigned long data
)
144 struct txx9aclc_dmadata
*dmadata
= (struct txx9aclc_dmadata
*)data
;
145 struct dma_chan
*chan
= dmadata
->dma_chan
;
146 struct dma_async_tx_descriptor
*desc
;
147 struct snd_pcm_substream
*substream
= dmadata
->substream
;
148 u32 ctlbit
= substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
?
149 ACCTL_AUDODMA
: ACCTL_AUDIDMA
;
153 spin_lock_irqsave(&dmadata
->dma_lock
, flags
);
154 if (dmadata
->frag_count
< 0) {
155 struct txx9aclc_soc_device
*dev
=
156 container_of(dmadata
, struct txx9aclc_soc_device
,
157 dmadata
[substream
->stream
]);
158 struct txx9aclc_plat_drvdata
*drvdata
=
159 txx9aclc_get_plat_drvdata(dev
);
160 void __iomem
*base
= drvdata
->base
;
162 spin_unlock_irqrestore(&dmadata
->dma_lock
, flags
);
163 chan
->device
->device_terminate_all(chan
);
165 for (i
= 0; i
< NR_DMA_CHAIN
; i
++) {
166 desc
= txx9aclc_dma_submit(dmadata
,
167 dmadata
->dma_addr
+ i
* dmadata
->frag_bytes
);
171 dmadata
->dmacount
= NR_DMA_CHAIN
;
172 chan
->device
->device_issue_pending(chan
);
173 spin_lock_irqsave(&dmadata
->dma_lock
, flags
);
174 __raw_writel(ctlbit
, base
+ ACCTLEN
);
175 dmadata
->frag_count
= NR_DMA_CHAIN
% dmadata
->frags
;
176 spin_unlock_irqrestore(&dmadata
->dma_lock
, flags
);
179 BUG_ON(dmadata
->dmacount
>= NR_DMA_CHAIN
);
180 while (dmadata
->dmacount
< NR_DMA_CHAIN
) {
182 spin_unlock_irqrestore(&dmadata
->dma_lock
, flags
);
183 desc
= txx9aclc_dma_submit(dmadata
,
185 dmadata
->frag_count
* dmadata
->frag_bytes
);
188 chan
->device
->device_issue_pending(chan
);
190 spin_lock_irqsave(&dmadata
->dma_lock
, flags
);
191 dmadata
->frag_count
++;
192 dmadata
->frag_count
%= dmadata
->frags
;
193 dmadata
->pos
+= dmadata
->frag_bytes
;
194 dmadata
->pos
%= dmadata
->buffer_bytes
;
195 if ((dmadata
->frag_count
* dmadata
->frag_bytes
) %
196 dmadata
->period_bytes
== 0)
197 snd_pcm_period_elapsed(substream
);
199 spin_unlock_irqrestore(&dmadata
->dma_lock
, flags
);
202 static int txx9aclc_pcm_trigger(struct snd_pcm_substream
*substream
, int cmd
)
204 struct txx9aclc_dmadata
*dmadata
= substream
->runtime
->private_data
;
205 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
206 struct txx9aclc_soc_device
*dev
=
207 container_of(rtd
->socdev
, struct txx9aclc_soc_device
, soc_dev
);
208 struct txx9aclc_plat_drvdata
*drvdata
= txx9aclc_get_plat_drvdata(dev
);
209 void __iomem
*base
= drvdata
->base
;
212 u32 ctlbit
= substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
?
213 ACCTL_AUDODMA
: ACCTL_AUDIDMA
;
215 spin_lock_irqsave(&dmadata
->dma_lock
, flags
);
217 case SNDRV_PCM_TRIGGER_START
:
218 dmadata
->frag_count
= -1;
219 tasklet_schedule(&dmadata
->tasklet
);
221 case SNDRV_PCM_TRIGGER_STOP
:
222 case SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
223 case SNDRV_PCM_TRIGGER_SUSPEND
:
224 __raw_writel(ctlbit
, base
+ ACCTLDIS
);
226 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
227 case SNDRV_PCM_TRIGGER_RESUME
:
228 __raw_writel(ctlbit
, base
+ ACCTLEN
);
233 spin_unlock_irqrestore(&dmadata
->dma_lock
, flags
);
237 static snd_pcm_uframes_t
238 txx9aclc_pcm_pointer(struct snd_pcm_substream
*substream
)
240 struct txx9aclc_dmadata
*dmadata
= substream
->runtime
->private_data
;
242 return bytes_to_frames(substream
->runtime
, dmadata
->pos
);
245 static int txx9aclc_pcm_open(struct snd_pcm_substream
*substream
)
247 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
248 struct txx9aclc_soc_device
*dev
=
249 container_of(rtd
->socdev
, struct txx9aclc_soc_device
, soc_dev
);
250 struct txx9aclc_dmadata
*dmadata
= &dev
->dmadata
[substream
->stream
];
253 ret
= snd_soc_set_runtime_hwparams(substream
, &txx9aclc_pcm_hardware
);
256 /* ensure that buffer size is a multiple of period size */
257 ret
= snd_pcm_hw_constraint_integer(substream
->runtime
,
258 SNDRV_PCM_HW_PARAM_PERIODS
);
261 substream
->runtime
->private_data
= dmadata
;
265 static int txx9aclc_pcm_close(struct snd_pcm_substream
*substream
)
267 struct txx9aclc_dmadata
*dmadata
= substream
->runtime
->private_data
;
268 struct dma_chan
*chan
= dmadata
->dma_chan
;
270 dmadata
->frag_count
= -1;
271 chan
->device
->device_terminate_all(chan
);
275 static struct snd_pcm_ops txx9aclc_pcm_ops
= {
276 .open
= txx9aclc_pcm_open
,
277 .close
= txx9aclc_pcm_close
,
278 .ioctl
= snd_pcm_lib_ioctl
,
279 .hw_params
= txx9aclc_pcm_hw_params
,
280 .hw_free
= txx9aclc_pcm_hw_free
,
281 .prepare
= txx9aclc_pcm_prepare
,
282 .trigger
= txx9aclc_pcm_trigger
,
283 .pointer
= txx9aclc_pcm_pointer
,
286 static void txx9aclc_pcm_free_dma_buffers(struct snd_pcm
*pcm
)
288 snd_pcm_lib_preallocate_free_for_all(pcm
);
291 static int txx9aclc_pcm_new(struct snd_card
*card
, struct snd_soc_dai
*dai
,
294 return snd_pcm_lib_preallocate_pages_for_all(pcm
, SNDRV_DMA_TYPE_DEV
,
295 card
->dev
, 64 * 1024, 4 * 1024 * 1024);
298 static bool filter(struct dma_chan
*chan
, void *param
)
300 struct txx9aclc_dmadata
*dmadata
= param
;
304 devname
= kasprintf(GFP_KERNEL
, "%s.%d", dmadata
->dma_res
->name
,
305 (int)dmadata
->dma_res
->start
);
306 if (strcmp(dev_name(chan
->device
->dev
), devname
) == 0) {
307 chan
->private = &dmadata
->dma_slave
;
314 static int txx9aclc_dma_init(struct txx9aclc_soc_device
*dev
,
315 struct txx9aclc_dmadata
*dmadata
)
317 struct txx9aclc_plat_drvdata
*drvdata
= txx9aclc_get_plat_drvdata(dev
);
318 struct txx9dmac_slave
*ds
= &dmadata
->dma_slave
;
321 spin_lock_init(&dmadata
->dma_lock
);
323 ds
->reg_width
= sizeof(u32
);
324 if (dmadata
->stream
== SNDRV_PCM_STREAM_PLAYBACK
) {
325 ds
->tx_reg
= drvdata
->physbase
+ ACAUDODAT
;
329 ds
->rx_reg
= drvdata
->physbase
+ ACAUDIDAT
;
332 /* Try to grab a DMA channel */
334 dma_cap_set(DMA_SLAVE
, mask
);
335 dmadata
->dma_chan
= dma_request_channel(mask
, filter
, dmadata
);
336 if (!dmadata
->dma_chan
) {
337 dev_err(dev
->soc_dev
.dev
,
338 "DMA channel for %s is not available\n",
339 dmadata
->stream
== SNDRV_PCM_STREAM_PLAYBACK
?
340 "playback" : "capture");
343 tasklet_init(&dmadata
->tasklet
, txx9aclc_dma_tasklet
,
344 (unsigned long)dmadata
);
348 static int txx9aclc_pcm_probe(struct platform_device
*pdev
)
350 struct snd_soc_device
*socdev
= platform_get_drvdata(pdev
);
351 struct txx9aclc_soc_device
*dev
=
352 container_of(socdev
, struct txx9aclc_soc_device
, soc_dev
);
357 dev
->dmadata
[0].stream
= SNDRV_PCM_STREAM_PLAYBACK
;
358 dev
->dmadata
[1].stream
= SNDRV_PCM_STREAM_CAPTURE
;
359 for (i
= 0; i
< 2; i
++) {
360 r
= platform_get_resource(dev
->aclc_pdev
, IORESOURCE_DMA
, i
);
365 dev
->dmadata
[i
].dma_res
= r
;
366 ret
= txx9aclc_dma_init(dev
, &dev
->dmadata
[i
]);
373 for (i
= 0; i
< 2; i
++) {
374 if (dev
->dmadata
[i
].dma_chan
)
375 dma_release_channel(dev
->dmadata
[i
].dma_chan
);
376 dev
->dmadata
[i
].dma_chan
= NULL
;
381 static int txx9aclc_pcm_remove(struct platform_device
*pdev
)
383 struct snd_soc_device
*socdev
= platform_get_drvdata(pdev
);
384 struct txx9aclc_soc_device
*dev
=
385 container_of(socdev
, struct txx9aclc_soc_device
, soc_dev
);
386 struct txx9aclc_plat_drvdata
*drvdata
= txx9aclc_get_plat_drvdata(dev
);
387 void __iomem
*base
= drvdata
->base
;
390 /* disable all FIFO DMAs */
391 __raw_writel(ACCTL_AUDODMA
| ACCTL_AUDIDMA
, base
+ ACCTLDIS
);
392 /* dummy R/W to clear pending DMAREQ if any */
393 __raw_writel(__raw_readl(base
+ ACAUDIDAT
), base
+ ACAUDODAT
);
395 for (i
= 0; i
< 2; i
++) {
396 struct txx9aclc_dmadata
*dmadata
= &dev
->dmadata
[i
];
397 struct dma_chan
*chan
= dmadata
->dma_chan
;
399 dmadata
->frag_count
= -1;
400 chan
->device
->device_terminate_all(chan
);
401 dma_release_channel(chan
);
403 dev
->dmadata
[i
].dma_chan
= NULL
;
408 struct snd_soc_platform txx9aclc_soc_platform
= {
409 .name
= "txx9aclc-audio",
410 .probe
= txx9aclc_pcm_probe
,
411 .remove
= txx9aclc_pcm_remove
,
412 .pcm_ops
= &txx9aclc_pcm_ops
,
413 .pcm_new
= txx9aclc_pcm_new
,
414 .pcm_free
= txx9aclc_pcm_free_dma_buffers
,
416 EXPORT_SYMBOL_GPL(txx9aclc_soc_platform
);
418 static int __init
txx9aclc_soc_platform_init(void)
420 return snd_soc_register_platform(&txx9aclc_soc_platform
);
423 static void __exit
txx9aclc_soc_platform_exit(void)
425 snd_soc_unregister_platform(&txx9aclc_soc_platform
);
428 module_init(txx9aclc_soc_platform_init
);
429 module_exit(txx9aclc_soc_platform_exit
);
431 MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>");
432 MODULE_DESCRIPTION("TXx9 ACLC Audio DMA driver");
433 MODULE_LICENSE("GPL");