aboutsummaryrefslogtreecommitdiffstats
path: root/sound/core
diff options
context:
space:
mode:
authorJaroslav Kysela <perex@perex.cz>2010-01-26 11:08:24 -0500
committerJaroslav Kysela <perex@perex.cz>2010-01-26 11:50:50 -0500
commite7636925789b042ff9d98c51d48392e8c5549480 (patch)
tree4462f95057322b7d63d3b625644abd1f8fef6d7a /sound/core
parentfd0b092a7b14559e2ff17ef3aaefb5d8adc7e15f (diff)
ALSA: pcm_lib - return back hw_ptr_interrupt
Clemens Ladisch noted for hw_ptr_removal in "cleanup & merge hw_ptr update functions" commit: "It is possible for the status/delay ioctls to be called when the sound card's pointer register alreay shows a position at the beginning of the new period, but immediately before the interrupt is actually executed. (This happens regularly on a SMP machine with mplayer.) When that happens, the code thinks that the position must be at least one period ahead of the current position and drops an entire buffer of data." Return back the hw_ptr_interrupt variable. The last interrupt pointer is always computed from the latest hw_ptr instead of tracking it separately (in this case all hw_ptr checks and modifications might influence also hw_ptr_interrupt and it is difficult to keep it consistent). Signed-off-by: Jaroslav Kysela <perex@perex.cz>
Diffstat (limited to 'sound/core')
-rw-r--r--sound/core/oss/pcm_oss.c3
-rw-r--r--sound/core/pcm_lib.c7
-rw-r--r--sound/core/pcm_native.c2
3 files changed, 8 insertions, 4 deletions
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index 255ad910077a..82d4e3329b3d 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -635,8 +635,7 @@ static long snd_pcm_alsa_frames(struct snd_pcm_substream *substream, long bytes)
635static inline 635static inline
636snd_pcm_uframes_t get_hw_ptr_period(struct snd_pcm_runtime *runtime) 636snd_pcm_uframes_t get_hw_ptr_period(struct snd_pcm_runtime *runtime)
637{ 637{
638 snd_pcm_uframes_t ptr = runtime->status->hw_ptr; 638 return runtime->hw_ptr_interrupt;
639 return ptr - (ptr % runtime->period_size);
640} 639}
641 640
642/* define extended formats in the recent OSS versions (if any) */ 641/* define extended formats in the recent OSS versions (if any) */
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index e2a817eac2a9..aa54195ef3b0 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -325,8 +325,7 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
325 if (in_interrupt) { 325 if (in_interrupt) {
326 /* we know that one period was processed */ 326 /* we know that one period was processed */
327 /* delta = "expected next hw_ptr" for in_interrupt != 0 */ 327 /* delta = "expected next hw_ptr" for in_interrupt != 0 */
328 delta = old_hw_ptr - (old_hw_ptr % runtime->period_size) 328 delta = runtime->hw_ptr_interrupt + runtime->period_size;
329 + runtime->period_size;
330 if (delta > new_hw_ptr) { 329 if (delta > new_hw_ptr) {
331 hw_base += runtime->buffer_size; 330 hw_base += runtime->buffer_size;
332 if (hw_base >= runtime->boundary) 331 if (hw_base >= runtime->boundary)
@@ -437,6 +436,10 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
437 runtime->silence_size > 0) 436 runtime->silence_size > 0)
438 snd_pcm_playback_silence(substream, new_hw_ptr); 437 snd_pcm_playback_silence(substream, new_hw_ptr);
439 438
439 if (in_interrupt) {
440 runtime->hw_ptr_interrupt = new_hw_ptr -
441 (new_hw_ptr % runtime->period_size);
442 }
440 runtime->hw_ptr_base = hw_base; 443 runtime->hw_ptr_base = hw_base;
441 runtime->status->hw_ptr = new_hw_ptr; 444 runtime->status->hw_ptr = new_hw_ptr;
442 runtime->hw_ptr_jiffies = jiffies; 445 runtime->hw_ptr_jiffies = jiffies;
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 56ec35e8510b..7a002db512b4 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -1252,6 +1252,8 @@ static int snd_pcm_do_reset(struct snd_pcm_substream *substream, int state)
1252 if (err < 0) 1252 if (err < 0)
1253 return err; 1253 return err;
1254 runtime->hw_ptr_base = 0; 1254 runtime->hw_ptr_base = 0;
1255 runtime->hw_ptr_interrupt = runtime->status->hw_ptr -
1256 runtime->status->hw_ptr % runtime->period_size;
1255 runtime->silence_start = runtime->status->hw_ptr; 1257 runtime->silence_start = runtime->status->hw_ptr;
1256 runtime->silence_filled = 0; 1258 runtime->silence_filled = 0;
1257 return 0; 1259 return 0;