Source-Changes-HG archive

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

[src/netbsd-7]: src/sys/dev Pull up following revision(s) (requested by mrg i...



details:   https://anonhg.NetBSD.org/src/rev/6e4ac90b5e6a
branches:  netbsd-7
changeset: 800451:6e4ac90b5e6a
user:      martin <martin%NetBSD.org@localhost>
date:      Wed Mar 21 12:04:35 2018 +0000

description:
Pull up following revision(s) (requested by mrg in ticket #1586):
        sys/dev/sbus/dbrivar.h: revision 1.14
        sys/dev/sbus/dbrivar.h: revision 1.15
        sys/dev/ic/cs4215reg.h: revision 1.5
        sys/dev/sbus/dbri.c: revision 1.36
        sys/dev/sbus/dbri.c: revision 1.37
        sys/dev/sbus/dbri.c: revision 1.38

fix audiomp bugs:
- switch from tsleep/wakeup to condvar
- fix locking in a bunch of places.  there were several locking
  against myself issues.
also:
- don't let dbri_process_interrupt_buffer() loop more than once
  over the array of intrs.

this fixes hangs when using audio on ss20 in -current, but does
not make audio work.  it eventually times out with eg:
dbri0: switching to control mode timed out (0 f6)
and may leave a sample in the audio buffer repeating.

overhaul the dbri driver and make it work again in the New Order Of Things
- fix switching between control and data mode
- make sure interrupts can happen in control mode
- implement audioif.commit_settings()
- switch to control mode only if needed - for changes in sample rate or format
  but not for things like volume control
should fix PR 52786

fix several KASSERT()s and locking in a few places.

fixes DIAGNOSTIC kernels and still plays.

diffstat:

 sys/dev/ic/cs4215reg.h |    4 +-
 sys/dev/sbus/dbri.c    |  176 +++++++++++++++++++++++++++++++-----------------
 sys/dev/sbus/dbrivar.h |    6 +-
 3 files changed, 119 insertions(+), 67 deletions(-)

diffs (truncated from 535 to 300 lines):

diff -r a4fa2c932f21 -r 6e4ac90b5e6a sys/dev/ic/cs4215reg.h
--- a/sys/dev/ic/cs4215reg.h    Wed Mar 21 11:54:47 2018 +0000
+++ b/sys/dev/ic/cs4215reg.h    Wed Mar 21 12:04:35 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: cs4215reg.h,v 1.4 2008/05/05 00:21:47 jmcneill Exp $   */
+/*     $NetBSD: cs4215reg.h,v 1.4.62.1 2018/03/21 12:04:35 martin Exp $        */
 
 /*
  * Copyright (c) 2001 Jared D. McNeill <jmcneill%NetBSD.org@localhost>
@@ -30,7 +30,7 @@
 /* time slot 1: status register */
 #define        CS4215_CLB      (1<<2)  /* control latch bit */
 #define        CS4215_MLB      (1<<4)  /* 1: mic: 20 dB gain disabled */
-#define        CS4215_RSRVD_1  (1<<5)
+#define        CS4215_ONE      (1<<5)  /* always one */
 
 /* time slot 2: data format register */
 #define        CS4215_DFR_LINEAR16     0
diff -r a4fa2c932f21 -r 6e4ac90b5e6a sys/dev/sbus/dbri.c
--- a/sys/dev/sbus/dbri.c       Wed Mar 21 11:54:47 2018 +0000
+++ b/sys/dev/sbus/dbri.c       Wed Mar 21 12:04:35 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: dbri.c,v 1.35 2013/10/19 21:00:32 mrg Exp $    */
+/*     $NetBSD: dbri.c,v 1.35.4.1 2018/03/21 12:04:35 martin Exp $     */
 
 /*
  * Copyright (C) 1997 Rudolf Koenig (rfkoenig%immd4.informatik.uni-erlangen.de@localhost)
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: dbri.c,v 1.35 2013/10/19 21:00:32 mrg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: dbri.c,v 1.35.4.1 2018/03/21 12:04:35 martin Exp $");
 
 #include "audio.h"
 #if NAUDIO > 0
@@ -165,6 +165,7 @@
 static void    dbri_bring_up(struct dbri_softc *);
 static bool    dbri_suspend(device_t, const pmf_qual_t *);
 static bool    dbri_resume(device_t, const pmf_qual_t *);
+static int     dbri_commit(void *);
 
 /* stupid support routines */
 static uint32_t        reverse_bytes(uint32_t, int);
@@ -195,6 +196,7 @@
        .trigger_output         = dbri_trigger_output,
        .trigger_input          = dbri_trigger_input,
        .get_locks              = dbri_get_locks,
+       .commit_settings        = dbri_commit,
 };
 
 CFATTACH_DECL_NEW(dbri, sizeof(struct dbri_softc),
@@ -277,6 +279,8 @@
        sc->sc_dmat = sa->sa_dmatag;
        sc->sc_powerstate = 1;
 
+       sc->sc_whack_codec = 0;
+
        pwr = prom_getpropint(sa->sa_node,"pwr-on-auxio",0);
        aprint_normal(": rev %s\n", ver);
 
@@ -365,9 +369,13 @@
        sc->sc_bufsiz = size;
 
        mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
-       mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_SCHED);
+       mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_AUDIO);
 
