aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/aoa/soundbus/i2sbus/i2sbus-core.c22
-rw-r--r--sound/aoa/soundbus/i2sbus/i2sbus-pcm.c328
-rw-r--r--sound/aoa/soundbus/i2sbus/i2sbus.h6
3 files changed, 210 insertions, 146 deletions
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus-core.c b/sound/aoa/soundbus/i2sbus/i2sbus-core.c
index e593a1333fe3..e36f6aa448d4 100644
--- a/sound/aoa/soundbus/i2sbus/i2sbus-core.c
+++ b/sound/aoa/soundbus/i2sbus/i2sbus-core.c
@@ -41,8 +41,8 @@ static int alloc_dbdma_descriptor_ring(struct i2sbus_dev *i2sdev,
41 struct dbdma_command_mem *r, 41 struct dbdma_command_mem *r,
42 int numcmds) 42 int numcmds)
43{ 43{
44 /* one more for rounding */ 44 /* one more for rounding, one for branch back, one for stop command */
45 r->size = (numcmds+1) * sizeof(struct dbdma_cmd); 45 r->size = (numcmds + 3) * sizeof(struct dbdma_cmd);
46 /* We use the PCI APIs for now until the generic one gets fixed 46 /* We use the PCI APIs for now until the generic one gets fixed
47 * enough or until we get some macio-specific versions 47 * enough or until we get some macio-specific versions
48 */ 48 */
@@ -377,11 +377,8 @@ static int i2sbus_suspend(struct macio_dev* dev, pm_message_t state)
377 if (i2sdev->sound.pcm) { 377 if (i2sdev->sound.pcm) {
378 /* Suspend PCM streams */ 378 /* Suspend PCM streams */
379 snd_pcm_suspend_all(i2sdev->sound.pcm); 379 snd_pcm_suspend_all(i2sdev->sound.pcm);
380 /* Probably useless as we handle
381 * power transitions ourselves */
382 snd_power_change_state(i2sdev->sound.pcm->card,
383 SNDRV_CTL_POWER_D3hot);
384 } 380 }
381
385 /* Notify codecs */ 382 /* Notify codecs */
386 list_for_each_entry(cii, &i2sdev->sound.codec_list, list) { 383 list_for_each_entry(cii, &i2sdev->sound.codec_list, list) {
387 err = 0; 384 err = 0;
@@ -390,7 +387,11 @@ static int i2sbus_suspend(struct macio_dev* dev, pm_message_t state)
390 if (err) 387 if (err)
391 ret = err; 388 ret = err;
392 } 389 }
390
391 /* wait until streams are stopped */
392 i2sbus_wait_for_stop_both(i2sdev);
393 } 393 }
394
394 return ret; 395 return ret;
395} 396}
396 397
@@ -402,6 +403,9 @@ static int i2sbus_resume(struct macio_dev* dev)
402 int err, ret = 0; 403 int err, ret = 0;
403 404
404 list_for_each_entry(i2sdev, &control->list, item) { 405 list_for_each_entry(i2sdev, &control->list, item) {
406 /* reset i2s bus format etc. */
407 i2sbus_pcm_prepare_both(i2sdev);
408
405 /* Notify codecs so they can re-initialize */ 409 /* Notify codecs so they can re-initialize */
406 list_for_each_entry(cii, &i2sdev->sound.codec_list, list) { 410 list_for_each_entry(cii, &i2sdev->sound.codec_list, list) {
407 err = 0; 411 err = 0;
@@ -410,12 +414,6 @@ static int i2sbus_resume(struct macio_dev* dev)
410 if (err) 414 if (err)
411 ret = err; 415 ret = err;
412 } 416 }
413 /* Notify Alsa */
414 if (i2sdev->sound.pcm) {
415 /* Same comment as above, probably useless */
416 snd_power_change_state(i2sdev->sound.pcm->card,
417 SNDRV_CTL_POWER_D0);
418 }
419 } 417 }
420 418
421 return ret; 419 return ret;
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus-pcm.c b/sound/aoa/soundbus/i2sbus/i2sbus-pcm.c
index 7c81db7e52c1..c6b42f9bdbc9 100644
--- a/sound/aoa/soundbus/i2sbus/i2sbus-pcm.c
+++ b/sound/aoa/soundbus/i2sbus/i2sbus-pcm.c
@@ -125,7 +125,8 @@ static int i2sbus_pcm_open(struct i2sbus_dev *i2sdev, int in)
125 } 125 }
126 /* bus dependent stuff */ 126 /* bus dependent stuff */
127 hw->info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | 127 hw->info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
128 SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_RESUME; 128 SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_RESUME |
129 SNDRV_PCM_INFO_JOINT_DUPLEX;
129 130
130 CHECK_RATE(5512); 131 CHECK_RATE(5512);
131 CHECK_RATE(8000); 132 CHECK_RATE(8000);
@@ -245,18 +246,78 @@ static int i2sbus_pcm_close(struct i2sbus_dev *i2sdev, int in)
245 return err; 246 return err;
246} 247}
247 248
249static void i2sbus_wait_for_stop(struct i2sbus_dev *i2sdev,
250 struct pcm_info *pi)
251{
252 unsigned long flags;
253 struct completion done;
254 long timeout;
255
256 spin_lock_irqsave(&i2sdev->low_lock, flags);
257 if (pi->dbdma_ring.stopping) {
258 init_completion(&done);
259 pi->stop_completion = &done;
260 spin_unlock_irqrestore(&i2sdev->low_lock, flags);
261 timeout = wait_for_completion_timeout(&done, HZ);
262 spin_lock_irqsave(&i2sdev->low_lock, flags);
263 pi->stop_completion = NULL;
264 if (timeout == 0) {
265 /* timeout expired, stop dbdma forcefully */
266 printk(KERN_ERR "i2sbus_wait_for_stop: timed out\n");
267 /* make sure RUN, PAUSE and S0 bits are cleared */
268 out_le32(&pi->dbdma->control, (RUN | PAUSE | 1) << 16);
269 pi->dbdma_ring.stopping = 0;
270 timeout = 10;
271 while (in_le32(&pi->dbdma->status) & ACTIVE) {
272 if (--timeout <= 0)
273 break;
274 udelay(1);
275 }
276 }
277 }
278 spin_unlock_irqrestore(&i2sdev->low_lock, flags);
279}
280
281#ifdef CONFIG_PM
282void i2sbus_wait_for_stop_both(struct i2sbus_dev *i2sdev)
283{
284 struct pcm_info *pi;
285
286 get_pcm_info(i2sdev, 0, &pi, NULL);
287 i2sbus_wait_for_stop(i2sdev, pi);
288 get_pcm_info(i2sdev, 1, &pi, NULL);
289 i2sbus_wait_for_stop(i2sdev, pi);
290}
291#endif
292
248static int i2sbus_hw_params(struct snd_pcm_substream *substream, 293static int i2sbus_hw_params(struct snd_pcm_substream *substream,
249 struct snd_pcm_hw_params *params) 294 struct snd_pcm_hw_params *params)
250{ 295{
251 return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); 296 return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
252} 297}
253 298
254static int i2sbus_hw_free(struct snd_pcm_substream *substream) 299static inline int i2sbus_hw_free(struct snd_pcm_substream *substream, int in)
255{ 300{
301 struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream);
302 struct pcm_info *pi;
303
304 get_pcm_info(i2sdev, in, &pi, NULL);
305 if (pi->dbdma_ring.stopping)
306 i2sbus_wait_for_stop(i2sdev, pi);
256 snd_pcm_lib_free_pages(substream); 307 snd_pcm_lib_free_pages(substream);
257 return 0; 308 return 0;
258} 309}
259 310
311static int i2sbus_playback_hw_free(struct snd_pcm_substream *substream)
312{
313 return i2sbus_hw_free(substream, 0);
314}
315
316static int i2sbus_record_hw_free(struct snd_pcm_substream *substream)
317{
318 return i2sbus_hw_free(substream, 1);
319}
320
260static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in) 321static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in)
261{ 322{
262 /* whee. Hard work now. The user has selected a bitrate 323 /* whee. Hard work now. The user has selected a bitrate
@@ -264,7 +325,7 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in)
264 * I2S controller appropriately. */ 325 * I2S controller appropriately. */
265 struct snd_pcm_runtime *runtime; 326 struct snd_pcm_runtime *runtime;
266 struct dbdma_cmd *command; 327 struct dbdma_cmd *command;
267 int i, periodsize; 328 int i, periodsize, nperiods;
268 dma_addr_t offset; 329 dma_addr_t offset;
269 struct bus_info bi; 330 struct bus_info bi;
270 struct codec_info_item *cii; 331 struct codec_info_item *cii;
@@ -274,6 +335,7 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in)
274 struct pcm_info *pi, *other; 335 struct pcm_info *pi, *other;
275 int cnt; 336 int cnt;
276 int result = 0; 337 int result = 0;
338 unsigned int cmd, stopaddr;
277 339
278 mutex_lock(&i2sdev->lock); 340 mutex_lock(&i2sdev->lock);
279 341
@@ -283,6 +345,13 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in)
283 result = -EBUSY; 345 result = -EBUSY;
284 goto out_unlock; 346 goto out_unlock;
285 } 347 }
348 if (pi->dbdma_ring.stopping)
349 i2sbus_wait_for_stop(i2sdev, pi);
350
351 if (!pi->substream || !pi->substream->runtime) {
352 result = -EINVAL;
353 goto out_unlock;
354 }
286 355
287 runtime = pi->substream->runtime; 356 runtime = pi->substream->runtime;
288 pi->active = 1; 357 pi->active = 1;
@@ -297,24 +366,43 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in)
297 i2sdev->rate = runtime->rate; 366 i2sdev->rate = runtime->rate;
298 367
299 periodsize = snd_pcm_lib_period_bytes(pi->substream); 368 periodsize = snd_pcm_lib_period_bytes(pi->substream);
369 nperiods = pi->substream->runtime->periods;
300 pi->current_period = 0; 370 pi->current_period = 0;
301 371
302 /* generate dbdma command ring first */ 372 /* generate dbdma command ring first */
303 command = pi->dbdma_ring.cmds; 373 command = pi->dbdma_ring.cmds;
374 memset(command, 0, (nperiods + 2) * sizeof(struct dbdma_cmd));
375
376 /* commands to DMA to/from the ring */
377 /*
378 * For input, we need to do a graceful stop; if we abort
379 * the DMA, we end up with leftover bytes that corrupt
380 * the next recording. To do this we set the S0 status
381 * bit and wait for the DMA controller to stop. Each
382 * command has a branch condition to
383 * make it branch to a stop command if S0 is set.
384 * On input we also need to wait for the S7 bit to be
385 * set before turning off the DMA controller.
386 * In fact we do the graceful stop for output as well.
387 */
304 offset = runtime->dma_addr; 388 offset = runtime->dma_addr;
305 for (i = 0; i < pi->substream->runtime->periods; 389 cmd = (in? INPUT_MORE: OUTPUT_MORE) | BR_IFSET | INTR_ALWAYS;
306 i++, command++, offset += periodsize) { 390 stopaddr = pi->dbdma_ring.bus_cmd_start +
307 memset(command, 0, sizeof(struct dbdma_cmd)); 391 (nperiods + 1) * sizeof(struct dbdma_cmd);
308 command->command = 392 for (i = 0; i < nperiods; i++, command++, offset += periodsize) {
309 cpu_to_le16((in ? INPUT_MORE : OUTPUT_MORE) | INTR_ALWAYS); 393 command->command = cpu_to_le16(cmd);
394 command->cmd_dep = cpu_to_le32(stopaddr);
310 command->phy_addr = cpu_to_le32(offset); 395 command->phy_addr = cpu_to_le32(offset);
311 command->req_count = cpu_to_le16(periodsize); 396 command->req_count = cpu_to_le16(periodsize);
312 command->xfer_status = cpu_to_le16(0);
313 } 397 }
314 /* last one branches back to first */ 398
315 command--; 399 /* branch back to beginning of ring */
316 command->command |= cpu_to_le16(BR_ALWAYS); 400 command->command = cpu_to_le16(DBDMA_NOP | BR_ALWAYS);
317 command->cmd_dep = cpu_to_le32(pi->dbdma_ring.bus_cmd_start); 401 command->cmd_dep = cpu_to_le32(pi->dbdma_ring.bus_cmd_start);
402 command++;
403
404 /* set stop command */
405 command->command = cpu_to_le16(DBDMA_STOP);
318 406
319 /* ok, let's set the serial format and stuff */ 407 /* ok, let's set the serial format and stuff */
320 switch (runtime->format) { 408 switch (runtime->format) {
@@ -435,16 +523,18 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in)
435 return result; 523 return result;
436} 524}
437 525
438static struct dbdma_cmd STOP_CMD = { 526#ifdef CONFIG_PM
439 .command = __constant_cpu_to_le16(DBDMA_STOP), 527void i2sbus_pcm_prepare_both(struct i2sbus_dev *i2sdev)
440}; 528{
529 i2sbus_pcm_prepare(i2sdev, 0);
530 i2sbus_pcm_prepare(i2sdev, 1);
531}
532#endif
441 533
442static int i2sbus_pcm_trigger(struct i2sbus_dev *i2sdev, int in, int cmd) 534static int i2sbus_pcm_trigger(struct i2sbus_dev *i2sdev, int in, int cmd)
443{ 535{
444 struct codec_info_item *cii; 536 struct codec_info_item *cii;
445 struct pcm_info *pi; 537 struct pcm_info *pi;
446 int timeout;
447 struct dbdma_cmd tmp;
448 int result = 0; 538 int result = 0;
449 unsigned long flags; 539 unsigned long flags;
450 540
@@ -464,92 +554,50 @@ static int i2sbus_pcm_trigger(struct i2sbus_dev *i2sdev, int in, int cmd)
464 cii->codec->start(cii, pi->substream); 554 cii->codec->start(cii, pi->substream);
465 pi->dbdma_ring.running = 1; 555 pi->dbdma_ring.running = 1;
466 556
467 /* reset dma engine */ 557 if (pi->dbdma_ring.stopping) {
468 out_le32(&pi->dbdma->control, 558 /* Clear the S0 bit, then see if we stopped yet */
469 0 | (RUN | PAUSE | FLUSH | WAKE) << 16); 559 out_le32(&pi->dbdma->control, 1 << 16);
470 timeout = 100; 560 if (in_le32(&pi->dbdma->status) & ACTIVE) {
471 while (in_le32(&pi->dbdma->status) & RUN && timeout--) 561 /* possible race here? */
472 udelay(1); 562 udelay(10);
473 if (timeout <= 0) { 563 if (in_le32(&pi->dbdma->status) & ACTIVE) {
474 printk(KERN_ERR 564 pi->dbdma_ring.stopping = 0;
475 "i2sbus: error waiting for dma reset\n"); 565 goto out_unlock; /* keep running */
476 result = -ENXIO; 566 }
477 goto out_unlock; 567 }
478 } 568 }
479 569
570 /* make sure RUN, PAUSE and S0 bits are cleared */
571 out_le32(&pi->dbdma->control, (RUN | PAUSE | 1) << 16);
572
573 /* set branch condition select register */
574 out_le32(&pi->dbdma->br_sel, (1 << 16) | 1);
575
480 /* write dma command buffer address to the dbdma chip */ 576 /* write dma command buffer address to the dbdma chip */
481 out_le32(&pi->dbdma->cmdptr, pi->dbdma_ring.bus_cmd_start); 577 out_le32(&pi->dbdma->cmdptr, pi->dbdma_ring.bus_cmd_start);
482 /* post PCI write */
483 mb();
484 (void)in_le32(&pi->dbdma->status);
485
486 /* change first command to STOP */
487 tmp = *pi->dbdma_ring.cmds;
488 *pi->dbdma_ring.cmds = STOP_CMD;
489
490 /* set running state, remember that the first command is STOP */
491 out_le32(&pi->dbdma->control, RUN | (RUN << 16));
492 timeout = 100;
493 /* wait for STOP to be executed */
494 while (in_le32(&pi->dbdma->status) & ACTIVE && timeout--)
495 udelay(1);
496 if (timeout <= 0) {
497 printk(KERN_ERR "i2sbus: error waiting for dma stop\n");
498 result = -ENXIO;
499 goto out_unlock;
500 }
501 /* again, write dma command buffer address to the dbdma chip,
502 * this time of the first real command */
503 *pi->dbdma_ring.cmds = tmp;
504 out_le32(&pi->dbdma->cmdptr, pi->dbdma_ring.bus_cmd_start);
505 /* post write */
506 mb();
507 (void)in_le32(&pi->dbdma->status);
508
509 /* reset dma engine again */
510 out_le32(&pi->dbdma->control,
511 0 | (RUN | PAUSE | FLUSH | WAKE) << 16);
512 timeout = 100;
513 while (in_le32(&pi->dbdma->status) & RUN && timeout--)
514 udelay(1);
515 if (timeout <= 0) {
516 printk(KERN_ERR
517 "i2sbus: error waiting for dma reset\n");
518 result = -ENXIO;
519 goto out_unlock;
520 }
521 578
522 /* wake up the chip with the next descriptor */ 579 /* initialize the frame count and current period */
523 out_le32(&pi->dbdma->control, 580 pi->current_period = 0;
524 (RUN | WAKE) | ((RUN | WAKE) << 16));
525 /* get the frame count */
526 pi->frame_count = in_le32(&i2sdev->intfregs->frame_count); 581 pi->frame_count = in_le32(&i2sdev->intfregs->frame_count);
527 582
583 /* set the DMA controller running */
584 out_le32(&pi->dbdma->control, (RUN << 16) | RUN);
585
528 /* off you go! */ 586 /* off you go! */
529 break; 587 break;
588
530 case SNDRV_PCM_TRIGGER_STOP: 589 case SNDRV_PCM_TRIGGER_STOP:
531 case SNDRV_PCM_TRIGGER_SUSPEND: 590 case SNDRV_PCM_TRIGGER_SUSPEND:
532 if (!pi->dbdma_ring.running) { 591 if (!pi->dbdma_ring.running) {
533 result = -EALREADY; 592 result = -EALREADY;
534 goto out_unlock; 593 goto out_unlock;
535 } 594 }
595 pi->dbdma_ring.running = 0;
536 596
537 /* turn off all relevant bits */ 597 /* Set the S0 bit to make the DMA branch to the stop cmd */
538 out_le32(&pi->dbdma->control, 598 out_le32(&pi->dbdma->control, (1 << 16) | 1);
539 (RUN | WAKE | FLUSH | PAUSE) << 16); 599 pi->dbdma_ring.stopping = 1;
540 {
541 /* FIXME: move to own function */
542 int timeout = 5000;
543 while ((in_le32(&pi->dbdma->status) & RUN)
544 && --timeout > 0)
545 udelay(1);
546 if (!timeout)
547 printk(KERN_ERR
548 "i2sbus: timed out turning "
549 "off dbdma engine!\n");
550 }
551 600
552 pi->dbdma_ring.running = 0;
553 list_for_each_entry(cii, &i2sdev->sound.codec_list, list) 601 list_for_each_entry(cii, &i2sdev->sound.codec_list, list)
554 if (cii->codec->stop) 602 if (cii->codec->stop)
555 cii->codec->stop(cii, pi->substream); 603 cii->codec->stop(cii, pi->substream);
@@ -574,70 +622,82 @@ static snd_pcm_uframes_t i2sbus_pcm_pointer(struct i2sbus_dev *i2sdev, int in)
574 fc = in_le32(&i2sdev->intfregs->frame_count); 622 fc = in_le32(&i2sdev->intfregs->frame_count);
575 fc = fc - pi->frame_count; 623 fc = fc - pi->frame_count;
576 624
577 return (bytes_to_frames(pi->substream->runtime, 625 if (fc >= pi->substream->runtime->buffer_size)
578 pi->current_period * 626 fc %= pi->substream->runtime->buffer_size;
579 snd_pcm_lib_period_bytes(pi->substream)) 627 return fc;
580 + fc) % pi->substream->runtime->buffer_size;
581} 628}
582 629
583static inline void handle_interrupt(struct i2sbus_dev *i2sdev, int in) 630static inline void handle_interrupt(struct i2sbus_dev *i2sdev, int in)
584{ 631{
585 struct pcm_info *pi; 632 struct pcm_info *pi;
586 u32 fc; 633 u32 fc, nframes;
587 u32 delta; 634 u32 status;
635 int timeout, i;
636 int dma_stopped = 0;
637 struct snd_pcm_runtime *runtime;
588 638
589 spin_lock(&i2sdev->low_lock); 639 spin_lock(&i2sdev->low_lock);
590 get_pcm_info(i2sdev, in, &pi, NULL); 640 get_pcm_info(i2sdev, in, &pi, NULL);
591 641 if (!pi->dbdma_ring.running && !pi->dbdma_ring.stopping)
592 if (!pi->dbdma_ring.running) {
593 /* there was still an interrupt pending
594 * while we stopped. or maybe another
595 * processor (not the one that was stopping
596 * the DMA engine) was spinning above
597 * waiting for the lock. */
598 goto out_unlock; 642 goto out_unlock;
599 }
600 643
601 fc = in_le32(&i2sdev->intfregs->frame_count); 644 i = pi->current_period;
602 /* a counter overflow does not change the calculation. */ 645 runtime = pi->substream->runtime;
603 delta = fc - pi->frame_count; 646 while (pi->dbdma_ring.cmds[i].xfer_status) {
604 647 if (le16_to_cpu(pi->dbdma_ring.cmds[i].xfer_status) & BT)
605 /* update current_period */ 648 /*
606 while (delta >= pi->substream->runtime->period_size) { 649 * BT is the branch taken bit. If it took a branch
607 pi->current_period++; 650 * it is because we set the S0 bit to make it
608 delta = delta - pi->substream->runtime->period_size; 651 * branch to the stop command.
609 } 652 */
610 653 dma_stopped = 1;
611 if (unlikely(delta)) { 654 pi->dbdma_ring.cmds[i].xfer_status = 0;
612 /* Some interrupt came late, so check the dbdma. 655
613 * This special case exists to syncronize the frame_count with 656 if (++i >= runtime->periods) {
614 * the dbdma transfer, but is hit every once in a while. */ 657 i = 0;
615 int period; 658 pi->frame_count += runtime->buffer_size;
616
617 period = (in_le32(&pi->dbdma->cmdptr)
618 - pi->dbdma_ring.bus_cmd_start)
619 / sizeof(struct dbdma_cmd);
620 pi->current_period = pi->current_period
621 % pi->substream->runtime->periods;
622
623 while (pi->current_period != period) {
624 pi->current_period++;
625 pi->current_period %= pi->substream->runtime->periods;
626 /* Set delta to zero, as the frame_count value is too
627 * high (otherwise the code path will not be executed).
628 * This corrects the fact that the frame_count is too
629 * low at the beginning due to buffering. */
630 delta = 0;
631 } 659 }
660 pi->current_period = i;
661
662 /*
663 * Check the frame count. The DMA tends to get a bit
664 * ahead of the frame counter, which confuses the core.
665 */
666 fc = in_le32(&i2sdev->intfregs->frame_count);
667 nframes = i * runtime->period_size;
668 if (fc < pi->frame_count + nframes)
669 pi->frame_count = fc - nframes;
632 } 670 }
633 671
634 pi->frame_count = fc - delta; 672 if (dma_stopped) {
635 pi->current_period %= pi->substream->runtime->periods; 673 timeout = 1000;
674 for (;;) {
675 status = in_le32(&pi->dbdma->status);
676 if (!(status & ACTIVE) && (!in || (status & 0x80)))
677 break;
678 if (--timeout <= 0) {
679 printk(KERN_ERR "i2sbus: timed out "
680 "waiting for DMA to stop!\n");
681 break;
682 }
683 udelay(1);
684 }
685
686 /* Turn off DMA controller, clear S0 bit */
687 out_le32(&pi->dbdma->control, (RUN | PAUSE | 1) << 16);
636 688
689 pi->dbdma_ring.stopping = 0;
690 if (pi->stop_completion)
691 complete(pi->stop_completion);
692 }
693
694 if (!pi->dbdma_ring.running)
695 goto out_unlock;
637 spin_unlock(&i2sdev->low_lock); 696 spin_unlock(&i2sdev->low_lock);
638 /* may call _trigger again, hence needs to be unlocked */ 697 /* may call _trigger again, hence needs to be unlocked */
639 snd_pcm_period_elapsed(pi->substream); 698 snd_pcm_period_elapsed(pi->substream);
640 return; 699 return;
700
641 out_unlock: 701 out_unlock:
642 spin_unlock(&i2sdev->low_lock); 702 spin_unlock(&i2sdev->low_lock);
643} 703}
@@ -718,7 +778,7 @@ static struct snd_pcm_ops i2sbus_playback_ops = {
718 .close = i2sbus_playback_close, 778 .close = i2sbus_playback_close,
719 .ioctl = snd_pcm_lib_ioctl, 779 .ioctl = snd_pcm_lib_ioctl,
720 .hw_params = i2sbus_hw_params, 780 .hw_params = i2sbus_hw_params,
721 .hw_free = i2sbus_hw_free, 781 .hw_free = i2sbus_playback_hw_free,
722 .prepare = i2sbus_playback_prepare, 782 .prepare = i2sbus_playback_prepare,
723 .trigger = i2sbus_playback_trigger, 783 .trigger = i2sbus_playback_trigger,
724 .pointer = i2sbus_playback_pointer, 784 .pointer = i2sbus_playback_pointer,
@@ -788,7 +848,7 @@ static struct snd_pcm_ops i2sbus_record_ops = {
788 .close = i2sbus_record_close, 848 .close = i2sbus_record_close,
789 .ioctl = snd_pcm_lib_ioctl, 849 .ioctl = snd_pcm_lib_ioctl,
790 .hw_params = i2sbus_hw_params, 850 .hw_params = i2sbus_hw_params,
791 .hw_free = i2sbus_hw_free, 851 .hw_free = i2sbus_record_hw_free,
792 .prepare = i2sbus_record_prepare, 852 .prepare = i2sbus_record_prepare,
793 .trigger = i2sbus_record_trigger, 853 .trigger = i2sbus_record_trigger,
794 .pointer = i2sbus_record_pointer, 854 .pointer = i2sbus_record_pointer,
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus.h b/sound/aoa/soundbus/i2sbus/i2sbus.h
index ec20ee615d7f..ff29654782c9 100644
--- a/sound/aoa/soundbus/i2sbus/i2sbus.h
+++ b/sound/aoa/soundbus/i2sbus/i2sbus.h
@@ -10,6 +10,7 @@
10#include <linux/interrupt.h> 10#include <linux/interrupt.h>
11#include <linux/spinlock.h> 11#include <linux/spinlock.h>
12#include <linux/mutex.h> 12#include <linux/mutex.h>
13#include <linux/completion.h>
13 14
14#include <sound/pcm.h> 15#include <sound/pcm.h>
15 16
@@ -34,6 +35,7 @@ struct dbdma_command_mem {
34 void *space; 35 void *space;
35 int size; 36 int size;
36 u32 running:1; 37 u32 running:1;
38 u32 stopping:1;
37}; 39};
38 40
39struct pcm_info { 41struct pcm_info {
@@ -45,6 +47,7 @@ struct pcm_info {
45 u32 frame_count; 47 u32 frame_count;
46 struct dbdma_command_mem dbdma_ring; 48 struct dbdma_command_mem dbdma_ring;
47 volatile struct dbdma_regs __iomem *dbdma; 49 volatile struct dbdma_regs __iomem *dbdma;
50 struct completion *stop_completion;
48}; 51};
49 52
50enum { 53enum {
@@ -101,6 +104,9 @@ i2sbus_tx_intr(int irq, void *devid);
101extern irqreturn_t 104extern irqreturn_t
102i2sbus_rx_intr(int irq, void *devid); 105i2sbus_rx_intr(int irq, void *devid);
103 106
107extern void i2sbus_wait_for_stop_both(struct i2sbus_dev *i2sdev);
108extern void i2sbus_pcm_prepare_both(struct i2sbus_dev *i2sdev);
109
104/* control specific functions */ 110/* control specific functions */
105extern int i2sbus_control_init(struct macio_dev* dev, 111extern int i2sbus_control_init(struct macio_dev* dev,
106 struct i2sbus_control **c); 112 struct i2sbus_control **c);