aboutsummaryrefslogtreecommitdiffstats
path: root/sound/core
diff options
context:
space:
mode:
authorClemens Ladisch <clemens@ladisch.de>2010-11-15 04:46:23 -0500
committerTakashi Iwai <tiwai@suse.de>2010-11-22 02:13:16 -0500
commitab69a4904b5dd4d7cd6996587ba066bca8d13838 (patch)
tree8d51c631f1bd0bb72b9b528aa065ec9c0f4d0600 /sound/core
parentd2b88e4c103f37584dc81ef8a41ca584c1ce847b (diff)
ALSA: pcm: support for period wakeup disabling
This patch allows to disable period interrupts which are not needed when the application relies on a system timer to wake-up and refill the ring buffer. The behavior of the driver is left unchanged, and interrupts are only disabled if the application requests this configuration. The behavior in case of underruns is slightly different, instead of being detected during the period interrupts the underruns are detected when the application calls snd_pcm_update_avail, which in turns forces a refresh of the hw pointer and shows the buffer is empty. More specifically this patch makes a lot of sense when PulseAudio relies on timer-based scheduling to access audio devices such as HDAudio or Intel SST. Disabling interrupts removes two unwanted wake-ups due to period elapsed events in low-power playback modes. It also simplifies PulseAudio voice modules used for speech calls. To quote Lennart "This patch looks very interesting and desirable. This is something have long been waiting for." Support for this in hardware drivers is optional. Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@intel.com> Signed-off-by: Clemens Ladisch <clemens@ladisch.de> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/core')
-rw-r--r--sound/core/pcm_lib.c6
-rw-r--r--sound/core/pcm_native.c3
2 files changed, 9 insertions, 0 deletions
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index b75db8e9cc0f..bc57501c584a 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -373,6 +373,11 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
373 (unsigned long)new_hw_ptr, 373 (unsigned long)new_hw_ptr,
374 (unsigned long)runtime->hw_ptr_base); 374 (unsigned long)runtime->hw_ptr_base);
375 } 375 }
376
377 /* without period interrupts, there are no regular pointer updates */
378 if (runtime->no_period_wakeup)
379 goto no_delta_check;
380
376 /* something must be really wrong */ 381 /* something must be really wrong */
377 if (delta >= runtime->buffer_size + runtime->period_size) { 382 if (delta >= runtime->buffer_size + runtime->period_size) {
378 hw_ptr_error(substream, 383 hw_ptr_error(substream,
@@ -442,6 +447,7 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
442 (long)old_hw_ptr); 447 (long)old_hw_ptr);
443 } 448 }
444 449
450 no_delta_check:
445 if (runtime->status->hw_ptr == new_hw_ptr) 451 if (runtime->status->hw_ptr == new_hw_ptr)
446 return 0; 452 return 0;
447 453
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 8bc7cb3db330..f91a439f675c 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -423,6 +423,9 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
423 runtime->info = params->info; 423 runtime->info = params->info;
424 runtime->rate_num = params->rate_num; 424 runtime->rate_num = params->rate_num;
425 runtime->rate_den = params->rate_den; 425 runtime->rate_den = params->rate_den;
426 runtime->no_period_wakeup =
427 (params->info & SNDRV_PCM_INFO_NO_PERIOD_WAKEUP) &&
428 (params->flags & SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP);
426 429
427 bits = snd_pcm_format_physical_width(runtime->format); 430 bits = snd_pcm_format_physical_width(runtime->format);
428 runtime->sample_bits = bits; 431 runtime->sample_bits = bits;