diff options
| -rw-r--r-- | sound/core/pcm_lib.c | 23 |
1 files changed, 18 insertions, 5 deletions
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index faedb1481b24..8f312fa6c282 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c | |||
| @@ -313,9 +313,22 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream, | |||
| 313 | snd_pcm_uframes_t old_hw_ptr, new_hw_ptr, hw_base; | 313 | snd_pcm_uframes_t old_hw_ptr, new_hw_ptr, hw_base; |
| 314 | snd_pcm_sframes_t hdelta, delta; | 314 | snd_pcm_sframes_t hdelta, delta; |
| 315 | unsigned long jdelta; | 315 | unsigned long jdelta; |
| 316 | unsigned long curr_jiffies; | ||
| 317 | struct timespec curr_tstamp; | ||
| 316 | 318 | ||
| 317 | old_hw_ptr = runtime->status->hw_ptr; | 319 | old_hw_ptr = runtime->status->hw_ptr; |
| 320 | |||
| 321 | /* | ||
| 322 | * group pointer, time and jiffies reads to allow for more | ||
| 323 | * accurate correlations/corrections. | ||
| 324 | * The values are stored at the end of this routine after | ||
| 325 | * corrections for hw_ptr position | ||
| 326 | */ | ||
| 318 | pos = substream->ops->pointer(substream); | 327 | pos = substream->ops->pointer(substream); |
| 328 | curr_jiffies = jiffies; | ||
| 329 | if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) | ||
| 330 | snd_pcm_gettime(runtime, (struct timespec *)&curr_tstamp); | ||
| 331 | |||
| 319 | if (pos == SNDRV_PCM_POS_XRUN) { | 332 | if (pos == SNDRV_PCM_POS_XRUN) { |
| 320 | xrun(substream); | 333 | xrun(substream); |
| 321 | return -EPIPE; | 334 | return -EPIPE; |
| @@ -343,7 +356,7 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream, | |||
| 343 | delta = runtime->hw_ptr_interrupt + runtime->period_size; | 356 | delta = runtime->hw_ptr_interrupt + runtime->period_size; |
| 344 | if (delta > new_hw_ptr) { | 357 | if (delta > new_hw_ptr) { |
| 345 | /* check for double acknowledged interrupts */ | 358 | /* check for double acknowledged interrupts */ |
| 346 | hdelta = jiffies - runtime->hw_ptr_jiffies; | 359 | hdelta = curr_jiffies - runtime->hw_ptr_jiffies; |
| 347 | if (hdelta > runtime->hw_ptr_buffer_jiffies/2) { | 360 | if (hdelta > runtime->hw_ptr_buffer_jiffies/2) { |
| 348 | hw_base += runtime->buffer_size; | 361 | hw_base += runtime->buffer_size; |
| 349 | if (hw_base >= runtime->boundary) | 362 | if (hw_base >= runtime->boundary) |
| @@ -388,7 +401,7 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream, | |||
| 388 | * Without regular period interrupts, we have to check | 401 | * Without regular period interrupts, we have to check |
| 389 | * the elapsed time to detect xruns. | 402 | * the elapsed time to detect xruns. |
| 390 | */ | 403 | */ |
| 391 | jdelta = jiffies - runtime->hw_ptr_jiffies; | 404 | jdelta = curr_jiffies - runtime->hw_ptr_jiffies; |
| 392 | if (jdelta < runtime->hw_ptr_buffer_jiffies / 2) | 405 | if (jdelta < runtime->hw_ptr_buffer_jiffies / 2) |
| 393 | goto no_delta_check; | 406 | goto no_delta_check; |
| 394 | hdelta = jdelta - delta * HZ / runtime->rate; | 407 | hdelta = jdelta - delta * HZ / runtime->rate; |
| @@ -430,7 +443,7 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream, | |||
| 430 | if (hdelta < runtime->delay) | 443 | if (hdelta < runtime->delay) |
| 431 | goto no_jiffies_check; | 444 | goto no_jiffies_check; |
| 432 | hdelta -= runtime->delay; | 445 | hdelta -= runtime->delay; |
| 433 | jdelta = jiffies - runtime->hw_ptr_jiffies; | 446 | jdelta = curr_jiffies - runtime->hw_ptr_jiffies; |
| 434 | if (((hdelta * HZ) / runtime->rate) > jdelta + HZ/100) { | 447 | if (((hdelta * HZ) / runtime->rate) > jdelta + HZ/100) { |
| 435 | delta = jdelta / | 448 | delta = jdelta / |
| 436 | (((runtime->period_size * HZ) / runtime->rate) | 449 | (((runtime->period_size * HZ) / runtime->rate) |
| @@ -492,9 +505,9 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream, | |||
| 492 | } | 505 | } |
| 493 | runtime->hw_ptr_base = hw_base; | 506 | runtime->hw_ptr_base = hw_base; |
| 494 | runtime->status->hw_ptr = new_hw_ptr; | 507 | runtime->status->hw_ptr = new_hw_ptr; |
| 495 | runtime->hw_ptr_jiffies = jiffies; | 508 | runtime->hw_ptr_jiffies = curr_jiffies; |
| 496 | if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) | 509 | if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) |
| 497 | snd_pcm_gettime(runtime, (struct timespec *)&runtime->status->tstamp); | 510 | runtime->status->tstamp = curr_tstamp; |
| 498 | 511 | ||
| 499 | return snd_pcm_update_state(substream, runtime); | 512 | return snd_pcm_update_state(substream, runtime); |
| 500 | } | 513 | } |
