aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorLars-Peter Clausen <lars@metafoo.de>2012-03-05 08:02:15 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2012-03-12 15:03:39 -0400
commitd7a42e1033b27cea8ae137eeaa038910fe334a55 (patch)
tree403becfa4e007b3b41c5a77fabfde7c94653ebcc /sound
parent7a08cf7022b3f6863cff004cf0531f3e44a772ea (diff)
ASoC: ep93xx-pcm: Use dmaengine PCM helper functions
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Acked-by: Vinod Koul <vinod.koul@linux.intel.com> Tested-by: Mika Westerberg <mika.westerberg@iki.fi> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/ep93xx/Kconfig1
-rw-r--r--sound/soc/ep93xx/ep93xx-pcm.c148
2 files changed, 23 insertions, 126 deletions
diff --git a/sound/soc/ep93xx/Kconfig b/sound/soc/ep93xx/Kconfig
index 91a28de94109..88143db7e753 100644
--- a/sound/soc/ep93xx/Kconfig
+++ b/sound/soc/ep93xx/Kconfig
@@ -1,6 +1,7 @@
1config SND_EP93XX_SOC 1config SND_EP93XX_SOC
2 tristate "SoC Audio support for the Cirrus Logic EP93xx series" 2 tristate "SoC Audio support for the Cirrus Logic EP93xx series"
3 depends on ARCH_EP93XX && SND_SOC 3 depends on ARCH_EP93XX && SND_SOC
4 select SND_SOC_DMAENGINE_PCM
4 help 5 help
5 Say Y or M if you want to add support for codecs attached to 6 Say Y or M if you want to add support for codecs attached to
6 the EP93xx I2S or AC97 interfaces. 7 the EP93xx I2S or AC97 interfaces.
diff --git a/sound/soc/ep93xx/ep93xx-pcm.c b/sound/soc/ep93xx/ep93xx-pcm.c
index 32adca38b48b..162dbb74f4cc 100644
--- a/sound/soc/ep93xx/ep93xx-pcm.c
+++ b/sound/soc/ep93xx/ep93xx-pcm.c
@@ -23,6 +23,7 @@
23#include <sound/pcm.h> 23#include <sound/pcm.h>
24#include <sound/pcm_params.h> 24#include <sound/pcm_params.h>
25#include <sound/soc.h> 25#include <sound/soc.h>
26#include <sound/dmaengine_pcm.h>
26 27
27#include <mach/dma.h> 28#include <mach/dma.h>
28#include <mach/hardware.h> 29#include <mach/hardware.h>
@@ -52,26 +53,6 @@ static const struct snd_pcm_hardware ep93xx_pcm_hardware = {
52 .fifo_size = 32, 53 .fifo_size = 32,
53}; 54};
54 55
55struct ep93xx_runtime_data
56{
57 int pointer_bytes;
58 int periods;
59 int period_bytes;
60 struct dma_chan *dma_chan;
61 struct ep93xx_dma_data dma_data;
62};
63
64static void ep93xx_pcm_dma_callback(void *data)
65{
66 struct snd_pcm_substream *substream = data;
67 struct ep93xx_runtime_data *rtd = substream->runtime->private_data;
68
69 rtd->pointer_bytes += rtd->period_bytes;
70 rtd->pointer_bytes %= rtd->period_bytes * rtd->periods;
71
72 snd_pcm_period_elapsed(substream);
73}
74
75static bool ep93xx_pcm_dma_filter(struct dma_chan *chan, void *filter_param) 56static bool ep93xx_pcm_dma_filter(struct dma_chan *chan, void *filter_param)
76{ 57{
77 struct ep93xx_dma_data *data = filter_param; 58 struct ep93xx_dma_data *data = filter_param;
@@ -86,98 +67,48 @@ static bool ep93xx_pcm_dma_filter(struct dma_chan *chan, void *filter_param)
86 67
87static int ep93xx_pcm_open(struct snd_pcm_substream *substream) 68static int ep93xx_pcm_open(struct snd_pcm_substream *substream)
88{ 69{
89 struct snd_soc_pcm_runtime *soc_rtd = substream->private_data; 70 struct snd_soc_pcm_runtime *rtd = substream->private_data;
90 struct snd_soc_dai *cpu_dai = soc_rtd->cpu_dai; 71 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
91 struct ep93xx_pcm_dma_params *dma_params; 72 struct ep93xx_pcm_dma_params *dma_params;
92 struct ep93xx_runtime_data *rtd; 73 struct ep93xx_dma_data *dma_data;
93 dma_cap_mask_t mask;
94 int ret; 74 int ret;
95 75
96 ret = snd_pcm_hw_constraint_integer(substream->runtime,
97 SNDRV_PCM_HW_PARAM_PERIODS);
98 if (ret < 0)
99 return ret;
100
101 snd_soc_set_runtime_hwparams(substream, &ep93xx_pcm_hardware); 76 snd_soc_set_runtime_hwparams(substream, &ep93xx_pcm_hardware);
102 77
103 rtd = kmalloc(sizeof(*rtd), GFP_KERNEL); 78 dma_data = kmalloc(sizeof(*dma_data), GFP_KERNEL);
104 if (!rtd) 79 if (!dma_data)
105 return -ENOMEM; 80 return -ENOMEM;
106 81
107 dma_cap_zero(mask);
108 dma_cap_set(DMA_SLAVE, mask);
109 dma_cap_set(DMA_CYCLIC, mask);
110
111 dma_params = snd_soc_dai_get_dma_data(cpu_dai, substream); 82 dma_params = snd_soc_dai_get_dma_data(cpu_dai, substream);
112 rtd->dma_data.port = dma_params->dma_port; 83 dma_data->port = dma_params->dma_port;
113 rtd->dma_data.name = dma_params->name; 84 dma_data->name = dma_params->name;
114 85 dma_data->direction = snd_pcm_substream_to_dma_direction(substream);
115 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
116 rtd->dma_data.direction = DMA_MEM_TO_DEV;
117 else
118 rtd->dma_data.direction = DMA_DEV_TO_MEM;
119
120 rtd->dma_chan = dma_request_channel(mask, ep93xx_pcm_dma_filter,
121 &rtd->dma_data);
122 if (!rtd->dma_chan) {
123 kfree(rtd);
124 return -EINVAL;
125 }
126
127 substream->runtime->private_data = rtd;
128 return 0;
129}
130 86
131static int ep93xx_pcm_close(struct snd_pcm_substream *substream) 87 ret = snd_dmaengine_pcm_open(substream, ep93xx_pcm_dma_filter, dma_data);
132{ 88 if (ret) {
133 struct ep93xx_runtime_data *rtd = substream->runtime->private_data; 89 kfree(dma_data);
90 return ret;
91 }
134 92
135 dma_release_channel(rtd->dma_chan); 93 snd_dmaengine_pcm_set_data(substream, dma_data);
136 kfree(rtd);
137 return 0;
138}
139 94
140static int ep93xx_pcm_dma_submit(struct snd_pcm_substream *substream)
141{
142 struct snd_pcm_runtime *runtime = substream->runtime;
143 struct ep93xx_runtime_data *rtd = runtime->private_data;
144 struct dma_chan *chan = rtd->dma_chan;
145 struct dma_device *dma_dev = chan->device;
146 struct dma_async_tx_descriptor *desc;
147
148 rtd->pointer_bytes = 0;
149 desc = dma_dev->device_prep_dma_cyclic(chan, runtime->dma_addr,
150 rtd->period_bytes * rtd->periods,
151 rtd->period_bytes,
152 rtd->dma_data.direction);
153 if (!desc)
154 return -EINVAL;
155
156 desc->callback = ep93xx_pcm_dma_callback;
157 desc->callback_param = substream;
158
159 dmaengine_submit(desc);
160 return 0; 95 return 0;
161} 96}
162 97
163static void ep93xx_pcm_dma_flush(struct snd_pcm_substream *substream) 98static int ep93xx_pcm_close(struct snd_pcm_substream *substream)
164{ 99{
165 struct snd_pcm_runtime *runtime = substream->runtime; 100 struct dma_data *dma_data = snd_dmaengine_pcm_get_data(substream);
166 struct ep93xx_runtime_data *rtd = runtime->private_data;
167 101
168 dmaengine_terminate_all(rtd->dma_chan); 102 snd_dmaengine_pcm_close(substream);
103 kfree(dma_data);
104 return 0;
169} 105}
170 106
171static int ep93xx_pcm_hw_params(struct snd_pcm_substream *substream, 107static int ep93xx_pcm_hw_params(struct snd_pcm_substream *substream,
172 struct snd_pcm_hw_params *params) 108 struct snd_pcm_hw_params *params)
173{ 109{
174 struct snd_pcm_runtime *runtime = substream->runtime;
175 struct ep93xx_runtime_data *rtd = runtime->private_data;
176
177 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); 110 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
178 111
179 rtd->periods = params_periods(params);
180 rtd->period_bytes = params_period_bytes(params);
181 return 0; 112 return 0;
182} 113}
183 114
@@ -187,41 +118,6 @@ static int ep93xx_pcm_hw_free(struct snd_pcm_substream *substream)
187 return 0; 118 return 0;
188} 119}
189 120
190static int ep93xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
191{
192 int ret;
193
194 ret = 0;
195 switch (cmd) {
196 case SNDRV_PCM_TRIGGER_START:
197 case SNDRV_PCM_TRIGGER_RESUME:
198 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
199 ret = ep93xx_pcm_dma_submit(substream);
200 break;
201
202 case SNDRV_PCM_TRIGGER_STOP:
203 case SNDRV_PCM_TRIGGER_SUSPEND:
204 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
205 ep93xx_pcm_dma_flush(substream);
206 break;
207
208 default:
209 ret = -EINVAL;
210 break;
211 }
212
213 return ret;
214}
215
216static snd_pcm_uframes_t ep93xx_pcm_pointer(struct snd_pcm_substream *substream)
217{
218 struct snd_pcm_runtime *runtime = substream->runtime;
219 struct ep93xx_runtime_data *rtd = substream->runtime->private_data;
220
221 /* FIXME: implement this with sub-period granularity */
222 return bytes_to_frames(runtime, rtd->pointer_bytes);
223}
224
225static int ep93xx_pcm_mmap(struct snd_pcm_substream *substream, 121static int ep93xx_pcm_mmap(struct snd_pcm_substream *substream,
226 struct vm_area_struct *vma) 122 struct vm_area_struct *vma)
227{ 123{
@@ -239,8 +135,8 @@ static struct snd_pcm_ops ep93xx_pcm_ops = {
239 .ioctl = snd_pcm_lib_ioctl, 135 .ioctl = snd_pcm_lib_ioctl,
240 .hw_params = ep93xx_pcm_hw_params, 136 .hw_params = ep93xx_pcm_hw_params,
241 .hw_free = ep93xx_pcm_hw_free, 137 .hw_free = ep93xx_pcm_hw_free,
242 .trigger = ep93xx_pcm_trigger, 138 .trigger = snd_dmaengine_pcm_trigger,
243 .pointer = ep93xx_pcm_pointer, 139 .pointer = snd_dmaengine_pcm_pointer,
244 .mmap = ep93xx_pcm_mmap, 140 .mmap = ep93xx_pcm_mmap,
245}; 141};
246 142