[alsa-devel] [PATCH v2 1/3] ALSA: core: keep track of boundary wrap-around
Takashi Iwai
tiwai at suse.de
Tue Oct 9 11:37:21 CEST 2012
At Mon, 8 Oct 2012 12:11:56 -0500,
Pierre-Louis Bossart wrote:
>
> Keep track of boundary crossing when hw_ptr
> exceeds boundary limit and wraps-around. This
> will help keep track of total number
> of frames played/received at the kernel level
>
> Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart at linux.intel.com>
> ---
> include/sound/pcm.h | 1 +
> sound/core/pcm_lib.c | 26 +++++++++++++++++++++-----
> 2 files changed, 22 insertions(+), 5 deletions(-)
>
> diff --git a/include/sound/pcm.h b/include/sound/pcm.h
> index cdca2ab..ba13e0b 100644
> --- a/include/sound/pcm.h
> +++ b/include/sound/pcm.h
> @@ -281,6 +281,7 @@ struct snd_pcm_runtime {
> unsigned long hw_ptr_jiffies; /* Time when hw_ptr is updated */
> unsigned long hw_ptr_buffer_jiffies; /* buffer time in jiffies */
> snd_pcm_sframes_t delay; /* extra delay; typically FIFO size */
> + u64 hw_ptr_wrap; /* offset for hw_ptr due to boundary wrap-around */
>
> /* -- HW params -- */
> snd_pcm_access_t access; /* access mode */
> diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
> index 7ae6719..ec996ca 100644
> --- a/sound/core/pcm_lib.c
> +++ b/sound/core/pcm_lib.c
> @@ -315,6 +315,7 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
> unsigned long jdelta;
> unsigned long curr_jiffies;
> struct timespec curr_tstamp;
> + int crossed_boundary = 0;
>
> old_hw_ptr = runtime->status->hw_ptr;
>
> @@ -359,8 +360,10 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
> hdelta = curr_jiffies - runtime->hw_ptr_jiffies;
> if (hdelta > runtime->hw_ptr_buffer_jiffies/2) {
> hw_base += runtime->buffer_size;
> - if (hw_base >= runtime->boundary)
> + if (hw_base >= runtime->boundary) {
> hw_base = 0;
> + crossed_boundary++;
> + }
> new_hw_ptr = hw_base + pos;
> goto __delta;
> }
> @@ -370,8 +373,10 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
> /* pointer crosses the end of the ring buffer */
> if (new_hw_ptr < old_hw_ptr) {
> hw_base += runtime->buffer_size;
> - if (hw_base >= runtime->boundary)
> + if (hw_base >= runtime->boundary) {
> hw_base = 0;
> + crossed_boundary++;
> + }
> new_hw_ptr = hw_base + pos;
> }
> __delta:
> @@ -409,8 +414,10 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
> while (hdelta > xrun_threshold) {
> delta += runtime->buffer_size;
> hw_base += runtime->buffer_size;
> - if (hw_base >= runtime->boundary)
> + if (hw_base >= runtime->boundary) {
> hw_base = 0;
> + crossed_boundary++;
> + }
> new_hw_ptr = hw_base + pos;
> hdelta -= runtime->hw_ptr_buffer_jiffies;
> }
> @@ -455,8 +462,10 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
> /* the delta value is small or zero in most cases */
> while (delta > 0) {
> new_hw_ptr += runtime->period_size;
> - if (new_hw_ptr >= runtime->boundary)
> + if (new_hw_ptr >= runtime->boundary) {
> new_hw_ptr -= runtime->boundary;
> + crossed_boundary--;
> + }
> delta--;
> }
> /* align hw_base to buffer_size */
> @@ -506,6 +515,11 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
> runtime->hw_ptr_base = hw_base;
> runtime->status->hw_ptr = new_hw_ptr;
> runtime->hw_ptr_jiffies = curr_jiffies;
> + if (crossed_boundary) {
> + BUG_ON(crossed_boundary > 1);
> + BUG_ON(crossed_boundary < 0);
BUG_ON() is too hard for such sanity checks, since it leads to a
kernel panic without recovery. Better to use WARN_ON() or
snd_BUG_ON()
snd_BUG_ON(crossed_boundary != 1);
Takashi
> + runtime->hw_ptr_wrap += runtime->boundary;
> + }
> if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE)
> runtime->status->tstamp = curr_tstamp;
>
> @@ -1660,8 +1674,10 @@ static int snd_pcm_lib_ioctl_reset(struct snd_pcm_substream *substream,
> if (snd_pcm_running(substream) &&
> snd_pcm_update_hw_ptr(substream) >= 0)
> runtime->status->hw_ptr %= runtime->buffer_size;
> - else
> + else {
> runtime->status->hw_ptr = 0;
> + runtime->hw_ptr_wrap = 0;
> + }
> snd_pcm_stream_unlock_irqrestore(substream, flags);
> return 0;
> }
> --
> 1.7.9.5
>
> _______________________________________________
> Alsa-devel mailing list
> Alsa-devel at alsa-project.org
> http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
>
More information about the Alsa-devel
mailing list