kirkwood-dma.c (e199e6136ce6b151e6638ae93dca60748424d900) | kirkwood-dma.c (697378972d075e1b26ed2935bf44fb828c6191f5) |
---|---|
1/* 2 * kirkwood-dma.c 3 * 4 * (c) 2010 Arnaud Patard <apatard@mandriva.com> | 1/* 2 * kirkwood-dma.c 3 * 4 * (c) 2010 Arnaud Patard <apatard@mandriva.com> |
5 * (c) 2010 Arnaud Patard <arnaud.patard@rtp-net.org> |
|
5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License as published by the 8 * Free Software Foundation; either version 2 of the License, or (at your 9 * option) any later version. 10 */ 11 12#include <linux/init.h> 13#include <linux/module.h> 14#include <linux/device.h> 15#include <linux/io.h> 16#include <linux/slab.h> 17#include <linux/interrupt.h> 18#include <linux/dma-mapping.h> 19#include <linux/mbus.h> 20#include <sound/soc.h> | 6 * 7 * This program is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License as published by the 9 * Free Software Foundation; either version 2 of the License, or (at your 10 * option) any later version. 11 */ 12 13#include <linux/init.h> 14#include <linux/module.h> 15#include <linux/device.h> 16#include <linux/io.h> 17#include <linux/slab.h> 18#include <linux/interrupt.h> 19#include <linux/dma-mapping.h> 20#include <linux/mbus.h> 21#include <sound/soc.h> |
21#include "kirkwood-dma.h" | |
22#include "kirkwood.h" 23 24#define KIRKWOOD_RATES \ 25 (SNDRV_PCM_RATE_44100 | \ 26 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000) 27#define KIRKWOOD_FORMATS \ 28 (SNDRV_PCM_FMTBIT_S16_LE | \ 29 SNDRV_PCM_FMTBIT_S24_LE | \ --- 88 unchanged lines hidden (view full) --- 118 } 119} 120 121static int kirkwood_dma_open(struct snd_pcm_substream *substream) 122{ 123 int err; 124 struct snd_pcm_runtime *runtime = substream->runtime; 125 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; | 22#include "kirkwood.h" 23 24#define KIRKWOOD_RATES \ 25 (SNDRV_PCM_RATE_44100 | \ 26 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000) 27#define KIRKWOOD_FORMATS \ 28 (SNDRV_PCM_FMTBIT_S16_LE | \ 29 SNDRV_PCM_FMTBIT_S24_LE | \ --- 88 unchanged lines hidden (view full) --- 118 } 119} 120 121static int kirkwood_dma_open(struct snd_pcm_substream *substream) 122{ 123 int err; 124 struct snd_pcm_runtime *runtime = substream->runtime; 125 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; |
126 struct snd_soc_dai *cpu_dai = soc_runtime->dai->cpu_dai; | 126 struct snd_soc_platform *platform = soc_runtime->platform; 127 struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai; |
127 struct kirkwood_dma_data *priv; | 128 struct kirkwood_dma_data *priv; |
128 struct kirkwood_dma_priv *prdata = cpu_dai->private_data; | 129 struct kirkwood_dma_priv *prdata = snd_soc_platform_get_drvdata(platform); |
129 unsigned long addr; 130 131 priv = snd_soc_dai_get_dma_data(cpu_dai, substream); 132 snd_soc_set_runtime_hwparams(substream, &kirkwood_dma_snd_hw); 133 134 /* Ensure that all constraints linked to dma burst are fullfilled */ 135 err = snd_pcm_hw_constraint_minmax(runtime, 136 SNDRV_PCM_HW_PARAM_BUFFER_BYTES, --- 9 unchanged lines hidden (view full) --- 146 return err; 147 148 err = snd_pcm_hw_constraint_step(substream->runtime, 0, 149 SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 150 priv->burst); 151 if (err < 0) 152 return err; 153 | 130 unsigned long addr; 131 132 priv = snd_soc_dai_get_dma_data(cpu_dai, substream); 133 snd_soc_set_runtime_hwparams(substream, &kirkwood_dma_snd_hw); 134 135 /* Ensure that all constraints linked to dma burst are fullfilled */ 136 err = snd_pcm_hw_constraint_minmax(runtime, 137 SNDRV_PCM_HW_PARAM_BUFFER_BYTES, --- 9 unchanged lines hidden (view full) --- 147 return err; 148 149 err = snd_pcm_hw_constraint_step(substream->runtime, 0, 150 SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 151 priv->burst); 152 if (err < 0) 153 return err; 154 |
154 if (soc_runtime->dai->cpu_dai->private_data == NULL) { | 155 if (prdata == NULL) { |
155 prdata = kzalloc(sizeof(struct kirkwood_dma_priv), GFP_KERNEL); 156 if (prdata == NULL) 157 return -ENOMEM; 158 159 prdata->data = priv; 160 161 err = request_irq(priv->irq, kirkwood_dma_irq, IRQF_SHARED, 162 "kirkwood-i2s", prdata); 163 if (err) { 164 kfree(prdata); 165 return -EBUSY; 166 } 167 | 156 prdata = kzalloc(sizeof(struct kirkwood_dma_priv), GFP_KERNEL); 157 if (prdata == NULL) 158 return -ENOMEM; 159 160 prdata->data = priv; 161 162 err = request_irq(priv->irq, kirkwood_dma_irq, IRQF_SHARED, 163 "kirkwood-i2s", prdata); 164 if (err) { 165 kfree(prdata); 166 return -EBUSY; 167 } 168 |
168 soc_runtime->dai->cpu_dai->private_data = prdata; | 169 snd_soc_platform_set_drvdata(platform, prdata); |
169 170 /* 171 * Enable Error interrupts. We're only ack'ing them but 172 * it's usefull for diagnostics 173 */ 174 writel((unsigned long)-1, priv->io + KIRKWOOD_ERR_MASK); 175 } 176 --- 9 unchanged lines hidden (view full) --- 186 } 187 188 return 0; 189} 190 191static int kirkwood_dma_close(struct snd_pcm_substream *substream) 192{ 193 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; | 170 171 /* 172 * Enable Error interrupts. We're only ack'ing them but 173 * it's usefull for diagnostics 174 */ 175 writel((unsigned long)-1, priv->io + KIRKWOOD_ERR_MASK); 176 } 177 --- 9 unchanged lines hidden (view full) --- 187 } 188 189 return 0; 190} 191 192static int kirkwood_dma_close(struct snd_pcm_substream *substream) 193{ 194 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; |
194 struct snd_soc_dai *cpu_dai = soc_runtime->dai->cpu_dai; 195 struct kirkwood_dma_priv *prdata = cpu_dai->private_data; | 195 struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai; 196 struct snd_soc_platform *platform = soc_runtime->platform; 197 struct kirkwood_dma_priv *prdata = snd_soc_platform_get_drvdata(platform); |
196 struct kirkwood_dma_data *priv; 197 198 priv = snd_soc_dai_get_dma_data(cpu_dai, substream); 199 200 if (!prdata || !priv) 201 return 0; 202 203 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 204 prdata->play_stream = NULL; 205 else 206 prdata->rec_stream = NULL; 207 208 if (!prdata->play_stream && !prdata->rec_stream) { 209 writel(0, priv->io + KIRKWOOD_ERR_MASK); 210 free_irq(priv->irq, prdata); 211 kfree(prdata); | 198 struct kirkwood_dma_data *priv; 199 200 priv = snd_soc_dai_get_dma_data(cpu_dai, substream); 201 202 if (!prdata || !priv) 203 return 0; 204 205 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 206 prdata->play_stream = NULL; 207 else 208 prdata->rec_stream = NULL; 209 210 if (!prdata->play_stream && !prdata->rec_stream) { 211 writel(0, priv->io + KIRKWOOD_ERR_MASK); 212 free_irq(priv->irq, prdata); 213 kfree(prdata); |
212 soc_runtime->dai->cpu_dai->private_data = NULL; | 214 snd_soc_platform_set_drvdata(platform, NULL); |
213 } 214 215 return 0; 216} 217 218static int kirkwood_dma_hw_params(struct snd_pcm_substream *substream, 219 struct snd_pcm_hw_params *params) 220{ --- 10 unchanged lines hidden (view full) --- 231 snd_pcm_set_runtime_buffer(substream, NULL); 232 return 0; 233} 234 235static int kirkwood_dma_prepare(struct snd_pcm_substream *substream) 236{ 237 struct snd_pcm_runtime *runtime = substream->runtime; 238 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; | 215 } 216 217 return 0; 218} 219 220static int kirkwood_dma_hw_params(struct snd_pcm_substream *substream, 221 struct snd_pcm_hw_params *params) 222{ --- 10 unchanged lines hidden (view full) --- 233 snd_pcm_set_runtime_buffer(substream, NULL); 234 return 0; 235} 236 237static int kirkwood_dma_prepare(struct snd_pcm_substream *substream) 238{ 239 struct snd_pcm_runtime *runtime = substream->runtime; 240 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; |
239 struct snd_soc_dai *cpu_dai = soc_runtime->dai->cpu_dai; | 241 struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai; |
240 struct kirkwood_dma_data *priv; 241 unsigned long size, count; 242 243 priv = snd_soc_dai_get_dma_data(cpu_dai, substream); 244 245 /* compute buffer size in term of "words" as requested in specs */ 246 size = frames_to_bytes(runtime, runtime->buffer_size); 247 size = (size>>2)-1; --- 12 unchanged lines hidden (view full) --- 260 261 return 0; 262} 263 264static snd_pcm_uframes_t kirkwood_dma_pointer(struct snd_pcm_substream 265 *substream) 266{ 267 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; | 242 struct kirkwood_dma_data *priv; 243 unsigned long size, count; 244 245 priv = snd_soc_dai_get_dma_data(cpu_dai, substream); 246 247 /* compute buffer size in term of "words" as requested in specs */ 248 size = frames_to_bytes(runtime, runtime->buffer_size); 249 size = (size>>2)-1; --- 12 unchanged lines hidden (view full) --- 262 263 return 0; 264} 265 266static snd_pcm_uframes_t kirkwood_dma_pointer(struct snd_pcm_substream 267 *substream) 268{ 269 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; |
268 struct snd_soc_dai *cpu_dai = soc_runtime->dai->cpu_dai; | 270 struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai; |
269 struct kirkwood_dma_data *priv; 270 snd_pcm_uframes_t count; 271 272 priv = snd_soc_dai_get_dma_data(cpu_dai, substream); 273 274 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 275 count = bytes_to_frames(substream->runtime, 276 readl(priv->io + KIRKWOOD_PLAY_BYTE_COUNT)); --- 38 unchanged lines hidden (view full) --- 315{ 316 int ret; 317 318 if (!card->dev->dma_mask) 319 card->dev->dma_mask = &kirkwood_dma_dmamask; 320 if (!card->dev->coherent_dma_mask) 321 card->dev->coherent_dma_mask = 0xffffffff; 322 | 271 struct kirkwood_dma_data *priv; 272 snd_pcm_uframes_t count; 273 274 priv = snd_soc_dai_get_dma_data(cpu_dai, substream); 275 276 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 277 count = bytes_to_frames(substream->runtime, 278 readl(priv->io + KIRKWOOD_PLAY_BYTE_COUNT)); --- 38 unchanged lines hidden (view full) --- 317{ 318 int ret; 319 320 if (!card->dev->dma_mask) 321 card->dev->dma_mask = &kirkwood_dma_dmamask; 322 if (!card->dev->coherent_dma_mask) 323 card->dev->coherent_dma_mask = 0xffffffff; 324 |
323 if (dai->playback.channels_min) { | 325 if (dai->driver->playback.channels_min) { |
324 ret = kirkwood_dma_preallocate_dma_buffer(pcm, 325 SNDRV_PCM_STREAM_PLAYBACK); 326 if (ret) 327 return ret; 328 } 329 | 326 ret = kirkwood_dma_preallocate_dma_buffer(pcm, 327 SNDRV_PCM_STREAM_PLAYBACK); 328 if (ret) 329 return ret; 330 } 331 |
330 if (dai->capture.channels_min) { | 332 if (dai->driver->capture.channels_min) { |
331 ret = kirkwood_dma_preallocate_dma_buffer(pcm, 332 SNDRV_PCM_STREAM_CAPTURE); 333 if (ret) 334 return ret; 335 } 336 337 return 0; 338} --- 13 unchanged lines hidden (view full) --- 352 continue; 353 354 dma_free_coherent(pcm->card->dev, buf->bytes, 355 buf->area, buf->addr); 356 buf->area = NULL; 357 } 358} 359 | 333 ret = kirkwood_dma_preallocate_dma_buffer(pcm, 334 SNDRV_PCM_STREAM_CAPTURE); 335 if (ret) 336 return ret; 337 } 338 339 return 0; 340} --- 13 unchanged lines hidden (view full) --- 354 continue; 355 356 dma_free_coherent(pcm->card->dev, buf->bytes, 357 buf->area, buf->addr); 358 buf->area = NULL; 359 } 360} 361 |
360struct snd_soc_platform kirkwood_soc_platform = { 361 .name = "kirkwood-dma", 362 .pcm_ops = &kirkwood_dma_ops, | 362static struct snd_soc_platform_driver kirkwood_soc_platform = { 363 .ops = &kirkwood_dma_ops, |
363 .pcm_new = kirkwood_dma_new, 364 .pcm_free = kirkwood_dma_free_dma_buffers, 365}; | 364 .pcm_new = kirkwood_dma_new, 365 .pcm_free = kirkwood_dma_free_dma_buffers, 366}; |
366EXPORT_SYMBOL_GPL(kirkwood_soc_platform); | |
367 | 367 |
368static int __init kirkwood_soc_platform_init(void) | 368static int __devinit kirkwood_soc_platform_probe(struct platform_device *pdev) |
369{ | 369{ |
370 return snd_soc_register_platform(&kirkwood_soc_platform); | 370 return snd_soc_register_platform(&pdev->dev, &kirkwood_soc_platform); |
371} | 371} |
372module_init(kirkwood_soc_platform_init); | |
373 | 372 |
374static void __exit kirkwood_soc_platform_exit(void) | 373static int __devexit kirkwood_soc_platform_remove(struct platform_device *pdev) |
375{ | 374{ |
376 snd_soc_unregister_platform(&kirkwood_soc_platform); | 375 snd_soc_unregister_platform(&pdev->dev); 376 return 0; |
377} | 377} |
378module_exit(kirkwood_soc_platform_exit); | |
379 | 378 |
380MODULE_AUTHOR("Arnaud Patard <apatard@mandriva.com>"); | 379static struct platform_driver kirkwood_pcm_driver = { 380 .driver = { 381 .name = "kirkwood-pcm-audio", 382 .owner = THIS_MODULE, 383 }, 384 385 .probe = kirkwood_soc_platform_probe, 386 .remove = __devexit_p(kirkwood_soc_platform_remove), 387}; 388 389static int __init kirkwood_pcm_init(void) 390{ 391 return platform_driver_register(&kirkwood_pcm_driver); 392} 393module_init(kirkwood_pcm_init); 394 395static void __exit kirkwood_pcm_exit(void) 396{ 397 platform_driver_unregister(&kirkwood_pcm_driver); 398} 399module_exit(kirkwood_pcm_exit); 400 401MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>"); |
381MODULE_DESCRIPTION("Marvell Kirkwood Audio DMA module"); 382MODULE_LICENSE("GPL"); | 402MODULE_DESCRIPTION("Marvell Kirkwood Audio DMA module"); 403MODULE_LICENSE("GPL"); |
383 | 404MODULE_ALIAS("platform:kirkwood-pcm-audio"); |