-       bus_intr_establish(sa->sa_bustag, sa->sa_pri, IPL_SCHED, dbri_intr,
+#ifndef DBRI_SPIN
+       cv_init(&sc->sc_cv, "dbricv");
+#endif
+
+       bus_intr_establish(sa->sa_bustag, sa->sa_pri, IPL_AUDIO, dbri_intr,
            sc);
 
        sc->sc_locked = 0;
@@ -444,23 +452,32 @@
 {
        struct dbri_softc *sc = device_private(dev);
 
-       if (sc->sc_init_done != 0)
+       mutex_spin_enter(&sc->sc_intr_lock);
+       if (sc->sc_init_done != 0) {
+               mutex_spin_exit(&sc->sc_intr_lock);
                return 0;
-
+       }
        sc->sc_init_done = 1;
 
        dbri_init(sc);
+
+       /* talking to the codec needs working interrupts */
        if (mmcodec_init(sc) == -1) {
+               mutex_spin_exit(&sc->sc_intr_lock);
                printf("%s: no codec detected, aborting\n",
                    device_xname(dev));
                return 0;
        }
+       mutex_spin_exit(&sc->sc_intr_lock);
 
        /* Attach ourselves to the high level audio interface */
        audio_attach_mi(&dbri_hw_if, sc, sc->sc_dev);
 
        /* power down until open() */
+       mutex_spin_enter(&sc->sc_intr_lock);
        dbri_set_power(sc, 0);
+       mutex_spin_exit(&sc->sc_intr_lock);
+
        return 0;
 }
 
@@ -532,7 +549,10 @@
        bus_addr_t dmaaddr;
        int n;
 
+       KASSERT(mutex_owned(&sc->sc_intr_lock));
+
        dbri_reset(sc);
+       sc->sc_mm.status = 0;
 
        cmd = dbri_command_lock(sc);
 
@@ -548,7 +568,6 @@
                sc->sc_dma->intr[n] = 0;
        }
 
-       /* Disable all SBus bursts */
        /* XXX 16 byte bursts cause errors, the rest works */
        reg = bus_space_read_4(iot, ioh, DBRI_REG0);
 
@@ -562,6 +581,7 @@
        *(cmd++) = dmaaddr;
 
        dbri_command_send(sc, cmd);
+
        return (0);
 }
 
@@ -603,7 +623,7 @@
        bus_space_tag_t iot = sc->sc_iot;
        int maxloops = 1000000;
 
-       mutex_spin_enter(&sc->sc_intr_lock);
+       KASSERT(mutex_owned(&sc->sc_intr_lock));
 
        sc->sc_locked--;
 
@@ -641,8 +661,6 @@
                }
        }
 
-       mutex_spin_exit(&sc->sc_intr_lock);
-
        return;
 }
 
@@ -650,6 +668,9 @@
 dbri_process_interrupt_buffer(struct dbri_softc *sc)
 {
        int32_t i;
+       int orig_irqp = sc->sc_irqp;
+
+       KASSERT(mutex_owned(&sc->sc_intr_lock));
 
        while ((i = sc->sc_dma->intr[sc->sc_irqp]) != 0) {
                sc->sc_dma->intr[sc->sc_irqp] = 0;
@@ -661,6 +682,10 @@
                        sc->sc_irqp++;
 
                dbri_process_interrupt(sc, i);
+
+               /* don't loop more than once. */
+               if (orig_irqp == sc->sc_irqp)
+                       break;
        }
 
        return;
@@ -688,6 +713,7 @@
                int td;
                struct dbri_desc *dd;
 
+               DPRINTF("%s:%d tx complete\n", __func__, channel);
                td = sc->sc_pipe[channel].desc;
                dd = &sc->sc_desc[td];
 
@@ -696,18 +722,15 @@
                break;
        }
        case DBRI_INTR_FXDT:            /* fixed data change */
