Source-Changes-HG archive

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

[src/trunk]: src/sys/dev A sysctl is now available to disable the in kernel m...



details:   https://anonhg.NetBSD.org/src/rev/2b47fe0c744e
branches:  trunk
changeset: 827653:2b47fe0c744e
user:      nat <nat%NetBSD.org@localhost>
date:      Tue Nov 07 01:13:19 2017 +0000

description:
A sysctl is now available to disable the in kernel mixer.
        sysctl -w hw.hdafg0.usemixer=0

There currently is a problem draining the last block with the mixer
disabled.  I will fix this in a follow up commit.

AFAIK there will be a problem wiht vs(4) on x68k with the mixer disabled
as the filters for mulaw, alaw and unsigned linear have been removed post
audio mixing changes.

Documentation for this sysctl variable will be made to audio.4 in a follow
up commit.

Ok christos@.

diffstat:

 sys/dev/audio.c    |  227 ++++++++++++++++++++++++++++++++++++++--------------
 sys/dev/audiovar.h |    3 +-
 2 files changed, 165 insertions(+), 65 deletions(-)

diffs (truncated from 437 to 300 lines):

diff -r c2a239826a00 -r 2b47fe0c744e sys/dev/audio.c
--- a/sys/dev/audio.c   Mon Nov 06 23:06:55 2017 +0000
+++ b/sys/dev/audio.c   Tue Nov 07 01:13:19 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: audio.c,v 1.429 2017/11/04 01:50:48 nat Exp $  */
+/*     $NetBSD: audio.c,v 1.430 2017/11/07 01:13:19 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.429 2017/11/04 01:50:48 nat Exp $");
+__KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.430 2017/11/07 01:13:19 nat Exp $");
 
 #ifdef _KERNEL_OPT
 #include "audio.h"
@@ -320,6 +320,7 @@
 static int audio_sysctl_precision(SYSCTLFN_PROTO);
 static int audio_sysctl_channels(SYSCTLFN_PROTO);
 static int audio_sysctl_latency(SYSCTLFN_PROTO);
+static int audio_sysctl_usemixer(SYSCTLFN_PROTO);
 
 static int     audiomatch(device_t, cfdata_t, void *);
 static void    audioattach(device_t, device_t, void *);
@@ -608,6 +609,7 @@
 
        sc->sc_lastgain = 128;
        sc->sc_multiuser = false;
+       sc->sc_usemixer = true;
 
        error = vchan_autoconfig(sc);
        if (error != 0) {
@@ -814,6 +816,15 @@
                        &sc->sc_multiuser, 0,
                        CTL_HW, node->sysctl_num,
                        CTL_CREATE, CTL_EOL);
+
+               sysctl_createv(&sc->sc_log, 0, NULL, NULL,
+                       CTLFLAG_READWRITE,
+                       CTLTYPE_BOOL, "usemixer",
+                       SYSCTL_DESCR("allow in-kernel mixing"),
+                       audio_sysctl_usemixer, 0,
+                       (void *)sc, 0,
+                       CTL_HW, node->sysctl_num,
+                       CTL_CREATE, CTL_EOL);
        }
 
        selinit(&sc->sc_rsel);
@@ -1594,6 +1605,9 @@
        /* Wait for pending I/O to complete. */
        error = cv_wait_sig(chan, sc->sc_lock);
 
