Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev Add latency sysctl to adjust hw blocksize and hence ...



details:   https://anonhg.NetBSD.org/src/rev/5ab5d6b2e852
branches:  trunk
changeset: 827402:5ab5d6b2e852
user:      nat <nat%NetBSD.org@localhost>
date:      Thu Oct 26 22:38:27 2017 +0000

description:
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.

diffstat:

 sys/dev/audio.c    |  80 ++++++++++++++++++++++++++++++++++++++++++++++++++---
 sys/dev/audiovar.h |   3 +-
 2 files changed, 77 insertions(+), 6 deletions(-)

diffs (160 lines):

diff -r 3d86fee53b28 -r 5ab5d6b2e852 sys/dev/audio.c
--- a/sys/dev/audio.c   Thu Oct 26 10:56:57 2017 +0000
+++ b/sys/dev/audio.c   Thu Oct 26 22:38:27 2017 +0000
@@ -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 <nathanialsloss%yahoo.com.au@localhost>
@@ -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 @@
 #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 @@
 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 @@
        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 @@
 
                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 @@
 {
        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 @@
            &sc->sc_encodings);
 
        if (error == 0)
-               error = audiosetinfo(sc, &ai, false, vc);
+               error = audiosetinfo(sc, &ai, true, vc);
 
        return error;
 }
@@ -5955,6 +5967,64 @@
        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)
 {
diff -r 3d86fee53b28 -r 5ab5d6b2e852 sys/dev/audiovar.h
--- a/sys/dev/audiovar.h        Thu Oct 26 10:56:57 2017 +0000
+++ b/sys/dev/audiovar.h        Thu Oct 26 22:38:27 2017 +0000
@@ -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 @@
        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;



Home | Main Index | Thread Index | Old Index