diff options
author | Kuninori Morimoto <morimoto.kuninori@renesas.com> | 2009-12-28 14:09:16 +0900 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2009-12-30 18:31:09 +0000 |
commit | 59c3b003ddd3c815de1aa015920710a9e4bf195b (patch) | |
tree | b582e2f661d4889428e93cbe6e7a9956dd6982fb /sound | |
parent | 142e8174b3c493f40469d3ecee0e404645e9c483 (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>
Diffstat (limited to 'sound')
-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 d078151e1de..123cd6f45e0 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c @@ -67,6 +67,7 @@ /* DOFF_ST */ #define ERR_OVER 0x00000010 #define ERR_UNDER 0x00000001 +#define ST_ERR (ERR_OVER | ERR_UNDER) /* CLK_RST */ #define B_CLK 0x00000010 @@ -375,11 +376,12 @@ static int fsi_data_push(struct fsi_priv *fsi) { struct snd_pcm_runtime *runtime; struct snd_pcm_substream *substream = NULL; + u32 status; int send; int fifo_free; int width; u8 *start; - int i, over_period; + int i, ret, over_period; if (!fsi || !fsi->substream || @@ -435,23 +437,33 @@ static int fsi_data_push(struct fsi_priv *fsi) fsi->byte_offset += send * width; + ret = 0; + status = fsi_reg_read(fsi, DOFF_ST); + if (status & ERR_OVER) { + struct snd_soc_dai *dai = fsi_get_dai(substream); + dev_err(dai->dev, "over run error\n"); + fsi_reg_write(fsi, DOFF_ST, status & ~ST_ERR); + ret = -EIO; + } + fsi_irq_enable(fsi, 1); if (over_period) snd_pcm_period_elapsed(substream); - return 0; + return ret; } static int fsi_data_pop(struct fsi_priv *fsi) { struct snd_pcm_runtime *runtime; struct snd_pcm_substream *substream = NULL; + u32 status; int free; int fifo_fill; int width; u8 *start; - int i, over_period; + int i, ret, over_period; if (!fsi || !fsi->substream || @@ -506,12 +518,21 @@ static int fsi_data_pop(struct fsi_priv *fsi) fsi->byte_offset += fifo_fill * width; + ret = 0; + status = fsi_reg_read(fsi, DIFF_ST); + if (status & ERR_UNDER) { + struct snd_soc_dai *dai = fsi_get_dai(substream); + dev_err(dai->dev, "under run error\n"); + fsi_reg_write(fsi, DIFF_ST, status & ~ST_ERR); + ret = -EIO; + } + fsi_irq_enable(fsi, 0); if (over_period) snd_pcm_period_elapsed(substream); - return 0; + return ret; } static irqreturn_t fsi_interrupt(int irq, void *data) |