aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKuninori Morimoto <morimoto.kuninori@renesas.com>2009-12-28 00:09:16 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2009-12-30 13:31:09 -0500
commit59c3b003ddd3c815de1aa015920710a9e4bf195b (patch)
treeb582e2f661d4889428e93cbe6e7a9956dd6982fb
parent142e8174b3c493f40469d3ecee0e404645e9c483 (diff)
ASoC: fsi: Add over/under run error settlement
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.c29
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
446static int fsi_data_pop(struct fsi_priv *fsi) 457static 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
517static irqreturn_t fsi_interrupt(int irq, void *data) 538static irqreturn_t fsi_interrupt(int irq, void *data)