diff options
author | Clemens Ladisch <clemens@ladisch.de> | 2010-11-15 10:46:23 +0100 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2010-11-22 08:13:16 +0100 |
commit | ab69a4904b5dd4d7cd6996587ba066bca8d13838 (patch) | |
tree | 8d51c631f1bd0bb72b9b528aa065ec9c0f4d0600 /sound/core | |
parent | d2b88e4c103f37584dc81ef8a41ca584c1ce847b (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.c | 6 | ||||
-rw-r--r-- | sound/core/pcm_native.c | 3 |
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, (unsigned long)new_hw_ptr, (unsigned long)runtime->hw_ptr_base); } + + /* without period interrupts, there are no regular pointer updates */ + if (runtime->no_period_wakeup) + goto no_delta_check; + /* something must be really wrong */ if (delta >= runtime->buffer_size + runtime->period_size) { hw_ptr_error(substream, @@ -442,6 +447,7 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream, (long)old_hw_ptr); } + no_delta_check: if (runtime->status->hw_ptr == new_hw_ptr) return 0; 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, runtime->info = params->info; runtime->rate_num = params->rate_num; runtime->rate_den = params->rate_den; + runtime->no_period_wakeup = + (params->info & SNDRV_PCM_INFO_NO_PERIOD_WAKEUP) && + (params->flags & SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP); bits = snd_pcm_format_physical_width(runtime->format); runtime->sample_bits = bits; |