+       if (!sc->sc_usemixer)
+               return error;
+
        found = false;
        SIMPLEQ_FOREACH(vchan, &sc->sc_audiochan, entries) {
                if (vchan->vc == vc) {
@@ -2153,7 +2167,7 @@
 
        KASSERT(mutex_owned(sc->sc_lock));
 
-       if (sc->sc_ready == false)
+       if (sc->sc_usemixer && !sc->sc_ready)
                return ENXIO;
 
        hw = sc->hw_if;
@@ -2166,36 +2180,50 @@
                n = chan->chan + 1;
 
        chan = kmem_zalloc(sizeof(struct audio_chan), KM_SLEEP);
-       vc = kmem_zalloc(sizeof(struct virtual_channel), KM_SLEEP);
+       if (sc->sc_usemixer)
+               vc = kmem_zalloc(sizeof(struct virtual_channel), KM_SLEEP);
+       else
+               vc = sc->sc_hwvc;
        chan->vc = vc;
 
-       vc->sc_open = 0;
-       vc->sc_mode = 0;
-       vc->sc_sil_count = 0;
-       vc->sc_nrfilters = 0;
-       memset(vc->sc_rfilters, 0,
-           sizeof(vc->sc_rfilters));
-       vc->sc_rbus = false;
-       vc->sc_npfilters = 0;
-       memset(vc->sc_pfilters, 0,
-           sizeof(vc->sc_pfilters));
-       vc->sc_draining = false;
-       vc->sc_pbus = false;
-       vc->sc_lastinfovalid = false;
-       vc->sc_swvol = 255;
-       vc->sc_recswvol = 255;
+       if (sc->sc_usemixer) {
+               vc->sc_open = 0;
+               vc->sc_mode = 0;
+               vc->sc_sil_count = 0;
+               vc->sc_nrfilters = 0;
+               memset(vc->sc_rfilters, 0,
+                   sizeof(vc->sc_rfilters));
+               vc->sc_rbus = false;
+               vc->sc_npfilters = 0;
+               memset(vc->sc_pfilters, 0,
+                   sizeof(vc->sc_pfilters));
+               vc->sc_draining = false;
+               vc->sc_pbus = false;
+               vc->sc_lastinfovalid = false;
+               vc->sc_swvol = 255;
+               vc->sc_recswvol = 255;
+       } else {
+               if (sc->sc_opens > 0 || sc->sc_recopens > 0 ) {
+                       kmem_free(chan, sizeof(struct audio_chan));
+                       return EBUSY;
+               }
+       }
 
        DPRINTF(("audio_open: flags=0x%x sc=%p hdl=%p\n",
                 flags, sc, sc->hw_hdl));
 
-       error = audio_alloc_ring(sc, &vc->sc_mpr, AUMODE_PLAY, AU_RING_SIZE);
-       if (error)
-               goto bad;
-       error = audio_alloc_ring(sc, &vc->sc_mrr, AUMODE_RECORD, AU_RING_SIZE);
-       if (error)
-               goto bad;
-
-       if (sc->sc_opens + sc->sc_recopens == 0) {
+       if (sc->sc_usemixer) {
+               error = audio_alloc_ring(sc, &vc->sc_mpr, AUMODE_PLAY,
+                   AU_RING_SIZE);
+               if (error)
+                       goto bad;
+               error = audio_alloc_ring(sc, &vc->sc_mrr, AUMODE_RECORD,
+                   AU_RING_SIZE);
+               if (error)
+                       goto bad;
+       }
+
+       if (!sc->sc_usemixer || sc->sc_opens + sc->sc_recopens == 0) {
                sc->sc_credentials = kauth_cred_get();
                kauth_cred_hold(sc->sc_credentials);
                if (hw->open != NULL) {
@@ -2290,7 +2318,8 @@
        chan->dev = dev;
        chan->chan = n;
        chan->deschan = n;
-       SIMPLEQ_INSERT_TAIL(&sc->sc_audiochan, chan, entries);
+       if (sc->sc_usemixer)
+               SIMPLEQ_INSERT_TAIL(&sc->sc_audiochan, chan, entries);
 
        error = fd_clone(fp, fd, flags, &audio_fileops, chan);
        KASSERT(error == EMOVEFD);
@@ -2304,10 +2333,14 @@
        if (hw->close != NULL && sc->sc_opens == 0 && sc->sc_recopens == 0)
                hw->close(sc->hw_hdl);
        mutex_exit(sc->sc_lock);
-       audio_free_ring(sc, &vc->sc_mpr);
-       audio_free_ring(sc, &vc->sc_mrr);
-       mutex_enter(sc->sc_lock);
-       kmem_free(vc, sizeof(struct virtual_channel));
+       if (sc->sc_usemixer) {
+               audio_free_ring(sc, &vc->sc_mpr);
+               audio_free_ring(sc, &vc->sc_mrr);
+               mutex_enter(sc->sc_lock);
+               kmem_free(vc, sizeof(struct virtual_channel));
+       } else
+               mutex_enter(sc->sc_lock);
+
        kmem_free(chan, sizeof(struct audio_chan));
        return error;
 }
@@ -2518,13 +2551,15 @@
                sc->sc_recopens--;
        if (flags & FWRITE)
                sc->sc_opens--;
-       shrink_mixer_states(sc, 2);
-       SIMPLEQ_REMOVE(&sc->sc_audiochan, chan, audio_chan, entries);
-       mutex_exit(sc->sc_lock);
-       audio_free_ring(sc, &vc->sc_mpr);
-       audio_free_ring(sc, &vc->sc_mrr);
-       mutex_enter(sc->sc_lock);
-       kmem_free(vc, sizeof(struct virtual_channel));
+       if (sc->sc_usemixer) {
+               shrink_mixer_states(sc, 2);
+               SIMPLEQ_REMOVE(&sc->sc_audiochan, chan, audio_chan, entries);
+               mutex_exit(sc->sc_lock);
+               audio_free_ring(sc, &vc->sc_mpr);
+               audio_free_ring(sc, &vc->sc_mrr);
+               mutex_enter(sc->sc_lock);
+               kmem_free(vc, sizeof(struct virtual_channel));
+       }
 
        return 0;
 }
@@ -3038,12 +3073,15 @@
 
        KASSERT(mutex_owned(sc->sc_lock));
 
-       SIMPLEQ_FOREACH(pchan, &sc->sc_audiochan, entries) {
-               if (pchan->chan == chan->deschan)
-                       break;
-       }
-       if (pchan == NULL)
-               return ENXIO;
+       if (sc->sc_usemixer) {
+               SIMPLEQ_FOREACH(pchan, &sc->sc_audiochan, entries) {
+                       if (pchan->chan == chan->deschan)
+                               break;
+               }
+               if (pchan == NULL)
+                       return ENXIO;
+       } else
+               pchan = chan;
 
        vc = pchan->vc;
 
@@ -3515,14 +3553,15 @@
 
        if (!audio_can_capture(sc))
                return EINVAL;
-       if (vc == sc->sc_hwvc)
+       if (vc == sc->sc_hwvc && sc->sc_usemixer)
                return 0;
 
        error = 0;
        if (sc->sc_rec_started == false) {
                mutex_enter(sc->sc_intr_lock);
                error = mix_read(sc);
-               cv_broadcast(&sc->sc_rcondvar);
+               if (sc->sc_usemixer)
+                       cv_broadcast(&sc->sc_rcondvar);
                mutex_exit(sc->sc_intr_lock);
        }
        vc->sc_rbus = true;
@@ -3545,7 +3584,7 @@
 
        if (!audio_can_playback(sc))
                return EINVAL;
-       if (vc == sc->sc_hwvc)
+       if (vc == sc->sc_hwvc && sc->sc_usemixer)
                return 0;
 
        if (!vc->sc_mpr.mmapped && used < sc->sc_mixring.sc_mpr.blksize) {
@@ -3556,9 +3595,11 @@
        
        vc->sc_pbus = true;
        if (sc->sc_trigger_started == false) {
-               audio_mix(sc);
-               audio_mix(sc);
-               audio_mix(sc);
+               if (sc->sc_usemixer) {
+                       audio_mix(sc);
+                       audio_mix(sc);
+                       audio_mix(sc);
+               }
                mutex_enter(sc->sc_intr_lock);
                error = mix_write(sc);
                if (error)
@@ -3568,7 +3609,8 @@
                    audio_stream_add_outp(&vc->sc_mpr.s,
                      vc->sc_mpr.s.outp, vc->sc_mpr.blksize);
                error = mix_write(sc);
-               cv_broadcast(&sc->sc_condvar);
+               if (sc->sc_usemixer)
+                       cv_broadcast(&sc->sc_condvar);
 done:
                mutex_exit(sc->sc_intr_lock);
        }
@@ -3690,8 +3732,8 @@
        if (sc->sc_dying == true || sc->sc_trigger_started == false)
                return;
 
-       if (vc->sc_draining == true && sc->sc_mixring.sc_mpr.drops !=
-                                               sc->sc_last_drops) {
+       if (vc->sc_draining && (!sc->sc_usemixer ||
+           (sc->sc_mixring.sc_mpr.drops != sc->sc_last_drops))) {
                vc->sc_mpr.drops += blksize;
                cv_broadcast(&sc->sc_wchan);
        }
@@ -3719,7 +3761,10 @@
 
        mix_write(sc);
 
-       cv_broadcast(&sc->sc_condvar);
+       if (sc->sc_usemixer)
+               cv_broadcast(&sc->sc_condvar);
+       else
+               cv_broadcast(&sc->sc_wchan);
 }
 
 void
@@ -3744,7 +3789,7 @@
        if (sc->sc_dying == true)
                return;
 
-       blksize = sc->sc_mixring.sc_mpr.blksize;
+       blksize = sc->sc_hwvc->sc_mpr.blksize;
        SIMPLEQ_FOREACH(chan, &sc->sc_audiochan, entries) {



Home | Main Index | Thread Index | Old Index