[alsa-devel] [PATCH 2/2] ASoC: sh: fsi: Add over/under run counter
Current FSI driver had printed under/over run error if status register have its error bit. But runtime print cause the next error because print out is slow. This patch add error counter and print error when sound stop
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- sound/soc/sh/fsi.c | 76 +++++++++++++++++++++++++++++++++------------------ 1 files changed, 49 insertions(+), 27 deletions(-)
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 9ab8593..2b06402 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c @@ -134,6 +134,9 @@ struct fsi_stream { int buff_len; int period_len; int period_num; + + int uerr_num; + int oerr_num; };
struct fsi_priv { @@ -326,17 +329,29 @@ static void fsi_stream_push(struct fsi_priv *fsi, io->buff_offset = 0; io->period_len = period_len; io->period_num = 0; + io->oerr_num = -1; /* ignore 1st err */ + io->uerr_num = -1; /* ignore 1st err */ }
static void fsi_stream_pop(struct fsi_priv *fsi, int is_play) { struct fsi_stream *io = fsi_get_stream(fsi, is_play); + struct snd_soc_dai *dai = fsi_get_dai(io->substream); + + + if (io->oerr_num > 0) + dev_err(dai->dev, "over_run = %d\n", io->oerr_num); + + if (io->uerr_num > 0) + dev_err(dai->dev, "under_run = %d\n", io->uerr_num);
io->substream = NULL; io->buff_len = 0; io->buff_offset = 0; io->period_len = 0; io->period_num = 0; + io->oerr_num = 0; + io->uerr_num = 0; }
static int fsi_get_fifo_data_num(struct fsi_priv *fsi, int is_play) @@ -375,6 +390,27 @@ static int fsi_get_frame_width(struct fsi_priv *fsi, int is_play) return frames_to_bytes(runtime, 1) / io->chan_num; }
+static void fsi_count_fifo_err(struct fsi_priv *fsi) +{ + u32 ostatus = fsi_reg_read(fsi, DOFF_ST); + u32 istatus = fsi_reg_read(fsi, DIFF_ST); + + if (ostatus & ERR_OVER) + fsi->playback.oerr_num++; + + if (ostatus & ERR_UNDER) + fsi->playback.uerr_num++; + + if (istatus & ERR_OVER) + fsi->capture.oerr_num++; + + if (istatus & ERR_UNDER) + fsi->capture.uerr_num++; + + fsi_reg_write(fsi, DOFF_ST, 0); + fsi_reg_write(fsi, DIFF_ST, 0); +} + /* * dma function */ @@ -574,7 +610,7 @@ static void fsi_soft_all_reset(struct fsi_master *master) mdelay(10); }
-static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int startup, int stream) +static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int stream) { struct snd_pcm_runtime *runtime; struct snd_pcm_substream *substream = NULL; @@ -667,37 +703,20 @@ static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int startup, int stream) /* update buff_offset */ io->buff_offset += fsi_num2offset(data_num, ch_width);
- /* check fifo status */ - if (!startup) { - struct snd_soc_dai *dai = fsi_get_dai(substream); - u32 status = is_play ? - fsi_reg_read(fsi, DOFF_ST) : - fsi_reg_read(fsi, DIFF_ST); - - if (status & ERR_OVER) - dev_err(dai->dev, "over run\n"); - if (status & ERR_UNDER) - dev_err(dai->dev, "under run\n"); - } - - is_play ? - fsi_reg_write(fsi, DOFF_ST, 0) : - fsi_reg_write(fsi, DIFF_ST, 0); - if (over_period) snd_pcm_period_elapsed(substream);
return 0; }
-static int fsi_data_pop(struct fsi_priv *fsi, int startup) +static int fsi_data_pop(struct fsi_priv *fsi) { - return fsi_fifo_data_ctrl(fsi, startup, SNDRV_PCM_STREAM_CAPTURE); + return fsi_fifo_data_ctrl(fsi, SNDRV_PCM_STREAM_CAPTURE); }
-static int fsi_data_push(struct fsi_priv *fsi, int startup) +static int fsi_data_push(struct fsi_priv *fsi) { - return fsi_fifo_data_ctrl(fsi, startup, SNDRV_PCM_STREAM_PLAYBACK); + return fsi_fifo_data_ctrl(fsi, SNDRV_PCM_STREAM_PLAYBACK); }
static irqreturn_t fsi_interrupt(int irq, void *data) @@ -710,13 +729,16 @@ static irqreturn_t fsi_interrupt(int irq, void *data) fsi_master_mask_set(master, SOFT_RST, IR, IR);
if (int_st & AB_IO(1, AO_SHIFT)) - fsi_data_push(&master->fsia, 0); + fsi_data_push(&master->fsia); if (int_st & AB_IO(1, BO_SHIFT)) - fsi_data_push(&master->fsib, 0); + fsi_data_push(&master->fsib); if (int_st & AB_IO(1, AI_SHIFT)) - fsi_data_pop(&master->fsia, 0); + fsi_data_pop(&master->fsia); if (int_st & AB_IO(1, BI_SHIFT)) - fsi_data_pop(&master->fsib, 0); + fsi_data_pop(&master->fsib); + + fsi_count_fifo_err(&master->fsia); + fsi_count_fifo_err(&master->fsib);
fsi_irq_clear_status(&master->fsia); fsi_irq_clear_status(&master->fsib); @@ -855,7 +877,7 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd, fsi_stream_push(fsi, is_play, substream, frames_to_bytes(runtime, runtime->buffer_size), frames_to_bytes(runtime, runtime->period_size)); - ret = is_play ? fsi_data_push(fsi, 1) : fsi_data_pop(fsi, 1); + ret = is_play ? fsi_data_push(fsi) : fsi_data_pop(fsi); fsi_irq_enable(fsi, is_play); break; case SNDRV_PCM_TRIGGER_STOP:
Hi Mark,
In the codec file which we are trying to write, we do not have any dynamic Switching paths. So for the structure snd_soc_dapm_route, its always {sink, NULL, source}. The DAPM widgets are getting enabled at the codec probe (as we saw that they are getting declared as static) . So this consumes power and we want them do be turned on only when DAI is started?
So, does that mean that for every stream, we make use of the startup and shutdown functions to do our power management of the widgets. Or is there a way ASOC automatically takes care of powering of the static paths as well?
Thanks, Harsha
On Fri, Dec 17, 2010 at 01:56:36PM +0530, Harsha, Priya wrote:
In the codec file which we are trying to write, we do not have any dynamic Switching paths. So for the structure snd_soc_dapm_route, its always {sink, NULL, source}. The DAPM widgets are getting enabled at the codec probe (as we saw that they are getting declared as static) . So this consumes power and we want them do be turned on only when DAI is started?
This most likely indicates an error in your DAPM map. DAPM will only power on audio routes which have a fully connected path from an input to an output - you will have defined a path which includes the widgets which are getting powered on. Looking through the debugfs file for DAPM should let you see which path this is.
So, does that mean that for every stream, we make use of the startup and shutdown functions to do our power management of the widgets. Or is there a way ASOC automatically takes care of powering of the static paths as well?
If your device contains unconditionally connected paths the machine driver should use SOC_DAPM_PIN_SWITCH() to add relevant controls for the power if it needs them, or use something like jack detection if that's supported.
On Fri, Dec 17, 2010 at 12:55:22PM +0900, Kuninori Morimoto wrote:
Current FSI driver had printed under/over run error if status register have its error bit. But runtime print cause the next error because print out is slow. This patch add error counter and print error when sound stop
Applied, thanks.
participants (3)
-
Harsha, Priya
-
Kuninori Morimoto
-
Mark Brown