summaryrefslogtreecommitdiffstats
path: root/src/modules/alsa/alsa-sink.c
diff options
context:
space:
mode:
authorPierre-Louis Bossart <pierre-louis.bossart@intel.com>2010-04-29 10:48:11 -0500
committerLennart Poettering <lennart@poettering.net>2010-05-08 01:38:25 +0200
commit4df443bbe682055a41e7c2248877dcc7682a69b8 (patch)
treee1c687b48d24f4c03fe7f43c1e4072fb70df9188 /src/modules/alsa/alsa-sink.c
parentf081c152f3d5f6a70edc6b7369445229b4f6a1b8 (diff)
add rewind-safeguard parameter
Rewinding the ring buffer completely causes audible issues with DMAs. Previous solution didn't work with tsched=0, and used tsched_watermark for guardband, which isn't linked to hardware and could become really high if underflows occurred. Added separate parameter that can be tuned to hardware limitations and size of DMA bursts.
Diffstat (limited to 'src/modules/alsa/alsa-sink.c')
-rw-r--r--src/modules/alsa/alsa-sink.c18
1 files changed, 14 insertions, 4 deletions
diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c
index 687a8300..ce7970b2 100644
--- a/src/modules/alsa/alsa-sink.c
+++ b/src/modules/alsa/alsa-sink.c
@@ -83,6 +83,8 @@
#define VOLUME_ACCURACY (PA_VOLUME_NORM/100) /* don't require volume adjustments to be perfectly correct. don't necessarily extend granularity in software unless the differences get greater than this level */
+#define DEFAULT_REWIND_SAFEGUARD_BYTES (256) /* 1.33ms @48kHz, should work for most hardware */
+
struct userdata {
pa_core *core;
pa_module *module;
@@ -112,7 +114,8 @@ struct userdata {
watermark_inc_step,
watermark_dec_step,
watermark_inc_threshold,
- watermark_dec_threshold;
+ watermark_dec_threshold,
+ rewind_safeguard;
pa_usec_t watermark_dec_not_before;
@@ -1312,8 +1315,8 @@ static int process_rewind(struct userdata *u) {
unused_nbytes = (size_t) unused * u->frame_size;
- if (u->use_tsched)
- unused_nbytes += u->tsched_watermark;
+ /* make sure rewind doesn't go too far, can cause issues with DMAs */
+ unused_nbytes += u->rewind_safeguard;
if (u->hwbuf_size > unused_nbytes)
limit_nbytes = u->hwbuf_size - unused_nbytes;
@@ -1668,7 +1671,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
pa_channel_map map;
uint32_t nfrags, frag_size, buffer_size, tsched_size, tsched_watermark;
snd_pcm_uframes_t period_frames, buffer_frames, tsched_frames;
- size_t frame_size;
+ size_t frame_size, rewind_safeguard;
pa_bool_t use_mmap = TRUE, b, use_tsched = TRUE, d, ignore_dB = FALSE;
pa_sink_new_data data;
pa_alsa_profile_set *profile_set = NULL;
@@ -1722,6 +1725,12 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
goto fail;
}
+ rewind_safeguard = DEFAULT_REWIND_SAFEGUARD_BYTES;
+ if (pa_modargs_get_value_u32(ma, "rewind_safeguard", &rewind_safeguard) < 0) {
+ pa_log("Failed to parse rewind_safeguard argument");
+ goto fail;
+ }
+
use_tsched = pa_alsa_may_tsched(use_tsched);
u = pa_xnew0(struct userdata, 1);
@@ -1730,6 +1739,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
u->use_mmap = use_mmap;
u->use_tsched = use_tsched;
u->first = TRUE;
+ u->rewind_safeguard = rewind_safeguard;
u->rtpoll = pa_rtpoll_new();
pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);