diff options
author | Kuninori Morimoto <morimoto.kuninori@renesas.com> | 2010-02-22 02:41:57 -0500 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2010-02-23 05:42:07 -0500 |
commit | 47fc9a0a808f23b7b305f6c018e4882118b88d92 (patch) | |
tree | 415001ffe968129e9afa5b775539812e0869348a | |
parent | db72c2f89790f919d65d0adbee390958005c40fc (diff) |
ASoC: fsi: Modify over/under run error settlement
In current FSI driver, playback function cares only overrun,
and capture function cares only underrun.
But playback function should had cared about underrun,
and capture function should had cared about overrun too.
Signed-off-by: Kuninori Morimoto <morimoto.kuninori@renesas.com>
Acked-by: Liam Girdwood <lrg@slimlogic.co.uk>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-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); |