Module Name:    src
Committed By:   isaki
Date:           Fri May  3 03:00:33 UTC 2019

Modified Files:
        src/sys/dev/isa [isaki-audio2]: pas.c sb.c sbdsp.c sbdspvar.h

Log Message:
Adapt sbdsp to audio2.
- Use new query_format/set_format interfaces.
  The formats are created from sb[pr]modes tables.
- Drop INDEPENDENT property for models proir to SB_16.


To generate a diff of this commit:
cvs rdiff -u -r1.71 -r1.71.2.1 src/sys/dev/isa/pas.c
cvs rdiff -u -r1.90 -r1.90.2.1 src/sys/dev/isa/sb.c
cvs rdiff -u -r1.139.2.1 -r1.139.2.2 src/sys/dev/isa/sbdsp.c
cvs rdiff -u -r1.61 -r1.61.54.1 src/sys/dev/isa/sbdspvar.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/isa/pas.c
diff -u src/sys/dev/isa/pas.c:1.71 src/sys/dev/isa/pas.c:1.71.2.1
--- src/sys/dev/isa/pas.c:1.71	Sat Mar 16 12:09:58 2019
+++ src/sys/dev/isa/pas.c	Fri May  3 03:00:33 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: pas.c,v 1.71 2019/03/16 12:09:58 isaki Exp $	*/
+/*	$NetBSD: pas.c,v 1.71.2.1 2019/05/03 03:00:33 isaki Exp $	*/
 
 /*
  * Copyright (c) 1991-1993 Regents of the University of California.
@@ -57,7 +57,7 @@
 
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pas.c,v 1.71 2019/03/16 12:09:58 isaki Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pas.c,v 1.71.2.1 2019/05/03 03:00:33 isaki Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -125,8 +125,8 @@ void	pasconf(int, int, int, int);
 const struct audio_hw_if pas_hw_if = {
 	.open			= sbdsp_open,
 	.close			= sbdsp_close,
-	.query_encoding		= sbdsp_query_encoding,
-	.set_params		= sbdsp_set_params,
+	.query_format		= sbdsp_query_format,
+	.set_format		= sbdsp_set_format,
 	.round_blocksize	= sbdsp_round_blocksize,
 	.halt_output		= sbdsp_halt_output,
 	.halt_input		= sbdsp_halt_input,
@@ -138,7 +138,6 @@ const struct audio_hw_if pas_hw_if = {
 	.allocm			= sb_malloc,
 	.freem			= sb_free,
 	.round_buffersize	= sb_round_buffersize,
-	.mappage		= sb_mappage,
 	.get_props		= sbdsp_get_props,
 	.trigger_output		= sbdsp_trigger_output,
 	.trigger_input		= sbdsp_trigger_input,

Index: src/sys/dev/isa/sb.c
diff -u src/sys/dev/isa/sb.c:1.90 src/sys/dev/isa/sb.c:1.90.2.1
--- src/sys/dev/isa/sb.c:1.90	Sat Mar 16 12:09:58 2019
+++ src/sys/dev/isa/sb.c	Fri May  3 03:00:33 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: sb.c,v 1.90 2019/03/16 12:09:58 isaki Exp $	*/
+/*	$NetBSD: sb.c,v 1.90.2.1 2019/05/03 03:00:33 isaki Exp $	*/
 
 /*
  * Copyright (c) 1991-1993 Regents of the University of California.
@@ -35,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sb.c,v 1.90 2019/03/16 12:09:58 isaki Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sb.c,v 1.90.2.1 2019/05/03 03:00:33 isaki Exp $");
 
 #include "midi.h"
 
@@ -82,8 +82,8 @@ int	sb_getdev(void *, struct audio_devic
 const struct audio_hw_if sb_hw_if = {
 	.open			= sbdsp_open,
 	.close			= sbdsp_close,
-	.query_encoding		= sbdsp_query_encoding,
-	.set_params		= sbdsp_set_params,
+	.query_format		= sbdsp_query_format,
+	.set_format		= sbdsp_set_format,
 	.round_blocksize	= sbdsp_round_blocksize,
 	.halt_output		= sbdsp_halt_output,
 	.halt_input		= sbdsp_halt_input,
@@ -95,7 +95,6 @@ const struct audio_hw_if sb_hw_if = {
 	.allocm			= sb_malloc,
 	.freem			= sb_free,
 	.round_buffersize	= sb_round_buffersize,
-	.mappage		= sb_mappage,
 	.get_props		= sbdsp_get_props,
 	.trigger_output		= sbdsp_trigger_output,
 	.trigger_input		= sbdsp_trigger_input,

Index: src/sys/dev/isa/sbdsp.c
diff -u src/sys/dev/isa/sbdsp.c:1.139.2.1 src/sys/dev/isa/sbdsp.c:1.139.2.2
--- src/sys/dev/isa/sbdsp.c:1.139.2.1	Sun Apr 21 06:17:02 2019
+++ src/sys/dev/isa/sbdsp.c	Fri May  3 03:00:33 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: sbdsp.c,v 1.139.2.1 2019/04/21 06:17:02 isaki Exp $	*/
+/*	$NetBSD: sbdsp.c,v 1.139.2.2 2019/05/03 03:00:33 isaki Exp $	*/
 
 /*-
  * Copyright (c) 1999, 2008 The NetBSD Foundation, Inc.
@@ -74,7 +74,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sbdsp.c,v 1.139.2.1 2019/04/21 06:17:02 isaki Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sbdsp.c,v 1.139.2.2 2019/05/03 03:00:33 isaki Exp $");
 
 #include "midi.h"
 #include "mpu.h"
@@ -95,6 +95,7 @@ __KERNEL_RCSID(0, "$NetBSD: sbdsp.c,v 1.
 
 #include <sys/audioio.h>
 #include <dev/audio_if.h>
+#include <dev/audio/linear.h>
 #include <dev/midi_if.h>
 
 #include <dev/isa/isavar.h>
@@ -206,8 +207,34 @@ static struct sbmode sbrmodes[] = {
  { .model = -1 }
 };
 
+/*
+ * We actually can specify any value within the frequency range defined
+ * above.  But according to definition of SB_RATE_TO_TC macro, only some
+ * of them are dividable (it's preferable, not mandatory).  There are 9
+ * values in the range that satisfy this condition but it's too much.
+ */
+static const int sbdsp_rates[] = {
+	4000,
+	/* 5000, */
+	/* 6250, */
+	/* 10000, */
+	12500,
+	/* 15625, */
+	20000,
+	/* 25000, */
+	31250,
+};
+
 void	sbversion(struct sbdsp_softc *);
 void	sbdsp_jazz16_probe(struct sbdsp_softc *);
