Module Name:    src
Committed By:   martin
Date:           Wed Mar 21 12:04:35 UTC 2018

Modified Files:
        src/sys/dev/ic [netbsd-7]: cs4215reg.h
        src/sys/dev/sbus [netbsd-7]: dbri.c dbrivar.h

Log Message:
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.


To generate a diff of this commit:
cvs rdiff -u -r1.4 -r1.4.62.1 src/sys/dev/ic/cs4215reg.h
cvs rdiff -u -r1.35 -r1.35.4.1 src/sys/dev/sbus/dbri.c
cvs rdiff -u -r1.13 -r1.13.24.1 src/sys/dev/sbus/dbrivar.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/ic/cs4215reg.h
diff -u src/sys/dev/ic/cs4215reg.h:1.4 src/sys/dev/ic/cs4215reg.h:1.4.62.1
--- src/sys/dev/ic/cs4215reg.h:1.4	Mon May  5 00:21:47 2008
+++ src/sys/dev/ic/cs4215reg.h	Wed Mar 21 12:04:35 2018
@@ -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 <jmcne...@netbsd.org>
@@ -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

Index: src/sys/dev/sbus/dbri.c
diff -u src/sys/dev/sbus/dbri.c:1.35 src/sys/dev/sbus/dbri.c:1.35.4.1
--- src/sys/dev/sbus/dbri.c:1.35	Sat Oct 19 21:00:32 2013
+++ src/sys/dev/sbus/dbri.c	Wed Mar 21 12:04:35 2018
@@ -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 (rfkoe...@immd4.informatik.uni-erlangen.de)
@@ -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_set_power(struct dbri_s
 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 @@ struct audio_hw_if dbri_hw_if = {
 	.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 @@ dbri_attach_sbus(device_t parent, device
 	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 @@ dbri_attach_sbus(device_t parent, device
 	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);
+
+#ifndef DBRI_SPIN
+	cv_init(&sc->sc_cv, "dbricv");
+#endif
 
-	bus_intr_establish(sa->sa_bustag, sa->sa_pri, IPL_SCHED, dbri_intr,
+	bus_intr_establish(sa->sa_bustag, sa->sa_pri, IPL_AUDIO, dbri_intr,
 	    sc);
 
 	sc->sc_locked = 0;
@@ -444,23 +452,32 @@ dbri_config_interrupts(device_t dev)
 {
 	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 @@ dbri_init(struct dbri_softc *sc)
 	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 @@ dbri_init(struct dbri_softc *sc)
 		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 @@ dbri_init(struct dbri_softc *sc)
 	*(cmd++) = dmaaddr;
 
 	dbri_command_send(sc, cmd);
+
 	return (0);
 }
 
@@ -603,7 +623,7 @@ dbri_command_send(struct dbri_softc *sc,
 	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 @@ dbri_command_send(struct dbri_softc *sc,
 		}
 	}
 
-	mutex_spin_exit(&sc->sc_intr_lock);
-
 	return;
 }
 
@@ -650,6 +668,9 @@ static void
 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 @@ dbri_process_interrupt_buffer(struct dbr
 			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 @@ dbri_process_interrupt(struct dbri_softc
 		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 @@ dbri_process_interrupt(struct dbri_softc
 		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 @@ dbri_process_interrupt(struct dbri_softc
 		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 @@ mmcodec_init_data(struct dbri_softc *sc)
 	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 @@ mmcodec_pipe_init(struct dbri_softc *sc)
 	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 @@ mmcodec_default(struct dbri_softc *sc)
 	 * 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 @@ mmcodec_setcontrol(struct dbri_softc *sc
 	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_setcontrol(struct dbri_softc *sc
 	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 @@ mmcodec_setcontrol(struct dbri_softc *sc
 	val |= (sc->sc_mm.onboard ? DBRI_PIO0 : DBRI_PIO2);
 
 	bus_space_write_4(iot, ioh, DBRI_REG2, val);
-
 	delay(34);
 
 	/*
@@ -1013,6 +1045,8 @@ mmcodec_setcontrol(struct dbri_softc *sc
 	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);
+
 	/* wait for the chip to echo back CLB as zero */
 	sc->sc_mm.c.bcontrol[0] &= ~CS4215_CLB;
 	pipe_transmit_fixed(sc, 17, sc->sc_mm.c.lcontrol);
@@ -1021,34 +1055,45 @@ mmcodec_setcontrol(struct dbri_softc *sc
 	tmp |= DBRI_CHI_ACTIVATE;
 	bus_space_write_4(iot, ioh, DBRI_REG0, tmp);
 
-#if DBRI_SPIN
+#ifdef DBRI_SPIN
 	i = 1024;
-	while (((sc->sc_mm.status & 0xe4) != 0x20) && --i) {
+	while (((sc->sc_mm.status & 0xe4) != CS4215_ONE) && (i > 0)) {
+		i--;
 		delay(125);
 	}
 
 	if (i == 0) {
 		DPRINTF("%s: cs4215 didn't respond to CLB (0x%02x)\n",
 		    device_xname(sc->sc_dev), sc->sc_mm.status);
-		return (-1);
+		ret = -1;
+		goto fail;
 	}
 #else
-	while (((sc->sc_mm.status & 0xe4) != 0x20) && (bail < 10)) {
-		DPRINTF("%s: tsleep %p\n", device_xname(sc->sc_dev), sc);
-		tsleep(sc, PCATCH | PZERO, "dbrifxdt", hz);
+	while (((sc->sc_mm.status & 0xe4) != CS4215_ONE) && (bail < 10)) {
+		DPRINTF("%s: cv_wait_sig %p\n", device_xname(sc->sc_dev), sc);
+		error = cv_timedwait_sig(&sc->sc_cv, &sc->sc_intr_lock, hz);
+		if (error == EINTR) {
+			DPRINTF("%s: interrupted\n", device_xname(sc->sc_dev));
+			ret = -1;
+			mutex_spin_exit(&sc->sc_intr_lock);
+			goto fail;
+		}
 		bail++;
 	}
-#endif
 	if (bail >= 10) {
-		DPRINTF("%s: switching to control mode timed out (%x %x)\n",
+		aprint_error("%s: switching to control mode timed out (%x %x)\n",
 		    device_xname(sc->sc_dev), sc->sc_mm.status,
 		    bus_space_read_4(iot, ioh, DBRI_REG2));
-		return -1;
+		ret = -1;
+		goto fail;
 	}
+#endif
 
 	/* copy the version information before it becomes unreadable again */
 	sc->sc_version = sc->sc_mm.version;
+	sc->sc_whack_codec = 0;
 
+fail:
 	/* terminate cs4215 control mode */
 	sc->sc_mm.c.bcontrol[0] |= CS4215_CLB;
 	pipe_transmit_fixed(sc, 17, sc->sc_mm.c.lcontrol);
@@ -1058,7 +1103,7 @@ mmcodec_setcontrol(struct dbri_softc *sc
 
 	mmcodec_setgain(sc, 0);
 
-	return (0);
+	return ret;
 
 }
 
@@ -1324,8 +1369,6 @@ setup_ring_xmit(struct dbri_softc *sc, i
 	dd->callback = callback;
 	dd->callback_args = callback_args;
 
-	mutex_spin_enter(&sc->sc_intr_lock);
-
 	/* the pipe shouldn't be active */
 	if (pipe_active(sc, pipe)) {
 		aprint_error("pipe active (CDP)\n");
@@ -1360,8 +1403,6 @@ setup_ring_xmit(struct dbri_softc *sc, i
 		DPRINTF("%s: starting DMA\n", __func__);
 	}
 
-	mutex_spin_exit(&sc->sc_intr_lock);
-
 	return;
 }
 
@@ -1421,8 +1462,6 @@ setup_ring_recv(struct dbri_softc *sc, i
 	dd->callback = callback;
 	dd->callback_args = callback_args;
 
-	mutex_spin_enter(&sc->sc_intr_lock);
-
 	/* the pipe shouldn't be active */
 	if (pipe_active(sc, pipe)) {
 		aprint_error("pipe active (CDP)\n");
@@ -1457,8 +1496,6 @@ setup_ring_recv(struct dbri_softc *sc, i
 		DPRINTF("%s: starting DMA\n", __func__);
 	}
 
-	mutex_spin_exit(&sc->sc_intr_lock);
-
 	return;
 }
 
@@ -1731,7 +1768,7 @@ dbri_set_params(void *hdl, int setmode, 
 		sc->sc_mm.c.bcontrol[1] |= CS4215_DFR_STEREO;
 		break;
 	}
-
+	sc->sc_whack_codec = 1;
 	return (0);
 }
 
@@ -1975,6 +2012,32 @@ dbri_get_props(void *hdl)
 }
 
 static int
+dbri_commit(void *hdl)
+{
+	struct dbri_softc *sc = hdl;
+	int ret = 0;
+
+	/*
+	 * we only need to whack the codec if things like sample format or
+	 * frequency changed, not for mixer stuff
+	 */
+	if (sc->sc_whack_codec == 0)
+		return 0;
+
+	mutex_spin_enter(&sc->sc_intr_lock);
+	ret = mmcodec_setcontrol(sc);
+	if (ret) {
+		DPRINTF("%s: control mode failed. Mutex %s PIL %x\n", __func__,
+		    mutex_owned(&sc->sc_intr_lock) ? "held" : "free",
+		    (getpsr() & PSR_PIL) >> 8);
+	} else
+		DPRINTF("%s: control mode ok\n", __func__);
+	mmcodec_init_data(sc);
+	mutex_spin_exit(&sc->sc_intr_lock);
+	return 0;
+}
+
+static int
 dbri_trigger_output(void *hdl, void *start, void *end, int blksize,
 		    void (*intr)(void *), void *intrarg,
 		    const struct audio_params *param)
@@ -1994,13 +2057,6 @@ dbri_trigger_output(void *hdl, void *sta
 
 	sc->sc_params = *param;
 
-	if (sc->sc_recording == 0) {
-		/* do not muck with the codec when it's already in use */
-		if (mmcodec_setcontrol(sc) != 0)
-			return -1;
-		mmcodec_init_data(sc);
-	}
-
 	/*
 	 * always use DMA descriptor 0 for output
 	 * no need to allocate them dynamically since we only ever have 
@@ -2044,17 +2100,6 @@ dbri_trigger_input(void *hdl, void *star
 
 	sc->sc_params = *param;
 
-	if (sc->sc_playing == 0) {
-
-		/*
-		 * we don't support different parameters for playing and
-		 * recording anyway so don't bother whacking the codec if
-		 * it's already set up
-		 */
-		mmcodec_setcontrol(sc);
-		mmcodec_init_data(sc);
-	}
-
 	sc->sc_recording = 1;
 	setup_ring_recv(sc, 6, 1, num, blksize, intr, intrarg);
 	return 0;
@@ -2181,8 +2226,9 @@ dbri_open(void *cookie, int flags)
 
 	DPRINTF("%s: %d\n", __func__, sc->sc_refcount);
 
-	if (sc->sc_refcount == 0)
+	if (sc->sc_refcount == 0) {
 		dbri_bring_up(sc);
+	}
 
 	sc->sc_refcount++;
 
@@ -2211,7 +2257,9 @@ dbri_suspend(device_t self, const pmf_qu
 {
 	struct dbri_softc *sc = device_private(self);
 
+	mutex_spin_enter(&sc->sc_intr_lock);
 	dbri_set_power(sc, 0);
+	mutex_spin_exit(&sc->sc_intr_lock);
 	return true;
 }
 
@@ -2226,8 +2274,8 @@ dbri_resume(device_t self, const pmf_qua
 	if (sc->sc_playing) {
 		volatile uint32_t *cmd;
 
-		dbri_bring_up(sc);
 		mutex_spin_enter(&sc->sc_intr_lock);
+		dbri_bring_up(sc);
 		cmd = dbri_command_lock(sc);
 		*(cmd++) = DBRI_CMD(DBRI_COMMAND_SDP,
 		    0, sc->sc_pipe[4].sdp |

Index: src/sys/dev/sbus/dbrivar.h
diff -u src/sys/dev/sbus/dbrivar.h:1.13 src/sys/dev/sbus/dbrivar.h:1.13.24.1
--- src/sys/dev/sbus/dbrivar.h:1.13	Wed Nov 23 23:07:36 2011
+++ src/sys/dev/sbus/dbrivar.h	Wed Mar 21 12:04:35 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: dbrivar.h,v 1.13 2011/11/23 23:07:36 jmcneill Exp $	*/
+/*	$NetBSD: dbrivar.h,v 1.13.24.1 2018/03/21 12:04:35 martin Exp $	*/
 
 /*
  * Copyright (C) 1997 Rudolf Koenig (rfkoe...@immd4.informatik.uni-erlangen.de)
@@ -153,6 +153,7 @@ struct dbri_softc {
 	int		sc_linp, sc_rinp;	/* input volume */
 	int		sc_monitor;		/* monitor volume */
 	int		sc_input;		/* 0 - line, 1 - mic */
+	int		sc_whack_codec;	 /* 1 - codec needs control mode */
 
 	int		sc_ctl_mode;
 	
@@ -169,6 +170,9 @@ struct dbri_softc {
 
 	kmutex_t	sc_lock;
 	kmutex_t	sc_intr_lock;
+#ifndef DBRI_SPIN
+	kcondvar_t	sc_cv;
+#endif
 };
 
 #define dbri_dma_off(member, elem)	\

Reply via email to