2 * linux/sound/arm/ep93xx-pcm.c - EP93xx ALSA PCM interface
4 * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
5 * Copyright (C) 2006 Applied Data Systems
7 * Rewritten for the SoC audio subsystem (Based on PXA2xx code):
8 * Copyright (c) 2008 Ryan Mallon
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.
15 #include <linux/module.h>
16 #include <linux/init.h>
17 #include <linux/device.h>
18 #include <linux/slab.h>
19 #include <linux/dmaengine.h>
20 #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>
26 #include <sound/dmaengine_pcm.h>
28 #include <linux/platform_data/dma-ep93xx.h>
29 #include <mach/hardware.h>
30 #include <mach/ep93xx-regs.h>
32 #include "ep93xx-pcm.h"
34 static const struct snd_pcm_hardware ep93xx_pcm_hardware
= {
35 .info
= (SNDRV_PCM_INFO_MMAP
|
36 SNDRV_PCM_INFO_MMAP_VALID
|
37 SNDRV_PCM_INFO_INTERLEAVED
|
38 SNDRV_PCM_INFO_BLOCK_TRANSFER
),
40 .rates
= SNDRV_PCM_RATE_8000_192000
,
41 .rate_min
= SNDRV_PCM_RATE_8000
,
42 .rate_max
= SNDRV_PCM_RATE_192000
,
44 .formats
= (SNDRV_PCM_FMTBIT_S16_LE
|
45 SNDRV_PCM_FMTBIT_S24_LE
|
46 SNDRV_PCM_FMTBIT_S32_LE
),
48 .buffer_bytes_max
= 131072,
49 .period_bytes_min
= 32,
50 .period_bytes_max
= 32768,
56 static bool ep93xx_pcm_dma_filter(struct dma_chan
*chan
, void *filter_param
)
58 struct ep93xx_dma_data
*data
= filter_param
;
60 if (data
->direction
== ep93xx_dma_chan_direction(chan
)) {
68 static int ep93xx_pcm_open(struct snd_pcm_substream
*substream
)
70 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
71 struct snd_soc_dai
*cpu_dai
= rtd
->cpu_dai
;
72 struct ep93xx_pcm_dma_params
*dma_params
;
73 struct ep93xx_dma_data
*dma_data
;
76 snd_soc_set_runtime_hwparams(substream
, &ep93xx_pcm_hardware
);
78 dma_data
= kmalloc(sizeof(*dma_data
), GFP_KERNEL
);
82 dma_params
= snd_soc_dai_get_dma_data(cpu_dai
, substream
);
83 dma_data
->port
= dma_params
->dma_port
;
84 dma_data
->name
= dma_params
->name
;
85 dma_data
->direction
= snd_pcm_substream_to_dma_direction(substream
);
87 ret
= snd_dmaengine_pcm_open(substream
, ep93xx_pcm_dma_filter
, dma_data
);
93 snd_dmaengine_pcm_set_data(substream
, dma_data
);
98 static int ep93xx_pcm_close(struct snd_pcm_substream
*substream
)
100 struct dma_data
*dma_data
= snd_dmaengine_pcm_get_data(substream
);
102 snd_dmaengine_pcm_close(substream
);
107 static int ep93xx_pcm_hw_params(struct snd_pcm_substream
*substream
,
108 struct snd_pcm_hw_params
*params
)
110 snd_pcm_set_runtime_buffer(substream
, &substream
->dma_buffer
);
115 static int ep93xx_pcm_hw_free(struct snd_pcm_substream
*substream
)
117 snd_pcm_set_runtime_buffer(substream
, NULL
);
121 static int ep93xx_pcm_mmap(struct snd_pcm_substream
*substream
,
122 struct vm_area_struct
*vma
)
124 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
126 return dma_mmap_writecombine(substream
->pcm
->card
->dev
, vma
,
132 static struct snd_pcm_ops ep93xx_pcm_ops
= {
133 .open
= ep93xx_pcm_open
,
134 .close
= ep93xx_pcm_close
,
135 .ioctl
= snd_pcm_lib_ioctl
,
136 .hw_params
= ep93xx_pcm_hw_params
,
137 .hw_free
= ep93xx_pcm_hw_free
,
138 .trigger
= snd_dmaengine_pcm_trigger
,
139 .pointer
= snd_dmaengine_pcm_pointer_no_residue
,
140 .mmap
= ep93xx_pcm_mmap
,
143 static int ep93xx_pcm_preallocate_dma_buffer(struct snd_pcm
*pcm
, int stream
)
145 struct snd_pcm_substream
*substream
= pcm
->streams
[stream
].substream
;
146 struct snd_dma_buffer
*buf
= &substream
->dma_buffer
;
147 size_t size
= ep93xx_pcm_hardware
.buffer_bytes_max
;
149 buf
->dev
.type
= SNDRV_DMA_TYPE_DEV
;
150 buf
->dev
.dev
= pcm
->card
->dev
;
151 buf
->private_data
= NULL
;
152 buf
->area
= dma_alloc_writecombine(pcm
->card
->dev
, size
,
153 &buf
->addr
, GFP_KERNEL
);
156 return (buf
->area
== NULL
) ? -ENOMEM
: 0;
159 static void ep93xx_pcm_free_dma_buffers(struct snd_pcm
*pcm
)
161 struct snd_pcm_substream
*substream
;
162 struct snd_dma_buffer
*buf
;
165 for (stream
= 0; stream
< 2; stream
++) {
166 substream
= pcm
->streams
[stream
].substream
;
170 buf
= &substream
->dma_buffer
;
174 dma_free_writecombine(pcm
->card
->dev
, buf
->bytes
, buf
->area
,
180 static u64 ep93xx_pcm_dmamask
= DMA_BIT_MASK(32);
182 static int ep93xx_pcm_new(struct snd_soc_pcm_runtime
*rtd
)
184 struct snd_card
*card
= rtd
->card
->snd_card
;
185 struct snd_pcm
*pcm
= rtd
->pcm
;
188 if (!card
->dev
->dma_mask
)
189 card
->dev
->dma_mask
= &ep93xx_pcm_dmamask
;
190 if (!card
->dev
->coherent_dma_mask
)
191 card
->dev
->coherent_dma_mask
= DMA_BIT_MASK(32);
193 if (pcm
->streams
[SNDRV_PCM_STREAM_PLAYBACK
].substream
) {
194 ret
= ep93xx_pcm_preallocate_dma_buffer(pcm
,
195 SNDRV_PCM_STREAM_PLAYBACK
);
200 if (pcm
->streams
[SNDRV_PCM_STREAM_CAPTURE
].substream
) {
201 ret
= ep93xx_pcm_preallocate_dma_buffer(pcm
,
202 SNDRV_PCM_STREAM_CAPTURE
);
210 static struct snd_soc_platform_driver ep93xx_soc_platform
= {
211 .ops
= &ep93xx_pcm_ops
,
212 .pcm_new
= &ep93xx_pcm_new
,
213 .pcm_free
= &ep93xx_pcm_free_dma_buffers
,
216 static int ep93xx_soc_platform_probe(struct platform_device
*pdev
)
218 return snd_soc_register_platform(&pdev
->dev
, &ep93xx_soc_platform
);
221 static int ep93xx_soc_platform_remove(struct platform_device
*pdev
)
223 snd_soc_unregister_platform(&pdev
->dev
);
227 static struct platform_driver ep93xx_pcm_driver
= {
229 .name
= "ep93xx-pcm-audio",
230 .owner
= THIS_MODULE
,
233 .probe
= ep93xx_soc_platform_probe
,
234 .remove
= ep93xx_soc_platform_remove
,
237 module_platform_driver(ep93xx_pcm_driver
);
239 MODULE_AUTHOR("Ryan Mallon");
240 MODULE_DESCRIPTION("EP93xx ALSA PCM interface");
241 MODULE_LICENSE("GPL");
242 MODULE_ALIAS("platform:ep93xx-pcm-audio");