aboutsummaryrefslogtreecommitdiffstats
path: root/sound/core
diff options
context:
space:
mode:
authorJaroslav Kysela <perex@perex.cz>2010-08-18 08:16:54 -0400
committerTakashi Iwai <tiwai@suse.de>2010-08-18 09:18:02 -0400
commitbd76af0f87f7a1815b311bde269a3f18305b3169 (patch)
tree27f95b3e568146eed0958989f3f8d0c4eae3616b /sound/core
parente7cfbea9cb7a02ea29fdae5d39c9e3d09102c4d5 (diff)
ALSA: pcm midlevel code - add time check for double interrupt acknowledge
The current code in pcm_lib.c do all checks using only the position in the ring buffer. Unfortunately, where the interrupts gets delayed or merged into one, we need another timing source to check when the buffer size boundary overlaps to avoid the wrong updating of the ring buffer pointers. This code uses jiffies to check the right time window without any performance impact. Signed-off-by: Jaroslav Kysela <perex@perex.cz> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/core')
-rw-r--r--sound/core/pcm_lib.c14
-rw-r--r--sound/core/pcm_native.c2
2 files changed, 11 insertions, 5 deletions
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index e23e0e7ab26f..a1707cca9c66 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -334,11 +334,15 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
334 /* delta = "expected next hw_ptr" for in_interrupt != 0 */ 334 /* delta = "expected next hw_ptr" for in_interrupt != 0 */
335 delta = runtime->hw_ptr_interrupt + runtime->period_size; 335 delta = runtime->hw_ptr_interrupt + runtime->period_size;
336 if (delta > new_hw_ptr) { 336 if (delta > new_hw_ptr) {
337 hw_base += runtime->buffer_size; 337 /* check for double acknowledged interrupts */
338 if (hw_base >= runtime->boundary) 338 hdelta = jiffies - runtime->hw_ptr_jiffies;
339 hw_base = 0; 339 if (hdelta > runtime->hw_ptr_buffer_jiffies/2) {
340 new_hw_ptr = hw_base + pos; 340 hw_base += runtime->buffer_size;
341 goto __delta; 341 if (hw_base >= runtime->boundary)
342 hw_base = 0;
343 new_hw_ptr = hw_base + pos;
344 goto __delta;
345 }
342 } 346 }
343 } 347 }
344 /* new_hw_ptr might be lower than old_hw_ptr in case when */ 348 /* new_hw_ptr might be lower than old_hw_ptr in case when */
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 134fc6c2e08d..e2e73895db12 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -864,6 +864,8 @@ static void snd_pcm_post_start(struct snd_pcm_substream *substream, int state)
864 struct snd_pcm_runtime *runtime = substream->runtime; 864 struct snd_pcm_runtime *runtime = substream->runtime;
865 snd_pcm_trigger_tstamp(substream); 865 snd_pcm_trigger_tstamp(substream);
866 runtime->hw_ptr_jiffies = jiffies; 866 runtime->hw_ptr_jiffies = jiffies;
867 runtime->hw_ptr_buffer_jiffies = (runtime->buffer_size * HZ) /
868 runtime->rate;
867 runtime->status->state = state; 869 runtime->status->state = state;
868 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && 870 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
869 runtime->silence_size > 0) 871 runtime->silence_size > 0)