aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/blackfin/bf5xx-i2s-pcm.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/blackfin/bf5xx-i2s-pcm.c')
-rw-r--r--sound/soc/blackfin/bf5xx-i2s-pcm.c78
1 files changed, 54 insertions, 24 deletions
diff --git a/sound/soc/blackfin/bf5xx-i2s-pcm.c b/sound/soc/blackfin/bf5xx-i2s-pcm.c
index 1d2a1adf2575..f1fd95bb6416 100644
--- a/sound/soc/blackfin/bf5xx-i2s-pcm.c
+++ b/sound/soc/blackfin/bf5xx-i2s-pcm.c
@@ -40,7 +40,6 @@
40#include <asm/dma.h> 40#include <asm/dma.h>
41 41
42#include "bf5xx-i2s-pcm.h" 42#include "bf5xx-i2s-pcm.h"
43#include "bf5xx-i2s.h"
44#include "bf5xx-sport.h" 43#include "bf5xx-sport.h"
45 44
46static void bf5xx_dma_irq(void *data) 45static void bf5xx_dma_irq(void *data)
@@ -139,20 +138,34 @@ static snd_pcm_uframes_t bf5xx_pcm_pointer(struct snd_pcm_substream *substream)
139 pr_debug("%s enter\n", __func__); 138 pr_debug("%s enter\n", __func__);
140 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 139 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
141 diff = sport_curr_offset_tx(sport); 140 diff = sport_curr_offset_tx(sport);
142 frames = bytes_to_frames(substream->runtime, diff);
143 } else { 141 } else {
144 diff = sport_curr_offset_rx(sport); 142 diff = sport_curr_offset_rx(sport);
145 frames = bytes_to_frames(substream->runtime, diff);
146 } 143 }
144
145 /*
146 * TX at least can report one frame beyond the end of the
147 * buffer if we hit the wraparound case - clamp to within the
148 * buffer as the ALSA APIs require.
149 */
150 if (diff == snd_pcm_lib_buffer_bytes(substream))
151 diff = 0;
152
153 frames = bytes_to_frames(substream->runtime, diff);
154
147 return frames; 155 return frames;
148} 156}
149 157
150static int bf5xx_pcm_open(struct snd_pcm_substream *substream) 158static int bf5xx_pcm_open(struct snd_pcm_substream *substream)
151{ 159{
160 struct snd_soc_pcm_runtime *rtd = substream->private_data;
161 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
162 struct sport_device *sport_handle = snd_soc_dai_get_drvdata(cpu_dai);
152 struct snd_pcm_runtime *runtime = substream->runtime; 163 struct snd_pcm_runtime *runtime = substream->runtime;
164 struct snd_dma_buffer *buf = &substream->dma_buffer;
153 int ret; 165 int ret;
154 166
155 pr_debug("%s enter\n", __func__); 167 pr_debug("%s enter\n", __func__);
168
156 snd_soc_set_runtime_hwparams(substream, &bf5xx_pcm_hardware); 169 snd_soc_set_runtime_hwparams(substream, &bf5xx_pcm_hardware);
157 170
158 ret = snd_pcm_hw_constraint_integer(runtime, \ 171 ret = snd_pcm_hw_constraint_integer(runtime, \
@@ -160,9 +173,14 @@ static int bf5xx_pcm_open(struct snd_pcm_substream *substream)
160 if (ret < 0) 173 if (ret < 0)
161 goto out; 174 goto out;
162 175
163 if (sport_handle != NULL) 176 if (sport_handle != NULL) {
177 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
178 sport_handle->tx_buf = buf->area;
179 else
180 sport_handle->rx_buf = buf->area;
181
164 runtime->private_data = sport_handle; 182 runtime->private_data = sport_handle;
165 else { 183 } else {
166 pr_err("sport_handle is NULL\n"); 184 pr_err("sport_handle is NULL\n");
167 return -1; 185 return -1;
168 } 186 }
@@ -215,11 +233,6 @@ static int bf5xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
215 pr_debug("%s, area:%p, size:0x%08lx\n", __func__, 233 pr_debug("%s, area:%p, size:0x%08lx\n", __func__,
216 buf->area, buf->bytes); 234 buf->area, buf->bytes);
217 235
218 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
219 sport_handle->tx_buf = buf->area;
220 else
221 sport_handle->rx_buf = buf->area;
222
223 return 0; 236 return 0;
224} 237}
225 238
@@ -240,8 +253,6 @@ static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
240 dma_free_coherent(NULL, buf->bytes, buf->area, 0); 253 dma_free_coherent(NULL, buf->bytes, buf->area, 0);
241 buf->area = NULL; 254 buf->area = NULL;
242 } 255 }
243 if (sport_handle)
244 sport_done(sport_handle);
245} 256}
246 257
247static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32); 258static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32);
@@ -257,14 +268,14 @@ int bf5xx_pcm_i2s_new(struct snd_card *card, struct snd_soc_dai *dai,
257 if (!card->dev->coherent_dma_mask) 268 if (!card->dev->coherent_dma_mask)
258 card->dev->coherent_dma_mask = DMA_BIT_MASK(32); 269 card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
259 270
260 if (dai->playback.channels_min) { 271 if (dai->driver->playback.channels_min) {
261 ret = bf5xx_pcm_preallocate_dma_buffer(pcm, 272 ret = bf5xx_pcm_preallocate_dma_buffer(pcm,
262 SNDRV_PCM_STREAM_PLAYBACK); 273 SNDRV_PCM_STREAM_PLAYBACK);
263 if (ret) 274 if (ret)
264 goto out; 275 goto out;
265 } 276 }
266 277
267 if (dai->capture.channels_min) { 278 if (dai->driver->capture.channels_min) {
268 ret = bf5xx_pcm_preallocate_dma_buffer(pcm, 279 ret = bf5xx_pcm_preallocate_dma_buffer(pcm,
269 SNDRV_PCM_STREAM_CAPTURE); 280 SNDRV_PCM_STREAM_CAPTURE);
270 if (ret) 281 if (ret)
@@ -274,25 +285,44 @@ int bf5xx_pcm_i2s_new(struct snd_card *card, struct snd_soc_dai *dai,
274 return ret; 285 return ret;
275} 286}
276 287
277struct snd_soc_platform bf5xx_i2s_soc_platform = { 288static struct snd_soc_platform_driver bf5xx_i2s_soc_platform = {
278 .name = "bf5xx-audio", 289 .ops = &bf5xx_pcm_i2s_ops,
279 .pcm_ops = &bf5xx_pcm_i2s_ops,
280 .pcm_new = bf5xx_pcm_i2s_new, 290 .pcm_new = bf5xx_pcm_i2s_new,
281 .pcm_free = bf5xx_pcm_free_dma_buffers, 291 .pcm_free = bf5xx_pcm_free_dma_buffers,
282}; 292};
283EXPORT_SYMBOL_GPL(bf5xx_i2s_soc_platform);
284 293
285static int __init bfin_i2s_init(void) 294static int __devinit bfin_i2s_soc_platform_probe(struct platform_device *pdev)
295{
296 return snd_soc_register_platform(&pdev->dev, &bf5xx_i2s_soc_platform);
297}
298
299static int __devexit bfin_i2s_soc_platform_remove(struct platform_device *pdev)
300{
301 snd_soc_unregister_platform(&pdev->dev);
302 return 0;
303}
304
305static struct platform_driver bfin_i2s_pcm_driver = {
306 .driver = {
307 .name = "bfin-i2s-pcm-audio",
308 .owner = THIS_MODULE,
309 },
310
311 .probe = bfin_i2s_soc_platform_probe,
312 .remove = __devexit_p(bfin_i2s_soc_platform_remove),
313};
314
315static int __init snd_bfin_i2s_pcm_init(void)
286{ 316{
287 return snd_soc_register_platform(&bf5xx_i2s_soc_platform); 317 return platform_driver_register(&bfin_i2s_pcm_driver);
288} 318}
289module_init(bfin_i2s_init); 319module_init(snd_bfin_i2s_pcm_init);
290 320
291static void __exit bfin_i2s_exit(void) 321static void __exit snd_bfin_i2s_pcm_exit(void)
292{ 322{
293 snd_soc_unregister_platform(&bf5xx_i2s_soc_platform); 323 platform_driver_unregister(&bfin_i2s_pcm_driver);
294} 324}
295module_exit(bfin_i2s_exit); 325module_exit(snd_bfin_i2s_pcm_exit);
296 326
297MODULE_AUTHOR("Cliff Cai"); 327MODULE_AUTHOR("Cliff Cai");
298MODULE_DESCRIPTION("ADI Blackfin I2S PCM DMA module"); 328MODULE_DESCRIPTION("ADI Blackfin I2S PCM DMA module");