-               DPRINTF("dbri_intr: Fixed data change (%d: %x)\n", channel,
+               DPRINTF("%s:%d: Fixed data change: %x\n", __func__, channel,
                    val);
-#if 0
-               printf("reg: %08x\n", sc->sc_mm.status);
-#endif
                if (sc->sc_pipe[channel].sdp & DBRI_SDP_MSB)
                        val = reverse_bytes(val, sc->sc_pipe[channel].length);
                if (sc->sc_pipe[channel].prec)
                        *(sc->sc_pipe[channel].prec) = val;
 #ifndef DBRI_SPIN
-               DPRINTF("%s: wakeup %p\n", device_xname(sc->sc_dev), sc);
-               wakeup(sc);
+               DPRINTF("%s: cv_broadcast %p\n", device_xname(sc->sc_dev), sc);
+               cv_broadcast(&sc->sc_cv);
 #endif
                break;
        case DBRI_INTR_SBRI:
@@ -718,6 +741,7 @@
                int td;
                struct dbri_desc *dd;
 
+               DPRINTF("dbri_intr: buffer ready (%d)\n", channel);
                td = sc->sc_pipe[channel].desc;
                dd = &sc->sc_desc[td];
 
@@ -859,10 +883,12 @@
        pipe_ts_link(sc, 20, PIPEoutput, 16, 32, sc->sc_mm.offset + 32);
        pipe_ts_link(sc, 4, PIPEoutput, 16, data_width, sc->sc_mm.offset);
        pipe_ts_link(sc, 6, PIPEinput, 16, data_width, sc->sc_mm.offset);
+#if 0
+       /* readback for the mixer registers - we don't use that */
        pipe_ts_link(sc, 21, PIPEinput, 16, 32, sc->sc_mm.offset + 32);
 
-       pipe_receive_fixed(sc, 21, &sc->sc_mm.status);
-
+       pipe_receive_fixed(sc, 21, &sc->sc_mm.d.ldata);
+#endif
        mmcodec_setgain(sc, 0);
 
        tmp = bus_space_read_4(iot, ioh, DBRI_REG0);
@@ -879,14 +905,13 @@
        pipe_setup(sc, 4, DBRI_SDP_MEM | DBRI_SDP_TO_SER | DBRI_SDP_MSB);
        pipe_setup(sc, 20, DBRI_SDP_FIXED | DBRI_SDP_TO_SER | DBRI_SDP_MSB);
        pipe_setup(sc, 6, DBRI_SDP_MEM | DBRI_SDP_FROM_SER | DBRI_SDP_MSB);
+#if 0
        pipe_setup(sc, 21, DBRI_SDP_FIXED | DBRI_SDP_FROM_SER | DBRI_SDP_MSB);
-
+#endif
        pipe_setup(sc, 17, DBRI_SDP_FIXED | DBRI_SDP_TO_SER | DBRI_SDP_MSB);
        pipe_setup(sc, 18, DBRI_SDP_FIXED | DBRI_SDP_FROM_SER | DBRI_SDP_MSB);
        pipe_setup(sc, 19, DBRI_SDP_FIXED | DBRI_SDP_FROM_SER | DBRI_SDP_MSB);
 
-       sc->sc_mm.status = 0;
-
        pipe_receive_fixed(sc, 18, &sc->sc_mm.status);
        pipe_receive_fixed(sc, 19, &sc->sc_mm.version);
 
@@ -925,7 +950,7 @@
         * 2: serial enable, CHI master, 128 bits per frame, clock 1
         * 3: tests disabled
         */
-       mm->c.bcontrol[0] = CS4215_RSRVD_1 | CS4215_MLB;
+       mm->c.bcontrol[0] = CS4215_ONE | CS4215_MLB;
        mm->c.bcontrol[1] = CS4215_DFR_ULAW | CS4215_FREQ[0].csval;
        mm->c.bcontrol[2] = CS4215_XCLK | CS4215_BSEL_128 | CS4215_FREQ[0].xtal;
        mm->c.bcontrol[3] = 0;
@@ -970,11 +995,15 @@
        bus_space_handle_t ioh = sc->sc_ioh;
        uint32_t val;
        uint32_t tmp;
-       int bail = 0;
-#if DBRI_SPIN
+       int ret = 0;
+#ifdef DBRI_SPIN
        int i;
+#else
+       int error, bail = 0;
 #endif
 
+       KASSERT(mutex_owned(&sc->sc_intr_lock));
+
        /*
         * Temporarily mute outputs and wait 125 us to make sure that it
         * happens. This avoids clicking noises.
@@ -982,6 +1011,10 @@
        mmcodec_setgain(sc, 1);
        delay(125);
 
+       tmp = bus_space_read_4(iot, ioh, DBRI_REG0);
+       tmp &= ~(DBRI_CHI_ACTIVATE);    /* disable CHI */
+       bus_space_write_4(iot, ioh, DBRI_REG0, tmp);
+
        bus_space_write_4(iot, ioh, DBRI_REG2, 0);
        delay(125);
 
@@ -992,7 +1025,6 @@
        val |= (sc->sc_mm.onboard ? DBRI_PIO0 : DBRI_PIO2);
 
        bus_space_write_4(iot, ioh, DBRI_REG2, val);
-
        delay(34);
 
        /*
@@ -1013,6 +1045,8 @@
        pipe_ts_link(sc, 18, PIPEinput, 16, 8, sc->sc_mm.offset);
        pipe_ts_link(sc, 19, PIPEinput, 16, 8, sc->sc_mm.offset + 48);
 
+       pipe_receive_fixed(sc, 18, &sc->sc_mm.status);
+



Home | Main Index | Thread Index | Old Index