aboutsummaryrefslogtreecommitdiffstats
path: root/sound/core
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2009-05-29 05:46:10 -0400
committerTakashi Iwai <tiwai@suse.de>2009-05-29 05:46:10 -0400
commite93721a70263afefbac781f575bfe851c6f95d84 (patch)
treeab359f12a0688802aa99339bae82c51763dae9f6 /sound/core
parentae1ec5e1e97f67d41e641a73380129e5905e41cc (diff)
parentc87d9732004b3f8fd82d729f12ccfb96c0df279e (diff)
Merge branch 'fix/pcm-jiffies-check' into topic/pcm-jiffies-check
Diffstat (limited to 'sound/core')
-rw-r--r--sound/core/pcm_lib.c17
-rw-r--r--sound/core/pcm_native.c6
2 files changed, 21 insertions, 2 deletions
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 63d088f2265f..d659995ac3ac 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -249,6 +249,17 @@ static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream)
249 new_hw_ptr = hw_base + pos; 249 new_hw_ptr = hw_base + pos;
250 } 250 }
251 } 251 }
252
253 /* Do jiffies check only in xrun_debug mode */
254 if (!xrun_debug(substream))
255 goto no_jiffies_check;
256
257 /* Skip the jiffies check for hardwares with BATCH flag.
258 * Such hardware usually just increases the position at each IRQ,
259 * thus it can't give any strange position.
260 */
261 if (runtime->hw.info & SNDRV_PCM_INFO_BATCH)
262 goto no_jiffies_check;
252 hdelta = new_hw_ptr - old_hw_ptr; 263 hdelta = new_hw_ptr - old_hw_ptr;
253 jdelta = jiffies - runtime->hw_ptr_jiffies; 264 jdelta = jiffies - runtime->hw_ptr_jiffies;
254 if (((hdelta * HZ) / runtime->rate) > jdelta + HZ/100) { 265 if (((hdelta * HZ) / runtime->rate) > jdelta + HZ/100) {
@@ -272,6 +283,7 @@ static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream)
272 hw_base -= hw_base % runtime->buffer_size; 283 hw_base -= hw_base % runtime->buffer_size;
273 delta = 0; 284 delta = 0;
274 } 285 }
286 no_jiffies_check:
275 if (delta > runtime->period_size + runtime->period_size / 2) { 287 if (delta > runtime->period_size + runtime->period_size / 2) {
276 hw_ptr_error(substream, 288 hw_ptr_error(substream,
277 "Lost interrupts? " 289 "Lost interrupts? "
@@ -329,7 +341,9 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream)
329 hw_base = 0; 341 hw_base = 0;
330 new_hw_ptr = hw_base + pos; 342 new_hw_ptr = hw_base + pos;
331 } 343 }
332 if (((delta * HZ) / runtime->rate) > jdelta + HZ/100) { 344 /* Do jiffies check only in xrun_debug mode */
345 if (xrun_debug(substream) &&
346 ((delta * HZ) / runtime->rate) > jdelta + HZ/100) {
333 hw_ptr_error(substream, 347 hw_ptr_error(substream,
334 "hw_ptr skipping! " 348 "hw_ptr skipping! "
335 "(pos=%ld, delta=%ld, period=%ld, jdelta=%lu/%lu)\n", 349 "(pos=%ld, delta=%ld, period=%ld, jdelta=%lu/%lu)\n",
@@ -1471,7 +1485,6 @@ static int snd_pcm_lib_ioctl_reset(struct snd_pcm_substream *substream,
1471 runtime->status->hw_ptr %= runtime->buffer_size; 1485 runtime->status->hw_ptr %= runtime->buffer_size;
1472 else 1486 else
1473 runtime->status->hw_ptr = 0; 1487 runtime->status->hw_ptr = 0;
1474 runtime->hw_ptr_jiffies = jiffies;
1475 snd_pcm_stream_unlock_irqrestore(substream, flags); 1488 snd_pcm_stream_unlock_irqrestore(substream, flags);
1476 return 0; 1489 return 0;
1477} 1490}
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index cb769d415db7..45dc53fcfa2f 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -849,6 +849,7 @@ static void snd_pcm_post_start(struct snd_pcm_substream *substream, int state)
849{ 849{
850 struct snd_pcm_runtime *runtime = substream->runtime; 850 struct snd_pcm_runtime *runtime = substream->runtime;
851 snd_pcm_trigger_tstamp(substream); 851 snd_pcm_trigger_tstamp(substream);
852 runtime->hw_ptr_jiffies = jiffies;
852 runtime->status->state = state; 853 runtime->status->state = state;
853 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && 854 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
854 runtime->silence_size > 0) 855 runtime->silence_size > 0)
@@ -962,6 +963,11 @@ static int snd_pcm_do_pause(struct snd_pcm_substream *substream, int push)
962{ 963{
963 if (substream->runtime->trigger_master != substream) 964 if (substream->runtime->trigger_master != substream)
964 return 0; 965 return 0;
966 /* The jiffies check in snd_pcm_update_hw_ptr*() is done by
967 * a delta betwen the current jiffies, this gives a large enough
968 * delta, effectively to skip the check once.
969 */
970 substream->runtime->hw_ptr_jiffies = jiffies - HZ * 1000;
965 return substream->ops->trigger(substream, 971 return substream->ops->trigger(substream,
966 push ? SNDRV_PCM_TRIGGER_PAUSE_PUSH : 972 push ? SNDRV_PCM_TRIGGER_PAUSE_PUSH :
967 SNDRV_PCM_TRIGGER_PAUSE_RELEASE); 973 SNDRV_PCM_TRIGGER_PAUSE_RELEASE);