diff options
Diffstat (limited to 'sound/soc/sh/fsi.c')
-rw-r--r-- | sound/soc/sh/fsi.c | 29 |
1 files changed, 25 insertions, 4 deletions
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index d078151e1de6..123cd6f45e0c 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c | |||
@@ -67,6 +67,7 @@ | |||
67 | /* DOFF_ST */ | 67 | /* DOFF_ST */ |
68 | #define ERR_OVER 0x00000010 | 68 | #define ERR_OVER 0x00000010 |
69 | #define ERR_UNDER 0x00000001 | 69 | #define ERR_UNDER 0x00000001 |
70 | #define ST_ERR (ERR_OVER | ERR_UNDER) | ||
70 | 71 | ||
71 | /* CLK_RST */ | 72 | /* CLK_RST */ |
72 | #define B_CLK 0x00000010 | 73 | #define B_CLK 0x00000010 |
@@ -375,11 +376,12 @@ static int fsi_data_push(struct fsi_priv *fsi) | |||
375 | { | 376 | { |
376 | struct snd_pcm_runtime *runtime; | 377 | struct snd_pcm_runtime *runtime; |
377 | struct snd_pcm_substream *substream = NULL; | 378 | struct snd_pcm_substream *substream = NULL; |
379 | u32 status; | ||
378 | int send; | 380 | int send; |
379 | int fifo_free; | 381 | int fifo_free; |
380 | int width; | 382 | int width; |
381 | u8 *start; | 383 | u8 *start; |
382 | int i, over_period; | 384 | int i, ret, over_period; |
383 | 385 | ||
384 | if (!fsi || | 386 | if (!fsi || |
385 | !fsi->substream || | 387 | !fsi->substream || |
@@ -435,23 +437,33 @@ static int fsi_data_push(struct fsi_priv *fsi) | |||
435 | 437 | ||
436 | fsi->byte_offset += send * width; | 438 | fsi->byte_offset += send * width; |
437 | 439 | ||
440 | ret = 0; | ||
441 | status = fsi_reg_read(fsi, DOFF_ST); | ||
442 | if (status & ERR_OVER) { | ||
443 | struct snd_soc_dai *dai = fsi_get_dai(substream); | ||
444 | dev_err(dai->dev, "over run error\n"); | ||
445 | fsi_reg_write(fsi, DOFF_ST, status & ~ST_ERR); | ||
446 | ret = -EIO; | ||
447 | } | ||
448 | |||
438 | fsi_irq_enable(fsi, 1); | 449 | fsi_irq_enable(fsi, 1); |
439 | 450 | ||
440 | if (over_period) | 451 | if (over_period) |
441 | snd_pcm_period_elapsed(substream); | 452 | snd_pcm_period_elapsed(substream); |
442 | 453 | ||
443 | return 0; | 454 | return ret; |
444 | } | 455 | } |
445 | 456 | ||
446 | static int fsi_data_pop(struct fsi_priv *fsi) | 457 | static int fsi_data_pop(struct fsi_priv *fsi) |
447 | { | 458 | { |
448 | struct snd_pcm_runtime *runtime; | 459 | struct snd_pcm_runtime *runtime; |
449 | struct snd_pcm_substream *substream = NULL; | 460 | struct snd_pcm_substream *substream = NULL; |
461 | u32 status; | ||
450 | int free; | 462 | int free; |
451 | int fifo_fill; | 463 | int fifo_fill; |
452 | int width; | 464 | int width; |
453 | u8 *start; | 465 | u8 *start; |
454 | int i, over_period; | 466 | int i, ret, over_period; |
455 | 467 | ||
456 | if (!fsi || | 468 | if (!fsi || |
457 | !fsi->substream || | 469 | !fsi->substream || |
@@ -506,12 +518,21 @@ static int fsi_data_pop(struct fsi_priv *fsi) | |||
506 | 518 | ||
507 | fsi->byte_offset += fifo_fill * width; | 519 | fsi->byte_offset += fifo_fill * width; |
508 | 520 | ||
521 | ret = 0; | ||
522 | status = fsi_reg_read(fsi, DIFF_ST); | ||
523 | if (status & ERR_UNDER) { | ||
524 | struct snd_soc_dai *dai = fsi_get_dai(substream); | ||
525 | dev_err(dai->dev, "under run error\n"); | ||
526 | fsi_reg_write(fsi, DIFF_ST, status & ~ST_ERR); | ||
527 | ret = -EIO; | ||
528 | } | ||
529 | |||
509 | fsi_irq_enable(fsi, 0); | 530 | fsi_irq_enable(fsi, 0); |
510 | 531 | ||
511 | if (over_period) | 532 | if (over_period) |
512 | snd_pcm_period_elapsed(substream); | 533 | snd_pcm_period_elapsed(substream); |
513 | 534 | ||
514 | return 0; | 535 | return ret; |
515 | } | 536 | } |
516 | 537 | ||
517 | static irqreturn_t fsi_interrupt(int irq, void *data) | 538 | static irqreturn_t fsi_interrupt(int irq, void *data) |