aboutsummaryrefslogtreecommitdiffstats
path: root/sound/core
diff options
context:
space:
mode:
authorPierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>2012-10-22 17:42:14 -0400
committerTakashi Iwai <tiwai@suse.de>2012-10-23 10:13:41 -0400
commit0e8014d772a7639f48d234b23dc4ce97335cce7f (patch)
treedc2be9b0067a1eb896474e8dfa1b0b2d88d14e93 /sound/core
parent86a778a78d06cdc8c3994837cd963c146acfba6a (diff)
ALSA: core: keep track of boundary wrap-around
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@linux.intel.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/core')
-rw-r--r--sound/core/pcm_lib.c25
1 files changed, 20 insertions, 5 deletions
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index f42c10a43315..3dc029e106a2 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -316,6 +316,7 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
316 unsigned long jdelta; 316 unsigned long jdelta;
317 unsigned long curr_jiffies; 317 unsigned long curr_jiffies;
318 struct timespec curr_tstamp; 318 struct timespec curr_tstamp;
319 int crossed_boundary = 0;
319 320
320 old_hw_ptr = runtime->status->hw_ptr; 321 old_hw_ptr = runtime->status->hw_ptr;
321 322
@@ -360,8 +361,10 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
360 hdelta = curr_jiffies - runtime->hw_ptr_jiffies; 361 hdelta = curr_jiffies - runtime->hw_ptr_jiffies;
361 if (hdelta > runtime->hw_ptr_buffer_jiffies/2) { 362 if (hdelta > runtime->hw_ptr_buffer_jiffies/2) {
362 hw_base += runtime->buffer_size; 363 hw_base += runtime->buffer_size;
363 if (hw_base >= runtime->boundary) 364 if (hw_base >= runtime->boundary) {
364 hw_base = 0; 365 hw_base = 0;
366 crossed_boundary++;
367 }
365 new_hw_ptr = hw_base + pos; 368 new_hw_ptr = hw_base + pos;
366 goto __delta; 369 goto __delta;
367 } 370 }
@@ -371,8 +374,10 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
371 /* pointer crosses the end of the ring buffer */ 374 /* pointer crosses the end of the ring buffer */
372 if (new_hw_ptr < old_hw_ptr) { 375 if (new_hw_ptr < old_hw_ptr) {
373 hw_base += runtime->buffer_size; 376 hw_base += runtime->buffer_size;
374 if (hw_base >= runtime->boundary) 377 if (hw_base >= runtime->boundary) {
375 hw_base = 0; 378 hw_base = 0;
379 crossed_boundary++;
380 }
376 new_hw_ptr = hw_base + pos; 381 new_hw_ptr = hw_base + pos;
377 } 382 }
378 __delta: 383 __delta:
@@ -410,8 +415,10 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
410 while (hdelta > xrun_threshold) { 415 while (hdelta > xrun_threshold) {
411 delta += runtime->buffer_size; 416 delta += runtime->buffer_size;
412 hw_base += runtime->buffer_size; 417 hw_base += runtime->buffer_size;
413 if (hw_base >= runtime->boundary) 418 if (hw_base >= runtime->boundary) {
414 hw_base = 0; 419 hw_base = 0;
420 crossed_boundary++;
421 }
415 new_hw_ptr = hw_base + pos; 422 new_hw_ptr = hw_base + pos;
416 hdelta -= runtime->hw_ptr_buffer_jiffies; 423 hdelta -= runtime->hw_ptr_buffer_jiffies;
417 } 424 }
@@ -456,8 +463,10 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
456 /* the delta value is small or zero in most cases */ 463 /* the delta value is small or zero in most cases */
457 while (delta > 0) { 464 while (delta > 0) {
458 new_hw_ptr += runtime->period_size; 465 new_hw_ptr += runtime->period_size;
459 if (new_hw_ptr >= runtime->boundary) 466 if (new_hw_ptr >= runtime->boundary) {
460 new_hw_ptr -= runtime->boundary; 467 new_hw_ptr -= runtime->boundary;
468 crossed_boundary--;
469 }
461 delta--; 470 delta--;
462 } 471 }
463 /* align hw_base to buffer_size */ 472 /* align hw_base to buffer_size */
@@ -507,6 +516,10 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
507 runtime->hw_ptr_base = hw_base; 516 runtime->hw_ptr_base = hw_base;
508 runtime->status->hw_ptr = new_hw_ptr; 517 runtime->status->hw_ptr = new_hw_ptr;
509 runtime->hw_ptr_jiffies = curr_jiffies; 518 runtime->hw_ptr_jiffies = curr_jiffies;
519 if (crossed_boundary) {
520 snd_BUG_ON(crossed_boundary != 1);
521 runtime->hw_ptr_wrap += runtime->boundary;
522 }
510 if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) 523 if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE)
511 runtime->status->tstamp = curr_tstamp; 524 runtime->status->tstamp = curr_tstamp;
512 525
@@ -1661,8 +1674,10 @@ static int snd_pcm_lib_ioctl_reset(struct snd_pcm_substream *substream,
1661 if (snd_pcm_running(substream) && 1674 if (snd_pcm_running(substream) &&
1662 snd_pcm_update_hw_ptr(substream) >= 0) 1675 snd_pcm_update_hw_ptr(substream) >= 0)
1663 runtime->status->hw_ptr %= runtime->buffer_size; 1676 runtime->status->hw_ptr %= runtime->buffer_size;
1664 else 1677 else {
1665 runtime->status->hw_ptr = 0; 1678 runtime->status->hw_ptr = 0;
1679 runtime->hw_ptr_wrap = 0;
1680 }
1666 snd_pcm_stream_unlock_irqrestore(substream, flags); 1681 snd_pcm_stream_unlock_irqrestore(substream, flags);
1667 return 0; 1682 return 0;
1668} 1683}