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 struct txx9aclc_soc_device
{
26 struct txx9aclc_dmadata dmadata
[2];
27 } txx9aclc_soc_device
;
29 /* REVISIT: How to find txx9aclc_drvdata from snd_ac97? */
30 static struct txx9aclc_plat_drvdata
*txx9aclc_drvdata
;
32 static int txx9aclc_dma_init(struct txx9aclc_soc_device
*dev
,
33 struct txx9aclc_dmadata
*dmadata
);
35 static const struct snd_pcm_hardware txx9aclc_pcm_hardware
= {
37 * REVISIT: SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID
38 * needs more works for noncoherent MIPS.
40 .info
= SNDRV_PCM_INFO_INTERLEAVED
|
41 SNDRV_PCM_INFO_BATCH
|
44 .formats
= SNDRV_PCM_FMTBIT_S16_BE
,
46 .formats
= SNDRV_PCM_FMTBIT_S16_LE
,
48 .period_bytes_min
= 1024,
49 .period_bytes_max
= 8 * 1024,
52 .buffer_bytes_max
= 32 * 1024,
55 static int txx9aclc_pcm_hw_params(struct snd_pcm_substream
*substream
,
56 struct snd_pcm_hw_params
*params
)
58 struct snd_soc_pcm_runtime
*rtd
= snd_pcm_substream_chip(substream
);
59 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
60 struct txx9aclc_dmadata
*dmadata
= runtime
->private_data
;
63 ret
= snd_pcm_lib_malloc_pages(substream
, params_buffer_bytes(params
));
67 dev_dbg(rtd
->platform
->dev
,
68 "runtime->dma_area = %#lx dma_addr = %#lx dma_bytes = %zd "
69 "runtime->min_align %ld\n",
70 (unsigned long)runtime
->dma_area
,
71 (unsigned long)runtime
->dma_addr
, runtime
->dma_bytes
,
73 dev_dbg(rtd
->platform
->dev
,
74 "periods %d period_bytes %d stream %d\n",
75 params_periods(params
), params_period_bytes(params
),
78 dmadata
->substream
= substream
;
83 static int txx9aclc_pcm_hw_free(struct snd_pcm_substream
*substream
)
85 return snd_pcm_lib_free_pages(substream
);
88 static int txx9aclc_pcm_prepare(struct snd_pcm_substream
*substream
)
90 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
91 struct txx9aclc_dmadata
*dmadata
= runtime
->private_data
;
93 dmadata
->dma_addr
= runtime
->dma_addr
;
94 dmadata
->buffer_bytes
= snd_pcm_lib_buffer_bytes(substream
);
95 dmadata
->period_bytes
= snd_pcm_lib_period_bytes(substream
);
97 if (dmadata
->buffer_bytes
== dmadata
->period_bytes
) {
98 dmadata
->frag_bytes
= dmadata
->period_bytes
>> 1;
101 dmadata
->frag_bytes
= dmadata
->period_bytes
;
102 dmadata
->frags
= dmadata
->buffer_bytes
/ dmadata
->period_bytes
;
104 dmadata
->frag_count
= 0;
109 static void txx9aclc_dma_complete(void *arg
)
111 struct txx9aclc_dmadata
*dmadata
= arg
;
114 /* dma completion handler cannot submit new operations */
115 spin_lock_irqsave(&dmadata
->dma_lock
, flags
);
116 if (dmadata
->frag_count
>= 0) {
118 BUG_ON(dmadata
->dmacount
< 0);
119 tasklet_schedule(&dmadata
->tasklet
);
121 spin_unlock_irqrestore(&dmadata
->dma_lock
, flags
);
124 static struct dma_async_tx_descriptor
*
125 txx9aclc_dma_submit(struct txx9aclc_dmadata
*dmadata
, dma_addr_t buf_dma_addr
)
127 struct dma_chan
*chan
= dmadata
->dma_chan
;
128 struct dma_async_tx_descriptor
*desc
;
129 struct scatterlist sg
;
131 sg_init_table(&sg
, 1);
132 sg_set_page(&sg
, pfn_to_page(PFN_DOWN(buf_dma_addr
)),
133 dmadata
->frag_bytes
, buf_dma_addr
& (PAGE_SIZE
- 1));
134 sg_dma_address(&sg
) = buf_dma_addr
;
135 desc
= dmaengine_prep_slave_sg(chan
, &sg
, 1,
136 dmadata
->substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
?
137 DMA_MEM_TO_DEV
: DMA_DEV_TO_MEM
,
138 DMA_PREP_INTERRUPT
| DMA_CTRL_ACK
);
140 dev_err(&chan
->dev
->device
, "cannot prepare slave dma\n");
143 desc
->callback
= txx9aclc_dma_complete
;
144 desc
->callback_param
= dmadata
;
145 desc
->tx_submit(desc
);
149 #define NR_DMA_CHAIN 2
151 static void txx9aclc_dma_tasklet(unsigned long data
)
153 struct txx9aclc_dmadata
*dmadata
= (struct txx9aclc_dmadata
*)data
;
154 struct dma_chan
*chan
= dmadata
->dma_chan
;
155 struct dma_async_tx_descriptor
*desc
;
156 struct snd_pcm_substream
*substream
= dmadata
->substream
;
157 u32 ctlbit
= substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
?
158 ACCTL_AUDODMA
: ACCTL_AUDIDMA
;
162 spin_lock_irqsave(&dmadata
->dma_lock
, flags
);
163 if (dmadata
->frag_count
< 0) {
164 struct txx9aclc_plat_drvdata
*drvdata
= txx9aclc_drvdata
;
165 void __iomem
*base
= drvdata
->base
;
167 spin_unlock_irqrestore(&dmadata
->dma_lock
, flags
);
168 chan
->device
->device_control(chan
, DMA_TERMINATE_ALL
, 0);
170 for (i
= 0; i
< NR_DMA_CHAIN
; i
++) {
171 desc
= txx9aclc_dma_submit(dmadata
,
172 dmadata
->dma_addr
+ i
* dmadata
->frag_bytes
);
176 dmadata
->dmacount
= NR_DMA_CHAIN
;
177 chan
->device
->device_issue_pending(chan
);
178 spin_lock_irqsave(&dmadata
->dma_lock
, flags
);
179 __raw_writel(ctlbit
, base
+ ACCTLEN
);
180 dmadata
->frag_count
= NR_DMA_CHAIN
% dmadata
->frags
;
181 spin_unlock_irqrestore(&dmadata
->dma_lock
, flags
);
184 BUG_ON(dmadata
->dmacount
>= NR_DMA_CHAIN
);
185 while (dmadata
->dmacount
< NR_DMA_CHAIN
) {
187 spin_unlock_irqrestore(&dmadata
->dma_lock
, flags
);
188 desc
= txx9aclc_dma_submit(dmadata
,
190 dmadata
->frag_count
* dmadata
->frag_bytes
);
193 chan
->device
->device_issue_pending(chan
);
195 spin_lock_irqsave(&dmadata
->dma_lock
, flags
);
196 dmadata
->frag_count
++;
197 dmadata
->frag_count
%= dmadata
->frags
;
198 dmadata
->pos
+= dmadata
->frag_bytes
;
199 dmadata
->pos
%= dmadata
->buffer_bytes
;
200 if ((dmadata
->frag_count
* dmadata
->frag_bytes
) %
201 dmadata
->period_bytes
== 0)
202 snd_pcm_period_elapsed(substream
);
204 spin_unlock_irqrestore(&dmadata
->dma_lock
, flags
);
207 static int txx9aclc_pcm_trigger(struct snd_pcm_substream
*substream
, int cmd
)
209 struct txx9aclc_dmadata
*dmadata
= substream
->runtime
->private_data
;
210 struct txx9aclc_plat_drvdata
*drvdata
=txx9aclc_drvdata
;
211 void __iomem
*base
= drvdata
->base
;
214 u32 ctlbit
= substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
?
215 ACCTL_AUDODMA
: ACCTL_AUDIDMA
;
217 spin_lock_irqsave(&dmadata
->dma_lock
, flags
);
219 case SNDRV_PCM_TRIGGER_START
:
220 dmadata
->frag_count
= -1;
221 tasklet_schedule(&dmadata
->tasklet
);
223 case SNDRV_PCM_TRIGGER_STOP
:
224 case SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
225 case SNDRV_PCM_TRIGGER_SUSPEND
:
226 __raw_writel(ctlbit
, base
+ ACCTLDIS
);
228 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
229 case SNDRV_PCM_TRIGGER_RESUME
:
230 __raw_writel(ctlbit
, base
+ ACCTLEN
);
235 spin_unlock_irqrestore(&dmadata
->dma_lock
, flags
);
239 static snd_pcm_uframes_t
240 txx9aclc_pcm_pointer(struct snd_pcm_substream
*substream
)
242 struct txx9aclc_dmadata
*dmadata
= substream
->runtime
->private_data
;
244 return bytes_to_frames(substream
->runtime
, dmadata
->pos
);
247 static int txx9aclc_pcm_open(struct snd_pcm_substream
*substream
)
249 struct txx9aclc_soc_device
*dev
= &txx9aclc_soc_device
;
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_control(chan
, DMA_TERMINATE_ALL
, 0);
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_soc_pcm_runtime
*rtd
)
293 struct snd_card
*card
= rtd
->card
->snd_card
;
294 struct snd_soc_dai
*dai
= rtd
->cpu_dai
;
295 struct snd_pcm
*pcm
= rtd
->pcm
;
296 struct platform_device
*pdev
= to_platform_device(dai
->platform
->dev
);
297 struct txx9aclc_soc_device
*dev
;
302 /* at this point onwards the AC97 component has probed and this will be valid */
303 dev
= snd_soc_dai_get_drvdata(dai
);
305 dev
->dmadata
[0].stream
= SNDRV_PCM_STREAM_PLAYBACK
;
306 dev
->dmadata
[1].stream
= SNDRV_PCM_STREAM_CAPTURE
;
307 for (i
= 0; i
< 2; i
++) {
308 r
= platform_get_resource(pdev
, IORESOURCE_DMA
, i
);
313 dev
->dmadata
[i
].dma_res
= r
;
314 ret
= txx9aclc_dma_init(dev
, &dev
->dmadata
[i
]);
318 return snd_pcm_lib_preallocate_pages_for_all(pcm
, SNDRV_DMA_TYPE_DEV
,
319 card
->dev
, 64 * 1024, 4 * 1024 * 1024);
322 for (i
= 0; i
< 2; i
++) {
323 if (dev
->dmadata
[i
].dma_chan
)
324 dma_release_channel(dev
->dmadata
[i
].dma_chan
);
325 dev
->dmadata
[i
].dma_chan
= NULL
;
330 static bool filter(struct dma_chan
*chan
, void *param
)
332 struct txx9aclc_dmadata
*dmadata
= param
;
336 devname
= kasprintf(GFP_KERNEL
, "%s.%d", dmadata
->dma_res
->name
,
337 (int)dmadata
->dma_res
->start
);
338 if (strcmp(dev_name(chan
->device
->dev
), devname
) == 0) {
339 chan
->private = &dmadata
->dma_slave
;
346 static int txx9aclc_dma_init(struct txx9aclc_soc_device
*dev
,
347 struct txx9aclc_dmadata
*dmadata
)
349 struct txx9aclc_plat_drvdata
*drvdata
=txx9aclc_drvdata
;
350 struct txx9dmac_slave
*ds
= &dmadata
->dma_slave
;
353 spin_lock_init(&dmadata
->dma_lock
);
355 ds
->reg_width
= sizeof(u32
);
356 if (dmadata
->stream
== SNDRV_PCM_STREAM_PLAYBACK
) {
357 ds
->tx_reg
= drvdata
->physbase
+ ACAUDODAT
;
361 ds
->rx_reg
= drvdata
->physbase
+ ACAUDIDAT
;
364 /* Try to grab a DMA channel */
366 dma_cap_set(DMA_SLAVE
, mask
);
367 dmadata
->dma_chan
= dma_request_channel(mask
, filter
, dmadata
);
368 if (!dmadata
->dma_chan
) {
370 "DMA channel for %s is not available\n",
371 dmadata
->stream
== SNDRV_PCM_STREAM_PLAYBACK
?
372 "playback" : "capture");
375 tasklet_init(&dmadata
->tasklet
, txx9aclc_dma_tasklet
,
376 (unsigned long)dmadata
);
380 static int txx9aclc_pcm_probe(struct snd_soc_platform
*platform
)
382 snd_soc_platform_set_drvdata(platform
, &txx9aclc_soc_device
);
386 static int txx9aclc_pcm_remove(struct snd_soc_platform
*platform
)
388 struct txx9aclc_soc_device
*dev
= snd_soc_platform_get_drvdata(platform
);
389 struct txx9aclc_plat_drvdata
*drvdata
= txx9aclc_drvdata
;
390 void __iomem
*base
= drvdata
->base
;
393 /* disable all FIFO DMAs */
394 __raw_writel(ACCTL_AUDODMA
| ACCTL_AUDIDMA
, base
+ ACCTLDIS
);
395 /* dummy R/W to clear pending DMAREQ if any */
396 __raw_writel(__raw_readl(base
+ ACAUDIDAT
), base
+ ACAUDODAT
);
398 for (i
= 0; i
< 2; i
++) {
399 struct txx9aclc_dmadata
*dmadata
= &dev
->dmadata
[i
];
400 struct dma_chan
*chan
= dmadata
->dma_chan
;
402 dmadata
->frag_count
= -1;
403 chan
->device
->device_control(chan
,
404 DMA_TERMINATE_ALL
, 0);
405 dma_release_channel(chan
);
407 dev
->dmadata
[i
].dma_chan
= NULL
;
412 static struct snd_soc_platform_driver txx9aclc_soc_platform
= {
413 .probe
= txx9aclc_pcm_probe
,
414 .remove
= txx9aclc_pcm_remove
,
415 .ops
= &txx9aclc_pcm_ops
,
416 .pcm_new
= txx9aclc_pcm_new
,
417 .pcm_free
= txx9aclc_pcm_free_dma_buffers
,
420 static int txx9aclc_soc_platform_probe(struct platform_device
*pdev
)
422 return snd_soc_register_platform(&pdev
->dev
, &txx9aclc_soc_platform
);
425 static int txx9aclc_soc_platform_remove(struct platform_device
*pdev
)
427 snd_soc_unregister_platform(&pdev
->dev
);
431 static struct platform_driver txx9aclc_pcm_driver
= {
433 .name
= "txx9aclc-pcm-audio",
434 .owner
= THIS_MODULE
,
437 .probe
= txx9aclc_soc_platform_probe
,
438 .remove
= txx9aclc_soc_platform_remove
,
441 module_platform_driver(txx9aclc_pcm_driver
);
443 MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>");
444 MODULE_DESCRIPTION("TXx9 ACLC Audio DMA driver");
445 MODULE_LICENSE("GPL");