Module Name: src Committed By: nat Date: Thu Oct 26 22:38:27 UTC 2017
Modified Files: src/sys/dev: audio.c audiovar.h Log Message: Add latency sysctl to adjust hw blocksize and hence latency of the mixer. usage: sysctl -w hw.hdafg0.lantency="value in milliseconds" It is possible to set the latency of the mixer unless a static blocksize is configured by the underlying hardware driver (pad, vcaudio on RPI). Documentation updates to audio.4 will occur in a follow up commit. OK christos@. XXX pullup-8. To generate a diff of this commit: cvs rdiff -u -r1.414 -r1.415 src/sys/dev/audio.c cvs rdiff -u -r1.65 -r1.66 src/sys/dev/audiovar.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/audio.c diff -u src/sys/dev/audio.c:1.414 src/sys/dev/audio.c:1.415 --- src/sys/dev/audio.c:1.414 Wed Oct 25 08:12:38 2017 +++ src/sys/dev/audio.c Thu Oct 26 22:38:27 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: audio.c,v 1.414 2017/10/25 08:12:38 maya Exp $ */ +/* $NetBSD: audio.c,v 1.415 2017/10/26 22:38:27 nat Exp $ */ /*- * Copyright (c) 2016 Nathanial Sloss <nathanialsl...@yahoo.com.au> @@ -148,7 +148,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.414 2017/10/25 08:12:38 maya Exp $"); +__KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.415 2017/10/26 22:38:27 nat Exp $"); #ifdef _KERNEL_OPT #include "audio.h" @@ -205,6 +205,7 @@ int audiodebug = AUDIO_DEBUG; #define DPRINTFN(n,x) #endif +#define PREFILL_BLOCKS 3 /* no. audioblocks required to start stream */ #define ROUNDSIZE(x) (x) &= -16 /* round to nice boundary */ #define SPECIFIED(x) ((int)(x) != ~0) #define SPECIFIED_CH(x) ((x) != (u_char)~0) @@ -313,6 +314,7 @@ int audio_set_defaults(struct audio_soft static int audio_sysctl_frequency(SYSCTLFN_PROTO); static int audio_sysctl_precision(SYSCTLFN_PROTO); static int audio_sysctl_channels(SYSCTLFN_PROTO); +static int audio_sysctl_latency(SYSCTLFN_PROTO); static int audiomatch(device_t, cfdata_t, void *); static void audioattach(device_t, device_t, void *); @@ -498,6 +500,7 @@ audioattach(device_t parent, device_t se sc->sc_recopens = 0; sc->sc_aivalid = false; sc->sc_ready = true; + sc->sc_latency = audio_blk_ms * PREFILL_BLOCKS; sc->sc_format[0].mode = AUMODE_PLAY | AUMODE_RECORD; sc->sc_format[0].encoding = @@ -793,6 +796,15 @@ audioattach(device_t parent, device_t se sysctl_createv(&sc->sc_log, 0, NULL, NULL, CTLFLAG_READWRITE, + CTLTYPE_INT, "latency", + SYSCTL_DESCR("latency"), + audio_sysctl_latency, 0, + (void *)sc, 0, + CTL_HW, node->sysctl_num, + CTL_CREATE, CTL_EOL); + + sysctl_createv(&sc->sc_log, 0, NULL, NULL, + CTLFLAG_READWRITE, CTLTYPE_BOOL, "multiuser", SYSCTL_DESCR("allow multiple user acess"), NULL, 0, @@ -2634,8 +2646,8 @@ audio_calc_blksize(struct audio_softc *s { int blksize; - blksize = parm->sample_rate * audio_blk_ms / 1000 * - parm->channels * parm->precision / NBBY; + blksize = parm->sample_rate * sc->sc_latency * parm->channels / + 1000 * parm->precision / NBBY / PREFILL_BLOCKS; return blksize; } @@ -4106,7 +4118,7 @@ audio_set_vchan_defaults(struct audio_so &sc->sc_encodings); if (error == 0) - error = audiosetinfo(sc, &ai, false, vc); + error = audiosetinfo(sc, &ai, true, vc); return error; } @@ -5955,6 +5967,64 @@ audio_sysctl_channels(SYSCTLFN_ARGS) return error; } +/* sysctl helper to set audio latency */ +static int +audio_sysctl_latency(SYSCTLFN_ARGS) +{ + struct sysctlnode node; + struct audio_softc *sc; + int t, error; + + node = *rnode; + sc = node.sysctl_data; + + t = sc->sc_latency; + node.sysctl_data = &t; + error = sysctl_lookup(SYSCTLFN_CALL(&node)); + if (error || newp == NULL) + return error; + + mutex_enter(sc->sc_lock); + + /* This may not change when a virtual channel is open */ + if (sc->sc_opens || sc->sc_recopens) { + mutex_exit(sc->sc_lock); + return EBUSY; + } + + if (t < 0 || t > 4000) { + mutex_exit(sc->sc_lock); + return EINVAL; + } + + if (t == 0) + sc->sc_latency = audio_blk_ms * PREFILL_BLOCKS; + else + sc->sc_latency = (unsigned int)t; + + error = audio_set_vchan_defaults(sc, + AUMODE_PLAY | AUMODE_PLAY_ALL | AUMODE_RECORD); + if (error) { + aprint_error_dev(sc->sc_dev, "Error setting latency, " + "latency restored to default\n"); + sc->sc_latency = audio_blk_ms * PREFILL_BLOCKS; + error = audio_set_vchan_defaults(sc, + AUMODE_PLAY | AUMODE_PLAY_ALL | AUMODE_RECORD); + } + + if (sc->sc_vchan_params.sample_rate > 0 && + sc->sc_vchan_params.channels > 0 && + sc->sc_vchan_params.precision > 0) { + sc->sc_latency = sc->sc_hwvc->sc_mpr.blksize * 1000 * + PREFILL_BLOCKS / sc->sc_vchan_params.sample_rate / + sc->sc_vchan_params.channels * NBBY / + sc->sc_vchan_params.precision; + } + mutex_exit(sc->sc_lock); + + return error; +} + static int vchan_autoconfig(struct audio_softc *sc) { Index: src/sys/dev/audiovar.h diff -u src/sys/dev/audiovar.h:1.65 src/sys/dev/audiovar.h:1.66 --- src/sys/dev/audiovar.h:1.65 Sun Sep 24 23:40:41 2017 +++ src/sys/dev/audiovar.h Thu Oct 26 22:38:27 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: audiovar.h,v 1.65 2017/09/24 23:40:41 nat Exp $ */ +/* $NetBSD: audiovar.h,v 1.66 2017/10/26 22:38:27 nat Exp $ */ /*- * Copyright (c) 2002 The NetBSD Foundation, Inc. @@ -205,6 +205,7 @@ struct audio_softc { bool sc_rec_started; bool sc_writeme; bool sc_ready; /* audio hw configured properly */ + unsigned int sc_latency; int sc_opens; int sc_recopens; bool sc_dying;