diff options
Diffstat (limited to 'sound/soc/blackfin/bf5xx-i2s-pcm.c')
-rw-r--r-- | sound/soc/blackfin/bf5xx-i2s-pcm.c | 78 |
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 | ||
46 | static void bf5xx_dma_irq(void *data) | 45 | static 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 | ||
150 | static int bf5xx_pcm_open(struct snd_pcm_substream *substream) | 158 | static 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 | ||
247 | static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32); | 258 | static 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 | ||
277 | struct snd_soc_platform bf5xx_i2s_soc_platform = { | 288 | static 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 | }; |
283 | EXPORT_SYMBOL_GPL(bf5xx_i2s_soc_platform); | ||
284 | 293 | ||
285 | static int __init bfin_i2s_init(void) | 294 | static 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 | |||
299 | static int __devexit bfin_i2s_soc_platform_remove(struct platform_device *pdev) | ||
300 | { | ||
301 | snd_soc_unregister_platform(&pdev->dev); | ||
302 | return 0; | ||
303 | } | ||
304 | |||
305 | static 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 | |||
315 | static 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 | } |
289 | module_init(bfin_i2s_init); | 319 | module_init(snd_bfin_i2s_pcm_init); |
290 | 320 | ||
291 | static void __exit bfin_i2s_exit(void) | 321 | static 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 | } |
295 | module_exit(bfin_i2s_exit); | 325 | module_exit(snd_bfin_i2s_pcm_exit); |
296 | 326 | ||
297 | MODULE_AUTHOR("Cliff Cai"); | 327 | MODULE_AUTHOR("Cliff Cai"); |
298 | MODULE_DESCRIPTION("ADI Blackfin I2S PCM DMA module"); | 328 | MODULE_DESCRIPTION("ADI Blackfin I2S PCM DMA module"); |