xref: /openbsd/sys/dev/isa/sbdsp.c (revision c8819f5d)
1 /*	$OpenBSD: sbdsp.c,v 1.44 2022/11/02 10:41:34 kn Exp $	*/
2 
3 /*
4  * Copyright (c) 1991-1993 Regents of the University of California.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *	This product includes software developed by the Computer Systems
18  *	Engineering Group at Lawrence Berkeley Laboratory.
19  * 4. Neither the name of the University nor of the Laboratory may be used
20  *    to endorse or promote products derived from this software without
21  *    specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  *
35  */
36 
37 /*
38  * SoundBlaster Pro code provided by John Kohl, based on lots of
39  * information he gleaned from Steve Haehnichen <steve@vigra.com>'s
40  * SBlast driver for 386BSD and DOS driver code from Daniel Sachs
41  * <sachs@meibm15.cen.uiuc.edu>.
42  * Lots of rewrites by Lennart Augustsson <augustss@cs.chalmers.se>
43  * with information from SB "Hardware Programming Guide" and the
44  * Linux drivers.
45  */
46 
47 #include "midi.h"
48 
49 #include <sys/param.h>
50 #include <sys/systm.h>
51 #include <sys/errno.h>
52 #include <sys/ioctl.h>
53 #include <sys/syslog.h>
54 #include <sys/device.h>
55 #include <sys/buf.h>
56 #include <sys/fcntl.h>
57 
58 #include <machine/cpu.h>
59 #include <machine/intr.h>
60 #include <machine/bus.h>
61 
62 #include <sys/audioio.h>
63 #include <dev/audio_if.h>
64 #include <dev/midi_if.h>
65 
66 #include <dev/isa/isavar.h>
67 #include <dev/isa/isadmavar.h>
68 
69 #include <dev/isa/sbreg.h>
70 #include <dev/isa/sbdspvar.h>
71 
72 
73 #ifdef AUDIO_DEBUG
74 #define DPRINTF(x)	if (sbdspdebug) printf x
75 #define DPRINTFN(n,x)	if (sbdspdebug >= (n)) printf x
76 int	sbdspdebug = 0;
77 #else
78 #define DPRINTF(x)
79 #define DPRINTFN(n,x)
80 #endif
81 
82 #ifndef SBDSP_NPOLL
83 #define SBDSP_NPOLL 3000
84 #endif
85 
86 struct {
87 	int wdsp;
88 	int rdsp;
89 	int wmidi;
90 } sberr;
91 
92 /*
93  * Time constant routines follow.  See SBK, section 12.
94  * Although they don't come out and say it (in the docs),
95  * the card clearly uses a 1MHz countdown timer, as the
96  * low-speed formula (p. 12-4) is:
97  *	tc = 256 - 10^6 / sr
98  * In high-speed mode, the constant is the upper byte of a 16-bit counter,
99  * and a 256MHz clock is used:
100  *	tc = 65536 - 256 * 10^ 6 / sr
101  * Since we can only use the upper byte of the HS TC, the two formulae
102  * are equivalent.  (Why didn't they say so?)  E.g.,
103  *	(65536 - 256 * 10 ^ 6 / x) >> 8 = 256 - 10^6 / x
104  *
105  * The crossover point (from low- to high-speed modes) is different
106  * for the SBPRO and SB20.  The table on p. 12-5 gives the following data:
107  *
108  *				SBPRO			SB20
109  *				-----			--------
110  * input ls min			4	KHz		4	KHz
111  * input ls max			23	KHz		13	KHz
112  * input hs max			44.1	KHz		15	KHz
113  * output ls min		4	KHz		4	KHz
114  * output ls max		23	KHz		23	KHz
115  * output hs max		44.1	KHz		44.1	KHz
116  */
117 /* XXX Should we round the tc?
118 #define SB_RATE_TO_TC(x) (((65536 - 256 * 1000000 / (x)) + 128) >> 8)
119 */
120 #define SB_RATE_TO_TC(x) (256 - 1000000 / (x))
121 #define SB_TC_TO_RATE(tc) (1000000 / (256 - (tc)))
122 
123 struct sbmode {
124 	short	model;
125 	u_char	channels;
126 	u_char	precision;
127 	u_short	lowrate, highrate;
128 	u_char	cmd;
129 	u_char	cmdchan;
130 };
131 static struct sbmode sbpmodes[] = {
132  { SB_1,    1,  8,  4000, 22727, SB_DSP_WDMA      },
133  { SB_20,   1,  8,  4000, 22727, SB_DSP_WDMA_LOOP },
134  { SB_2x,   1,  8,  4000, 22727, SB_DSP_WDMA_LOOP },
135  { SB_2x,   1,  8, 22727, 45454, SB_DSP_HS_OUTPUT },
136  { SB_PRO,  1,  8,  4000, 22727, SB_DSP_WDMA_LOOP },
137  { SB_PRO,  1,  8, 22727, 45454, SB_DSP_HS_OUTPUT },
138  { SB_PRO,  2,  8, 11025, 22727, SB_DSP_HS_OUTPUT },
139  /* Yes, we write the record mode to set 16-bit playback mode. weird, huh? */
140  { SB_JAZZ, 1,  8,  4000, 22727, SB_DSP_WDMA_LOOP, SB_DSP_RECORD_MONO },
141  { SB_JAZZ, 1,  8, 22727, 45454, SB_DSP_HS_OUTPUT, SB_DSP_RECORD_MONO },
142  { SB_JAZZ, 2,  8, 11025, 22727, SB_DSP_HS_OUTPUT, SB_DSP_RECORD_STEREO },
143  { SB_JAZZ, 1, 16,  4000, 22727, SB_DSP_WDMA_LOOP, JAZZ16_RECORD_MONO },
144  { SB_JAZZ, 1, 16, 22727, 45454, SB_DSP_HS_OUTPUT, JAZZ16_RECORD_MONO },
145  { SB_JAZZ, 2, 16, 11025, 22727, SB_DSP_HS_OUTPUT, JAZZ16_RECORD_STEREO },
146  { SB_16,   1,  8,  5000, 45000, SB_DSP16_WDMA_8  },
147  { SB_16,   2,  8,  5000, 45000, SB_DSP16_WDMA_8  },
148 #define PLAY16 15 /* must be the index of the next entry in the table */
149  { SB_16,   1, 16,  5000, 45000, SB_DSP16_WDMA_16 },
150  { SB_16,   2, 16,  5000, 45000, SB_DSP16_WDMA_16 },
151  { -1 }
152 };
153 static struct sbmode sbrmodes[] = {
154  { SB_1,    1,  8,  4000, 12987, SB_DSP_RDMA      },
155  { SB_20,   1,  8,  4000, 12987, SB_DSP_RDMA_LOOP },
156  { SB_2x,   1,  8,  4000, 12987, SB_DSP_RDMA_LOOP },
157  { SB_2x,   1,  8, 12987, 14925, SB_DSP_HS_INPUT  },
158  { SB_PRO,  1,  8,  4000, 22727, SB_DSP_RDMA_LOOP, SB_DSP_RECORD_MONO },
159  { SB_PRO,  1,  8, 22727, 45454, SB_DSP_HS_INPUT,  SB_DSP_RECORD_MONO },
160  { SB_PRO,  2,  8, 11025, 22727, SB_DSP_HS_INPUT,  SB_DSP_RECORD_STEREO },
161  { SB_JAZZ, 1,  8,  4000, 22727, SB_DSP_RDMA_LOOP, SB_DSP_RECORD_MONO },
162  { SB_JAZZ, 1,  8, 22727, 45454, SB_DSP_HS_INPUT,  SB_DSP_RECORD_MONO },
163  { SB_JAZZ, 2,  8, 11025, 22727, SB_DSP_HS_INPUT,  SB_DSP_RECORD_STEREO },
164  { SB_JAZZ, 1, 16,  4000, 22727, SB_DSP_RDMA_LOOP, JAZZ16_RECORD_MONO },
165  { SB_JAZZ, 1, 16, 22727, 45454, SB_DSP_HS_INPUT,  JAZZ16_RECORD_MONO },
166  { SB_JAZZ, 2, 16, 11025, 22727, SB_DSP_HS_INPUT,  JAZZ16_RECORD_STEREO },
167  { SB_16,   1,  8,  5000, 45000, SB_DSP16_RDMA_8  },
168  { SB_16,   2,  8,  5000, 45000, SB_DSP16_RDMA_8  },
169  { SB_16,   1, 16,  5000, 45000, SB_DSP16_RDMA_16 },
170  { SB_16,   2, 16,  5000, 45000, SB_DSP16_RDMA_16 },
171  { -1 }
172 };
173 
174 static struct audio_params sbdsp_audio_default =
175 	{44100, AUDIO_ENCODING_SLINEAR_LE, 16, 2, 1, 2};
176 
177 void	sbversion(struct sbdsp_softc *);
178 void	sbdsp_jazz16_probe(struct sbdsp_softc *);
179 void	sbdsp_set_mixer_gain(struct sbdsp_softc *sc, int port);
180 void	sbdsp_to(void *);
181 void	sbdsp_pause(struct sbdsp_softc *);
182 int	sbdsp_set_timeconst(struct sbdsp_softc *, int);
183 int	sbdsp16_set_rate(struct sbdsp_softc *, int, int);
184 int	sbdsp_set_in_ports(struct sbdsp_softc *, int);
185 void	sbdsp_set_ifilter(void *, int);
186 int	sbdsp_get_ifilter(void *);
187 
188 int	sbdsp_block_output(void *);
189 int	sbdsp_block_input(void *);
190 static	int sbdsp_adjust(int, int);
191 
192 int	sbdsp_midi_intr(void *);
193 
194 #ifdef AUDIO_DEBUG
195 void	sb_printsc(struct sbdsp_softc *);
196 
197 void
sb_printsc(struct sbdsp_softc * sc)198 sb_printsc(struct sbdsp_softc *sc)
199 {
200 	int i;
201 
202 	printf("open %d dmachan %d/%d %d/%d iobase 0x%x irq %d\n",
203 	    (int)sc->sc_open, sc->sc_i.run, sc->sc_o.run,
204 	    sc->sc_drq8, sc->sc_drq16,
205 	    sc->sc_iobase, sc->sc_irq);
206 	printf("irate %d itc %x orate %d otc %x\n",
207 	    sc->sc_i.rate, sc->sc_i.tc,
208 	    sc->sc_o.rate, sc->sc_o.tc);
209 	printf("spkron %u nintr %lu\n",
210 	    sc->spkr_state, sc->sc_interrupts);
211 	printf("intr8 %p arg8 %p\n",
212 	    sc->sc_intr8, sc->sc_arg16);
213 	printf("intr16 %p arg16 %p\n",
214 	    sc->sc_intr8, sc->sc_arg16);
215 	printf("gain:");
216 	for (i = 0; i < SB_NDEVS; i++)
217 		printf(" %u,%u", sc->gain[i][SB_LEFT], sc->gain[i][SB_RIGHT]);
218 	printf("\n");
219 }
220 #endif /* AUDIO_DEBUG */
221 
222 /*
223  * Probe / attach routines.
224  */
225 
226 /*
227  * Probe for the soundblaster hardware.
228  */
229 int
sbdsp_probe(struct sbdsp_softc * sc)230 sbdsp_probe(struct sbdsp_softc *sc)
231 {
232 
233 	if (sbdsp_reset(sc) < 0) {
234 		DPRINTF(("sbdsp: couldn't reset card\n"));
235 		return 0;
236 	}
237 	/* if flags set, go and probe the jazz16 stuff */
238 	if (sc->sc_dev.dv_cfdata->cf_flags & 1)
239 		sbdsp_jazz16_probe(sc);
240 	else
241 		sbversion(sc);
242 	if (sc->sc_model == SB_UNK) {
243 		/* Unknown SB model found. */
244 		DPRINTF(("sbdsp: unknown SB model found\n"));
245 		return 0;
246 	}
247 	return 1;
248 }
249 
250 /*
251  * Try add-on stuff for Jazz16.
252  */
253 void
sbdsp_jazz16_probe(struct sbdsp_softc * sc)254 sbdsp_jazz16_probe(struct sbdsp_softc *sc)
255 {
256 	static u_char jazz16_irq_conf[16] = {
257 	    -1, -1, 0x02, 0x03,
258 	    -1, 0x01, -1, 0x04,
259 	    -1, 0x02, 0x05, -1,
260 	    -1, -1, -1, 0x06};
261 	static u_char jazz16_drq_conf[8] = {
262 	    -1, 0x01, -1, 0x02,
263 	    -1, 0x03, -1, 0x04};
264 
265 	bus_space_tag_t iot = sc->sc_iot;
266 	bus_space_handle_t ioh;
267 
268 	sbversion(sc);
269 
270 	DPRINTF(("jazz16 probe\n"));
271 
272 	if (bus_space_map(iot, JAZZ16_CONFIG_PORT, 1, 0, &ioh)) {
273 		DPRINTF(("bus map failed\n"));
274 		return;
275 	}
276 
277 	if (jazz16_drq_conf[sc->sc_drq8] == (u_char)-1 ||
278 	    jazz16_irq_conf[sc->sc_irq] == (u_char)-1) {
279 		DPRINTF(("drq/irq check failed\n"));
280 		goto done;		/* give up, we can't do it. */
281 	}
282 
283 	bus_space_write_1(iot, ioh, 0, JAZZ16_WAKEUP);
284 	delay(10000);			/* delay 10 ms */
285 	bus_space_write_1(iot, ioh, 0, JAZZ16_SETBASE);
286 	bus_space_write_1(iot, ioh, 0, sc->sc_iobase & 0x70);
287 
288 	if (sbdsp_reset(sc) < 0) {
289 		DPRINTF(("sbdsp_reset check failed\n"));
290 		goto done;		/* XXX? what else could we do? */
291 	}
292 
293 	if (sbdsp_wdsp(sc, JAZZ16_READ_VER)) {
294 		DPRINTF(("read16 setup failed\n"));
295 		goto done;
296 	}
297 
298 	if (sbdsp_rdsp(sc) != JAZZ16_VER_JAZZ) {
299 		DPRINTF(("read16 failed\n"));
300 		goto done;
301 	}
302 
303 	/* XXX set both 8 & 16-bit drq to same channel, it works fine. */
304 	sc->sc_drq16 = sc->sc_drq8;
305 	if (sbdsp_wdsp(sc, JAZZ16_SET_DMAINTR) ||
306 	    sbdsp_wdsp(sc, (jazz16_drq_conf[sc->sc_drq16] << 4) |
307 		jazz16_drq_conf[sc->sc_drq8]) ||
308 	    sbdsp_wdsp(sc, jazz16_irq_conf[sc->sc_irq])) {
309 		DPRINTF(("sbdsp: can't write jazz16 probe stuff\n"));
310 	} else {
311 		DPRINTF(("jazz16 detected!\n"));
312 		sc->sc_model = SB_JAZZ;
313 		sc->sc_mixer_model = SBM_CT1345; /* XXX really? */
314 	}
315 
316 done:
317 	bus_space_unmap(iot, ioh, 1);
318 }
319 
320 /*
321  * Attach hardware to driver, attach hardware driver to audio
322  * pseudo-device driver .
323  */
324 void
sbdsp_attach(struct sbdsp_softc * sc)325 sbdsp_attach(struct sbdsp_softc *sc)
326 {
327 	struct audio_params pparams, rparams;
328         int i;
329         u_int v;
330 
331 	/*
332 	 * Create our DMA maps.
333 	 */
334 	if (sc->sc_drq8 != -1) {
335 		if (isa_dmamap_create(sc->sc_isa, sc->sc_drq8,
336 		    MAX_ISADMA, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW)) {
337 			printf("%s: can't create map for drq %d\n",
338 			    sc->sc_dev.dv_xname, sc->sc_drq8);
339 			return;
340 		}
341 	}
342 	if (sc->sc_drq16 != -1 && sc->sc_drq16 != sc->sc_drq8) {
343 		if (isa_dmamap_create(sc->sc_isa, sc->sc_drq16,
344 		    MAX_ISADMA, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW)) {
345 			printf("%s: can't create map for drq %d\n",
346 			    sc->sc_dev.dv_xname, sc->sc_drq16);
347 			return;
348 		}
349 	}
350 
351 	pparams = sbdsp_audio_default;
352 	rparams = sbdsp_audio_default;
353         sbdsp_set_params(sc, AUMODE_RECORD|AUMODE_PLAY, 0, &pparams, &rparams);
354 
355 	sbdsp_set_in_ports(sc, 1 << SB_MIC_VOL);
356 
357 	if (sc->sc_mixer_model != SBM_NONE) {
358 		/* Reset the mixer.*/
359 		sbdsp_mix_write(sc, SBP_MIX_RESET, SBP_MIX_RESET);
360                 /* And set our own default values */
361 		for (i = 0; i < SB_NDEVS; i++) {
362 			switch(i) {
363 			case SB_MIC_VOL:
364 			case SB_LINE_IN_VOL:
365 				v = 0;
366 				break;
367 			case SB_BASS:
368 			case SB_TREBLE:
369 				v = SB_ADJUST_GAIN(sc, AUDIO_MAX_GAIN/2);
370 				break;
371 			case SB_CD_IN_MUTE:
372 			case SB_MIC_IN_MUTE:
373 			case SB_LINE_IN_MUTE:
374 			case SB_MIDI_IN_MUTE:
375 			case SB_CD_SWAP:
376 			case SB_MIC_SWAP:
377 			case SB_LINE_SWAP:
378 			case SB_MIDI_SWAP:
379 			case SB_CD_OUT_MUTE:
380 			case SB_MIC_OUT_MUTE:
381 			case SB_LINE_OUT_MUTE:
382 				v = 0;
383 				break;
384 			default:
385 				v = SB_ADJUST_GAIN(sc, AUDIO_MAX_GAIN / 2);
386 				break;
387 			}
388 			sc->gain[i][SB_LEFT] = sc->gain[i][SB_RIGHT] = v;
389 			sbdsp_set_mixer_gain(sc, i);
390 		}
391 		sc->in_filter = 0;	/* no filters turned on, please */
392 	}
393 
394 	printf(": dsp v%d.%02d%s\n",
395 	       SBVER_MAJOR(sc->sc_version), SBVER_MINOR(sc->sc_version),
396 	       sc->sc_model == SB_JAZZ ? ": <Jazz16>" : "");
397 
398 	timeout_set(&sc->sc_tmo, sbdsp_to, sbdsp_to);
399 	sc->sc_fullduplex = ISSB16CLASS(sc) &&
400 		sc->sc_drq8 != -1 && sc->sc_drq16 != -1 &&
401 		sc->sc_drq8 != sc->sc_drq16;
402 }
403 
404 void
sbdsp_mix_write(struct sbdsp_softc * sc,int mixerport,int val)405 sbdsp_mix_write(struct sbdsp_softc *sc, int mixerport, int val)
406 {
407 	bus_space_tag_t iot = sc->sc_iot;
408 	bus_space_handle_t ioh = sc->sc_ioh;
409 
410 	mtx_enter(&audio_lock);
411 	bus_space_write_1(iot, ioh, SBP_MIXER_ADDR, mixerport);
412 	delay(20);
413 	bus_space_write_1(iot, ioh, SBP_MIXER_DATA, val);
414 	delay(30);
415 	mtx_leave(&audio_lock);
416 }
417 
418 int
sbdsp_mix_read(struct sbdsp_softc * sc,int mixerport)419 sbdsp_mix_read(struct sbdsp_softc *sc, int mixerport)
420 {
421 	bus_space_tag_t iot = sc->sc_iot;
422 	bus_space_handle_t ioh = sc->sc_ioh;
423 	int val;
424 
425 	mtx_enter(&audio_lock);
426 	bus_space_write_1(iot, ioh, SBP_MIXER_ADDR, mixerport);
427 	delay(20);
428 	val = bus_space_read_1(iot, ioh, SBP_MIXER_DATA);
429 	delay(30);
430 	mtx_leave(&audio_lock);
431 	return val;
432 }
433 
434 /*
435  * Various routines to interface to higher level audio driver
436  */
437 
438 int
sbdsp_set_params(void * addr,int setmode,int usemode,struct audio_params * play,struct audio_params * rec)439 sbdsp_set_params(void *addr, int setmode, int usemode,
440     struct audio_params *play, struct audio_params *rec)
441 {
442 	struct sbdsp_softc *sc = addr;
443 	struct sbmode *m;
444 	u_int rate, tc, bmode;
445 	int model;
446 	int chan;
447 	struct audio_params *p;
448 	int mode;
449 
450 	if (sc->sc_open == SB_OPEN_MIDI)
451 		return EBUSY;
452 
453 	model = sc->sc_model;
454 	if (model > SB_16)
455 		model = SB_16;	/* later models work like SB16 */
456 
457 	/*
458 	 * Prior to the SB16, we have only one clock, so make the sample
459 	 * rates match.
460 	 */
461 	if (!ISSB16CLASS(sc) &&
462 	    play->sample_rate != rec->sample_rate &&
463 	    usemode == (AUMODE_PLAY | AUMODE_RECORD)) {
464 		if (setmode == AUMODE_PLAY) {
465 			rec->sample_rate = play->sample_rate;
466 			setmode |= AUMODE_RECORD;
467 		} else if (setmode == AUMODE_RECORD) {
468 			play->sample_rate = rec->sample_rate;
469 			setmode |= AUMODE_PLAY;
470 		} else
471 			return (EINVAL);
472 	}
473 
474 	/* Set first record info, then play info */
475 	for (mode = AUMODE_RECORD; mode != -1;
476 	     mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
477 		if ((setmode & mode) == 0)
478 			continue;
479 
480 		p = mode == AUMODE_PLAY ? play : rec;
481 
482 		switch (model) {
483 		case SB_1:
484 		case SB_20:
485 			if (mode == AUMODE_PLAY) {
486 				if (p->sample_rate < 4000)
487 					p->sample_rate = 4000;
488 				else if (p->sample_rate > 22727)
489 					p->sample_rate = 22727; /* 22050 ? */
490 			} else {
491 				if (p->sample_rate < 4000)
492 					p->sample_rate = 4000;
493 				else if (p->sample_rate > 12987)
494 					p->sample_rate = 12987;
495 			}
496 			break;
497 		case SB_2x:
498 			if (mode == AUMODE_PLAY) {
499 				if (p->sample_rate < 4000)
500 					p->sample_rate = 4000;
501 				else if (p->sample_rate > 45454)
502 					p->sample_rate = 45454; /* 44100 ? */
503 			} else {
504 				if (p->sample_rate < 4000)
505 					p->sample_rate = 4000;
506 				else if (p->sample_rate > 14925)
507 					p->sample_rate = 14925; /* ??? */
508 			}
509 			break;
510 		case SB_PRO:
511 		case SB_JAZZ:
512 			if (p->channels == 2) {
513 				if (p->sample_rate < 11025)
514 					p->sample_rate = 11025;
515 				else if (p->sample_rate > 22727)
516 					p->sample_rate = 22727; /* 22050 ? */
517 			} else {
518 				if (p->sample_rate < 4000)
519 					p->sample_rate = 4000;
520 				else if (p->sample_rate > 45454)
521 					p->sample_rate = 45454; /* 44100 ? */
522 			}
523 			break;
524 		case SB_16:
525 			if (p->sample_rate < 5000)
526 				p->sample_rate = 5000;
527 			else if (p->sample_rate > 45000)
528 				p->sample_rate = 45000; /* 44100 ? */
529 			break;
530 		}
531 
532 		/* Locate proper commands */
533 		for(m = mode == AUMODE_PLAY ? sbpmodes : sbrmodes;
534 		    m->model != -1; m++) {
535 			if (model == m->model &&
536 			    p->channels == m->channels &&
537 			    p->precision == m->precision &&
538 			    p->sample_rate >= m->lowrate &&
539 			    p->sample_rate <= m->highrate)
540 				break;
541 		}
542 		if (m->model == -1)
543 			return EINVAL;
544 		rate = p->sample_rate;
545 		tc = 1;
546 		bmode = -1;
547 		if (model == SB_16) {
548 			switch (p->encoding) {
549 			case AUDIO_ENCODING_SLINEAR_BE:
550 				if (p->precision == 16)
551 					return EINVAL;
552 				/* fall into */
553 			case AUDIO_ENCODING_SLINEAR_LE:
554 				bmode = SB_BMODE_SIGNED;
555 				break;
556 			case AUDIO_ENCODING_ULINEAR_BE:
557 				if (p->precision == 16)
558 					return EINVAL;
559 				/* fall into */
560 			case AUDIO_ENCODING_ULINEAR_LE:
561 				bmode = SB_BMODE_UNSIGNED;
562 				break;
563 			default:
564 				return EINVAL;
565 			}
566 			if (p->channels == 2)
567 				bmode |= SB_BMODE_STEREO;
568 		} else if (m->model == SB_JAZZ && m->precision == 16) {
569 			switch (p->encoding) {
570 			case AUDIO_ENCODING_SLINEAR_LE:
571 				break;
572 			default:
573 				return EINVAL;
574 			}
575 			tc = SB_RATE_TO_TC(p->sample_rate * p->channels);
576 			p->sample_rate = SB_TC_TO_RATE(tc) / p->channels;
577 		} else {
578 			switch (p->encoding) {
579 			case AUDIO_ENCODING_ULINEAR_BE:
580 			case AUDIO_ENCODING_ULINEAR_LE:
581 				break;
582 			default:
583 				return EINVAL;
584 			}
585 			tc = SB_RATE_TO_TC(p->sample_rate * p->channels);
586 			p->sample_rate = SB_TC_TO_RATE(tc) / p->channels;
587 		}
588 
589 		chan = m->precision == 16 ? sc->sc_drq16 : sc->sc_drq8;
590 		if (mode == AUMODE_PLAY) {
591 			sc->sc_o.rate = rate;
592 			sc->sc_o.tc = tc;
593 			sc->sc_o.modep = m;
594 			sc->sc_o.bmode = bmode;
595 			sc->sc_o.dmachan = chan;
596 		} else {
597 			sc->sc_i.rate = rate;
598 			sc->sc_i.tc = tc;
599 			sc->sc_i.modep = m;
600 			sc->sc_i.bmode = bmode;
601 			sc->sc_i.dmachan = chan;
602 		}
603 
604 		p->bps = AUDIO_BPS(p->precision);
605 		p->msb = 1;
606 		DPRINTF(("sbdsp_set_params: model=%d, mode=%d, rate=%ld, prec=%d, chan=%d, enc=%d -> tc=%02x, cmd=%02x, bmode=%02x, cmdchan=%02x\n",
607 			 sc->sc_model, mode, p->sample_rate, p->precision, p->channels,
608 			 p->encoding, tc, m->cmd, bmode, m->cmdchan));
609 
610 	}
611 
612 	/*
613 	 * XXX
614 	 * Should wait for chip to be idle.
615 	 */
616 	sc->sc_i.run = SB_NOTRUNNING;
617 	sc->sc_o.run = SB_NOTRUNNING;
618 
619 	if (sc->sc_fullduplex &&
620 	    usemode == (AUMODE_PLAY | AUMODE_RECORD) &&
621 	    sc->sc_i.dmachan == sc->sc_o.dmachan) {
622 		DPRINTF(("sbdsp_set_params: fd=%d, usemode=%d, idma=%d, odma=%d\n", sc->sc_fullduplex, usemode, sc->sc_i.dmachan, sc->sc_o.dmachan));
623 		return EINVAL;
624 	}
625 	DPRINTF(("sbdsp_set_params ichan=%d, ochan=%d\n",
626 		 sc->sc_i.dmachan, sc->sc_o.dmachan));
627 
628 	return 0;
629 }
630 
631 void
sbdsp_set_ifilter(void * addr,int which)632 sbdsp_set_ifilter(void *addr, int which)
633 {
634 	struct sbdsp_softc *sc = addr;
635 	int mixval;
636 
637 	mixval = sbdsp_mix_read(sc, SBP_INFILTER) & ~SBP_IFILTER_MASK;
638 	switch (which) {
639 	case 0:
640 		mixval |= SBP_FILTER_OFF;
641 		break;
642 	case SB_TREBLE:
643 		mixval |= SBP_FILTER_ON | SBP_IFILTER_HIGH;
644 		break;
645 	case SB_BASS:
646 		mixval |= SBP_FILTER_ON | SBP_IFILTER_LOW;
647 		break;
648 	default:
649 		return;
650 	}
651 	sc->in_filter = mixval & SBP_IFILTER_MASK;
652 	sbdsp_mix_write(sc, SBP_INFILTER, mixval);
653 }
654 
655 int
sbdsp_get_ifilter(void * addr)656 sbdsp_get_ifilter(void *addr)
657 {
658 	struct sbdsp_softc *sc = addr;
659 
660 	sc->in_filter =
661 		sbdsp_mix_read(sc, SBP_INFILTER) & SBP_IFILTER_MASK;
662 	switch (sc->in_filter) {
663 	case SBP_FILTER_ON|SBP_IFILTER_HIGH:
664 		return SB_TREBLE;
665 	case SBP_FILTER_ON|SBP_IFILTER_LOW:
666 		return SB_BASS;
667 	default:
668 		return 0;
669 	}
670 }
671 
672 int
sbdsp_set_in_ports(struct sbdsp_softc * sc,int mask)673 sbdsp_set_in_ports(struct sbdsp_softc *sc, int mask)
674 {
675 	int bitsl, bitsr;
676 	int sbport;
677 
678 	if (sc->sc_open == SB_OPEN_MIDI)
679 		return EBUSY;
680 
681 	DPRINTF(("sbdsp_set_in_ports: model=%d, mask=%x\n",
682 		 sc->sc_mixer_model, mask));
683 
684 	switch(sc->sc_mixer_model) {
685 	case SBM_NONE:
686 		return EINVAL;
687 	case SBM_CT1335:
688 		if (mask != (1 << SB_MIC_VOL))
689 			return EINVAL;
690 		break;
691 	case SBM_CT1345:
692 		switch (mask) {
693 		case 1 << SB_MIC_VOL:
694 			sbport = SBP_FROM_MIC;
695 			break;
696 		case 1 << SB_LINE_IN_VOL:
697 			sbport = SBP_FROM_LINE;
698 			break;
699 		case 1 << SB_CD_VOL:
700 			sbport = SBP_FROM_CD;
701 			break;
702 		default:
703 			return (EINVAL);
704 		}
705 		sbdsp_mix_write(sc, SBP_RECORD_SOURCE, sbport | sc->in_filter);
706 		break;
707 	case SBM_CT1XX5:
708 	case SBM_CT1745:
709 		if (mask & ~((1<<SB_MIDI_VOL) | (1<<SB_LINE_IN_VOL) |
710 			     (1<<SB_CD_VOL) | (1<<SB_MIC_VOL)))
711 			return EINVAL;
712 		bitsr = 0;
713 		if (mask & (1<<SB_MIDI_VOL))    bitsr |= SBP_MIDI_SRC_R;
714 		if (mask & (1<<SB_LINE_IN_VOL)) bitsr |= SBP_LINE_SRC_R;
715 		if (mask & (1<<SB_CD_VOL))      bitsr |= SBP_CD_SRC_R;
716 		bitsl = SB_SRC_R_TO_L(bitsr);
717 		if (mask & (1<<SB_MIC_VOL)) {
718 			bitsl |= SBP_MIC_SRC;
719 			bitsr |= SBP_MIC_SRC;
720 		}
721 		sbdsp_mix_write(sc, SBP_RECORD_SOURCE_L, bitsl);
722 		sbdsp_mix_write(sc, SBP_RECORD_SOURCE_R, bitsr);
723 		break;
724 	}
725 	sc->in_mask = mask;
726 
727 	return 0;
728 }
729 
730 int
sbdsp_speaker_ctl(void * addr,int newstate)731 sbdsp_speaker_ctl(void *addr, int newstate)
732 {
733 	struct sbdsp_softc *sc = addr;
734 
735 	if (sc->sc_open == SB_OPEN_MIDI)
736 		return EBUSY;
737 
738 	if ((newstate == SPKR_ON) &&
739 	    (sc->spkr_state == SPKR_OFF)) {
740 		sbdsp_spkron(sc);
741 		sc->spkr_state = SPKR_ON;
742 	}
743 	if ((newstate == SPKR_OFF) &&
744 	    (sc->spkr_state == SPKR_ON)) {
745 		sbdsp_spkroff(sc);
746 		sc->spkr_state = SPKR_OFF;
747 	}
748 	return 0;
749 }
750 
751 int
sbdsp_round_blocksize(void * addr,int blk)752 sbdsp_round_blocksize(void *addr, int blk)
753 {
754 	return (blk + 3) & -4;	/* round to biggest sample size */
755 }
756 
757 int
sbdsp_open(void * addr,int flags)758 sbdsp_open(void *addr, int flags)
759 {
760 	struct sbdsp_softc *sc = addr;
761 
762         DPRINTF(("sbdsp_open: sc=%p\n", sc));
763 
764 	if ((flags & (FWRITE | FREAD)) == (FWRITE | FREAD) &&
765 	    !sc->sc_fullduplex)
766 		return ENXIO;
767 	if (sc->sc_open != SB_CLOSED)
768 		return EBUSY;
769 	if (sbdsp_reset(sc) != 0)
770 		return EIO;
771 
772 	sbdsp_speaker_ctl(sc, (flags & FWRITE) ? SPKR_ON : SPKR_OFF);
773 
774 	sc->sc_open = SB_OPEN_AUDIO;
775 	sc->sc_openflags = flags;
776 	sc->sc_intrm = 0;
777 	if (ISSBPRO(sc) &&
778 	    sbdsp_wdsp(sc, SB_DSP_RECORD_MONO) < 0) {
779 		DPRINTF(("sbdsp_open: can't set mono mode\n"));
780 		/* we'll readjust when it's time for DMA. */
781 	}
782 
783 	/*
784 	 * Leave most things as they were; users must change things if
785 	 * the previous process didn't leave it they way they wanted.
786 	 * Looked at another way, it's easy to set up a configuration
787 	 * in one program and leave it for another to inherit.
788 	 */
789 	DPRINTF(("sbdsp_open: opened\n"));
790 
791 	return 0;
792 }
793 
794 void
sbdsp_close(void * addr)795 sbdsp_close(void *addr)
796 {
797 	struct sbdsp_softc *sc = addr;
798 
799         DPRINTF(("sbdsp_close: sc=%p\n", sc));
800 
801 	sc->sc_open = SB_CLOSED;
802 	sbdsp_spkroff(sc);
803 	sc->spkr_state = SPKR_OFF;
804 	sc->sc_intr8 = 0;
805 	sc->sc_intr16 = 0;
806 	sc->sc_intrm = 0;
807 	sbdsp_haltdma(sc);
808 
809 	DPRINTF(("sbdsp_close: closed\n"));
810 }
811 
812 /*
813  * Lower-level routines
814  */
815 
816 /*
817  * Reset the card.
818  * Return non-zero if the card isn't detected.
819  */
820 int
sbdsp_reset(struct sbdsp_softc * sc)821 sbdsp_reset(struct sbdsp_softc *sc)
822 {
823 	bus_space_tag_t iot = sc->sc_iot;
824 	bus_space_handle_t ioh = sc->sc_ioh;
825 
826 	sc->sc_intr8 = 0;
827 	sc->sc_intr16 = 0;
828 	if (sc->sc_i.run != SB_NOTRUNNING) {
829 		isa_dmaabort(sc->sc_isa, sc->sc_i.dmachan);
830 		sc->sc_i.run = SB_NOTRUNNING;
831 	}
832 	if (sc->sc_o.run != SB_NOTRUNNING) {
833 		isa_dmaabort(sc->sc_isa, sc->sc_o.dmachan);
834 		sc->sc_o.run = SB_NOTRUNNING;
835 	}
836 
837 	/*
838 	 * See SBK, section 11.3.
839 	 * We pulse a reset signal into the card.
840 	 * Gee, what a brilliant hardware design.
841 	 */
842 	bus_space_write_1(iot, ioh, SBP_DSP_RESET, 1);
843 	delay(10);
844 	bus_space_write_1(iot, ioh, SBP_DSP_RESET, 0);
845 	delay(30);
846 	if (sbdsp_rdsp(sc) != SB_MAGIC)
847 		return -1;
848 
849 	return 0;
850 }
851 
852 /*
853  * Write a byte to the dsp.
854  * We are at the mercy of the card as we use a
855  * polling loop and wait until it can take the byte.
856  */
857 int
sbdsp_wdsp(struct sbdsp_softc * sc,int v)858 sbdsp_wdsp(struct sbdsp_softc *sc, int v)
859 {
860 	bus_space_tag_t iot = sc->sc_iot;
861 	bus_space_handle_t ioh = sc->sc_ioh;
862 	int i;
863 	u_char x;
864 
865 	for (i = SBDSP_NPOLL; --i >= 0; ) {
866 		x = bus_space_read_1(iot, ioh, SBP_DSP_WSTAT);
867 		delay(10);
868 		if ((x & SB_DSP_BUSY) == 0) {
869 			bus_space_write_1(iot, ioh, SBP_DSP_WRITE, v);
870 			delay(10);
871 			return 0;
872 		}
873 	}
874 	++sberr.wdsp;
875 	return -1;
876 }
877 
878 /*
879  * Read a byte from the DSP, using polling.
880  */
881 int
sbdsp_rdsp(struct sbdsp_softc * sc)882 sbdsp_rdsp(struct sbdsp_softc *sc)
883 {
884 	bus_space_tag_t iot = sc->sc_iot;
885 	bus_space_handle_t ioh = sc->sc_ioh;
886 	int i;
887 	u_char x;
888 
889 	for (i = SBDSP_NPOLL; --i >= 0; ) {
890 		x = bus_space_read_1(iot, ioh, SBP_DSP_RSTAT);
891 		delay(10);
892 		if (x & SB_DSP_READY) {
893 			x = bus_space_read_1(iot, ioh, SBP_DSP_READ);
894 			delay(10);
895 			return x;
896 		}
897 	}
898 	++sberr.rdsp;
899 	return -1;
900 }
901 
902 /*
903  * Doing certain things (like toggling the speaker) make
904  * the SB hardware go away for a while, so pause a little.
905  */
906 void
sbdsp_to(void * arg)907 sbdsp_to(void *arg)
908 {
909 	wakeup(arg);
910 }
911 
912 void
sbdsp_pause(struct sbdsp_softc * sc)913 sbdsp_pause(struct sbdsp_softc *sc)
914 {
915 	timeout_add_msec(&sc->sc_tmo, 125);	/* 8x per second */
916 	tsleep_nsec(sbdsp_to, PWAIT, "sbpause", INFSLP);
917 }
918 
919 /*
920  * Turn on the speaker.  The SBK documentation says this operation
921  * can take up to 1/10 of a second.  Higher level layers should
922  * probably let the task sleep for this amount of time after
923  * calling here.  Otherwise, things might not work (because
924  * sbdsp_wdsp() and sbdsp_rdsp() will probably timeout.)
925  *
926  * These engineers had their heads up their ass when
927  * they designed this card.
928  */
929 void
sbdsp_spkron(struct sbdsp_softc * sc)930 sbdsp_spkron(struct sbdsp_softc *sc)
931 {
932 	(void)sbdsp_wdsp(sc, SB_DSP_SPKR_ON);
933 	sbdsp_pause(sc);
934 }
935 
936 /*
937  * Turn off the speaker; see comment above.
938  */
939 void
sbdsp_spkroff(struct sbdsp_softc * sc)940 sbdsp_spkroff(struct sbdsp_softc *sc)
941 {
942 	(void)sbdsp_wdsp(sc, SB_DSP_SPKR_OFF);
943 	sbdsp_pause(sc);
944 }
945 
946 /*
947  * Read the version number out of the card.
948  * Store version information in the softc.
949  */
950 void
sbversion(struct sbdsp_softc * sc)951 sbversion(struct sbdsp_softc *sc)
952 {
953 	int v;
954 
955 	sc->sc_model = SB_UNK;
956 	sc->sc_version = 0;
957 	if (sbdsp_wdsp(sc, SB_DSP_VERSION) < 0)
958 		return;
959 	v = sbdsp_rdsp(sc) << 8;
960 	v |= sbdsp_rdsp(sc);
961 	if (v < 0)
962 		return;
963 	sc->sc_version = v;
964 	switch(SBVER_MAJOR(v)) {
965 	case 1:
966 		sc->sc_mixer_model = SBM_NONE;
967 		sc->sc_model = SB_1;
968 		break;
969 	case 2:
970 		/* Some SB2 have a mixer, some don't. */
971 		sbdsp_mix_write(sc, SBP_1335_MASTER_VOL, 0x04);
972 		sbdsp_mix_write(sc, SBP_1335_MIDI_VOL,   0x06);
973 		/* Check if we can read back the mixer values. */
974 		if ((sbdsp_mix_read(sc, SBP_1335_MASTER_VOL) & 0x0e) == 0x04 &&
975 		    (sbdsp_mix_read(sc, SBP_1335_MIDI_VOL)   & 0x0e) == 0x06)
976 			sc->sc_mixer_model = SBM_CT1335;
977 		else
978 			sc->sc_mixer_model = SBM_NONE;
979 		if (SBVER_MINOR(v) == 0)
980 			sc->sc_model = SB_20;
981 		else
982 			sc->sc_model = SB_2x;
983 		break;
984 	case 3:
985 		sc->sc_mixer_model = SBM_CT1345;
986 		sc->sc_model = SB_PRO;
987 		break;
988 	case 4:
989 #if 0
990 /* XXX This does not work */
991 		/* Most SB16 have a tone controls, but some don't. */
992 		sbdsp_mix_write(sc, SB16P_TREBLE_L, 0x80);
993 		/* Check if we can read back the mixer value. */
994 		if ((sbdsp_mix_read(sc, SB16P_TREBLE_L) & 0xf0) == 0x80)
995 			sc->sc_mixer_model = SBM_CT1745;
996 		else
997 			sc->sc_mixer_model = SBM_CT1XX5;
998 #else
999 		sc->sc_mixer_model = SBM_CT1745;
1000 #endif
1001 #if 0
1002 /* XXX figure out a good way of determining the model */
1003 		/* XXX what about SB_32 */
1004 		if (SBVER_MINOR(v) == 16)
1005 			sc->sc_model = SB_64;
1006 		else
1007 #endif
1008 			sc->sc_model = SB_16;
1009 		break;
1010 	}
1011 }
1012 
1013 /*
1014  * Halt a DMA in progress.
1015  */
1016 int
sbdsp_haltdma(void * addr)1017 sbdsp_haltdma(void *addr)
1018 {
1019 	struct sbdsp_softc *sc = addr;
1020 
1021 	DPRINTF(("sbdsp_haltdma: sc=%p\n", sc));
1022 
1023 	mtx_enter(&audio_lock);
1024 	sbdsp_reset(sc);
1025 	mtx_leave(&audio_lock);
1026 	return 0;
1027 }
1028 
1029 int
sbdsp_set_timeconst(struct sbdsp_softc * sc,int tc)1030 sbdsp_set_timeconst(struct sbdsp_softc *sc, int tc)
1031 {
1032 	DPRINTF(("sbdsp_set_timeconst: sc=%p tc=%d\n", sc, tc));
1033 
1034 	if (sbdsp_wdsp(sc, SB_DSP_TIMECONST) < 0 ||
1035 	    sbdsp_wdsp(sc, tc) < 0)
1036 		return EIO;
1037 
1038 	return 0;
1039 }
1040 
1041 int
sbdsp16_set_rate(struct sbdsp_softc * sc,int cmd,int rate)1042 sbdsp16_set_rate(struct sbdsp_softc *sc, int cmd, int rate)
1043 {
1044 	DPRINTF(("sbdsp16_set_rate: sc=%p cmd=0x%02x rate=%d\n", sc, cmd, rate));
1045 
1046 	if (sbdsp_wdsp(sc, cmd) < 0 ||
1047 	    sbdsp_wdsp(sc, rate >> 8) < 0 ||
1048 	    sbdsp_wdsp(sc, rate) < 0)
1049 		return EIO;
1050 	return 0;
1051 }
1052 
1053 int
sbdsp_trigger_input(void * addr,void * start,void * end,int blksize,void (* intr)(void *),void * arg,struct audio_params * param)1054 sbdsp_trigger_input(void *addr, void *start, void *end, int blksize,
1055     void (*intr)(void *), void *arg, struct audio_params *param)
1056 {
1057 	struct sbdsp_softc *sc = addr;
1058 	int stereo = param->channels == 2;
1059 	int width = param->precision;
1060 	int filter;
1061 	int rc;
1062 
1063 #ifdef DIAGNOSTIC
1064 	if (stereo && (blksize & 1)) {
1065 		DPRINTF(("stereo record odd bytes (%d)\n", blksize));
1066 		return (EIO);
1067 	}
1068 #endif
1069 
1070 	sc->sc_intrr = intr;
1071 	sc->sc_argr = arg;
1072 
1073 	if (width == 8) {
1074 #ifdef DIAGNOSTIC
1075 		if (sc->sc_i.dmachan != sc->sc_drq8) {
1076 			printf("sbdsp_trigger_input: width=%d bad chan %d\n",
1077 			    width, sc->sc_i.dmachan);
1078 			return (EIO);
1079 		}
1080 #endif
1081 		sc->sc_intr8 = sbdsp_block_input;
1082 		sc->sc_arg8 = addr;
1083 	} else {
1084 #ifdef DIAGNOSTIC
1085 		if (sc->sc_i.dmachan != sc->sc_drq16) {
1086 			printf("sbdsp_trigger_input: width=%d bad chan %d\n",
1087 			    width, sc->sc_i.dmachan);
1088 			return (EIO);
1089 		}
1090 #endif
1091 		sc->sc_intr16 = sbdsp_block_input;
1092 		sc->sc_arg16 = addr;
1093 	}
1094 
1095 	if ((sc->sc_model == SB_JAZZ) ? (sc->sc_i.dmachan > 3) : (width == 16))
1096 		blksize >>= 1;
1097 	--blksize;
1098 	sc->sc_i.blksize = blksize;
1099 
1100 	if (ISSBPRO(sc)) {
1101 		if (sbdsp_wdsp(sc, sc->sc_i.modep->cmdchan) < 0)
1102 			return (EIO);
1103 		filter = stereo ? SBP_FILTER_OFF : sc->in_filter;
1104 		sbdsp_mix_write(sc, SBP_INFILTER,
1105 		    (sbdsp_mix_read(sc, SBP_INFILTER) & ~SBP_IFILTER_MASK) |
1106 		    filter);
1107 	}
1108 
1109 	if (ISSB16CLASS(sc)) {
1110 		if (sbdsp16_set_rate(sc, SB_DSP16_INPUTRATE, sc->sc_i.rate)) {
1111 			DPRINTF(("sbdsp_trigger_input: rate=%d set failed\n",
1112 				 sc->sc_i.rate));
1113 			return (EIO);
1114 		}
1115 	} else {
1116 		if (sbdsp_set_timeconst(sc, sc->sc_i.tc)) {
1117 			DPRINTF(("sbdsp_trigger_input: tc=%d set failed\n",
1118 				 sc->sc_i.rate));
1119 			return (EIO);
1120 		}
1121 	}
1122 
1123 	DPRINTF(("sbdsp: dma start loop input start=%p end=%p chan=%d\n",
1124 	    start, end, sc->sc_i.dmachan));
1125 	mtx_enter(&audio_lock);
1126 	isa_dmastart(sc->sc_isa, sc->sc_i.dmachan, start, (char *)end -
1127 	    (char *)start, NULL, DMAMODE_READ | DMAMODE_LOOP, BUS_DMA_NOWAIT);
1128 	rc = sbdsp_block_input(addr);
1129 	mtx_leave(&audio_lock);
1130 	return rc;
1131 }
1132 
1133 int
sbdsp_block_input(void * addr)1134 sbdsp_block_input(void *addr)
1135 {
1136 	struct sbdsp_softc *sc = addr;
1137 	int cc = sc->sc_i.blksize;
1138 
1139 	DPRINTFN(2, ("sbdsp_block_input: sc=%p cc=%d\n", addr, cc));
1140 
1141 	if (sc->sc_i.run != SB_NOTRUNNING)
1142 		sc->sc_intrr(sc->sc_argr);
1143 
1144 	if (sc->sc_model == SB_1) {
1145 		/* Non-looping mode, start DMA */
1146 		if (sbdsp_wdsp(sc, sc->sc_i.modep->cmd) < 0 ||
1147 		    sbdsp_wdsp(sc, cc) < 0 ||
1148 		    sbdsp_wdsp(sc, cc >> 8) < 0) {
1149 			DPRINTF(("sbdsp_block_input: SB1 DMA start failed\n"));
1150 			return (EIO);
1151 		}
1152 		sc->sc_i.run = SB_RUNNING;
1153 	} else if (sc->sc_i.run == SB_NOTRUNNING) {
1154 		/* Initialize looping PCM */
1155 		if (ISSB16CLASS(sc)) {
1156 			DPRINTFN(3, ("sbdsp16 input command cmd=0x%02x bmode=0x%02x cc=%d\n",
1157 			    sc->sc_i.modep->cmd, sc->sc_i.bmode, cc));
1158 			if (sbdsp_wdsp(sc, sc->sc_i.modep->cmd) < 0 ||
1159 			    sbdsp_wdsp(sc, sc->sc_i.bmode) < 0 ||
1160 			    sbdsp_wdsp(sc, cc) < 0 ||
1161 			    sbdsp_wdsp(sc, cc >> 8) < 0) {
1162 				DPRINTF(("sbdsp_block_input: SB16 DMA start failed\n"));
1163 				return (EIO);
1164 			}
1165 		} else {
1166 			DPRINTF(("sbdsp_block_input: set blocksize=%d\n", cc));
1167 			if (sbdsp_wdsp(sc, SB_DSP_BLOCKSIZE) < 0 ||
1168 			    sbdsp_wdsp(sc, cc) < 0 ||
1169 			    sbdsp_wdsp(sc, cc >> 8) < 0) {
1170 				DPRINTF(("sbdsp_block_input: SB2 DMA blocksize failed\n"));
1171 				return (EIO);
1172 			}
1173 			if (sbdsp_wdsp(sc, sc->sc_i.modep->cmd) < 0) {
1174 				DPRINTF(("sbdsp_block_input: SB2 DMA start failed\n"));
1175 				return (EIO);
1176 			}
1177 		}
1178 		sc->sc_i.run = SB_LOOPING;
1179 	}
1180 
1181 	return (0);
1182 }
1183 
1184 int
sbdsp_trigger_output(void * addr,void * start,void * end,int blksize,void (* intr)(void *),void * arg,struct audio_params * param)1185 sbdsp_trigger_output(void *addr, void *start, void *end, int blksize,
1186     void (*intr)(void *), void *arg, struct audio_params *param)
1187 {
1188 	struct sbdsp_softc *sc = addr;
1189 	int stereo = param->channels == 2;
1190 	int width = param->precision;
1191 	int cmd;
1192 	int rc;
1193 
1194 #ifdef DIAGNOSTIC
1195 	if (stereo && (blksize & 1)) {
1196 		DPRINTF(("stereo playback odd bytes (%d)\n", blksize));
1197 		return (EIO);
1198 	}
1199 #endif
1200 
1201 	sc->sc_intrp = intr;
1202 	sc->sc_argp = arg;
1203 
1204 	if (width == 8) {
1205 #ifdef DIAGNOSTIC
1206 		if (sc->sc_o.dmachan != sc->sc_drq8) {
1207 			printf("sbdsp_trigger_output: width=%d bad chan %d\n",
1208 			    width, sc->sc_o.dmachan);
1209 			return (EIO);
1210 		}
1211 #endif
1212 		sc->sc_intr8 = sbdsp_block_output;
1213 		sc->sc_arg8 = addr;
1214 	} else {
1215 #ifdef DIAGNOSTIC
1216 		if (sc->sc_o.dmachan != sc->sc_drq16) {
1217 			printf("sbdsp_trigger_output: width=%d bad chan %d\n",
1218 			    width, sc->sc_o.dmachan);
1219 			return (EIO);
1220 		}
1221 #endif
1222 		sc->sc_intr16 = sbdsp_block_output;
1223 		sc->sc_arg16 = addr;
1224 	}
1225 
1226 	if ((sc->sc_model == SB_JAZZ) ? (sc->sc_o.dmachan > 3) : (width == 16))
1227 		blksize >>= 1;
1228 	--blksize;
1229 	sc->sc_o.blksize = blksize;
1230 
1231 	if (ISSBPRO(sc)) {
1232 		/* make sure we re-set stereo mixer bit when we start output. */
1233 		sbdsp_mix_write(sc, SBP_STEREO,
1234 		    (sbdsp_mix_read(sc, SBP_STEREO) & ~SBP_PLAYMODE_MASK) |
1235 		    (stereo ?  SBP_PLAYMODE_STEREO : SBP_PLAYMODE_MONO));
1236 		cmd = sc->sc_o.modep->cmdchan;
1237 		if (cmd && sbdsp_wdsp(sc, cmd) < 0)
1238 			return (EIO);
1239 	}
1240 
1241 	if (ISSB16CLASS(sc)) {
1242 		if (sbdsp16_set_rate(sc, SB_DSP16_OUTPUTRATE, sc->sc_o.rate)) {
1243 			DPRINTF(("sbdsp_trigger_output: rate=%d set failed\n",
1244 				 sc->sc_o.rate));
1245 			return (EIO);
1246 		}
1247 	} else {
1248 		if (sbdsp_set_timeconst(sc, sc->sc_o.tc)) {
1249 			DPRINTF(("sbdsp_trigger_output: tc=%d set failed\n",
1250 				 sc->sc_o.rate));
1251 			return (EIO);
1252 		}
1253 	}
1254 
1255 	DPRINTF(("sbdsp: dma start loop output start=%p end=%p chan=%d\n",
1256 	    start, end, sc->sc_o.dmachan));
1257 	mtx_enter(&audio_lock);
1258 	isa_dmastart(sc->sc_isa, sc->sc_o.dmachan, start, (char *)end -
1259 	    (char *)start, NULL, DMAMODE_WRITE | DMAMODE_LOOP, BUS_DMA_NOWAIT);
1260 	rc = sbdsp_block_output(addr);
1261 	mtx_leave(&audio_lock);
1262 	return rc;
1263 }
1264 
1265 int
sbdsp_block_output(void * addr)1266 sbdsp_block_output(void *addr)
1267 {
1268 	struct sbdsp_softc *sc = addr;
1269 	int cc = sc->sc_o.blksize;
1270 
1271 	DPRINTFN(2, ("sbdsp_block_output: sc=%p cc=%d\n", addr, cc));
1272 
1273 	if (sc->sc_o.run != SB_NOTRUNNING)
1274 		sc->sc_intrp(sc->sc_argp);
1275 
1276 	if (sc->sc_model == SB_1) {
1277 		/* Non-looping mode, initialized. Start DMA and PCM */
1278 		if (sbdsp_wdsp(sc, sc->sc_o.modep->cmd) < 0 ||
1279 		    sbdsp_wdsp(sc, cc) < 0 ||
1280 		    sbdsp_wdsp(sc, cc >> 8) < 0) {
1281 			DPRINTF(("sbdsp_block_output: SB1 DMA start failed\n"));
1282 			return (EIO);
1283 		}
1284 		sc->sc_o.run = SB_RUNNING;
1285 	} else if (sc->sc_o.run == SB_NOTRUNNING) {
1286 		/* Initialize looping PCM */
1287 		if (ISSB16CLASS(sc)) {
1288 			DPRINTF(("sbdsp_block_output: SB16 cmd=0x%02x bmode=0x%02x cc=%d\n",
1289 			    sc->sc_o.modep->cmd,sc->sc_o.bmode, cc));
1290 			if (sbdsp_wdsp(sc, sc->sc_o.modep->cmd) < 0 ||
1291 			    sbdsp_wdsp(sc, sc->sc_o.bmode) < 0 ||
1292 			    sbdsp_wdsp(sc, cc) < 0 ||
1293 			    sbdsp_wdsp(sc, cc >> 8) < 0) {
1294 				DPRINTF(("sbdsp_block_output: SB16 DMA start failed\n"));
1295 				return (EIO);
1296 			}
1297 		} else {
1298 			DPRINTF(("sbdsp_block_output: set blocksize=%d\n", cc));
1299 			if (sbdsp_wdsp(sc, SB_DSP_BLOCKSIZE) < 0 ||
1300 			    sbdsp_wdsp(sc, cc) < 0 ||
1301 			    sbdsp_wdsp(sc, cc >> 8) < 0) {
1302 				DPRINTF(("sbdsp_block_output: SB2 DMA blocksize failed\n"));
1303 				return (EIO);
1304 			}
1305 			if (sbdsp_wdsp(sc, sc->sc_o.modep->cmd) < 0) {
1306 				DPRINTF(("sbdsp_block_output: SB2 DMA start failed\n"));
1307 				return (EIO);
1308 			}
1309 		}
1310 		sc->sc_o.run = SB_LOOPING;
1311 	}
1312 
1313 	return (0);
1314 }
1315 
1316 /*
1317  * Only the DSP unit on the sound blaster generates interrupts.
1318  * There are three cases of interrupt: reception of a midi byte
1319  * (when mode is enabled), completion of dma transmission, or
1320  * completion of a dma reception.
1321  *
1322  * If there is interrupt sharing or a spurious interrupt occurs
1323  * there is no way to distinguish this on an SB2.  So if you have
1324  * an SB2 and experience problems, buy an SB16 (it's only $40).
1325  */
1326 int
sbdsp_intr(void * arg)1327 sbdsp_intr(void *arg)
1328 {
1329 	struct sbdsp_softc *sc = arg;
1330 	u_char irq;
1331 
1332 	mtx_enter(&audio_lock);
1333 	DPRINTFN(2, ("sbdsp_intr: intr8=%p, intr16=%p\n",
1334 		   sc->sc_intr8, sc->sc_intr16));
1335 	if (ISSB16CLASS(sc)) {
1336 		bus_space_write_1(sc->sc_iot, sc->sc_ioh,
1337 		    SBP_MIXER_ADDR, SBP_IRQ_STATUS);
1338 		delay(20);
1339 		irq = bus_space_read_1(sc->sc_iot, sc->sc_ioh,
1340 		    SBP_MIXER_DATA);
1341 		delay(30);
1342 		if ((irq & (SBP_IRQ_DMA8 | SBP_IRQ_DMA16 | SBP_IRQ_MPU401)) == 0) {
1343 			DPRINTF(("sbdsp_intr: Spurious interrupt 0x%x\n", irq));
1344 			mtx_leave(&audio_lock);
1345 			return 0;
1346 		}
1347 	} else {
1348 		/* XXXX CHECK FOR INTERRUPT */
1349 		irq = SBP_IRQ_DMA8;
1350 	}
1351 
1352 	sc->sc_interrupts++;
1353 	delay(10);		/* XXX why? */
1354 
1355 	/* clear interrupt */
1356 	if (irq & SBP_IRQ_DMA8) {
1357 		bus_space_read_1(sc->sc_iot, sc->sc_ioh, SBP_DSP_IRQACK8);
1358 		if (sc->sc_intr8)
1359 			sc->sc_intr8(sc->sc_arg8);
1360 	}
1361 	if (irq & SBP_IRQ_DMA16) {
1362 		bus_space_read_1(sc->sc_iot, sc->sc_ioh, SBP_DSP_IRQACK16);
1363 		if (sc->sc_intr16)
1364 			sc->sc_intr16(sc->sc_arg16);
1365 	}
1366 #if NMIDI > 0
1367 	if ((irq & SBP_IRQ_MPU401) && sc->sc_hasmpu) {
1368 		mpu_intr(&sc->sc_mpu_sc);
1369 	}
1370 #endif
1371 	mtx_leave(&audio_lock);
1372 	return 1;
1373 }
1374 
1375 /* Like val & mask, but make sure the result is correctly rounded. */
1376 #define MAXVAL 256
1377 static int
sbdsp_adjust(int val,int mask)1378 sbdsp_adjust(int val, int mask)
1379 {
1380 	val += (MAXVAL - mask) >> 1;
1381 	if (val >= MAXVAL)
1382 		val = MAXVAL-1;
1383 	return val & mask;
1384 }
1385 
1386 void
sbdsp_set_mixer_gain(struct sbdsp_softc * sc,int port)1387 sbdsp_set_mixer_gain(struct sbdsp_softc *sc, int port)
1388 {
1389 	int src, gain;
1390 
1391 	switch(sc->sc_mixer_model) {
1392 	case SBM_NONE:
1393 		return;
1394 	case SBM_CT1335:
1395 		gain = SB_1335_GAIN(sc->gain[port][SB_LEFT]);
1396 		switch(port) {
1397 		case SB_MASTER_VOL:
1398 			src = SBP_1335_MASTER_VOL;
1399 			break;
1400 		case SB_MIDI_VOL:
1401 			src = SBP_1335_MIDI_VOL;
1402 			break;
1403 		case SB_CD_VOL:
1404 			src = SBP_1335_CD_VOL;
1405 			break;
1406 		case SB_VOICE_VOL:
1407 			src = SBP_1335_VOICE_VOL;
1408 			gain = SB_1335_MASTER_GAIN(sc->gain[port][SB_LEFT]);
1409 			break;
1410 		default:
1411 			return;
1412 		}
1413 		sbdsp_mix_write(sc, src, gain);
1414 		break;
1415 	case SBM_CT1345:
1416 		gain = SB_STEREO_GAIN(sc->gain[port][SB_LEFT],
1417 				      sc->gain[port][SB_RIGHT]);
1418 		switch (port) {
1419 		case SB_MIC_VOL:
1420 			src = SBP_MIC_VOL;
1421 			gain = SB_MIC_GAIN(sc->gain[port][SB_LEFT]);
1422 			break;
1423 		case SB_MASTER_VOL:
1424 			src = SBP_MASTER_VOL;
1425 			break;
1426 		case SB_LINE_IN_VOL:
1427 			src = SBP_LINE_VOL;
1428 			break;
1429 		case SB_VOICE_VOL:
1430 			src = SBP_VOICE_VOL;
1431 			break;
1432 		case SB_MIDI_VOL:
1433 			src = SBP_MIDI_VOL;
1434 			break;
1435 		case SB_CD_VOL:
1436 			src = SBP_CD_VOL;
1437 			break;
1438 		default:
1439 			return;
1440 		}
1441 		sbdsp_mix_write(sc, src, gain);
1442 		break;
1443 	case SBM_CT1XX5:
1444 	case SBM_CT1745:
1445 		switch (port) {
1446 		case SB_MIC_VOL:
1447 			src = SB16P_MIC_L;
1448 			break;
1449 		case SB_MASTER_VOL:
1450 			src = SB16P_MASTER_L;
1451 			break;
1452 		case SB_LINE_IN_VOL:
1453 			src = SB16P_LINE_L;
1454 			break;
1455 		case SB_VOICE_VOL:
1456 			src = SB16P_VOICE_L;
1457 			break;
1458 		case SB_MIDI_VOL:
1459 			src = SB16P_MIDI_L;
1460 			break;
1461 		case SB_CD_VOL:
1462 			src = SB16P_CD_L;
1463 			break;
1464 		case SB_INPUT_GAIN:
1465 			src = SB16P_INPUT_GAIN_L;
1466 			break;
1467 		case SB_OUTPUT_GAIN:
1468 			src = SB16P_OUTPUT_GAIN_L;
1469 			break;
1470 		case SB_TREBLE:
1471 			src = SB16P_TREBLE_L;
1472 			break;
1473 		case SB_BASS:
1474 			src = SB16P_BASS_L;
1475 			break;
1476 		case SB_PCSPEAKER:
1477 			sbdsp_mix_write(sc, SB16P_PCSPEAKER, sc->gain[port][SB_LEFT]);
1478 			return;
1479 		default:
1480 			return;
1481 		}
1482 		sbdsp_mix_write(sc, src, sc->gain[port][SB_LEFT]);
1483 		sbdsp_mix_write(sc, SB16P_L_TO_R(src), sc->gain[port][SB_RIGHT]);
1484 		break;
1485 	}
1486 }
1487 
1488 int
sbdsp_mixer_set_port(void * addr,mixer_ctrl_t * cp)1489 sbdsp_mixer_set_port(void *addr, mixer_ctrl_t *cp)
1490 {
1491 	struct sbdsp_softc *sc = addr;
1492 	int lgain, rgain;
1493 	int mask, bits;
1494 	int lmask, rmask, lbits, rbits;
1495 	int mute, swap;
1496 
1497 	if (sc->sc_open == SB_OPEN_MIDI)
1498 		return EBUSY;
1499 
1500 	DPRINTF(("sbdsp_mixer_set_port: port=%d num_channels=%d\n", cp->dev,
1501 	    cp->un.value.num_channels));
1502 
1503 	if (sc->sc_mixer_model == SBM_NONE)
1504 		return EINVAL;
1505 
1506 	switch (cp->dev) {
1507 	case SB_TREBLE:
1508 	case SB_BASS:
1509 		if (sc->sc_mixer_model == SBM_CT1345 ||
1510                     sc->sc_mixer_model == SBM_CT1XX5) {
1511 			if (cp->type != AUDIO_MIXER_ENUM)
1512 				return EINVAL;
1513 			switch (cp->dev) {
1514 			case SB_TREBLE:
1515 				sbdsp_set_ifilter(addr, cp->un.ord ? SB_TREBLE : 0);
1516 				return 0;
1517 			case SB_BASS:
1518 				sbdsp_set_ifilter(addr, cp->un.ord ? SB_BASS : 0);
1519 				return 0;
1520 			}
1521 		}
1522 	case SB_PCSPEAKER:
1523 	case SB_INPUT_GAIN:
1524 	case SB_OUTPUT_GAIN:
1525 		if (!ISSBM1745(sc))
1526 			return EINVAL;
1527 	case SB_MIC_VOL:
1528 	case SB_LINE_IN_VOL:
1529 		if (sc->sc_mixer_model == SBM_CT1335)
1530 			return EINVAL;
1531 	case SB_VOICE_VOL:
1532 	case SB_MIDI_VOL:
1533 	case SB_CD_VOL:
1534 	case SB_MASTER_VOL:
1535 		if (cp->type != AUDIO_MIXER_VALUE)
1536 			return EINVAL;
1537 
1538 		/*
1539 		 * All the mixer ports are stereo except for the microphone.
1540 		 * If we get a single-channel gain value passed in, then we
1541 		 * duplicate it to both left and right channels.
1542 		 */
1543 
1544 		switch (cp->dev) {
1545 		case SB_MIC_VOL:
1546 			if (cp->un.value.num_channels != 1)
1547 				return EINVAL;
1548 
1549 			lgain = rgain = SB_ADJUST_MIC_GAIN(sc,
1550 			  cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
1551 			break;
1552 		case SB_PCSPEAKER:
1553 			if (cp->un.value.num_channels != 1)
1554 				return EINVAL;
1555 			/* fall into */
1556 		case SB_INPUT_GAIN:
1557 		case SB_OUTPUT_GAIN:
1558 			lgain = rgain = SB_ADJUST_2_GAIN(sc,
1559 			  cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
1560 			break;
1561 		default:
1562 			switch (cp->un.value.num_channels) {
1563 			case 1:
1564 				lgain = rgain = SB_ADJUST_GAIN(sc,
1565 				  cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
1566 				break;
1567 			case 2:
1568 				if (sc->sc_mixer_model == SBM_CT1335)
1569 					return EINVAL;
1570 				lgain = SB_ADJUST_GAIN(sc,
1571 				  cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]);
1572 				rgain = SB_ADJUST_GAIN(sc,
1573 				  cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]);
1574 				break;
1575 			default:
1576 				return EINVAL;
1577 			}
1578 			break;
1579 		}
1580 		sc->gain[cp->dev][SB_LEFT]  = lgain;
1581 		sc->gain[cp->dev][SB_RIGHT] = rgain;
1582 
1583 		sbdsp_set_mixer_gain(sc, cp->dev);
1584 		break;
1585 
1586 	case SB_RECORD_SOURCE:
1587 		if (ISSBM1745(sc)) {
1588 			if (cp->type != AUDIO_MIXER_SET)
1589 				return EINVAL;
1590 			return sbdsp_set_in_ports(sc, cp->un.mask);
1591 		} else {
1592 			if (cp->type != AUDIO_MIXER_ENUM)
1593 				return EINVAL;
1594 			sc->in_port = cp->un.ord;
1595 			return sbdsp_set_in_ports(sc, 1 << cp->un.ord);
1596 		}
1597 		break;
1598 
1599 	case SB_AGC:
1600 		if (!ISSBM1745(sc) || cp->type != AUDIO_MIXER_ENUM)
1601 			return EINVAL;
1602 		sbdsp_mix_write(sc, SB16P_AGC, cp->un.ord & 1);
1603 		break;
1604 
1605 	case SB_CD_OUT_MUTE:
1606 		mask = SB16P_SW_CD;
1607 		goto omute;
1608 	case SB_MIC_OUT_MUTE:
1609 		mask = SB16P_SW_MIC;
1610 		goto omute;
1611 	case SB_LINE_OUT_MUTE:
1612 		mask = SB16P_SW_LINE;
1613 	omute:
1614 		if (cp->type != AUDIO_MIXER_ENUM)
1615 			return EINVAL;
1616 		bits = sbdsp_mix_read(sc, SB16P_OSWITCH);
1617 		sc->gain[cp->dev][SB_LR] = cp->un.ord != 0;
1618 		if (cp->un.ord)
1619 			bits = bits & ~mask;
1620 		else
1621 			bits = bits | mask;
1622 		sbdsp_mix_write(sc, SB16P_OSWITCH, bits);
1623 		break;
1624 
1625 	case SB_MIC_IN_MUTE:
1626 	case SB_MIC_SWAP:
1627 		lmask = rmask = SB16P_SW_MIC;
1628 		goto imute;
1629 	case SB_CD_IN_MUTE:
1630 	case SB_CD_SWAP:
1631 		lmask = SB16P_SW_CD_L;
1632 		rmask = SB16P_SW_CD_R;
1633 		goto imute;
1634 	case SB_LINE_IN_MUTE:
1635 	case SB_LINE_SWAP:
1636 		lmask = SB16P_SW_LINE_L;
1637 		rmask = SB16P_SW_LINE_R;
1638 		goto imute;
1639 	case SB_MIDI_IN_MUTE:
1640 	case SB_MIDI_SWAP:
1641 		lmask = SB16P_SW_MIDI_L;
1642 		rmask = SB16P_SW_MIDI_R;
1643 	imute:
1644 		if (cp->type != AUDIO_MIXER_ENUM)
1645 			return EINVAL;
1646 		mask = lmask | rmask;
1647 		lbits = sbdsp_mix_read(sc, SB16P_ISWITCH_L) & ~mask;
1648 		rbits = sbdsp_mix_read(sc, SB16P_ISWITCH_R) & ~mask;
1649 		sc->gain[cp->dev][SB_LR] = cp->un.ord != 0;
1650 		if (SB_IS_IN_MUTE(cp->dev)) {
1651 			mute = cp->dev;
1652 			swap = mute - SB_CD_IN_MUTE + SB_CD_SWAP;
1653 		} else {
1654 			swap = cp->dev;
1655 			mute = swap + SB_CD_IN_MUTE - SB_CD_SWAP;
1656 		}
1657 		if (sc->gain[swap][SB_LR]) {
1658 			mask = lmask;
1659 			lmask = rmask;
1660 			rmask = mask;
1661 		}
1662 		if (!sc->gain[mute][SB_LR]) {
1663 			lbits = lbits | lmask;
1664 			rbits = rbits | rmask;
1665 		}
1666 		sbdsp_mix_write(sc, SB16P_ISWITCH_L, lbits);
1667 		sbdsp_mix_write(sc, SB16P_ISWITCH_L, rbits);
1668 		break;
1669 
1670 	default:
1671 		return EINVAL;
1672 	}
1673 
1674 	return 0;
1675 }
1676 
1677 int
sbdsp_mixer_get_port(void * addr,mixer_ctrl_t * cp)1678 sbdsp_mixer_get_port(void *addr, mixer_ctrl_t *cp)
1679 {
1680 	struct sbdsp_softc *sc = addr;
1681 
1682 	if (sc->sc_open == SB_OPEN_MIDI)
1683 		return EBUSY;
1684 
1685 	DPRINTF(("sbdsp_mixer_get_port: port=%d\n", cp->dev));
1686 
1687 	if (sc->sc_mixer_model == SBM_NONE)
1688 		return EINVAL;
1689 
1690 	switch (cp->dev) {
1691 	case SB_TREBLE:
1692 	case SB_BASS:
1693 		if (sc->sc_mixer_model == SBM_CT1345 ||
1694                     sc->sc_mixer_model == SBM_CT1XX5) {
1695 			switch (cp->dev) {
1696 			case SB_TREBLE:
1697 				cp->un.ord = sbdsp_get_ifilter(addr) == SB_TREBLE;
1698 				return 0;
1699 			case SB_BASS:
1700 				cp->un.ord = sbdsp_get_ifilter(addr) == SB_BASS;
1701 				return 0;
1702 			}
1703 		}
1704 	case SB_PCSPEAKER:
1705 	case SB_INPUT_GAIN:
1706 	case SB_OUTPUT_GAIN:
1707 		if (!ISSBM1745(sc))
1708 			return EINVAL;
1709 	case SB_MIC_VOL:
1710 	case SB_LINE_IN_VOL:
1711 		if (sc->sc_mixer_model == SBM_CT1335)
1712 			return EINVAL;
1713 	case SB_VOICE_VOL:
1714 	case SB_MIDI_VOL:
1715 	case SB_CD_VOL:
1716 	case SB_MASTER_VOL:
1717 		switch (cp->dev) {
1718 		case SB_MIC_VOL:
1719 		case SB_PCSPEAKER:
1720 			if (cp->un.value.num_channels != 1)
1721 				return EINVAL;
1722 			/* fall into */
1723 		default:
1724 			switch (cp->un.value.num_channels) {
1725 			case 1:
1726 				cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
1727 					sc->gain[cp->dev][SB_LEFT];
1728 				break;
1729 			case 2:
1730 				cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
1731 					sc->gain[cp->dev][SB_LEFT];
1732 				cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
1733 					sc->gain[cp->dev][SB_RIGHT];
1734 				break;
1735 			default:
1736 				return EINVAL;
1737 			}
1738 			break;
1739 		}
1740 		break;
1741 
1742 	case SB_RECORD_SOURCE:
1743 		if (ISSBM1745(sc))
1744 			cp->un.mask = sc->in_mask;
1745 		else
1746 			cp->un.ord = sc->in_port;
1747 		break;
1748 
1749 	case SB_AGC:
1750 		if (!ISSBM1745(sc))
1751 			return EINVAL;
1752 		cp->un.ord = sbdsp_mix_read(sc, SB16P_AGC);
1753 		break;
1754 
1755 	case SB_CD_IN_MUTE:
1756 	case SB_MIC_IN_MUTE:
1757 	case SB_LINE_IN_MUTE:
1758 	case SB_MIDI_IN_MUTE:
1759 	case SB_CD_SWAP:
1760 	case SB_MIC_SWAP:
1761 	case SB_LINE_SWAP:
1762 	case SB_MIDI_SWAP:
1763 	case SB_CD_OUT_MUTE:
1764 	case SB_MIC_OUT_MUTE:
1765 	case SB_LINE_OUT_MUTE:
1766 		cp->un.ord = sc->gain[cp->dev][SB_LR];
1767 		break;
1768 
1769 	default:
1770 		return EINVAL;
1771 	}
1772 
1773 	return 0;
1774 }
1775 
1776 int
sbdsp_mixer_query_devinfo(void * addr,mixer_devinfo_t * dip)1777 sbdsp_mixer_query_devinfo(void *addr, mixer_devinfo_t *dip)
1778 {
1779 	struct sbdsp_softc *sc = addr;
1780 	int chan, class, is1745;
1781 
1782 	DPRINTF(("sbdsp_mixer_query_devinfo: model=%d index=%d\n",
1783 		 sc->sc_mixer_model, dip->index));
1784 
1785 	if (dip->index < 0)
1786 		return ENXIO;
1787 
1788 	if (sc->sc_mixer_model == SBM_NONE)
1789 		return ENXIO;
1790 
1791 	chan = sc->sc_mixer_model == SBM_CT1335 ? 1 : 2;
1792 	is1745 = ISSBM1745(sc);
1793 	class = is1745 ? SB_INPUT_CLASS : SB_OUTPUT_CLASS;
1794 
1795 	switch (dip->index) {
1796 	case SB_MASTER_VOL:
1797 		dip->type = AUDIO_MIXER_VALUE;
1798 		dip->mixer_class = SB_OUTPUT_CLASS;
1799 		dip->prev = dip->next = AUDIO_MIXER_LAST;
1800 		strlcpy(dip->label.name, AudioNmaster, sizeof dip->label.name);
1801 		dip->un.v.num_channels = chan;
1802 		strlcpy(dip->un.v.units.name, AudioNvolume, sizeof dip->un.v.units.name);
1803 		return 0;
1804 	case SB_MIDI_VOL:
1805 		dip->type = AUDIO_MIXER_VALUE;
1806 		dip->mixer_class = class;
1807 		dip->prev = AUDIO_MIXER_LAST;
1808 		dip->next = is1745 ? SB_MIDI_IN_MUTE : AUDIO_MIXER_LAST;
1809 		strlcpy(dip->label.name, AudioNfmsynth, sizeof dip->label.name);
1810 		dip->un.v.num_channels = chan;
1811 		strlcpy(dip->un.v.units.name, AudioNvolume, sizeof dip->un.v.units.name);
1812 		return 0;
1813 	case SB_CD_VOL:
1814 		dip->type = AUDIO_MIXER_VALUE;
1815 		dip->mixer_class = class;
1816 		dip->prev = AUDIO_MIXER_LAST;
1817 		dip->next = is1745 ? SB_CD_IN_MUTE : AUDIO_MIXER_LAST;
1818 		strlcpy(dip->label.name, AudioNcd, sizeof dip->label.name);
1819 		dip->un.v.num_channels = chan;
1820 		strlcpy(dip->un.v.units.name, AudioNvolume, sizeof dip->un.v.units.name);
1821 		return 0;
1822 	case SB_VOICE_VOL:
1823 		dip->type = AUDIO_MIXER_VALUE;
1824 		dip->mixer_class = class;
1825 		dip->prev = AUDIO_MIXER_LAST;
1826 		dip->next = AUDIO_MIXER_LAST;
1827 		strlcpy(dip->label.name, AudioNdac, sizeof dip->label.name);
1828 		dip->un.v.num_channels = chan;
1829 		strlcpy(dip->un.v.units.name, AudioNvolume, sizeof dip->un.v.units.name);
1830 		return 0;
1831 	case SB_OUTPUT_CLASS:
1832 		dip->type = AUDIO_MIXER_CLASS;
1833 		dip->mixer_class = SB_OUTPUT_CLASS;
1834 		dip->next = dip->prev = AUDIO_MIXER_LAST;
1835 		strlcpy(dip->label.name, AudioCoutputs, sizeof dip->label.name);
1836 		return 0;
1837 	}
1838 
1839 	if (sc->sc_mixer_model == SBM_CT1335)
1840 		return ENXIO;
1841 
1842 	switch (dip->index) {
1843 	case SB_MIC_VOL:
1844 		dip->type = AUDIO_MIXER_VALUE;
1845 		dip->mixer_class = class;
1846 		dip->prev = AUDIO_MIXER_LAST;
1847 		dip->next = is1745 ? SB_MIC_IN_MUTE : AUDIO_MIXER_LAST;
1848 		strlcpy(dip->label.name, AudioNmicrophone,
1849 		    sizeof dip->label.name);
1850 		dip->un.v.num_channels = 1;
1851 		strlcpy(dip->un.v.units.name, AudioNvolume, sizeof dip->un.v.units.name);
1852 		return 0;
1853 
1854 	case SB_LINE_IN_VOL:
1855 		dip->type = AUDIO_MIXER_VALUE;
1856 		dip->mixer_class = class;
1857 		dip->prev = AUDIO_MIXER_LAST;
1858 		dip->next = is1745 ? SB_LINE_IN_MUTE : AUDIO_MIXER_LAST;
1859 		strlcpy(dip->label.name, AudioNline, sizeof dip->label.name);
1860 		dip->un.v.num_channels = 2;
1861 		strlcpy(dip->un.v.units.name, AudioNvolume, sizeof dip->un.v.units.name);
1862 		return 0;
1863 
1864 	case SB_RECORD_SOURCE:
1865 		dip->mixer_class = SB_RECORD_CLASS;
1866 		dip->prev = dip->next = AUDIO_MIXER_LAST;
1867 		strlcpy(dip->label.name, AudioNsource, sizeof dip->label.name);
1868 		if (ISSBM1745(sc)) {
1869 			dip->type = AUDIO_MIXER_SET;
1870 			dip->un.s.num_mem = 4;
1871 			strlcpy(dip->un.s.member[0].label.name,
1872 			    AudioNmicrophone,
1873 			    sizeof dip->un.s.member[0].label.name);
1874 			dip->un.s.member[0].mask = 1 << SB_MIC_VOL;
1875 			strlcpy(dip->un.s.member[1].label.name,
1876 			    AudioNcd, sizeof dip->un.s.member[1].label.name);
1877 			dip->un.s.member[1].mask = 1 << SB_CD_VOL;
1878 			strlcpy(dip->un.s.member[2].label.name,
1879 			    AudioNline, sizeof dip->un.s.member[2].label.name);
1880 			dip->un.s.member[2].mask = 1 << SB_LINE_IN_VOL;
1881 			strlcpy(dip->un.s.member[3].label.name,
1882 			    AudioNfmsynth,
1883 			    sizeof dip->un.s.member[3].label.name);
1884 			dip->un.s.member[3].mask = 1 << SB_MIDI_VOL;
1885 		} else {
1886 			dip->type = AUDIO_MIXER_ENUM;
1887 			dip->un.e.num_mem = 3;
1888 			strlcpy(dip->un.e.member[0].label.name,
1889 			    AudioNmicrophone,
1890 			    sizeof dip->un.e.member[0].label.name);
1891 			dip->un.e.member[0].ord = SB_MIC_VOL;
1892 			strlcpy(dip->un.e.member[1].label.name, AudioNcd,
1893 			    sizeof dip->un.e.member[1].label.name);
1894 			dip->un.e.member[1].ord = SB_CD_VOL;
1895 			strlcpy(dip->un.e.member[2].label.name, AudioNline,
1896 			    sizeof dip->un.e.member[2].label.name);
1897 			dip->un.e.member[2].ord = SB_LINE_IN_VOL;
1898 		}
1899 		return 0;
1900 
1901 	case SB_BASS:
1902 		dip->prev = dip->next = AUDIO_MIXER_LAST;
1903 		strlcpy(dip->label.name, AudioNbass, sizeof dip->label.name);
1904 		if (sc->sc_mixer_model == SBM_CT1745) {
1905 			dip->type = AUDIO_MIXER_VALUE;
1906 			dip->mixer_class = SB_EQUALIZATION_CLASS;
1907 			dip->un.v.num_channels = 2;
1908 			strlcpy(dip->un.v.units.name, AudioNbass, sizeof dip->un.v.units.name);
1909 		} else {
1910 			dip->type = AUDIO_MIXER_ENUM;
1911 			dip->mixer_class = SB_INPUT_CLASS;
1912 			dip->un.e.num_mem = 2;
1913 			strlcpy(dip->un.e.member[0].label.name, AudioNoff,
1914 			    sizeof dip->un.e.member[0].label.name);
1915 			dip->un.e.member[0].ord = 0;
1916 			strlcpy(dip->un.e.member[1].label.name, AudioNon,
1917 			    sizeof dip->un.e.member[1].label.name);
1918 			dip->un.e.member[1].ord = 1;
1919 		}
1920 		return 0;
1921 
1922 	case SB_TREBLE:
1923 		dip->prev = dip->next = AUDIO_MIXER_LAST;
1924 		strlcpy(dip->label.name, AudioNtreble, sizeof dip->label.name);
1925 		if (sc->sc_mixer_model == SBM_CT1745) {
1926 			dip->type = AUDIO_MIXER_VALUE;
1927 			dip->mixer_class = SB_EQUALIZATION_CLASS;
1928 			dip->un.v.num_channels = 2;
1929 			strlcpy(dip->un.v.units.name, AudioNtreble, sizeof dip->un.v.units.name);
1930 		} else {
1931 			dip->type = AUDIO_MIXER_ENUM;
1932 			dip->mixer_class = SB_INPUT_CLASS;
1933 			dip->un.e.num_mem = 2;
1934 			strlcpy(dip->un.e.member[0].label.name, AudioNoff,
1935 			    sizeof dip->un.e.member[0].label.name);
1936 			dip->un.e.member[0].ord = 0;
1937 			strlcpy(dip->un.e.member[1].label.name, AudioNon,
1938 			    sizeof dip->un.e.member[1].label.name);
1939 			dip->un.e.member[1].ord = 1;
1940 		}
1941 		return 0;
1942 
1943 	case SB_RECORD_CLASS:			/* record source class */
1944 		dip->type = AUDIO_MIXER_CLASS;
1945 		dip->mixer_class = SB_RECORD_CLASS;
1946 		dip->next = dip->prev = AUDIO_MIXER_LAST;
1947 		strlcpy(dip->label.name, AudioCrecord, sizeof dip->label.name);
1948 		return 0;
1949 
1950 	case SB_INPUT_CLASS:
1951 		dip->type = AUDIO_MIXER_CLASS;
1952 		dip->mixer_class = SB_INPUT_CLASS;
1953 		dip->next = dip->prev = AUDIO_MIXER_LAST;
1954 		strlcpy(dip->label.name, AudioCinputs, sizeof dip->label.name);
1955 		return 0;
1956 
1957 	}
1958 
1959 	if (sc->sc_mixer_model == SBM_CT1345)
1960 		return ENXIO;
1961 
1962 	switch(dip->index) {
1963 	case SB_PCSPEAKER:
1964 		dip->type = AUDIO_MIXER_VALUE;
1965 		dip->mixer_class = SB_INPUT_CLASS;
1966 		dip->prev = dip->next = AUDIO_MIXER_LAST;
1967 		strlcpy(dip->label.name, "pc_speaker", sizeof dip->label.name);
1968 		dip->un.v.num_channels = 1;
1969 		strlcpy(dip->un.v.units.name, AudioNvolume, sizeof dip->un.v.units.name);
1970 		return 0;
1971 
1972 	case SB_INPUT_GAIN:
1973 		dip->type = AUDIO_MIXER_VALUE;
1974 		dip->mixer_class = SB_INPUT_CLASS;
1975 		dip->prev = dip->next = AUDIO_MIXER_LAST;
1976 		strlcpy(dip->label.name, AudioNinput, sizeof dip->label.name);
1977 		dip->un.v.num_channels = 2;
1978 		strlcpy(dip->un.v.units.name, AudioNvolume, sizeof dip->un.v.units.name);
1979 		return 0;
1980 
1981 	case SB_OUTPUT_GAIN:
1982 		dip->type = AUDIO_MIXER_VALUE;
1983 		dip->mixer_class = SB_OUTPUT_CLASS;
1984 		dip->prev = dip->next = AUDIO_MIXER_LAST;
1985 		strlcpy(dip->label.name, AudioNoutput, sizeof dip->label.name);
1986 		dip->un.v.num_channels = 2;
1987 		strlcpy(dip->un.v.units.name, AudioNvolume, sizeof dip->un.v.units.name);
1988 		return 0;
1989 
1990 	case SB_AGC:
1991 		dip->type = AUDIO_MIXER_ENUM;
1992 		dip->mixer_class = SB_INPUT_CLASS;
1993 		dip->prev = dip->next = AUDIO_MIXER_LAST;
1994 		strlcpy(dip->label.name, "agc", sizeof dip->label.name);
1995 		dip->un.e.num_mem = 2;
1996 		strlcpy(dip->un.e.member[0].label.name, AudioNoff,
1997 		    sizeof dip->un.e.member[0].label.name);
1998 		dip->un.e.member[0].ord = 0;
1999 		strlcpy(dip->un.e.member[1].label.name, AudioNon,
2000 		    sizeof dip->un.e.member[1].label.name);
2001 		dip->un.e.member[1].ord = 1;
2002 		return 0;
2003 
2004 	case SB_EQUALIZATION_CLASS:
2005 		dip->type = AUDIO_MIXER_CLASS;
2006 		dip->mixer_class = SB_EQUALIZATION_CLASS;
2007 		dip->next = dip->prev = AUDIO_MIXER_LAST;
2008 		strlcpy(dip->label.name, AudioCequalization, sizeof dip->label.name);
2009 		return 0;
2010 
2011 	case SB_CD_IN_MUTE:
2012 		dip->prev = SB_CD_VOL;
2013 		dip->next = SB_CD_SWAP;
2014 		dip->mixer_class = SB_INPUT_CLASS;
2015 		goto mute;
2016 
2017 	case SB_MIC_IN_MUTE:
2018 		dip->prev = SB_MIC_VOL;
2019 		dip->next = SB_MIC_SWAP;
2020 		dip->mixer_class = SB_INPUT_CLASS;
2021 		goto mute;
2022 
2023 	case SB_LINE_IN_MUTE:
2024 		dip->prev = SB_LINE_IN_VOL;
2025 		dip->next = SB_LINE_SWAP;
2026 		dip->mixer_class = SB_INPUT_CLASS;
2027 		goto mute;
2028 
2029 	case SB_MIDI_IN_MUTE:
2030 		dip->prev = SB_MIDI_VOL;
2031 		dip->next = SB_MIDI_SWAP;
2032 		dip->mixer_class = SB_INPUT_CLASS;
2033 		goto mute;
2034 
2035 	case SB_CD_SWAP:
2036 		dip->prev = SB_CD_IN_MUTE;
2037 		dip->next = SB_CD_OUT_MUTE;
2038 		goto swap;
2039 
2040 	case SB_MIC_SWAP:
2041 		dip->prev = SB_MIC_IN_MUTE;
2042 		dip->next = SB_MIC_OUT_MUTE;
2043 		goto swap;
2044 
2045 	case SB_LINE_SWAP:
2046 		dip->prev = SB_LINE_IN_MUTE;
2047 		dip->next = SB_LINE_OUT_MUTE;
2048 		goto swap;
2049 
2050 	case SB_MIDI_SWAP:
2051 		dip->prev = SB_MIDI_IN_MUTE;
2052 		dip->next = AUDIO_MIXER_LAST;
2053 	swap:
2054 		dip->mixer_class = SB_INPUT_CLASS;
2055 		strlcpy(dip->label.name, AudioNswap, sizeof dip->label.name);
2056 		goto mute1;
2057 
2058 	case SB_CD_OUT_MUTE:
2059 		dip->prev = SB_CD_SWAP;
2060 		dip->next = AUDIO_MIXER_LAST;
2061 		dip->mixer_class = SB_OUTPUT_CLASS;
2062 		goto mute;
2063 
2064 	case SB_MIC_OUT_MUTE:
2065 		dip->prev = SB_MIC_SWAP;
2066 		dip->next = AUDIO_MIXER_LAST;
2067 		dip->mixer_class = SB_OUTPUT_CLASS;
2068 		goto mute;
2069 
2070 	case SB_LINE_OUT_MUTE:
2071 		dip->prev = SB_LINE_SWAP;
2072 		dip->next = AUDIO_MIXER_LAST;
2073 		dip->mixer_class = SB_OUTPUT_CLASS;
2074 	mute:
2075 		strlcpy(dip->label.name, AudioNmute, sizeof dip->label.name);
2076 	mute1:
2077 		dip->type = AUDIO_MIXER_ENUM;
2078 		dip->un.e.num_mem = 2;
2079 		strlcpy(dip->un.e.member[0].label.name, AudioNoff,
2080 		    sizeof dip->un.e.member[0].label.name);
2081 		dip->un.e.member[0].ord = 0;
2082 		strlcpy(dip->un.e.member[1].label.name, AudioNon,
2083 		    sizeof dip->un.e.member[1].label.name);
2084 		dip->un.e.member[1].ord = 1;
2085 		return 0;
2086 
2087 	}
2088 
2089 	return ENXIO;
2090 }
2091 
2092 void *
sb_malloc(void * addr,int direction,size_t size,int pool,int flags)2093 sb_malloc(void *addr, int direction, size_t size, int pool, int flags)
2094 {
2095 	struct sbdsp_softc *sc = addr;
2096 	int drq;
2097 
2098 	/* 8-bit has more restrictive alignment */
2099 	if (sc->sc_drq8 != -1)
2100 		drq = sc->sc_drq8;
2101 	else
2102 		drq = sc->sc_drq16;
2103 
2104 	return isa_malloc(sc->sc_isa, drq, size, pool, flags);
2105 }
2106 
2107 void
sb_free(void * addr,void * ptr,int pool)2108 sb_free(void *addr, void *ptr, int pool)
2109 {
2110 	isa_free(ptr, pool);
2111 }
2112 
2113 size_t
sb_round(void * addr,int direction,size_t size)2114 sb_round(void *addr, int direction, size_t size)
2115 {
2116 	if (size > MAX_ISADMA)
2117 		size = MAX_ISADMA;
2118 	return size;
2119 }
2120 
2121 #if NMIDI > 0
2122 /*
2123  * MIDI related routines.
2124  */
2125 
2126 int
sbdsp_midi_open(void * addr,int flags,void (* iintr)(void *,int),void (* ointr)(void *),void * arg)2127 sbdsp_midi_open(void *addr, int flags, void (*iintr)(void *, int),
2128     void (*ointr)(void *), void *arg)
2129 {
2130 	struct sbdsp_softc *sc = addr;
2131 
2132         DPRINTF(("sbdsp_midi_open: sc=%p\n", sc));
2133 
2134 	if (sc->sc_open != SB_CLOSED)
2135 		return EBUSY;
2136 	if (sbdsp_reset(sc) != 0)
2137 		return EIO;
2138 
2139 	if (sc->sc_model >= SB_20)
2140 		if (sbdsp_wdsp(sc, SB_MIDI_UART_INTR)) /* enter UART mode */
2141 			return EIO;
2142 	sc->sc_open = SB_OPEN_MIDI;
2143 	sc->sc_openflags = flags;
2144 	sc->sc_intr8 = sbdsp_midi_intr;
2145 	sc->sc_arg8 = addr;
2146 	sc->sc_intrm = iintr;
2147 	sc->sc_argm = arg;
2148 	return 0;
2149 }
2150 
2151 void
sbdsp_midi_close(void * addr)2152 sbdsp_midi_close(void *addr)
2153 {
2154 	struct sbdsp_softc *sc = addr;
2155 
2156         DPRINTF(("sbdsp_midi_close: sc=%p\n", sc));
2157 
2158 	if (sc->sc_model >= SB_20)
2159 		sbdsp_reset(sc); /* exit UART mode */
2160 	sc->sc_open = SB_CLOSED;
2161 	sc->sc_intrm = 0;
2162 }
2163 
2164 int
sbdsp_midi_output(void * addr,int d)2165 sbdsp_midi_output(void *addr, int d)
2166 {
2167 	struct sbdsp_softc *sc = addr;
2168 
2169 	if (sc->sc_model < SB_20 && sbdsp_wdsp(sc, SB_MIDI_WRITE))
2170 		return 1;
2171 	(void)sbdsp_wdsp(sc, d);
2172 	return 1;
2173 }
2174 
2175 void
sbdsp_midi_getinfo(void * addr,struct midi_info * mi)2176 sbdsp_midi_getinfo(void *addr, struct midi_info *mi)
2177 {
2178 	struct sbdsp_softc *sc = addr;
2179 
2180 	mi->name = sc->sc_model < SB_20 ? "SB MIDI cmd" : "SB MIDI UART";
2181 	mi->props = MIDI_PROP_CAN_INPUT;
2182 }
2183 
2184 int
sbdsp_midi_intr(void * addr)2185 sbdsp_midi_intr(void *addr)
2186 {
2187 	struct sbdsp_softc *sc = addr;
2188 
2189 	sc->sc_intrm(sc->sc_argm, sbdsp_rdsp(sc));
2190 	return (0);
2191 }
2192 
2193 #endif
2194