diff options
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/sh/fsi.c | 46 |
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 */ |
391 | static int fsi_data_push(struct fsi_priv *fsi) | 391 | static 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 | ||
473 | static int fsi_data_pop(struct fsi_priv *fsi) | 475 | static 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 | ||
554 | static irqreturn_t fsi_interrupt(int irq, void *data) | 558 | static 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); |