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>
This commit is contained in:
parent
142e8174b3
commit
59c3b003dd
|
@ -67,6 +67,7 @@
|
||||||
/* DOFF_ST */
|
/* DOFF_ST */
|
||||||
#define ERR_OVER 0x00000010
|
#define ERR_OVER 0x00000010
|
||||||
#define ERR_UNDER 0x00000001
|
#define ERR_UNDER 0x00000001
|
||||||
|
#define ST_ERR (ERR_OVER | ERR_UNDER)
|
||||||
|
|
||||||
/* CLK_RST */
|
/* CLK_RST */
|
||||||
#define B_CLK 0x00000010
|
#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_runtime *runtime;
|
||||||
struct snd_pcm_substream *substream = NULL;
|
struct snd_pcm_substream *substream = NULL;
|
||||||
|
u32 status;
|
||||||
int send;
|
int send;
|
||||||
int fifo_free;
|
int fifo_free;
|
||||||
int width;
|
int width;
|
||||||
u8 *start;
|
u8 *start;
|
||||||
int i, over_period;
|
int i, ret, over_period;
|
||||||
|
|
||||||
if (!fsi ||
|
if (!fsi ||
|
||||||
!fsi->substream ||
|
!fsi->substream ||
|
||||||
|
@ -435,23 +437,33 @@ static int fsi_data_push(struct fsi_priv *fsi)
|
||||||
|
|
||||||
fsi->byte_offset += send * width;
|
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);
|
fsi_irq_enable(fsi, 1);
|
||||||
|
|
||||||
if (over_period)
|
if (over_period)
|
||||||
snd_pcm_period_elapsed(substream);
|
snd_pcm_period_elapsed(substream);
|
||||||
|
|
||||||
return 0;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fsi_data_pop(struct fsi_priv *fsi)
|
static int fsi_data_pop(struct fsi_priv *fsi)
|
||||||
{
|
{
|
||||||
struct snd_pcm_runtime *runtime;
|
struct snd_pcm_runtime *runtime;
|
||||||
struct snd_pcm_substream *substream = NULL;
|
struct snd_pcm_substream *substream = NULL;
|
||||||
|
u32 status;
|
||||||
int free;
|
int free;
|
||||||
int fifo_fill;
|
int fifo_fill;
|
||||||
int width;
|
int width;
|
||||||
u8 *start;
|
u8 *start;
|
||||||
int i, over_period;
|
int i, ret, over_period;
|
||||||
|
|
||||||
if (!fsi ||
|
if (!fsi ||
|
||||||
!fsi->substream ||
|
!fsi->substream ||
|
||||||
|
@ -506,12 +518,21 @@ static int fsi_data_pop(struct fsi_priv *fsi)
|
||||||
|
|
||||||
fsi->byte_offset += fifo_fill * width;
|
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);
|
fsi_irq_enable(fsi, 0);
|
||||||
|
|
||||||
if (over_period)
|
if (over_period)
|
||||||
snd_pcm_period_elapsed(substream);
|
snd_pcm_period_elapsed(substream);
|
||||||
|
|
||||||
return 0;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static irqreturn_t fsi_interrupt(int irq, void *data)
|
static irqreturn_t fsi_interrupt(int irq, void *data)
|
||||||
|
|
Loading…
Reference in a new issue