diff options
Diffstat (limited to 'sound/soc/s6000/s6000-pcm.c')
-rw-r--r-- | sound/soc/s6000/s6000-pcm.c | 100 |
1 files changed, 61 insertions, 39 deletions
diff --git a/sound/soc/s6000/s6000-pcm.c b/sound/soc/s6000/s6000-pcm.c index 9c7f7f00cebb..271fd222bf19 100644 --- a/sound/soc/s6000/s6000-pcm.c +++ b/sound/soc/s6000/s6000-pcm.c | |||
@@ -65,7 +65,7 @@ static void s6000_pcm_enqueue_dma(struct snd_pcm_substream *substream) | |||
65 | dma_addr_t dma_pos; | 65 | dma_addr_t dma_pos; |
66 | dma_addr_t src, dst; | 66 | dma_addr_t src, dst; |
67 | 67 | ||
68 | par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); | 68 | par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream); |
69 | 69 | ||
70 | period_size = snd_pcm_lib_period_bytes(substream); | 70 | period_size = snd_pcm_lib_period_bytes(substream); |
71 | dma_offset = prtd->period * period_size; | 71 | dma_offset = prtd->period * period_size; |
@@ -103,23 +103,25 @@ static irqreturn_t s6000_pcm_irq(int irq, void *data) | |||
103 | { | 103 | { |
104 | struct snd_pcm *pcm = data; | 104 | struct snd_pcm *pcm = data; |
105 | struct snd_soc_pcm_runtime *runtime = pcm->private_data; | 105 | struct snd_soc_pcm_runtime *runtime = pcm->private_data; |
106 | struct s6000_pcm_dma_params *params = | ||
107 | snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); | ||
108 | struct s6000_runtime_data *prtd; | 106 | struct s6000_runtime_data *prtd; |
109 | unsigned int has_xrun; | 107 | unsigned int has_xrun; |
110 | int i, ret = IRQ_NONE; | 108 | int i, ret = IRQ_NONE; |
111 | u32 channel[2] = { | ||
112 | [SNDRV_PCM_STREAM_PLAYBACK] = params->dma_out, | ||
113 | [SNDRV_PCM_STREAM_CAPTURE] = params->dma_in | ||
114 | }; | ||
115 | |||
116 | has_xrun = params->check_xrun(runtime->dai->cpu_dai); | ||
117 | 109 | ||
118 | for (i = 0; i < ARRAY_SIZE(channel); ++i) { | 110 | for (i = 0; i < 2; ++i) { |
119 | struct snd_pcm_substream *substream = pcm->streams[i].substream; | 111 | struct snd_pcm_substream *substream = pcm->streams[i].substream; |
112 | struct s6000_pcm_dma_params *params = | ||
113 | snd_soc_dai_get_dma_data(runtime->cpu_dai, substream); | ||
114 | u32 channel; | ||
120 | unsigned int pending; | 115 | unsigned int pending; |
121 | 116 | ||
122 | if (!channel[i]) | 117 | if (substream == SNDRV_PCM_STREAM_PLAYBACK) |
118 | channel = params->dma_out; | ||
119 | else | ||
120 | channel = params->dma_in; | ||
121 | |||
122 | has_xrun = params->check_xrun(runtime->cpu_dai); | ||
123 | |||
124 | if (!channel) | ||
123 | continue; | 125 | continue; |
124 | 126 | ||
125 | if (unlikely(has_xrun & (1 << i)) && | 127 | if (unlikely(has_xrun & (1 << i)) && |
@@ -130,8 +132,8 @@ static irqreturn_t s6000_pcm_irq(int irq, void *data) | |||
130 | ret = IRQ_HANDLED; | 132 | ret = IRQ_HANDLED; |
131 | } | 133 | } |
132 | 134 | ||
133 | pending = s6dmac_int_sources(DMA_MASK_DMAC(channel[i]), | 135 | pending = s6dmac_int_sources(DMA_MASK_DMAC(channel), |
134 | DMA_INDEX_CHNL(channel[i])); | 136 | DMA_INDEX_CHNL(channel)); |
135 | 137 | ||
136 | if (pending & 1) { | 138 | if (pending & 1) { |
137 | ret = IRQ_HANDLED; | 139 | ret = IRQ_HANDLED; |
@@ -139,10 +141,10 @@ static irqreturn_t s6000_pcm_irq(int irq, void *data) | |||
139 | snd_pcm_running(substream))) { | 141 | snd_pcm_running(substream))) { |
140 | snd_pcm_period_elapsed(substream); | 142 | snd_pcm_period_elapsed(substream); |
141 | dev_dbg(pcm->dev, "period elapsed %x %x\n", | 143 | dev_dbg(pcm->dev, "period elapsed %x %x\n", |
142 | s6dmac_cur_src(DMA_MASK_DMAC(channel[i]), | 144 | s6dmac_cur_src(DMA_MASK_DMAC(channel), |
143 | DMA_INDEX_CHNL(channel[i])), | 145 | DMA_INDEX_CHNL(channel)), |
144 | s6dmac_cur_dst(DMA_MASK_DMAC(channel[i]), | 146 | s6dmac_cur_dst(DMA_MASK_DMAC(channel), |
145 | DMA_INDEX_CHNL(channel[i]))); | 147 | DMA_INDEX_CHNL(channel))); |
146 | prtd = substream->runtime->private_data; | 148 | prtd = substream->runtime->private_data; |
147 | spin_lock(&prtd->lock); | 149 | spin_lock(&prtd->lock); |
148 | s6000_pcm_enqueue_dma(substream); | 150 | s6000_pcm_enqueue_dma(substream); |
@@ -154,16 +156,16 @@ static irqreturn_t s6000_pcm_irq(int irq, void *data) | |||
154 | if (pending & (1 << 3)) | 156 | if (pending & (1 << 3)) |
155 | printk(KERN_WARNING | 157 | printk(KERN_WARNING |
156 | "s6000-pcm: DMA %x Underflow\n", | 158 | "s6000-pcm: DMA %x Underflow\n", |
157 | channel[i]); | 159 | channel); |
158 | if (pending & (1 << 4)) | 160 | if (pending & (1 << 4)) |
159 | printk(KERN_WARNING | 161 | printk(KERN_WARNING |
160 | "s6000-pcm: DMA %x Overflow\n", | 162 | "s6000-pcm: DMA %x Overflow\n", |
161 | channel[i]); | 163 | channel); |
162 | if (pending & 0x1e0) | 164 | if (pending & 0x1e0) |
163 | printk(KERN_WARNING | 165 | printk(KERN_WARNING |
164 | "s6000-pcm: DMA %x Master Error " | 166 | "s6000-pcm: DMA %x Master Error " |
165 | "(mask %x)\n", | 167 | "(mask %x)\n", |
166 | channel[i], pending >> 5); | 168 | channel, pending >> 5); |
167 | 169 | ||
168 | } | 170 | } |
169 | } | 171 | } |
@@ -180,7 +182,7 @@ static int s6000_pcm_start(struct snd_pcm_substream *substream) | |||
180 | int srcinc; | 182 | int srcinc; |
181 | u32 dma; | 183 | u32 dma; |
182 | 184 | ||
183 | par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); | 185 | par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream); |
184 | 186 | ||
185 | spin_lock_irqsave(&prtd->lock, flags); | 187 | spin_lock_irqsave(&prtd->lock, flags); |
186 | 188 | ||
@@ -221,7 +223,7 @@ static int s6000_pcm_stop(struct snd_pcm_substream *substream) | |||
221 | unsigned long flags; | 223 | unsigned long flags; |
222 | u32 channel; | 224 | u32 channel; |
223 | 225 | ||
224 | par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); | 226 | par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream); |
225 | 227 | ||
226 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 228 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
227 | channel = par->dma_out; | 229 | channel = par->dma_out; |
@@ -246,7 +248,7 @@ static int s6000_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
246 | struct s6000_pcm_dma_params *par; | 248 | struct s6000_pcm_dma_params *par; |
247 | int ret; | 249 | int ret; |
248 | 250 | ||
249 | par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); | 251 | par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream); |
250 | 252 | ||
251 | ret = par->trigger(substream, cmd, 0); | 253 | ret = par->trigger(substream, cmd, 0); |
252 | if (ret < 0) | 254 | if (ret < 0) |
@@ -291,7 +293,7 @@ static snd_pcm_uframes_t s6000_pcm_pointer(struct snd_pcm_substream *substream) | |||
291 | unsigned int offset; | 293 | unsigned int offset; |
292 | dma_addr_t count; | 294 | dma_addr_t count; |
293 | 295 | ||
294 | par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); | 296 | par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream); |
295 | 297 | ||
296 | spin_lock_irqsave(&prtd->lock, flags); | 298 | spin_lock_irqsave(&prtd->lock, flags); |
297 | 299 | ||
@@ -321,7 +323,7 @@ static int s6000_pcm_open(struct snd_pcm_substream *substream) | |||
321 | struct s6000_runtime_data *prtd; | 323 | struct s6000_runtime_data *prtd; |
322 | int ret; | 324 | int ret; |
323 | 325 | ||
324 | par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); | 326 | par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream); |
325 | snd_soc_set_runtime_hwparams(substream, &s6000_pcm_hardware); | 327 | snd_soc_set_runtime_hwparams(substream, &s6000_pcm_hardware); |
326 | 328 | ||
327 | ret = snd_pcm_hw_constraint_step(runtime, 0, | 329 | ret = snd_pcm_hw_constraint_step(runtime, 0, |
@@ -385,7 +387,7 @@ static int s6000_pcm_hw_params(struct snd_pcm_substream *substream, | |||
385 | return ret; | 387 | return ret; |
386 | } | 388 | } |
387 | 389 | ||
388 | par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); | 390 | par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream); |
389 | 391 | ||
390 | if (par->same_rate) { | 392 | if (par->same_rate) { |
391 | spin_lock(&par->lock); | 393 | spin_lock(&par->lock); |
@@ -407,7 +409,7 @@ static int s6000_pcm_hw_free(struct snd_pcm_substream *substream) | |||
407 | { | 409 | { |
408 | struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; | 410 | struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; |
409 | struct s6000_pcm_dma_params *par = | 411 | struct s6000_pcm_dma_params *par = |
410 | snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); | 412 | snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream); |
411 | 413 | ||
412 | spin_lock(&par->lock); | 414 | spin_lock(&par->lock); |
413 | par->in_use &= ~(1 << substream->stream); | 415 | par->in_use &= ~(1 << substream->stream); |
@@ -433,7 +435,7 @@ static void s6000_pcm_free(struct snd_pcm *pcm) | |||
433 | { | 435 | { |
434 | struct snd_soc_pcm_runtime *runtime = pcm->private_data; | 436 | struct snd_soc_pcm_runtime *runtime = pcm->private_data; |
435 | struct s6000_pcm_dma_params *params = | 437 | struct s6000_pcm_dma_params *params = |
436 | snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); | 438 | snd_soc_dai_get_dma_data(runtime->cpu_dai, pcm->streams[0].substream); |
437 | 439 | ||
438 | free_irq(params->irq, pcm); | 440 | free_irq(params->irq, pcm); |
439 | snd_pcm_lib_preallocate_free_for_all(pcm); | 441 | snd_pcm_lib_preallocate_free_for_all(pcm); |
@@ -448,7 +450,8 @@ static int s6000_pcm_new(struct snd_card *card, | |||
448 | struct s6000_pcm_dma_params *params; | 450 | struct s6000_pcm_dma_params *params; |
449 | int res; | 451 | int res; |
450 | 452 | ||
451 | params = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); | 453 | params = snd_soc_dai_get_dma_data(runtime->cpu_dai, |
454 | pcm->streams[0].substream); | ||
452 | 455 | ||
453 | if (!card->dev->dma_mask) | 456 | if (!card->dev->dma_mask) |
454 | card->dev->dma_mask = &s6000_pcm_dmamask; | 457 | card->dev->dma_mask = &s6000_pcm_dmamask; |
@@ -490,25 +493,44 @@ static int s6000_pcm_new(struct snd_card *card, | |||
490 | return 0; | 493 | return 0; |
491 | } | 494 | } |
492 | 495 | ||
493 | struct snd_soc_platform s6000_soc_platform = { | 496 | static struct snd_soc_platform_driver s6000_soc_platform = { |
494 | .name = "s6000-audio", | 497 | .ops = &s6000_pcm_ops, |
495 | .pcm_ops = &s6000_pcm_ops, | ||
496 | .pcm_new = s6000_pcm_new, | 498 | .pcm_new = s6000_pcm_new, |
497 | .pcm_free = s6000_pcm_free, | 499 | .pcm_free = s6000_pcm_free, |
498 | }; | 500 | }; |
499 | EXPORT_SYMBOL_GPL(s6000_soc_platform); | ||
500 | 501 | ||
501 | static int __init s6000_pcm_init(void) | 502 | static int __devinit s6000_soc_platform_probe(struct platform_device *pdev) |
503 | { | ||
504 | return snd_soc_register_platform(&pdev->dev, &s6000_soc_platform); | ||
505 | } | ||
506 | |||
507 | static int __devexit s6000_soc_platform_remove(struct platform_device *pdev) | ||
508 | { | ||
509 | snd_soc_unregister_platform(&pdev->dev); | ||
510 | return 0; | ||
511 | } | ||
512 | |||
513 | static struct platform_driver s6000_pcm_driver = { | ||
514 | .driver = { | ||
515 | .name = "s6000-pcm-audio", | ||
516 | .owner = THIS_MODULE, | ||
517 | }, | ||
518 | |||
519 | .probe = s6000_soc_platform_probe, | ||
520 | .remove = __devexit_p(s6000_soc_platform_remove), | ||
521 | }; | ||
522 | |||
523 | static int __init snd_s6000_pcm_init(void) | ||
502 | { | 524 | { |
503 | return snd_soc_register_platform(&s6000_soc_platform); | 525 | return platform_driver_register(&s6000_pcm_driver); |
504 | } | 526 | } |
505 | module_init(s6000_pcm_init); | 527 | module_init(snd_s6000_pcm_init); |
506 | 528 | ||
507 | static void __exit s6000_pcm_exit(void) | 529 | static void __exit snd_s6000_pcm_exit(void) |
508 | { | 530 | { |
509 | snd_soc_unregister_platform(&s6000_soc_platform); | 531 | platform_driver_unregister(&s6000_pcm_driver); |
510 | } | 532 | } |
511 | module_exit(s6000_pcm_exit); | 533 | module_exit(snd_s6000_pcm_exit); |
512 | 534 | ||
513 | MODULE_AUTHOR("Daniel Gloeckner"); | 535 | MODULE_AUTHOR("Daniel Gloeckner"); |
514 | MODULE_DESCRIPTION("Stretch s6000 family PCM DMA module"); | 536 | MODULE_DESCRIPTION("Stretch s6000 family PCM DMA module"); |