aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/s6000/s6000-pcm.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/s6000/s6000-pcm.c')
-rw-r--r--sound/soc/s6000/s6000-pcm.c100
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
493struct snd_soc_platform s6000_soc_platform = { 496static 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};
499EXPORT_SYMBOL_GPL(s6000_soc_platform);
500 501
501static int __init s6000_pcm_init(void) 502static int __devinit s6000_soc_platform_probe(struct platform_device *pdev)
503{
504 return snd_soc_register_platform(&pdev->dev, &s6000_soc_platform);
505}
506
507static int __devexit s6000_soc_platform_remove(struct platform_device *pdev)
508{
509 snd_soc_unregister_platform(&pdev->dev);
510 return 0;
511}
512
513static 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
523static 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}
505module_init(s6000_pcm_init); 527module_init(snd_s6000_pcm_init);
506 528
507static void __exit s6000_pcm_exit(void) 529static 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}
511module_exit(s6000_pcm_exit); 533module_exit(snd_s6000_pcm_exit);
512 534
513MODULE_AUTHOR("Daniel Gloeckner"); 535MODULE_AUTHOR("Daniel Gloeckner");
514MODULE_DESCRIPTION("Stretch s6000 family PCM DMA module"); 536MODULE_DESCRIPTION("Stretch s6000 family PCM DMA module");