+void	sbdsp_sbmode2format(struct audio_format *, const struct sbmode *, int);
+int	sbdsp_set_format16(struct sbdsp_softc *, int,
+	    const audio_params_t *, const audio_params_t *,
+	    audio_filter_reg_t *, audio_filter_reg_t *);
+int	sbdsp_set_format8(struct sbdsp_softc *, int,
+	    const audio_params_t *, const audio_params_t *,
+	    audio_filter_reg_t *, audio_filter_reg_t *);
+void	sbdsp_init_format(struct sbdsp_softc *);
 void	sbdsp_set_mixer_gain(struct sbdsp_softc *, int);
 void	sbdsp_pause(struct sbdsp_softc *);
 int	sbdsp_set_timeconst(struct sbdsp_softc *, int);
@@ -410,9 +437,6 @@ sbdsp_attach(struct sbdsp_softc *sc)
 	       SBVER_MAJOR(sc->sc_version), SBVER_MINOR(sc->sc_version),
 	       sc->sc_model == SB_JAZZ ? ": <Jazz16>" : "");
 
-	/* XXX It's not true full duplex. */
-	sc->sc_fullduplex = 0;
-
 	if (sc->sc_drq8 != -1) {
 		sc->sc_drq8_maxsize = isa_dmamaxsize(sc->sc_ic,
 		    sc->sc_drq8);
@@ -438,6 +462,14 @@ sbdsp_attach(struct sbdsp_softc *sc)
 		}
 	}
 
+	/* Construct sc_format from model */
+	sbdsp_init_format(sc);
+	if (sc->sc_nformats == 0) {
+		aprint_error_dev(sc->sc_dev,
+		    "No available formats; model mismatch?\n");
+		return;
+	}
+
 	if (!pmf_device_register(sc->sc_dev, NULL, sbdsp_resume))
 		aprint_error_dev(sc->sc_dev,
 		    "couldn't establish power handler\n");
@@ -488,119 +520,245 @@ sbdsp_mix_read(struct sbdsp_softc *sc, i
 	return val;
 }
 
