From fb87726303b6e620a06fec1d3b2988d428e33ac2 Mon Sep 17 00:00:00 2001 From: Florian Walpen Date: Sun, 28 Jan 2024 20:18:20 +0000 Subject: [PATCH] snd_hdspe(4): Per device sysctl for period. Let the user choose a period (interrupt cadence in samples), in the official RME drivers this setting is available as "Buffer Size". Override the period propagated through blocksize by pcm channel latency settings (see sound(4)), since these are unreliable and differ between playback and recording channels. Differential Revision: https://reviews.freebsd.org/D43527 --- share/man/man4/snd_hdspe.4 | 7 ++++++- sys/dev/sound/pci/hdspe-pcm.c | 3 +++ sys/dev/sound/pci/hdspe.c | 38 +++++++++++++++++++++++++++++++++++ sys/dev/sound/pci/hdspe.h | 1 + 4 files changed, 48 insertions(+), 1 deletion(-) diff --git a/share/man/man4/snd_hdspe.4 b/share/man/man4/snd_hdspe.4 index 6023cd3d2ccd..d4ddc70f4070 100644 --- a/share/man/man4/snd_hdspe.4 +++ b/share/man/man4/snd_hdspe.4 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd January 8, 2024 +.Dd January 19, 2024 .Dt SND_HDSPE 4 .Os .Sh NAME @@ -76,6 +76,11 @@ To adjust the following sysctl identifiers for a specific sound card, insert the respective device number in place of .Ql 0 . .Bl -tag -width indent +.It Va dev.hdspe.0.period +The number of samples processed per interrupt, from 32, 64, 128, up to 4096. +Setting a lower value here results in less latency, but increases system load +due to frequent interrupt processing. +Extreme values may cause audio gaps and glitches. .It Va dev.hdspe.0.clock_list Lists possible clock sources to sync with, depending on the hardware model. This includes internal and external master clocks as well as incoming digital diff --git a/sys/dev/sound/pci/hdspe-pcm.c b/sys/dev/sound/pci/hdspe-pcm.c index db39b867879f..f6c7c84e026e 100644 --- a/sys/dev/sound/pci/hdspe-pcm.c +++ b/sys/dev/sound/pci/hdspe-pcm.c @@ -891,6 +891,9 @@ hdspechan_setblocksize(kobj_t obj, void *data, uint32_t blocksize) blocksize /= 4 /* samples */; + if (sc->force_period > 0) + blocksize = sc->force_period; + /* First look for equal latency. */ for (i = 0; latency_map[i].period != 0; i++) { if (latency_map[i].period == blocksize) diff --git a/sys/dev/sound/pci/hdspe.c b/sys/dev/sound/pci/hdspe.c index e0197d1e981a..b1ca67bdc313 100644 --- a/sys/dev/sound/pci/hdspe.c +++ b/sys/dev/sound/pci/hdspe.c @@ -228,6 +228,31 @@ hdspe_map_dmabuf(struct sc_info *sc) } } +static int +hdspe_sysctl_period(SYSCTL_HANDLER_ARGS) +{ + struct sc_info *sc = oidp->oid_arg1; + int error; + unsigned int period; + + period = sc->force_period; + + /* Process sysctl (unsigned) integer request. */ + error = sysctl_handle_int(oidp, &period, 0, req); + if (error != 0 || req->newptr == NULL) + return (error); + + /* Period is from 2^5 to 2^14, 0 falls back to pcm latency settings. */ + sc->force_period = 0; + if (period > 0) { + sc->force_period = 32; + while (sc->force_period < period && sc->force_period < 4096) + sc->force_period <<= 1; + } + + return (0); +} + static int hdspe_sysctl_clock_preference(SYSCTL_HANDLER_ARGS) { @@ -419,6 +444,13 @@ hdspe_init(struct sc_info *sc) /* Set latency. */ sc->period = 32; + /* + * The pcm channel latency settings propagate unreliable blocksizes, + * different for recording and playback, and skewed due to rounding + * and total buffer size limits. + * Force period to a consistent default until these issues are fixed. + */ + sc->force_period = 256; sc->ctrl_register = hdspe_encode_latency(7); /* Set rate. */ @@ -524,6 +556,12 @@ hdspe_attach(device_t dev) sc, 0, hdspe_sysctl_clock_list, "A", "List of supported clock sources"); + SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), + SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, + "period", CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_MPSAFE, + sc, 0, hdspe_sysctl_period, "A", + "Force period of samples per interrupt (32, 64, ... 4096)"); + return (bus_generic_attach(dev)); } diff --git a/sys/dev/sound/pci/hdspe.h b/sys/dev/sound/pci/hdspe.h index d5d8dd46e580..81116e0cd437 100644 --- a/sys/dev/sound/pci/hdspe.h +++ b/sys/dev/sound/pci/hdspe.h @@ -227,6 +227,7 @@ struct sc_info { bus_dmamap_t rmap; uint32_t period; uint32_t speed; + uint32_t force_period; }; #define hdspe_read_1(sc, regno) \