aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/sh/fsi.c46
1 files changed, 25 insertions, 21 deletions
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c
index 3c36d24a6c20..993abb730dfa 100644
--- a/sound/soc/sh/fsi.c
+++ b/sound/soc/sh/fsi.c
@@ -388,7 +388,7 @@ static void fsi_soft_all_reset(struct fsi_master *master)
388} 388}
389 389
390/* playback interrupt */ 390/* playback interrupt */
391static int fsi_data_push(struct fsi_priv *fsi) 391static int fsi_data_push(struct fsi_priv *fsi, int startup)
392{ 392{
393 struct snd_pcm_runtime *runtime; 393 struct snd_pcm_runtime *runtime;
394 struct snd_pcm_substream *substream = NULL; 394 struct snd_pcm_substream *substream = NULL;
@@ -397,7 +397,7 @@ static int fsi_data_push(struct fsi_priv *fsi)
397 int fifo_free; 397 int fifo_free;
398 int width; 398 int width;
399 u8 *start; 399 u8 *start;
400 int i, ret, over_period; 400 int i, over_period;
401 401
402 if (!fsi || 402 if (!fsi ||
403 !fsi->substream || 403 !fsi->substream ||
@@ -453,24 +453,26 @@ static int fsi_data_push(struct fsi_priv *fsi)
453 453
454 fsi->byte_offset += send * width; 454 fsi->byte_offset += send * width;
455 455
456 ret = 0;
457 status = fsi_reg_read(fsi, DOFF_ST); 456 status = fsi_reg_read(fsi, DOFF_ST);
458 if (status & ERR_OVER) { 457 if (!startup) {
459 struct snd_soc_dai *dai = fsi_get_dai(substream); 458 struct snd_soc_dai *dai = fsi_get_dai(substream);
460 dev_err(dai->dev, "over run error\n"); 459
461 fsi_reg_write(fsi, DOFF_ST, status & ~ST_ERR); 460 if (status & ERR_OVER)
462 ret = -EIO; 461 dev_err(dai->dev, "over run\n");
462 if (status & ERR_UNDER)
463 dev_err(dai->dev, "under run\n");
463 } 464 }
465 fsi_reg_write(fsi, DOFF_ST, 0);
464 466
465 fsi_irq_enable(fsi, 1); 467 fsi_irq_enable(fsi, 1);
466 468
467 if (over_period) 469 if (over_period)
468 snd_pcm_period_elapsed(substream); 470 snd_pcm_period_elapsed(substream);
469 471
470 return ret; 472 return 0;
471} 473}
472 474
473static int fsi_data_pop(struct fsi_priv *fsi) 475static int fsi_data_pop(struct fsi_priv *fsi, int startup)
474{ 476{
475 struct snd_pcm_runtime *runtime; 477 struct snd_pcm_runtime *runtime;
476 struct snd_pcm_substream *substream = NULL; 478 struct snd_pcm_substream *substream = NULL;
@@ -479,7 +481,7 @@ static int fsi_data_pop(struct fsi_priv *fsi)
479 int fifo_fill; 481 int fifo_fill;
480 int width; 482 int width;
481 u8 *start; 483 u8 *start;
482 int i, ret, over_period; 484 int i, over_period;
483 485
484 if (!fsi || 486 if (!fsi ||
485 !fsi->substream || 487 !fsi->substream ||
@@ -534,21 +536,23 @@ static int fsi_data_pop(struct fsi_priv *fsi)
534 536
535 fsi->byte_offset += fifo_fill * width; 537 fsi->byte_offset += fifo_fill * width;
536 538
537 ret = 0;
538 status = fsi_reg_read(fsi, DIFF_ST); 539 status = fsi_reg_read(fsi, DIFF_ST);
539 if (status & ERR_UNDER) { 540 if (!startup) {
540 struct snd_soc_dai *dai = fsi_get_dai(substream); 541 struct snd_soc_dai *dai = fsi_get_dai(substream);
541 dev_err(dai->dev, "under run error\n"); 542
542 fsi_reg_write(fsi, DIFF_ST, status & ~ST_ERR); 543 if (status & ERR_OVER)
543 ret = -EIO; 544 dev_err(dai->dev, "over run\n");
545 if (status & ERR_UNDER)
546 dev_err(dai->dev, "under run\n");
544 } 547 }
548 fsi_reg_write(fsi, DIFF_ST, 0);
545 549
546 fsi_irq_enable(fsi, 0); 550 fsi_irq_enable(fsi, 0);
547 551
548 if (over_period) 552 if (over_period)
549 snd_pcm_period_elapsed(substream); 553 snd_pcm_period_elapsed(substream);
550 554
551 return ret; 555 return 0;
552} 556}
553 557
554static irqreturn_t fsi_interrupt(int irq, void *data) 558static irqreturn_t fsi_interrupt(int irq, void *data)
@@ -562,13 +566,13 @@ static irqreturn_t fsi_interrupt(int irq, void *data)
562 fsi_master_write(master, SOFT_RST, status | 0x00000010); 566 fsi_master_write(master, SOFT_RST, status | 0x00000010);
563 567
564 if (int_st & INT_A_OUT) 568 if (int_st & INT_A_OUT)
565 fsi_data_push(&master->fsia); 569 fsi_data_push(&master->fsia, 0);
566 if (int_st & INT_B_OUT) 570 if (int_st & INT_B_OUT)
567 fsi_data_push(&master->fsib); 571 fsi_data_push(&master->fsib, 0);
568 if (int_st & INT_A_IN) 572 if (int_st & INT_A_IN)
569 fsi_data_pop(&master->fsia); 573 fsi_data_pop(&master->fsia, 0);
570 if (int_st & INT_B_IN) 574 if (int_st & INT_B_IN)
571 fsi_data_pop(&master->fsib); 575 fsi_data_pop(&master->fsib, 0);
572 576
573 fsi_master_write(master, INT_ST, 0x0000000); 577 fsi_master_write(master, INT_ST, 0x0000000);
574 578
@@ -726,7 +730,7 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
726 fsi_stream_push(fsi, substream, 730 fsi_stream_push(fsi, substream,
727 frames_to_bytes(runtime, runtime->buffer_size), 731 frames_to_bytes(runtime, runtime->buffer_size),
728 frames_to_bytes(runtime, runtime->period_size)); 732 frames_to_bytes(runtime, runtime->period_size));
729 ret = is_play ? fsi_data_push(fsi) : fsi_data_pop(fsi); 733 ret = is_play ? fsi_data_push(fsi, 1) : fsi_data_pop(fsi, 1);
730 break; 734 break;
731 case SNDRV_PCM_TRIGGER_STOP: 735 case SNDRV_PCM_TRIGGER_STOP:
732 fsi_irq_disable(fsi, is_play); 736 fsi_irq_disable(fsi, is_play);