+void
+sbdsp_sbmode2format(struct audio_format *f, const struct sbmode *m, int mode)
+{
+	memset(f, 0, sizeof(*f));
+	f->mode = mode;
+	if (m->precision == 8) {
+		/* ulinear8 is always native endian */
+		f->encoding = AUDIO_ENCODING_ULINEAR_NE;
+		f->validbits = 8;
+		f->precision = 8;
+	} else {
+		f->encoding = AUDIO_ENCODING_SLINEAR_LE;
+		f->validbits = 16;
+		f->precision = 16;
+	}
+	f->channels = m->channels;
+	f->channel_mask = (m->channels == 1) ? AUFMT_MONAURAL : AUFMT_STEREO;
+	f->frequency_type = 0;
+	f->frequency[0] = m->lowrate;
+	f->frequency[1] = m->highrate;
+}
+
+/*
+ * Create sc_formats[] array from sbpmodes[], sbrmodes[].
+ */
+void
+sbdsp_init_format(struct sbdsp_softc *sc)
+{
+	struct audio_format dp[4];
+	struct audio_format dr[4];
+	struct audio_format *dbase;
+	struct audio_format *d;
+	struct audio_format tmp;
+	struct sbmode *sbmodes;
+	struct sbmode *m;
+	int mode;
+	int minrate;
+	int maxrate;
+	int idx;
+	int model;
+	int i;
+	int j;
+	int n;
+
+	/* Later models work like SB16. */
+	model = uimin(sc->sc_model, SB_16);
+
+	memset(&dp, 0, sizeof(dp));
+	memset(&dr, 0, sizeof(dr));
+
+	/*
+	 * Step1. Extract elements corresponding to this model.
+	 */
+	for (i = 0; i < 2; i++) {
+		if (i == 0) {
+			mode = AUMODE_PLAY;
+			sbmodes = sbpmodes;
+			dbase = dp;
+		} else {
+			mode = AUMODE_RECORD;
+			sbmodes = sbrmodes;
+			dbase = dr;
+		}
+		for (m = sbmodes; m->model != -1; m++) {
+			if (m->model != model)
+				continue;
+
+			sbdsp_sbmode2format(&tmp, m, mode);
+			/*
+			 * [0] 8bit mono
+			 * [1] 8bit st
+			 * [2] 16bit mono
+			 * [3] 16bit st
+			 */
+			idx = (m->precision / 16) * 2 + (m->channels - 1);
+			d = &dbase[idx];
+			if (d->mode == 0) {
+				/* The first elements of this room */
+				*d = tmp;
+				continue;
+			}
+
+			/* Otherwise merge frequency */
+			/*
+			 * Currently the frequency of multiple elements in
+			 * the same model are all contiguous.
+			 */
+			if (tmp.frequency[0] == d->frequency[1]) {
+				d->frequency[1] = tmp.frequency[1];
+			} else if (tmp.frequency[1] == d->frequency[0]) {
+				d->frequency[0] = tmp.frequency[0];
+			} else {
+				panic("frequency range must be contiguous. "
+				    "model=%d\n", model);
+			}
+			DPRINTF(("%s: 1 [%d] mode=%d freq={ %d, %d }\n",
+			    __func__, idx, d->mode,
+			    d->frequency[0], d->frequency[1]));
+		}
+	}
+
+	/*
+	 * Step2. Merge dr into dp.
+	 */
+	for (i = 0; i < __arraycount(dp); i++) {
+		if (dp[i].mode == 0 && dr[i].mode == 0)
+			continue;
+		/* Currently all entries in sb[pr]modes are PLAY|REC */
+		if (dp[i].mode == 0 || dr[i].mode == 0)
+			panic("invalid sb[pr]mode table?. model=%d\n", model);
+		dp[i].mode |= dr[i].mode;
+
+		/*
+		 * Usually, the recording range is the same or smaller than
+		 * the playback range.  So extract the common range.
+		 */
+		if (dp[i].frequency[0] < dr[i].frequency[0])
+			dp[i].frequency[0] = dr[i].frequency[0];
+		if (dp[i].frequency[1] > dr[i].frequency[1])
+			dp[i].frequency[1] = dr[i].frequency[1];
+
+		DPRINTF(("%s: 2 [%d] mode=%d freq={ %d, %d }\n",
+		    __func__, i, dp[i].mode,
+		    dp[i].frequency[0], dp[i].frequency[1]));
+	}
+
+	/*
+	 * Step3. Prior to SB16, use fixed frequencies rather than raw
+	 * frequency range.
+	 */
+	if (!ISSB16CLASS(sc)) {
+		for (i = 0; i < __arraycount(dp); i++) {
+			if (dp[i].mode == 0)
+				continue;
+			minrate = dp[i].frequency[0];
+			maxrate = dp[i].frequency[1];
+			n = 0;
+			for (j = 0; j < __arraycount(sbdsp_rates); j++) {
+				if (minrate <= sbdsp_rates[j] &&
+				    sbdsp_rates[j] <= maxrate) {
+					dp[i].frequency[n++] = sbdsp_rates[j];
+				}
+			}
+			dp[i].frequency_type = n;
+			if (n == 0) {
+				/* this should not happened */
+				dp[i].frequency[0] = minrate;
+				dp[i].frequency[1] = maxrate;
+			}
+
+			DPRINTF(("%s: 3 [%d] mode=%d freq={ ",
+			    __func__, i, dp[i].mode));
+			for (j = 0; j < dp[i].frequency_type; j++) {
+				DPRINTF(("%s%d", (j == 0) ? "" : ", ",
+				    dp[i].frequency[j]));
+			}
+			DPRINTF((" }\n"));
+		}
+	}
+
+	/*
+	 * Step4. Copy merged dp to sc_formats.
+	 */
+	n = 0;
+	for (i = 0; i < __arraycount(dp); i++) {
+		if (dp[i].mode)
+			sc->sc_formats[n++] = dp[i];
+	}
+	sc->sc_nformats = n;
+}
+
 /*
  * Various routines to interface to higher level audio driver
  */
 
 int
-sbdsp_query_encoding(void *addr, struct audio_encoding *fp)
+sbdsp_query_format(void *addr, audio_format_query_t *afp)
 {
 	struct sbdsp_softc *sc;
-	int emul;
 
 	sc = addr;
-	emul = ISSB16CLASS(sc) ? 0 : AUDIO_ENCODINGFLAG_EMULATED;
+	return audio_query_format(sc->sc_formats, sc->sc_nformats, afp);
+}
 
-	switch (fp->index) {
-	case 0:
-		strcpy(fp->name, AudioEulinear);
-		fp->encoding = AUDIO_ENCODING_ULINEAR;
-		fp->precision = 8;
-		fp->flags = 0;
-		return 0;
-	case 1:
-		strcpy(fp->name, AudioEmulaw);
-		fp->encoding = AUDIO_ENCODING_ULAW;
-		fp->precision = 8;
-		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
-		return 0;
-	case 2:
-		strcpy(fp->name, AudioEalaw);
-		fp->encoding = AUDIO_ENCODING_ALAW;
-		fp->precision = 8;
-		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
-		return 0;
-	case 3:
-		strcpy(fp->name, AudioEslinear);
-		fp->encoding = AUDIO_ENCODING_SLINEAR;
-		fp->precision = 8;
-		fp->flags = emul;
-		return 0;
-	}
-	if (!ISSB16CLASS(sc) && sc->sc_model != SB_JAZZ)
-		return EINVAL;
+static struct sbmode *
+sbdsp_find_mode(struct sbmode *sbmodes, int model, const audio_params_t *p)
+{
+	struct sbmode *m;
 
-	switch(fp->index) {
-	case 4:
-		strcpy(fp->name, AudioEslinear_le);
-		fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
-		fp->precision = 16;
-		fp->flags = 0;
-		return 0;
-	case 5:
-		strcpy(fp->name, AudioEulinear_le);
-		fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
-		fp->precision = 16;
-		fp->flags = emul;
-		return 0;
-	case 6:
-		strcpy(fp->name, AudioEslinear_be);
-		fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
-		fp->precision = 16;
-		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
-		return 0;
-	case 7:
-		strcpy(fp->name, AudioEulinear_be);
-		fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
-		fp->precision = 16;
-		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
-		return 0;
-	default:
-		return EINVAL;
+	for (m = sbmodes; m->model != -1; m++) {
+		if (model == m->model &&
+		    p->channels == m->channels &&
+		    p->precision == m->precision &&
+		    p->sample_rate >= m->lowrate &&
+		    p->sample_rate <= m->highrate)
+			return m;
 	}
-	return 0;
+	return NULL;
 }
 
 int
-sbdsp_set_params(
-	void *addr,
-	int setmode, int usemode,
-	audio_params_t *play, audio_params_t *rec,
-	stream_filter_list_t *pfil, stream_filter_list_t *rfil)
+sbdsp_set_format(void *addr, int setmode,
+	const audio_params_t *play, const audio_params_t *rec,
+	audio_filter_reg_t *pfil, audio_filter_reg_t *rfil)
 {
 	struct sbdsp_softc *sc;
-	struct sbmode *m;
-	u_int rate, tc, bmode;
-	int model;
-	int chan;
-	struct audio_params *p;
-	audio_params_t hw __unused;
-	int mode;
+	int error;
 
 	sc = addr;
 
 	if (sc->sc_open == SB_OPEN_MIDI)
 		return EBUSY;
 
-	/* Later models work like SB16. */
-	model = uimin(sc->sc_model, SB_16);
-
-	/*
-	 * Prior to the SB16, we have only one clock, so make the sample
-	 * rates match.
-	 */
-	if (!ISSB16CLASS(sc) &&
-	    play->sample_rate != rec->sample_rate &&
-	    usemode == (AUMODE_PLAY | AUMODE_RECORD)) {
-		if (setmode == AUMODE_PLAY) {
-			rec->sample_rate = play->sample_rate;
-			setmode |= AUMODE_RECORD;
-		} else if (setmode == AUMODE_RECORD) {
-			play->sample_rate = rec->sample_rate;
-			setmode |= AUMODE_PLAY;
-		} else
-			return EINVAL;
+	if (ISSB16CLASS(sc)) {
+		/* Later models work like SB16. */
+		error = sbdsp_set_format16(sc, setmode, play, rec, pfil, rfil);
+	} else {
+		error = sbdsp_set_format8(sc, setmode, play, rec, pfil, rfil);
 	}
+	if (error)
+		return error;
+
+	DPRINTF(("%s ichan=%d, ochan=%d\n", __func__,
+	    sc->sc_i.dmachan, sc->sc_o.dmachan));
+	return 0;
+}
+
+/* set_format for SB_16 or later */
+int
+sbdsp_set_format16(struct sbdsp_softc *sc, int setmode,
+	const audio_params_t *play, const audio_params_t *rec,
+	audio_filter_reg_t *pfil, audio_filter_reg_t *rfil)
+{
+	struct sbmode *sbmodes;
+	struct sbmode *m;
+	struct sbdsp_state *io;
+	const audio_params_t *p;
+	u_int bmode;
+	int mode;
 
 	/* Set first record info, then play info */
 	for (mode = AUMODE_RECORD; mode != -1;
@@ -608,76 +766,98 @@ sbdsp_set_params(
 		if ((setmode & mode) == 0)
 			continue;
 
-		p = mode == AUMODE_PLAY ? play : rec;
-		/* Locate proper commands */
-		for (m = mode == AUMODE_PLAY ? sbpmodes : sbrmodes;
-		    m->model != -1; m++) {
-			if (model == m->model &&
-			    p->channels == m->channels &&
-			    p->precision == m->precision &&
-			    p->sample_rate >= m->lowrate &&
-			    p->sample_rate <= m->highrate)
-				break;
+		p = NULL; /* XXX shut up gcc */
+		if (mode == AUMODE_PLAY) {
+			p = play;
+			sbmodes = sbpmodes;
+			io = &sc->sc_o;
+		} else {
+			p = rec;
+			sbmodes = sbrmodes;
+			io = &sc->sc_i;
 		}
-		if (m->model == -1)
+		/* Locate proper commands */
+		m = sbdsp_find_mode(sbmodes, SB_16, p);
+		if (m == NULL)
 			return EINVAL;
-		rate = p->sample_rate;
-		hw = *p;
-		tc = 1;
-		bmode = -1;
-		if (model == SB_16) {
-			switch (p->encoding) {
-				/* FALLTHROUGH */
-			case AUDIO_ENCODING_SLINEAR:
-			case AUDIO_ENCODING_SLINEAR_LE:
-				bmode = SB_BMODE_SIGNED;
-				break;
 
-			default:
-				return EINVAL;
-			}
-			if (p->channels == 2)
-				bmode |= SB_BMODE_STEREO;
-		} else if (m->model == SB_JAZZ && m->precision == 16) {
-			switch (p->encoding) {
-			case AUDIO_ENCODING_SLINEAR:
-			case AUDIO_ENCODING_SLINEAR_LE:
-				break;
-			default:
-				return EINVAL;
-			}
-			tc = SB_RATE_TO_TC(p->sample_rate * p->channels);
-			p->sample_rate = SB_TC_TO_RATE(tc) / p->channels;
-			hw.sample_rate = p->sample_rate;
+		bmode = SB_BMODE_UNSIGNED;
+		if (p->precision == 16) {
+			/* 16bit is slinear16_le */
+			bmode = SB_BMODE_SIGNED;
 		} else {
-			panic("ulinear8 not supported; use set_format.");
+			/* 8bit is ulinear8_ne */
+			if (mode == AUMODE_PLAY)
+				pfil->codec = audio_internal_to_linear8;
+			else
+				rfil->codec = audio_linear8_to_internal;
 		}
+		if (p->channels == 2)
+			bmode |= SB_BMODE_STEREO;
 
-		chan = m->precision == 16 ? sc->sc_drq16 : sc->sc_drq8;
-		if (mode == AUMODE_PLAY) {
-			sc->sc_o.rate = rate;
-			sc->sc_o.tc = tc;
-			sc->sc_o.modep = m;
-			sc->sc_o.bmode = bmode;
-			sc->sc_o.dmachan = chan;
-		} else {
-			sc->sc_i.rate = rate;
-			sc->sc_i.tc = tc;
-			sc->sc_i.modep = m;
-			sc->sc_i.bmode = bmode;
-			sc->sc_i.dmachan = chan;
-		}
+		io->rate = p->sample_rate;
+		io->tc = 1;
+		io->modep = m;
+		io->bmode = bmode;
+		io->dmachan = m->precision == 16 ? sc->sc_drq16 : sc->sc_drq8;
+
+		DPRINTF(("%s: model=%d, mode=%d, "
+		    "rate=%u, prec=%d, chan=%d, enc=%d -> "
+		    "cmd=%02x, bmode=%02x, cmdchan=%02x\n",
+		    __func__, sc->sc_model, mode,
+		    p->sample_rate, p->precision, p->channels, p->encoding,
+		    m->cmd, bmode, m->cmdchan));
+	}
+	return 0;
+}
+
+/* set_format for prior to SB_16 */
+int
+sbdsp_set_format8(struct sbdsp_softc *sc, int setmode,
+	const audio_params_t *play, const audio_params_t *rec,
+	audio_filter_reg_t *pfil, audio_filter_reg_t *rfil)
+{
+	struct sbmode *mp;
+	struct sbmode *mr;
+	u_int tc;
+	int chan;
 
-		DPRINTF(("sbdsp_set_params: model=%d, mode=%d, rate=%u, "
-			 "prec=%d, chan=%d, enc=%d -> tc=%02x, cmd=%02x, "
-			 "bmode=%02x, cmdchan=%02x\n", sc->sc_model, mode,
-			 p->sample_rate, p->precision, p->channels,
-			 p->encoding, tc, m->cmd, bmode, m->cmdchan));
+	/* *play and *rec are the identical because !AUDIO_PROP_INDEPENDENT. */
 
-	}
+	/* Locate proper commands */
+	mp = sbdsp_find_mode(sbpmodes, sc->sc_model, play);
+	if (mp == NULL)
+		return EINVAL;
+	mr = sbdsp_find_mode(sbrmodes, sc->sc_model, rec);
+	if (mr == NULL)
+		return EINVAL;
+
+	tc = SB_RATE_TO_TC(play->sample_rate * play->channels);
+	chan = mp->precision == 16 ? sc->sc_drq16 : sc->sc_drq8;
 
-	DPRINTF(("sbdsp_set_params ichan=%d, ochan=%d\n",
-		 sc->sc_i.dmachan, sc->sc_o.dmachan));
+	sc->sc_o.rate = play->sample_rate;
+	sc->sc_o.tc = tc;
+	sc->sc_o.modep = mp;
+	sc->sc_o.bmode = -1;
+	sc->sc_o.dmachan = chan;
+
+	sc->sc_i.rate = rec->sample_rate;
+	sc->sc_i.tc = tc;
+	sc->sc_i.modep = mr;
+	sc->sc_i.bmode = -1;
+	sc->sc_i.dmachan = chan;
+
+	if (mp->precision == 8) {
+		pfil->codec = audio_internal_to_linear8;
+		rfil->codec = audio_linear8_to_internal;
+	}
+
+	DPRINTF(("%s: model=%d, "
+	    "rate=%u, prec=%d, chan=%d, enc=%d -> "
+	    "tc=%02x, cmd=%02x, cmdchan=%02x\n",
+	    __func__, sc->sc_model,
+	    play->sample_rate, play->precision, play->channels, play->encoding,
+	    tc, mp->cmd, mp->cmdchan));
 
 	return 0;
 }
@@ -2293,21 +2473,20 @@ sb_round_buffersize(void *addr, int dire
 	return size;
 }
 
-paddr_t
-sb_mappage(void *addr, void *mem, off_t off, int prot)
-{
-
-	return isa_mappage(mem, off, prot);
-}
-
 int
 sbdsp_get_props(void *addr)
 {
 	struct sbdsp_softc *sc;
+	int prop;
 
 	sc = addr;
-	return AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT |
-	       (sc->sc_fullduplex ? AUDIO_PROP_FULLDUPLEX : 0);
+	prop = AUDIO_PROP_MMAP;
+
+	/* Prior to the SB16, it has only one clock */
+	if (ISSB16CLASS(sc))
+		prop |= AUDIO_PROP_INDEPENDENT;
+
+	return prop;
 }
 
 void

Index: src/sys/dev/isa/sbdspvar.h
diff -u src/sys/dev/isa/sbdspvar.h:1.61 src/sys/dev/isa/sbdspvar.h:1.61.54.1
--- src/sys/dev/isa/sbdspvar.h:1.61	Wed Nov 23 23:07:33 2011
+++ src/sys/dev/isa/sbdspvar.h	Fri May  3 03:00:33 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: sbdspvar.h,v 1.61 2011/11/23 23:07:33 jmcneill Exp $	*/
+/*	$NetBSD: sbdspvar.h,v 1.61.54.1 2019/05/03 03:00:33 isaki Exp $	*/
 
 /*
  * Copyright (c) 1991-1993 Regents of the University of California.
@@ -116,7 +116,6 @@ struct sbdsp_softc {
 #define SB_CLOSED 0
 #define SB_OPEN_AUDIO 1
 #define SB_OPEN_MIDI 2
-	u_char	sc_fullduplex;		/* can do full duplex */
 
 	u_char	gain[SB_NDEVS][2];	/* kept in input levels */
 #define SB_LEFT 0
@@ -179,6 +178,9 @@ struct sbdsp_softc {
 #define SBVER_MAJOR(v)	(((v)>>8) & 0xff)
 #define SBVER_MINOR(v)	((v)&0xff)
 
+	struct audio_format sc_formats[4];
+	int sc_nformats;
+
 #if NMPU > 0
 	int	sc_hasmpu;
 #define SBMPU_EXTERNAL	1
@@ -211,9 +213,10 @@ int	sbdsp_set_out_gain_real(void *, u_in
 int	sbdsp_get_out_gain(void *);
 int	sbdsp_set_monitor_gain(void *, u_int);
 int	sbdsp_get_monitor_gain(void *);
-int	sbdsp_query_encoding(void *, struct audio_encoding *);
-int	sbdsp_set_params(void *, int, int, audio_params_t *, audio_params_t *,
-	    stream_filter_list_t *, stream_filter_list_t *);
+int	sbdsp_query_format(void *, audio_format_query_t *);
+int	sbdsp_set_format(void *, int,
+	    const audio_params_t *, const audio_params_t *,
+	    audio_filter_reg_t *, audio_filter_reg_t *);
 int	sbdsp_round_blocksize(void *, int, int, const audio_params_t *);
 int	sbdsp_get_avail_in_ports(void *);
 int	sbdsp_get_avail_out_ports(void *);
@@ -251,7 +254,6 @@ int	sbdsp_mixer_query_devinfo(void *, mi
 void	*sb_malloc(void *, int, size_t);
 void	sb_free(void *, void *, size_t);
 size_t	sb_round_buffersize(void *, int, size_t);
-paddr_t	sb_mappage(void *, void *, off_t, int);
 
 int	sbdsp_get_props(void *);
 void	sbdsp_get_locks(void *, kmutex_t **, kmutex_t **);

Reply via email to