xref: /openbsd-src/sys/dev/isa/gus.c (revision 0b7734b3d77bb9b21afec6f4621cae6c805dbd45)
1 /*	$OpenBSD: gus.c,v 1.43 2015/06/25 20:05:11 ratchov Exp $	*/
2 /*	$NetBSD: gus.c,v 1.51 1998/01/25 23:48:06 mycroft Exp $	*/
3 
4 /*-
5  * Copyright (c) 1996 The NetBSD Foundation, Inc.
6  * All rights reserved.
7  *
8  * This code is derived from software contributed to The NetBSD Foundation
9  * by Ken Hornstein and John Kohl.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 /*
34  *
35  * TODO:
36  *	. figure out why mixer activity while sound is playing causes problems
37  *	  (phantom interrupts?)
38  *	. figure out a better deinterleave strategy that avoids sucking up
39  *	  CPU, memory and cache bandwidth.  (Maybe a special encoding?
40  *	  Maybe use the double-speed sampling/hardware deinterleave trick
41  *	  from the GUS SDK?)  A 486/33 isn't quite fast enough to keep
42  *	  up with 44.1kHz 16-bit stereo output without some drop-outs.
43  *	. use CS4231 for 16-bit sampling, for a-law and mu-law playback.
44  *	. actually test full-duplex sampling(recording) and playback.
45  */
46 
47 /*
48  * Gravis UltraSound driver
49  *
50  * For more detailed information, see the GUS developers' kit
51  * available on the net at:
52  *
53  * http://www.gravis.com/Public/sdk/GUSDK222.ZIP
54  *
55  *		See ultrawrd.doc inside--it's MS Word (ick), but it's the bible
56  *
57  */
58 
59 /*
60  * The GUS Max has a slightly strange set of connections between the CS4231
61  * and the GF1 and the DMA interconnects.  It's set up so that the CS4231 can
62  * be playing while the GF1 is loading patches from the system.
63  *
64  * Here's a recreation of the DMA interconnect diagram:
65  *
66  *       GF1
67  *   +---------+				 digital
68  *   |         |  record			 ASIC
69  *   |         |--------------+
70  *   |         |              |		       +--------+
71  *   |         | play (dram)  |      +----+    |	|
72  *   |         |--------------(------|-\  |    |   +-+  |
73  *   +---------+              |      |  >-|----|---|C|--|------  dma chan 1
74  *                            |  +---|-/  |    |   +-+	|
75  *                            |  |   +----+    |    |   |
76  *                            |	 |   +----+    |    |   |
77  *   +---------+        +-+   +--(---|-\  |    |    |   |
78  *   |         | play   |8|      |   |  >-|----|----+---|------  dma chan 2
79  *   | ---C----|--------|/|------(---|-/  |    |        |
80  *   |    ^    |record  |1|      |   +----+    |	|
81  *   |    |    |   /----|6|------+	       +--------+
82  *   | ---+----|--/     +-+
83  *   +---------+
84  *     CS4231	8-to-16 bit bus conversion, if needed
85  *
86  *
87  * "C" is an optional combiner.
88  *
89  */
90 
91 #include <sys/param.h>
92 #include <sys/systm.h>
93 #include <sys/errno.h>
94 #include <sys/ioctl.h>
95 #include <sys/syslog.h>
96 #include <sys/device.h>
97 #include <sys/buf.h>
98 #include <sys/fcntl.h>
99 #include <sys/malloc.h>
100 #include <sys/kernel.h>
101 #include <sys/timeout.h>
102 
103 #include <machine/cpu.h>
104 #include <machine/intr.h>
105 #include <machine/bus.h>
106 #include <machine/cpufunc.h>
107 #include <sys/audioio.h>
108 #include <dev/audio_if.h>
109 
110 #include <dev/isa/isavar.h>
111 #include <dev/isa/isadmavar.h>
112 
113 #include <dev/ic/ics2101reg.h>
114 #include <dev/ic/cs4231reg.h>
115 #include <dev/ic/ad1848reg.h>
116 #include <dev/isa/ics2101var.h>
117 #include <dev/isa/ad1848var.h>
118 #include <dev/isa/cs4231var.h>
119 #include "gusreg.h"
120 #include "gusvar.h"
121 
122 #ifdef AUDIO_DEBUG
123 #define GUSPLAYDEBUG	/*XXX*/
124 #define DPRINTF(x)	if (gusdebug) printf x
125 #define DMAPRINTF(x)	if (gusdmadebug) printf x
126 int	gusdebug = 0;
127 int	gusdmadebug = 0;
128 #else
129 #define DPRINTF(x)
130 #define DMAPRINTF(x)
131 #endif
132 int	gus_dostereo = 1;
133 
134 #define NDMARECS 2048
135 #ifdef GUSPLAYDEBUG
136 int	gusstats = 0;
137 
138 struct dma_record dmarecords[NDMARECS];
139 
140 int dmarecord_index = 0;
141 #endif
142 
143 struct cfdriver gus_cd = {
144 	NULL, "gus", DV_DULL
145 };
146 
147 /*
148  * A mapping from IRQ/DRQ values to the values used in the GUS's internal
149  * registers.  A zero means that the referenced IRQ/DRQ is invalid
150  */
151 const int gus_irq_map[] = {
152 	IRQUNK, IRQUNK, 1, 3, IRQUNK, 2, IRQUNK, 4, IRQUNK, 1, IRQUNK, 5, 6,
153 	IRQUNK, IRQUNK, 7
154 };
155 const int gus_drq_map[] = {
156 	DRQUNK, 1, DRQUNK, 2, DRQUNK, 3, 4, 5
157 };
158 
159 /*
160  * A list of valid base addresses for the GUS
161  */
162 
163 const int gus_base_addrs[] = {
164 	0x210, 0x220, 0x230, 0x240, 0x250, 0x260
165 };
166 const int gus_addrs = sizeof(gus_base_addrs) / sizeof(gus_base_addrs[0]);
167 
168 /*
169  * Maximum frequency values of the GUS based on the number of currently active
170  * voices.  Since the GUS samples a voice every 1.6 us, the maximum frequency
171  * is dependent on the number of active voices.  Yes, it is pretty weird.
172  */
173 
174 static const int gus_max_frequency[] = {
175 		44100,		/* 14 voices */
176 		41160,		/* 15 voices */
177 		38587,		/* 16 voices */
178 		36317,		/* 17 voices */
179 		34300,		/* 18 voices */
180 		32494,		/* 19 voices */
181 		30870,		/* 20 voices */
182 		29400,		/* 21 voices */
183 		28063,		/* 22 voices */
184 		26843,		/* 23 voices */
185 		25725,		/* 24 voices */
186 		24696,		/* 25 voices */
187 		23746,		/* 26 voices */
188 		22866,		/* 27 voices */
189 		22050,		/* 28 voices */
190 		21289,		/* 29 voices */
191 		20580,		/* 30 voices */
192 		19916,		/* 31 voices */
193 		19293		/* 32 voices */
194 };
195 /*
196  * A mapping of linear volume levels to the logarithmic volume values used
197  * by the GF1 chip on the GUS.  From GUS SDK vol1.c.
198  */
199 
200 static const unsigned short gus_log_volumes[512] = {
201  0x0000,
202  0x0700, 0x07ff, 0x0880, 0x08ff, 0x0940, 0x0980, 0x09c0, 0x09ff, 0x0a20,
203  0x0a40, 0x0a60, 0x0a80, 0x0aa0, 0x0ac0, 0x0ae0, 0x0aff, 0x0b10, 0x0b20,
204  0x0b30, 0x0b40, 0x0b50, 0x0b60, 0x0b70, 0x0b80, 0x0b90, 0x0ba0, 0x0bb0,
205  0x0bc0, 0x0bd0, 0x0be0, 0x0bf0, 0x0bff, 0x0c08, 0x0c10, 0x0c18, 0x0c20,
206  0x0c28, 0x0c30, 0x0c38, 0x0c40, 0x0c48, 0x0c50, 0x0c58, 0x0c60, 0x0c68,
207  0x0c70, 0x0c78, 0x0c80, 0x0c88, 0x0c90, 0x0c98, 0x0ca0, 0x0ca8, 0x0cb0,
208  0x0cb8, 0x0cc0, 0x0cc8, 0x0cd0, 0x0cd8, 0x0ce0, 0x0ce8, 0x0cf0, 0x0cf8,
209  0x0cff, 0x0d04, 0x0d08, 0x0d0c, 0x0d10, 0x0d14, 0x0d18, 0x0d1c, 0x0d20,
210  0x0d24, 0x0d28, 0x0d2c, 0x0d30, 0x0d34, 0x0d38, 0x0d3c, 0x0d40, 0x0d44,
211  0x0d48, 0x0d4c, 0x0d50, 0x0d54, 0x0d58, 0x0d5c, 0x0d60, 0x0d64, 0x0d68,
212  0x0d6c, 0x0d70, 0x0d74, 0x0d78, 0x0d7c, 0x0d80, 0x0d84, 0x0d88, 0x0d8c,
213  0x0d90, 0x0d94, 0x0d98, 0x0d9c, 0x0da0, 0x0da4, 0x0da8, 0x0dac, 0x0db0,
214  0x0db4, 0x0db8, 0x0dbc, 0x0dc0, 0x0dc4, 0x0dc8, 0x0dcc, 0x0dd0, 0x0dd4,
215  0x0dd8, 0x0ddc, 0x0de0, 0x0de4, 0x0de8, 0x0dec, 0x0df0, 0x0df4, 0x0df8,
216  0x0dfc, 0x0dff, 0x0e02, 0x0e04, 0x0e06, 0x0e08, 0x0e0a, 0x0e0c, 0x0e0e,
217  0x0e10, 0x0e12, 0x0e14, 0x0e16, 0x0e18, 0x0e1a, 0x0e1c, 0x0e1e, 0x0e20,
218  0x0e22, 0x0e24, 0x0e26, 0x0e28, 0x0e2a, 0x0e2c, 0x0e2e, 0x0e30, 0x0e32,
219  0x0e34, 0x0e36, 0x0e38, 0x0e3a, 0x0e3c, 0x0e3e, 0x0e40, 0x0e42, 0x0e44,
220  0x0e46, 0x0e48, 0x0e4a, 0x0e4c, 0x0e4e, 0x0e50, 0x0e52, 0x0e54, 0x0e56,
221  0x0e58, 0x0e5a, 0x0e5c, 0x0e5e, 0x0e60, 0x0e62, 0x0e64, 0x0e66, 0x0e68,
222  0x0e6a, 0x0e6c, 0x0e6e, 0x0e70, 0x0e72, 0x0e74, 0x0e76, 0x0e78, 0x0e7a,
223  0x0e7c, 0x0e7e, 0x0e80, 0x0e82, 0x0e84, 0x0e86, 0x0e88, 0x0e8a, 0x0e8c,
224  0x0e8e, 0x0e90, 0x0e92, 0x0e94, 0x0e96, 0x0e98, 0x0e9a, 0x0e9c, 0x0e9e,
225  0x0ea0, 0x0ea2, 0x0ea4, 0x0ea6, 0x0ea8, 0x0eaa, 0x0eac, 0x0eae, 0x0eb0,
226  0x0eb2, 0x0eb4, 0x0eb6, 0x0eb8, 0x0eba, 0x0ebc, 0x0ebe, 0x0ec0, 0x0ec2,
227  0x0ec4, 0x0ec6, 0x0ec8, 0x0eca, 0x0ecc, 0x0ece, 0x0ed0, 0x0ed2, 0x0ed4,
228  0x0ed6, 0x0ed8, 0x0eda, 0x0edc, 0x0ede, 0x0ee0, 0x0ee2, 0x0ee4, 0x0ee6,
229  0x0ee8, 0x0eea, 0x0eec, 0x0eee, 0x0ef0, 0x0ef2, 0x0ef4, 0x0ef6, 0x0ef8,
230  0x0efa, 0x0efc, 0x0efe, 0x0eff, 0x0f01, 0x0f02, 0x0f03, 0x0f04, 0x0f05,
231  0x0f06, 0x0f07, 0x0f08, 0x0f09, 0x0f0a, 0x0f0b, 0x0f0c, 0x0f0d, 0x0f0e,
232  0x0f0f, 0x0f10, 0x0f11, 0x0f12, 0x0f13, 0x0f14, 0x0f15, 0x0f16, 0x0f17,
233  0x0f18, 0x0f19, 0x0f1a, 0x0f1b, 0x0f1c, 0x0f1d, 0x0f1e, 0x0f1f, 0x0f20,
234  0x0f21, 0x0f22, 0x0f23, 0x0f24, 0x0f25, 0x0f26, 0x0f27, 0x0f28, 0x0f29,
235  0x0f2a, 0x0f2b, 0x0f2c, 0x0f2d, 0x0f2e, 0x0f2f, 0x0f30, 0x0f31, 0x0f32,
236  0x0f33, 0x0f34, 0x0f35, 0x0f36, 0x0f37, 0x0f38, 0x0f39, 0x0f3a, 0x0f3b,
237  0x0f3c, 0x0f3d, 0x0f3e, 0x0f3f, 0x0f40, 0x0f41, 0x0f42, 0x0f43, 0x0f44,
238  0x0f45, 0x0f46, 0x0f47, 0x0f48, 0x0f49, 0x0f4a, 0x0f4b, 0x0f4c, 0x0f4d,
239  0x0f4e, 0x0f4f, 0x0f50, 0x0f51, 0x0f52, 0x0f53, 0x0f54, 0x0f55, 0x0f56,
240  0x0f57, 0x0f58, 0x0f59, 0x0f5a, 0x0f5b, 0x0f5c, 0x0f5d, 0x0f5e, 0x0f5f,
241  0x0f60, 0x0f61, 0x0f62, 0x0f63, 0x0f64, 0x0f65, 0x0f66, 0x0f67, 0x0f68,
242  0x0f69, 0x0f6a, 0x0f6b, 0x0f6c, 0x0f6d, 0x0f6e, 0x0f6f, 0x0f70, 0x0f71,
243  0x0f72, 0x0f73, 0x0f74, 0x0f75, 0x0f76, 0x0f77, 0x0f78, 0x0f79, 0x0f7a,
244  0x0f7b, 0x0f7c, 0x0f7d, 0x0f7e, 0x0f7f, 0x0f80, 0x0f81, 0x0f82, 0x0f83,
245  0x0f84, 0x0f85, 0x0f86, 0x0f87, 0x0f88, 0x0f89, 0x0f8a, 0x0f8b, 0x0f8c,
246  0x0f8d, 0x0f8e, 0x0f8f, 0x0f90, 0x0f91, 0x0f92, 0x0f93, 0x0f94, 0x0f95,
247  0x0f96, 0x0f97, 0x0f98, 0x0f99, 0x0f9a, 0x0f9b, 0x0f9c, 0x0f9d, 0x0f9e,
248  0x0f9f, 0x0fa0, 0x0fa1, 0x0fa2, 0x0fa3, 0x0fa4, 0x0fa5, 0x0fa6, 0x0fa7,
249  0x0fa8, 0x0fa9, 0x0faa, 0x0fab, 0x0fac, 0x0fad, 0x0fae, 0x0faf, 0x0fb0,
250  0x0fb1, 0x0fb2, 0x0fb3, 0x0fb4, 0x0fb5, 0x0fb6, 0x0fb7, 0x0fb8, 0x0fb9,
251  0x0fba, 0x0fbb, 0x0fbc, 0x0fbd, 0x0fbe, 0x0fbf, 0x0fc0, 0x0fc1, 0x0fc2,
252  0x0fc3, 0x0fc4, 0x0fc5, 0x0fc6, 0x0fc7, 0x0fc8, 0x0fc9, 0x0fca, 0x0fcb,
253  0x0fcc, 0x0fcd, 0x0fce, 0x0fcf, 0x0fd0, 0x0fd1, 0x0fd2, 0x0fd3, 0x0fd4,
254  0x0fd5, 0x0fd6, 0x0fd7, 0x0fd8, 0x0fd9, 0x0fda, 0x0fdb, 0x0fdc, 0x0fdd,
255  0x0fde, 0x0fdf, 0x0fe0, 0x0fe1, 0x0fe2, 0x0fe3, 0x0fe4, 0x0fe5, 0x0fe6,
256  0x0fe7, 0x0fe8, 0x0fe9, 0x0fea, 0x0feb, 0x0fec, 0x0fed, 0x0fee, 0x0fef,
257  0x0ff0, 0x0ff1, 0x0ff2, 0x0ff3, 0x0ff4, 0x0ff5, 0x0ff6, 0x0ff7, 0x0ff8,
258  0x0ff9, 0x0ffa, 0x0ffb, 0x0ffc, 0x0ffd, 0x0ffe, 0x0fff};
259 
260 /*
261  * Interface to higher level audio driver
262  */
263 struct audio_hw_if gus_hw_if = {
264 	gusopen,
265 	gusclose,
266 	NULL,				/* drain */
267 
268 	gus_query_encoding,
269 
270 	gus_set_params,
271 
272 	gus_round_blocksize,
273 
274 	gus_commit_settings,
275 
276 	NULL,
277 	NULL,
278 
279 	gus_dma_output,
280 	gus_dma_input,
281 	gus_halt_out_dma,
282 	gus_halt_in_dma,
283 	gus_speaker_ctl,
284 
285 	gus_getdev,
286 	NULL,
287 	gus_mixer_set_port,
288 	gus_mixer_get_port,
289 	gus_mixer_query_devinfo,
290 	gus_malloc,
291 	gus_free,
292 	gus_round,
293 	gus_mappage,
294 	gus_get_props,
295 
296 	NULL,
297 	NULL,
298 	NULL
299 };
300 
301 static struct audio_hw_if gusmax_hw_if = {
302 	gusmaxopen,
303 	gusmax_close,
304 	NULL,				/* drain */
305 
306 	gus_query_encoding, /* query encoding */
307 
308 	gusmax_set_params,
309 
310 	gusmax_round_blocksize,
311 
312 	gusmax_commit_settings,
313 
314 	NULL,
315 	NULL,
316 
317 	gusmax_dma_output,
318 	gusmax_dma_input,
319 	gusmax_halt_out_dma,
320 	gusmax_halt_in_dma,
321 
322 	gusmax_speaker_ctl,
323 
324 	gus_getdev,
325 	NULL,
326 	gusmax_mixer_set_port,
327 	gusmax_mixer_get_port,
328 	gusmax_mixer_query_devinfo,
329 	ad1848_malloc,
330 	ad1848_free,
331 	ad1848_round,
332 	ad1848_mappage,
333 	gusmax_get_props,
334 
335 	NULL,
336 	NULL,
337 	NULL
338 };
339 
340 /*
341  * Some info about the current audio device
342  */
343 struct audio_device gus_device = {
344 	"UltraSound",
345 	"",
346 	"gus",
347 };
348 
349 
350 int
351 gusopen(void *addr, int flags)
352 {
353 	struct gus_softc *sc = addr;
354 
355 	DPRINTF(("gusopen() called\n"));
356 
357 	if (sc->sc_flags & GUS_OPEN)
358 		return EBUSY;
359 
360 	/*
361 	 * Some initialization
362 	 */
363 
364 	sc->sc_flags |= GUS_OPEN;
365 	sc->sc_dmabuf = 0;
366 	sc->sc_playbuf = -1;
367 	sc->sc_bufcnt = 0;
368 	sc->sc_voc[GUS_VOICE_LEFT].start_addr = GUS_MEM_OFFSET - 1;
369 	sc->sc_voc[GUS_VOICE_LEFT].current_addr = GUS_MEM_OFFSET;
370 
371 	if (HAS_CODEC(sc)) {
372 		ad1848_open(&sc->sc_codec, flags);
373 		sc->sc_codec.mute[AD1848_AUX1_CHANNEL] = 0;
374 		ad1848_mute_channel(&sc->sc_codec, AD1848_AUX1_CHANNEL, 0); /* turn on DAC output */
375 		if (flags & FREAD) {
376 			sc->sc_codec.mute[AD1848_MONO_CHANNEL] = 0;
377 			ad1848_mute_channel(&sc->sc_codec, AD1848_MONO_CHANNEL, 0);
378 		}
379 	} else if (flags & FREAD) {
380 		/* enable/unmute the microphone */
381 		if (HAS_MIXER(sc)) {
382 			gusics_mic_mute(&sc->sc_mixer, 0);
383 		} else
384 			gus_mic_ctl(sc, SPKR_ON);
385 	}
386 	if (sc->sc_nbufs == 0)
387 	    gus_round_blocksize(sc, GUS_BUFFER_MULTIPLE); /* default blksiz */
388 	return 0;
389 }
390 
391 int
392 gusmaxopen(void *addr, int flags)
393 {
394 	struct ad1848_softc *ac = addr;
395 	return gusopen(ac->parent, flags);
396 }
397 
398 void
399 gus_deinterleave(struct gus_softc *sc, void *buf, int size)
400 {
401 	/* deinterleave the stereo data.  We can use sc->sc_deintr_buf
402 	   for scratch space. */
403 	int i;
404 
405 	if (size > sc->sc_blocksize) {
406 		printf("gus: deinterleave %d > %d\n", size, sc->sc_blocksize);
407 		return;
408 	} else if (size < sc->sc_blocksize) {
409 		DPRINTF(("gus: deinterleave %d < %d\n", size, sc->sc_blocksize));
410 	}
411 
412 	/*
413 	 * size is in bytes.
414 	 */
415 	if (sc->sc_precision == 16) {
416 		u_short *dei = sc->sc_deintr_buf;
417 		u_short *sbuf = buf;
418 		size >>= 1;		/* bytecnt to shortcnt */
419 		/* copy 2nd of each pair of samples to the staging area, while
420 		   compacting the 1st of each pair into the original area. */
421 		for (i = 0; i < size/2-1; i++)  {
422 			dei[i] = sbuf[i*2+1];
423 			sbuf[i+1] = sbuf[i*2+2];
424 		}
425 		/*
426 		 * this has copied one less sample than half of the
427 		 * buffer.  The first sample of the 1st stream was
428 		 * already in place and didn't need copying.
429 		 * Therefore, we've moved all of the 1st stream's
430 		 * samples into place.  We have one sample from 2nd
431 		 * stream in the last slot of original area, not
432 		 * copied to the staging area (But we don't need to!).
433 		 * Copy the remainder of the original stream into place.
434 		 */
435 		bcopy(dei, &sbuf[size/2], i * sizeof(short));
436 	} else {
437 		u_char *dei = sc->sc_deintr_buf;
438 		u_char *sbuf = buf;
439 		for (i = 0; i < size/2-1; i++)  {
440 			dei[i] = sbuf[i*2+1];
441 			sbuf[i+1] = sbuf[i*2+2];
442 		}
443 		bcopy(dei, &sbuf[size/2], i);
444 	}
445 }
446 
447 /*
448  * Actually output a buffer to the DSP chip
449  */
450 
451 int
452 gusmax_dma_output(void *addr, void *buf, int size, void (*intr)(void *),
453     void *arg)
454 {
455 	struct ad1848_softc *ac = addr;
456 	return gus_dma_output(ac->parent, buf, size, intr, arg);
457 }
458 
459 /*
460  * called at splaudio() from interrupt handler.
461  */
462 void
463 stereo_dmaintr(void *arg)
464 {
465     struct gus_softc *sc = arg;
466     struct stereo_dma_intr *sa = &sc->sc_stereo;
467 
468     DMAPRINTF(("stereo_dmaintr"));
469 
470     /*
471      * Put other half in its place, then call the real interrupt routine :)
472      */
473 
474     sc->sc_dmaoutintr = sa->intr;
475     sc->sc_outarg = sa->arg;
476 
477 #ifdef GUSPLAYDEBUG
478     if (gusstats) {
479       microtime(&dmarecords[dmarecord_index].tv);
480       dmarecords[dmarecord_index].gusaddr = sa->dmabuf;
481       dmarecords[dmarecord_index].bsdaddr = sa->buffer;
482       dmarecords[dmarecord_index].count = sa->size;
483       dmarecords[dmarecord_index].channel = 1;
484       dmarecords[dmarecord_index++].direction = 1;
485       dmarecord_index = dmarecord_index % NDMARECS;
486     }
487 #endif
488 
489     gusdmaout(sc, sa->flags, sa->dmabuf, (caddr_t) sa->buffer, sa->size);
490 
491     sa->flags = 0;
492     sa->dmabuf = 0;
493     sa->buffer = 0;
494     sa->size = 0;
495     sa->intr = 0;
496     sa->arg = 0;
497 }
498 
499 /*
500  * Start up DMA output to the card.
501  * Called at splaudio(), either from intr handler or from
502  * generic audio code.
503  */
504 int
505 gus_dma_output(void *addr, void *buf, int size, void (*intr)(void *), void *arg)
506 {
507 	struct gus_softc *sc = addr;
508 	u_char *buffer = buf;
509 	u_long boarddma;
510 	int flags;
511 
512 	DMAPRINTF(("gus_dma_output %d @ %p\n", size, buf));
513 	if (size != sc->sc_blocksize) {
514 	    DPRINTF(("gus_dma_output reqsize %d not sc_blocksize %d\n",
515 		     size, sc->sc_blocksize));
516 	    return EINVAL;
517 	}
518 
519 	flags = GUSMASK_DMA_WRITE;
520 	if (sc->sc_precision == 16)
521 	    flags |= GUSMASK_DMA_DATA_SIZE;
522 	if (sc->sc_encoding == AUDIO_ENCODING_ULAW ||
523 	    sc->sc_encoding == AUDIO_ENCODING_ALAW ||
524 	    sc->sc_encoding == AUDIO_ENCODING_ULINEAR_BE ||
525 	    sc->sc_encoding == AUDIO_ENCODING_ULINEAR_LE)
526 	    flags |= GUSMASK_DMA_INVBIT;
527 
528 	if (sc->sc_channels == 2) {
529 		if (sc->sc_precision == 16) {
530 			if (size & 3) {
531 				DPRINTF(("gus_dma_output: unpaired 16bit samples"));
532 				size &= 3;
533 			}
534 		} else if (size & 1) {
535 			DPRINTF(("gus_dma_output: unpaired samples"));
536 			size &= 1;
537 		}
538 		if (size == 0) {
539 			return 0;
540 		}
541 
542 		gus_deinterleave(sc, (void *)buffer, size);
543 
544 		size >>= 1;
545 
546 		boarddma = size * sc->sc_dmabuf + GUS_MEM_OFFSET;
547 
548 		sc->sc_stereo.intr = intr;
549 		sc->sc_stereo.arg = arg;
550 		sc->sc_stereo.size = size;
551 		sc->sc_stereo.dmabuf = boarddma + GUS_LEFT_RIGHT_OFFSET;
552 		sc->sc_stereo.buffer = buffer + size;
553 		sc->sc_stereo.flags = flags;
554 		if (gus_dostereo) {
555 		  intr = stereo_dmaintr;
556 		  arg = sc;
557 		}
558 	} else
559 		boarddma = size * sc->sc_dmabuf + GUS_MEM_OFFSET;
560 
561 
562 	sc->sc_flags |= GUS_LOCKED;
563 	sc->sc_dmaoutintr = intr;
564 	sc->sc_outarg = arg;
565 
566 #ifdef GUSPLAYDEBUG
567 	if (gusstats) {
568 	  microtime(&dmarecords[dmarecord_index].tv);
569 	  dmarecords[dmarecord_index].gusaddr = boarddma;
570 	  dmarecords[dmarecord_index].bsdaddr = buffer;
571 	  dmarecords[dmarecord_index].count = size;
572 	  dmarecords[dmarecord_index].channel = 0;
573 	  dmarecords[dmarecord_index++].direction = 1;
574 	  dmarecord_index = dmarecord_index % NDMARECS;
575 	}
576 #endif
577 
578 	gusdmaout(sc, flags, boarddma, (caddr_t) buffer, size);
579 	return 0;
580 }
581 
582 void
583 gusmax_close(void *addr)
584 {
585 	struct ad1848_softc *ac = addr;
586 	struct gus_softc *sc = ac->parent;
587 #if 0
588 	ac->mute[AD1848_AUX1_CHANNEL] = MUTE_ALL;
589 	ad1848_mute_channel(ac, MUTE_ALL); /* turn off DAC output */
590 #endif
591 	ad1848_close(ac);
592 	gusclose(sc);
593 }
594 
595 /*
596  * Close out device stuff.  Called at splaudio() from generic audio layer.
597  */
598 void
599 gusclose(void *addr)
600 {
601 	struct gus_softc *sc = addr;
602 
603         DPRINTF(("gus_close: sc=%p\n", sc));
604 
605 /*	if (sc->sc_flags & GUS_DMAOUT_ACTIVE) */ {
606 		gus_halt_out_dma(sc);
607 	}
608 /*	if (sc->sc_flags & GUS_DMAIN_ACTIVE) */ {
609 		gus_halt_in_dma(sc);
610 	}
611 	sc->sc_flags &= ~(GUS_OPEN|GUS_LOCKED|GUS_DMAOUT_ACTIVE|GUS_DMAIN_ACTIVE);
612 
613 	if (sc->sc_deintr_buf) {
614 		free(sc->sc_deintr_buf, M_DEVBUF, 0);
615 		sc->sc_deintr_buf = NULL;
616 	}
617 	/* turn off speaker, etc. */
618 
619 	/* make sure the voices shut up: */
620 	gus_stop_voice(sc, GUS_VOICE_LEFT, 1);
621 	gus_stop_voice(sc, GUS_VOICE_RIGHT, 0);
622 }
623 
624 /*
625  * Service interrupts.  Farm them off to helper routines if we are using the
626  * GUS for simple playback/record
627  */
628 
629 #ifdef AUDIO_DEBUG
630 int gusintrcnt;
631 int gusdmaintrcnt;
632 int gusvocintrcnt;
633 #endif
634 
635 int
636 gusintr(void *arg)
637 {
638 	struct gus_softc *sc = arg;
639 	bus_space_tag_t iot = sc->sc_iot;
640 	bus_space_handle_t ioh1 = sc->sc_ioh1;
641 	bus_space_handle_t ioh2 = sc->sc_ioh2;
642 	unsigned char intr;
643 
644 	int retval = 0;
645 
646 	DPRINTF(("gusintr\n"));
647 #ifdef AUDIO_DEBUG
648 	gusintrcnt++;
649 #endif
650 	if (HAS_CODEC(sc))
651 		retval = ad1848_intr(&sc->sc_codec);
652 	mtx_enter(&audio_lock);
653 	if ((intr = bus_space_read_1(iot, ioh1, GUS_IRQ_STATUS)) & GUSMASK_IRQ_DMATC) {
654 		DMAPRINTF(("gusintr dma flags=%x\n", sc->sc_flags));
655 #ifdef AUDIO_DEBUG
656 		gusdmaintrcnt++;
657 #endif
658 		retval += gus_dmaout_intr(sc);
659 		if (sc->sc_flags & GUS_DMAIN_ACTIVE) {
660 		    SELECT_GUS_REG(iot, ioh2, GUSREG_SAMPLE_CONTROL);
661 		    intr = bus_space_read_1(iot, ioh2, GUS_DATA_HIGH);
662 		    if (intr & GUSMASK_SAMPLE_DMATC) {
663 			retval += gus_dmain_intr(sc);
664 		    }
665 		}
666 	}
667 	if (intr & (GUSMASK_IRQ_VOICE | GUSMASK_IRQ_VOLUME)) {
668 		DMAPRINTF(("gusintr voice flags=%x\n", sc->sc_flags));
669 #ifdef AUDIO_DEBUG
670 		gusvocintrcnt++;
671 #endif
672 		retval += gus_voice_intr(sc);
673 	}
674 	if (retval) {
675 		mtx_leave(&audio_lock);
676 		return 1;
677 	}
678 	mtx_leave(&audio_lock);
679 	return retval;
680 }
681 
682 int gus_bufcnt[GUS_MEM_FOR_BUFFERS / GUS_BUFFER_MULTIPLE];
683 int gus_restart;				/* how many restarts? */
684 int gus_stops;				/* how many times did voice stop? */
685 int gus_falsestops;			/* stopped but not done? */
686 int gus_continues;
687 
688 struct playcont {
689 	struct timeval tv;
690 	u_int playbuf;
691 	u_int dmabuf;
692 	u_char bufcnt;
693 	u_char vaction;
694 	u_char voccntl;
695 	u_char volcntl;
696 	u_long curaddr;
697 	u_long endaddr;
698 } playstats[NDMARECS];
699 
700 int playcntr;
701 
702 void
703 gus_dmaout_timeout(void *arg)
704 {
705 	struct gus_softc *sc = arg;
706 	bus_space_tag_t iot = sc->sc_iot;
707 	bus_space_handle_t ioh2 = sc->sc_ioh2;
708 
709 	printf("%s: dmaout timeout\n", sc->sc_dev.dv_xname);
710 	/*
711 	 * Stop any DMA.
712 	 */
713 
714 	mtx_enter(&audio_lock);
715 	SELECT_GUS_REG(iot, ioh2, GUSREG_DMA_CONTROL);
716 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0);
717 
718 #if 0
719 	/* XXX we will dmadone below? */
720 	isa_dmaabort(sc->sc_dev.dv_parent, sc->sc_drq);
721 #endif
722 
723 	gus_dmaout_dointr(sc);
724 	mtx_leave(&audio_lock);
725 }
726 
727 
728 /*
729  * Service DMA interrupts.  This routine will only get called if we're doing
730  * a DMA transfer for playback/record requests from the audio layer.
731  */
732 
733 int
734 gus_dmaout_intr(struct gus_softc *sc)
735 {
736 	bus_space_tag_t iot = sc->sc_iot;
737 	bus_space_handle_t ioh2 = sc->sc_ioh2;
738 
739 	/*
740 	 * If we got a DMA transfer complete from the GUS DRAM, then deal
741 	 * with it.
742 	 */
743 
744 	SELECT_GUS_REG(iot, ioh2, GUSREG_DMA_CONTROL);
745 	if (bus_space_read_1(iot, ioh2, GUS_DATA_HIGH) & GUSMASK_DMA_IRQPEND) {
746 	    timeout_del(&sc->sc_dma_tmo);
747 	    gus_dmaout_dointr(sc);
748 	    return 1;
749 	}
750 	return 0;
751 }
752 
753 void
754 gus_dmaout_dointr(struct gus_softc *sc)
755 {
756 	bus_space_tag_t iot = sc->sc_iot;
757 	bus_space_handle_t ioh2 = sc->sc_ioh2;
758 
759 	/* sc->sc_dmaoutcnt - 1 because DMA controller counts from zero?. */
760 	isa_dmadone(sc->sc_dev.dv_parent, sc->sc_drq);
761 	sc->sc_flags &= ~GUS_DMAOUT_ACTIVE;  /* pending DMA is done */
762 	DMAPRINTF(("gus_dmaout_dointr %d @ %p\n", sc->sc_dmaoutcnt,
763 		   sc->sc_dmaoutaddr));
764 
765 	/*
766 	 * to prevent clicking, we need to copy last sample
767 	 * from last buffer to scratch area just before beginning of
768 	 * buffer.  However, if we're doing formats that are converted by
769 	 * the card during the DMA process, we need to pick up the converted
770 	 * byte rather than the one we have in memory.
771 	 */
772 	if (sc->sc_dmabuf == sc->sc_nbufs - 1) {
773 	  int i;
774 	  switch (sc->sc_encoding) {
775 	  case AUDIO_ENCODING_SLINEAR_LE:
776 	  case AUDIO_ENCODING_SLINEAR_BE:
777 	    if (sc->sc_precision == 8)
778 	      goto byte;
779 	    /* we have the native format */
780 	    for (i = 1; i <= 2; i++)
781 	      guspoke(iot, ioh2, sc->sc_gusaddr -
782 		      (sc->sc_nbufs - 1) * sc->sc_chanblocksize - i,
783 		      sc->sc_dmaoutaddr[sc->sc_dmaoutcnt-i]);
784 	    break;
785 	  case AUDIO_ENCODING_ULINEAR_LE:
786 	  case AUDIO_ENCODING_ULINEAR_BE:
787 	    guspoke(iot, ioh2, sc->sc_gusaddr -
788 		    (sc->sc_nbufs - 1) * sc->sc_chanblocksize - 2,
789 		    guspeek(iot, ioh2,
790 			    sc->sc_gusaddr + sc->sc_chanblocksize - 2));
791 	  case AUDIO_ENCODING_ALAW:
792 	  case AUDIO_ENCODING_ULAW:
793 	  byte:
794 	    /* we need to fetch the translated byte, then stuff it. */
795 	    guspoke(iot, ioh2, sc->sc_gusaddr -
796 		    (sc->sc_nbufs - 1) * sc->sc_chanblocksize - 1,
797 		    guspeek(iot, ioh2,
798 			    sc->sc_gusaddr + sc->sc_chanblocksize - 1));
799 	    break;
800 	  }
801 	}
802 	/*
803 	 * If this is the first half of stereo, "ignore" this one
804 	 * and copy out the second half.
805 	 */
806 	if (sc->sc_dmaoutintr == stereo_dmaintr) {
807 	    (*sc->sc_dmaoutintr)(sc->sc_outarg);
808 	    return;
809 	}
810 	/*
811 	 * If the voice is stopped, then start it.  Reset the loop
812 	 * and roll bits.  Call the audio layer routine, since if
813 	 * we're starting a stopped voice, that means that the next
814 	 * buffer can be filled
815 	 */
816 
817 	sc->sc_flags &= ~GUS_LOCKED;
818 	if (sc->sc_voc[GUS_VOICE_LEFT].voccntl &
819 	    GUSMASK_VOICE_STOPPED) {
820 	    if (sc->sc_flags & GUS_PLAYING) {
821 		printf("%s: playing yet stopped?\n", sc->sc_dev.dv_xname);
822 	    }
823 	    sc->sc_bufcnt++; /* another yet to be played */
824 	    gus_start_playing(sc, sc->sc_dmabuf);
825 	    gus_restart++;
826 	} else {
827 	    /*
828 	     * set the sound action based on which buffer we
829 	     * just transferred.  If we just transferred buffer 0
830 	     * we want the sound to loop when it gets to the nth
831 	     * buffer; if we just transferred
832 	     * any other buffer, we want the sound to roll over
833 	     * at least one more time.  The voice interrupt
834 	     * handlers will take care of accounting &
835 	     * setting control bits if it's not caught up to us
836 	     * yet.
837 	     */
838 	    if (++sc->sc_bufcnt == 2) {
839 		/*
840 		 * XXX
841 		 * If we're too slow in reaction here,
842 		 * the voice could be just approaching the
843 		 * end of its run.  It should be set to stop,
844 		 * so these adjustments might not DTRT.
845 		 */
846 		if (sc->sc_dmabuf == 0 &&
847 		    sc->sc_playbuf == sc->sc_nbufs - 1) {
848 		    /* player is just at the last buf, we're at the
849 		       first.  Turn on looping, turn off rolling. */
850 		    sc->sc_voc[GUS_VOICE_LEFT].voccntl |= GUSMASK_LOOP_ENABLE;
851 		    sc->sc_voc[GUS_VOICE_LEFT].volcntl &= ~GUSMASK_VOICE_ROLL;
852 		    playstats[playcntr].vaction = 3;
853 		} else {
854 		    /* player is at previous buf:
855 		       turn on rolling, turn off looping */
856 		    sc->sc_voc[GUS_VOICE_LEFT].voccntl &= ~GUSMASK_LOOP_ENABLE;
857 		    sc->sc_voc[GUS_VOICE_LEFT].volcntl |= GUSMASK_VOICE_ROLL;
858 		    playstats[playcntr].vaction = 4;
859 		}
860 #ifdef GUSPLAYDEBUG
861 		if (gusstats) {
862 		  microtime(&playstats[playcntr].tv);
863 		  playstats[playcntr].endaddr = sc->sc_voc[GUS_VOICE_LEFT].end_addr;
864 		  playstats[playcntr].voccntl = sc->sc_voc[GUS_VOICE_LEFT].voccntl;
865 		  playstats[playcntr].volcntl = sc->sc_voc[GUS_VOICE_LEFT].volcntl;
866 		  playstats[playcntr].playbuf = sc->sc_playbuf;
867 		  playstats[playcntr].dmabuf = sc->sc_dmabuf;
868 		  playstats[playcntr].bufcnt = sc->sc_bufcnt;
869 		  playstats[playcntr++].curaddr = gus_get_curaddr(sc, GUS_VOICE_LEFT);
870 		  playcntr = playcntr % NDMARECS;
871 		}
872 #endif
873 		bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, GUS_VOICE_LEFT);
874 		SELECT_GUS_REG(iot, ioh2, GUSREG_VOICE_CNTL);
875 		bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_LEFT].voccntl);
876 		SELECT_GUS_REG(iot, ioh2, GUSREG_VOLUME_CONTROL);
877 		bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_LEFT].volcntl);
878 	    }
879 	}
880 	gus_bufcnt[sc->sc_bufcnt-1]++;
881 	/*
882 	 * flip to the next DMA buffer
883 	 */
884 
885 	sc->sc_dmabuf = ++sc->sc_dmabuf % sc->sc_nbufs;
886 	/*
887 	 * See comments below about DMA admission control strategy.
888 	 * We can call the upper level here if we have an
889 	 * idle buffer (not currently playing) to DMA into.
890 	 */
891 	if (sc->sc_dmaoutintr && sc->sc_bufcnt < sc->sc_nbufs) {
892 	    /* clean out to prevent double calls */
893 	    void (*pfunc)(void *) = sc->sc_dmaoutintr;
894 	    void *arg = sc->sc_outarg;
895 
896 	    sc->sc_outarg = 0;
897 	    sc->sc_dmaoutintr = 0;
898 	    (*pfunc)(arg);
899 	}
900 }
901 
902 /*
903  * Service voice interrupts
904  */
905 
906 int
907 gus_voice_intr(struct gus_softc *sc)
908 {
909 	bus_space_tag_t iot = sc->sc_iot;
910 	bus_space_handle_t ioh2 = sc->sc_ioh2;
911 	int ignore = 0, voice, rval = 0;
912 	unsigned char intr, status;
913 
914 	/*
915 	 * The point of this may not be obvious at first.  A voice can
916 	 * interrupt more than once; according to the GUS SDK we are supposed
917 	 * to ignore multiple interrupts for the same voice.
918 	 */
919 
920 	while(1) {
921 		SELECT_GUS_REG(iot, ioh2, GUSREG_IRQ_STATUS);
922 		intr = bus_space_read_1(iot, ioh2, GUS_DATA_HIGH);
923 
924 		if ((intr & (GUSMASK_WIRQ_VOLUME | GUSMASK_WIRQ_VOICE))
925 			== (GUSMASK_WIRQ_VOLUME | GUSMASK_WIRQ_VOICE))
926 			/*
927 			 * No more interrupts, time to return
928 			 */
929 			return rval;
930 
931 		if ((intr & GUSMASK_WIRQ_VOICE) == 0) {
932 
933 		    /*
934 		     * We've got a voice interrupt.  Ignore previous
935 		     * interrupts by the same voice.
936 		     */
937 
938 		    rval = 1;
939 		    voice = intr & GUSMASK_WIRQ_VOICEMASK;
940 
941 		    if ((1 << voice) & ignore)
942 			break;
943 
944 		    ignore |= 1 << voice;
945 
946 		    /*
947 		     * If the voice is stopped, then force it to stop
948 		     * (this stops it from continuously generating IRQs)
949 		     */
950 
951 		    SELECT_GUS_REG(iot, ioh2, GUSREG_VOICE_CNTL+0x80);
952 		    status = bus_space_read_1(iot, ioh2, GUS_DATA_HIGH);
953 		    if (status & GUSMASK_VOICE_STOPPED) {
954 			if (voice != GUS_VOICE_LEFT) {
955 			    DMAPRINTF(("%s: spurious voice %d stop?\n",
956 				       sc->sc_dev.dv_xname, voice));
957 			    gus_stop_voice(sc, voice, 0);
958 			    continue;
959 			}
960 			gus_stop_voice(sc, voice, 1);
961 			/* also kill right voice */
962 			gus_stop_voice(sc, GUS_VOICE_RIGHT, 0);
963 			sc->sc_bufcnt--; /* it finished a buffer */
964 			if (sc->sc_bufcnt > 0) {
965 			    /*
966 			     * probably a race to get here: the voice
967 			     * stopped while the DMA code was just trying to
968 			     * get the next buffer in place.
969 			     * Start the voice again.
970 			     */
971 			    printf("%s: stopped voice not drained? (%x)\n",
972 				   sc->sc_dev.dv_xname, sc->sc_bufcnt);
973 			    gus_falsestops++;
974 
975 			    sc->sc_playbuf = ++sc->sc_playbuf % sc->sc_nbufs;
976 			    gus_start_playing(sc, sc->sc_playbuf);
977 			} else if (sc->sc_bufcnt < 0) {
978 			    panic("%s: negative bufcnt in stopped voice",
979 				   sc->sc_dev.dv_xname);
980 			} else {
981 			    sc->sc_playbuf = -1; /* none are active */
982 			    gus_stops++;
983 			}
984 			/* fall through to callback and admit another
985 			   buffer.... */
986 		    } else if (sc->sc_bufcnt != 0) {
987 			/*
988 			 * This should always be taken if the voice
989 			 * is not stopped.
990 			 */
991 			gus_continues++;
992 			if (gus_continue_playing(sc, voice)) {
993 				/*
994 				 * we shouldn't have continued--active DMA
995 				 * is in the way in the ring, for
996 				 * some as-yet undebugged reason.
997 				 */
998 				gus_stop_voice(sc, GUS_VOICE_LEFT, 1);
999 				/* also kill right voice */
1000 				gus_stop_voice(sc, GUS_VOICE_RIGHT, 0);
1001 				sc->sc_playbuf = -1;
1002 				gus_stops++;
1003 			}
1004 		    }
1005 		    /*
1006 		     * call the upper level to send on down another
1007 		     * block. We do admission rate control as follows:
1008 		     *
1009 		     * When starting up output (in the first N
1010 		     * blocks), call the upper layer after the DMA is
1011 		     * complete (see above in gus_dmaout_intr()).
1012 		     *
1013 		     * When output is already in progress and we have
1014 		     * no more GUS buffers to use for DMA, the DMA
1015 		     * output routines do not call the upper layer.
1016 		     * Instead, we call the DMA completion routine
1017 		     * here, after the voice interrupts indicating
1018 		     * that it's finished with a buffer.
1019 		     *
1020 		     * However, don't call anything here if the DMA
1021 		     * output flag is set, (which shouldn't happen)
1022 		     * because we'll squish somebody else's DMA if
1023 		     * that's the case.  When DMA is done, it will
1024 		     * call back if there is a spare buffer.
1025 		     */
1026 		    if (sc->sc_dmaoutintr && !(sc->sc_flags & GUS_LOCKED)) {
1027 			if (sc->sc_dmaoutintr == stereo_dmaintr)
1028 			    printf("gusdmaout botch?\n");
1029 			else {
1030 			    /* clean out to avoid double calls */
1031 			    void (*pfunc)(void *) = sc->sc_dmaoutintr;
1032 			    void *arg = sc->sc_outarg;
1033 
1034 			    sc->sc_outarg = 0;
1035 			    sc->sc_dmaoutintr = 0;
1036 			    (*pfunc)(arg);
1037 			}
1038 		    }
1039 		}
1040 
1041 		/*
1042 		 * Ignore other interrupts for now
1043 		 */
1044 	}
1045 	return 0;
1046 }
1047 
1048 void
1049 gus_start_playing(struct gus_softc *sc, int bufno)
1050 {
1051 	bus_space_tag_t iot = sc->sc_iot;
1052 	bus_space_handle_t ioh2 = sc->sc_ioh2;
1053 	/*
1054 	 * Start the voices playing, with buffer BUFNO.
1055 	 */
1056 
1057 	/*
1058 	 * Loop or roll if we have buffers ready.
1059 	 */
1060 
1061 	if (sc->sc_bufcnt == 1) {
1062 		sc->sc_voc[GUS_VOICE_LEFT].voccntl &= ~(GUSMASK_LOOP_ENABLE);
1063 		sc->sc_voc[GUS_VOICE_LEFT].volcntl &= ~(GUSMASK_VOICE_ROLL);
1064 	} else {
1065 		if (bufno == sc->sc_nbufs - 1) {
1066 			sc->sc_voc[GUS_VOICE_LEFT].voccntl |= GUSMASK_LOOP_ENABLE;
1067 			sc->sc_voc[GUS_VOICE_LEFT].volcntl &= ~(GUSMASK_VOICE_ROLL);
1068 		} else {
1069 			sc->sc_voc[GUS_VOICE_LEFT].voccntl &= ~GUSMASK_LOOP_ENABLE;
1070 			sc->sc_voc[GUS_VOICE_LEFT].volcntl |= GUSMASK_VOICE_ROLL;
1071 		}
1072 	}
1073 
1074 	bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, GUS_VOICE_LEFT);
1075 
1076 	SELECT_GUS_REG(iot, ioh2, GUSREG_VOICE_CNTL);
1077 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_LEFT].voccntl);
1078 
1079 	SELECT_GUS_REG(iot, ioh2, GUSREG_VOLUME_CONTROL);
1080 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_LEFT].volcntl);
1081 
1082 	sc->sc_voc[GUS_VOICE_LEFT].current_addr =
1083 		GUS_MEM_OFFSET + sc->sc_chanblocksize * bufno;
1084 	sc->sc_voc[GUS_VOICE_LEFT].end_addr =
1085 		sc->sc_voc[GUS_VOICE_LEFT].current_addr + sc->sc_chanblocksize - 1;
1086 	sc->sc_voc[GUS_VOICE_RIGHT].current_addr =
1087 		sc->sc_voc[GUS_VOICE_LEFT].current_addr +
1088 		(gus_dostereo && sc->sc_channels == 2 ? GUS_LEFT_RIGHT_OFFSET : 0);
1089 	/*
1090 	 * set up right channel to just loop forever, no interrupts,
1091 	 * starting at the buffer we just filled.  We'll feed it data
1092 	 * at the same time as left channel.
1093 	 */
1094 	sc->sc_voc[GUS_VOICE_RIGHT].voccntl |= GUSMASK_LOOP_ENABLE;
1095 	sc->sc_voc[GUS_VOICE_RIGHT].volcntl &= ~(GUSMASK_VOICE_ROLL);
1096 
1097 #ifdef GUSPLAYDEBUG
1098 	if (gusstats) {
1099 		microtime(&playstats[playcntr].tv);
1100 		playstats[playcntr].curaddr = sc->sc_voc[GUS_VOICE_LEFT].current_addr;
1101 
1102 		playstats[playcntr].voccntl = sc->sc_voc[GUS_VOICE_LEFT].voccntl;
1103 		playstats[playcntr].volcntl = sc->sc_voc[GUS_VOICE_LEFT].volcntl;
1104 		playstats[playcntr].endaddr = sc->sc_voc[GUS_VOICE_LEFT].end_addr;
1105 		playstats[playcntr].playbuf = bufno;
1106 		playstats[playcntr].dmabuf = sc->sc_dmabuf;
1107 		playstats[playcntr].bufcnt = sc->sc_bufcnt;
1108 		playstats[playcntr++].vaction = 5;
1109 		playcntr = playcntr % NDMARECS;
1110 	}
1111 #endif
1112 
1113 	bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, GUS_VOICE_RIGHT);
1114 	SELECT_GUS_REG(iot, ioh2, GUSREG_VOICE_CNTL);
1115 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_RIGHT].voccntl);
1116 	SELECT_GUS_REG(iot, ioh2, GUSREG_VOLUME_CONTROL);
1117 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_RIGHT].volcntl);
1118 
1119 	gus_start_voice(sc, GUS_VOICE_RIGHT, 0);
1120 	gus_start_voice(sc, GUS_VOICE_LEFT, 1);
1121 	if (sc->sc_playbuf == -1)
1122 		/* mark start of playing */
1123 		sc->sc_playbuf = bufno;
1124 }
1125 
1126 int
1127 gus_continue_playing(struct gus_softc *sc, int voice)
1128 {
1129 	bus_space_tag_t iot = sc->sc_iot;
1130 	bus_space_handle_t ioh2 = sc->sc_ioh2;
1131 
1132 	/*
1133 	 * stop this voice from interrupting while we work.
1134 	 */
1135 
1136 	SELECT_GUS_REG(iot, ioh2, GUSREG_VOICE_CNTL);
1137 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[voice].voccntl & ~(GUSMASK_VOICE_IRQ));
1138 
1139 	/*
1140 	 * update playbuf to point to the buffer the hardware just started
1141 	 * playing
1142 	 */
1143 	sc->sc_playbuf = ++sc->sc_playbuf % sc->sc_nbufs;
1144 
1145 	/*
1146 	 * account for buffer just finished
1147 	 */
1148 	if (--sc->sc_bufcnt == 0) {
1149 		DPRINTF(("gus: bufcnt 0 on continuing voice?\n"));
1150 	}
1151 	if (sc->sc_playbuf == sc->sc_dmabuf && (sc->sc_flags & GUS_LOCKED)) {
1152 		printf("%s: continue into active dmabuf?\n", sc->sc_dev.dv_xname);
1153 		return 1;
1154 	}
1155 
1156 	/*
1157 	 * Select the end of the buffer based on the currently active
1158 	 * buffer, [plus extra contiguous buffers (if ready)].
1159 	 */
1160 
1161 	/*
1162 	 * set endpoint at end of buffer we just started playing.
1163 	 *
1164 	 * The total gets -1 because end addrs are one less than you might
1165 	 * think (the end_addr is the address of the last sample to play)
1166 	 */
1167 	gus_set_endaddr(sc, voice, GUS_MEM_OFFSET +
1168 			sc->sc_chanblocksize * (sc->sc_playbuf + 1) - 1);
1169 
1170 	if (sc->sc_bufcnt < 2) {
1171 		/*
1172 		 * Clear out the loop and roll flags, and rotate the currently
1173 		 * playing buffer.  That way, if we don't manage to get more
1174 		 * data before this buffer finishes, we'll just stop.
1175 		 */
1176 		sc->sc_voc[voice].voccntl &= ~GUSMASK_LOOP_ENABLE;
1177 		sc->sc_voc[voice].volcntl &= ~GUSMASK_VOICE_ROLL;
1178 		playstats[playcntr].vaction = 0;
1179 	} else {
1180 		/*
1181 		 * We have some buffers to play.  set LOOP if we're on the
1182 		 * last buffer in the ring, otherwise set ROLL.
1183 		 */
1184 		if (sc->sc_playbuf == sc->sc_nbufs - 1) {
1185 			sc->sc_voc[voice].voccntl |= GUSMASK_LOOP_ENABLE;
1186 			sc->sc_voc[voice].volcntl &= ~GUSMASK_VOICE_ROLL;
1187 			playstats[playcntr].vaction = 1;
1188 		} else {
1189 			sc->sc_voc[voice].voccntl &= ~GUSMASK_LOOP_ENABLE;
1190 			sc->sc_voc[voice].volcntl |= GUSMASK_VOICE_ROLL;
1191 			playstats[playcntr].vaction = 2;
1192 		}
1193 	}
1194 #ifdef GUSPLAYDEBUG
1195 	if (gusstats) {
1196 		microtime(&playstats[playcntr].tv);
1197 		playstats[playcntr].curaddr = gus_get_curaddr(sc, voice);
1198 
1199 		playstats[playcntr].voccntl = sc->sc_voc[voice].voccntl;
1200 		playstats[playcntr].volcntl = sc->sc_voc[voice].volcntl;
1201 		playstats[playcntr].endaddr = sc->sc_voc[voice].end_addr;
1202 		playstats[playcntr].playbuf = sc->sc_playbuf;
1203 		playstats[playcntr].dmabuf = sc->sc_dmabuf;
1204 		playstats[playcntr++].bufcnt = sc->sc_bufcnt;
1205 		playcntr = playcntr % NDMARECS;
1206 	}
1207 #endif
1208 
1209 	/*
1210 	 * (re-)set voice parameters.  This will reenable interrupts from this
1211 	 * voice.
1212 	 */
1213 
1214 	SELECT_GUS_REG(iot, ioh2, GUSREG_VOICE_CNTL);
1215 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[voice].voccntl);
1216 	SELECT_GUS_REG(iot, ioh2, GUSREG_VOLUME_CONTROL);
1217 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[voice].volcntl);
1218 	return 0;
1219 }
1220 
1221 /*
1222  * Send/receive data into GUS's DRAM using DMA.  Called at splaudio()
1223  */
1224 
1225 void
1226 gusdmaout(struct gus_softc *sc, int flags, u_long gusaddr, caddr_t buffaddr,
1227     int length)
1228 {
1229 	unsigned char c = (unsigned char) flags;
1230 	bus_space_tag_t iot = sc->sc_iot;
1231 	bus_space_handle_t ioh2 = sc->sc_ioh2;
1232 
1233 	DMAPRINTF(("gusdmaout flags=%x scflags=%x\n", flags, sc->sc_flags));
1234 
1235 	sc->sc_gusaddr = gusaddr;
1236 
1237 	/*
1238 	 * If we're using a 16 bit DMA channel, we have to jump through some
1239 	 * extra hoops; this includes translating the DRAM address a bit
1240 	 */
1241 
1242 	if (sc->sc_drq >= 4) {
1243 		c |= GUSMASK_DMA_WIDTH;
1244 		gusaddr = convert_to_16bit(gusaddr);
1245 	}
1246 
1247 	/*
1248 	 * Add flag bits that we always set - fast DMA, enable IRQ
1249 	 */
1250 
1251 	c |= GUSMASK_DMA_ENABLE | GUSMASK_DMA_R0 | GUSMASK_DMA_IRQ;
1252 
1253 	/*
1254 	 * Make sure the GUS _isn't_ setup for DMA
1255 	 */
1256 
1257 	SELECT_GUS_REG(iot, ioh2, GUSREG_DMA_CONTROL);
1258 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0);
1259 
1260 	/*
1261 	 * Tell the PC DMA controller to start doing DMA
1262 	 */
1263 
1264 	sc->sc_dmaoutaddr = (u_char *) buffaddr;
1265 	sc->sc_dmaoutcnt = length;
1266 	isa_dmastart(sc->sc_dev.dv_parent, sc->sc_drq, buffaddr, length,
1267 	    NULL, DMAMODE_WRITE, BUS_DMA_NOWAIT);
1268 
1269 	/*
1270 	 * Set up DMA address - use the upper 16 bits ONLY
1271 	 */
1272 
1273 	sc->sc_flags |= GUS_DMAOUT_ACTIVE;
1274 
1275 	SELECT_GUS_REG(iot, ioh2, GUSREG_DMA_START);
1276 	bus_space_write_2(iot, ioh2, GUS_DATA_LOW, (int) (gusaddr >> 4));
1277 
1278 	/*
1279 	 * Tell the GUS to start doing DMA
1280 	 */
1281 
1282 	SELECT_GUS_REG(iot, ioh2, GUSREG_DMA_CONTROL);
1283 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, c);
1284 
1285 	/*
1286 	 * XXX If we don't finish in one second, give up...
1287 	 */
1288 	timeout_add_sec(&sc->sc_dma_tmo, 1);
1289 }
1290 
1291 /*
1292  * Start a voice playing on the GUS.  Called from interrupt handler at
1293  * splaudio().
1294  */
1295 
1296 void
1297 gus_start_voice(struct gus_softc *sc, int voice, int intrs)
1298 {
1299 	bus_space_tag_t iot = sc->sc_iot;
1300 	bus_space_handle_t ioh2 = sc->sc_ioh2;
1301 	u_long start;
1302 	u_long current;
1303 	u_long end;
1304 
1305 	/*
1306 	 * Pick all the values for the voice out of the gus_voice struct
1307 	 * and use those to program the voice
1308 	 */
1309 
1310 	start = sc->sc_voc[voice].start_addr;
1311 	current = sc->sc_voc[voice].current_addr;
1312 	end = sc->sc_voc[voice].end_addr;
1313 
1314 	/*
1315 	 * If we're using 16 bit data, mangle the addresses a bit
1316 	 */
1317 
1318 	if (sc->sc_voc[voice].voccntl & GUSMASK_DATA_SIZE16) {
1319 	        /* -1 on start so that we get onto sample boundary--other
1320 		   code always sets it for 1-byte rollover protection */
1321 		start = convert_to_16bit(start-1);
1322 		current = convert_to_16bit(current);
1323 		end = convert_to_16bit(end);
1324 	}
1325 
1326 	/*
1327 	 * Select the voice we want to use, and program the data addresses
1328 	 */
1329 
1330 	bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, (unsigned char) voice);
1331 
1332 	SELECT_GUS_REG(iot, ioh2, GUSREG_START_ADDR_HIGH);
1333 	bus_space_write_2(iot, ioh2, GUS_DATA_LOW, ADDR_HIGH(start));
1334 	SELECT_GUS_REG(iot, ioh2, GUSREG_START_ADDR_LOW);
1335 	bus_space_write_2(iot, ioh2, GUS_DATA_LOW, ADDR_LOW(start));
1336 
1337 	SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_ADDR_HIGH);
1338 	bus_space_write_2(iot, ioh2, GUS_DATA_LOW, ADDR_HIGH(current));
1339 	SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_ADDR_LOW);
1340 	bus_space_write_2(iot, ioh2, GUS_DATA_LOW, ADDR_LOW(current));
1341 
1342 	SELECT_GUS_REG(iot, ioh2, GUSREG_END_ADDR_HIGH);
1343 	bus_space_write_2(iot, ioh2, GUS_DATA_LOW, ADDR_HIGH(end));
1344 	SELECT_GUS_REG(iot, ioh2, GUSREG_END_ADDR_LOW);
1345 	bus_space_write_2(iot, ioh2, GUS_DATA_LOW, ADDR_LOW(end));
1346 
1347 	/*
1348 	 * (maybe) enable interrupts, disable voice stopping
1349 	 */
1350 
1351 	if (intrs) {
1352 		sc->sc_flags |= GUS_PLAYING; /* playing is about to start */
1353 		sc->sc_voc[voice].voccntl |= GUSMASK_VOICE_IRQ;
1354 		DMAPRINTF(("gus voice playing=%x\n", sc->sc_flags));
1355 	} else
1356 		sc->sc_voc[voice].voccntl &= ~GUSMASK_VOICE_IRQ;
1357 	sc->sc_voc[voice].voccntl &= ~(GUSMASK_VOICE_STOPPED |
1358 		GUSMASK_STOP_VOICE);
1359 
1360 	/*
1361 	 * Tell the GUS about it.  Note that we're doing volume ramping here
1362 	 * from 0 up to the set volume to help reduce clicks.
1363 	 */
1364 
1365 	SELECT_GUS_REG(iot, ioh2, GUSREG_START_VOLUME);
1366 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x00);
1367 	SELECT_GUS_REG(iot, ioh2, GUSREG_END_VOLUME);
1368 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[voice].current_volume >> 4);
1369 	SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_VOLUME);
1370 	bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x00);
1371 	SELECT_GUS_REG(iot, ioh2, GUSREG_VOLUME_RATE);
1372 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 63);
1373 
1374 	SELECT_GUS_REG(iot, ioh2, GUSREG_VOICE_CNTL);
1375 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[voice].voccntl);
1376 	SELECT_GUS_REG(iot, ioh2, GUSREG_VOLUME_CONTROL);
1377 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x00);
1378 	delay(50);
1379 	SELECT_GUS_REG(iot, ioh2, GUSREG_VOICE_CNTL);
1380 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[voice].voccntl);
1381 	SELECT_GUS_REG(iot, ioh2, GUSREG_VOLUME_CONTROL);
1382 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x00);
1383 
1384 }
1385 
1386 /*
1387  * Stop a given voice.  Called at splaudio().
1388  */
1389 
1390 void
1391 gus_stop_voice(struct gus_softc *sc, int voice, int intrs_too)
1392 {
1393 	bus_space_tag_t iot = sc->sc_iot;
1394 	bus_space_handle_t ioh2 = sc->sc_ioh2;
1395 
1396 	sc->sc_voc[voice].voccntl |= GUSMASK_VOICE_STOPPED |
1397 		GUSMASK_STOP_VOICE;
1398 	if (intrs_too) {
1399 	  sc->sc_voc[voice].voccntl &= ~(GUSMASK_VOICE_IRQ);
1400 	  /* no more DMA to do */
1401 	  sc->sc_flags &= ~GUS_PLAYING;
1402 	}
1403 	DMAPRINTF(("gusintr voice notplaying=%x\n", sc->sc_flags));
1404 
1405 	guspoke(iot, ioh2, 0L, 0);
1406 
1407 	bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, (unsigned char) voice);
1408 
1409 	SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_VOLUME);
1410 	bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x0000);
1411 	SELECT_GUS_REG(iot, ioh2, GUSREG_VOICE_CNTL);
1412 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[voice].voccntl);
1413 	delay(100);
1414 	SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_VOLUME);
1415 	bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x0000);
1416 	SELECT_GUS_REG(iot, ioh2, GUSREG_VOICE_CNTL);
1417 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[voice].voccntl);
1418 
1419 	SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_ADDR_HIGH);
1420 	bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x0000);
1421 	SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_ADDR_LOW);
1422 	bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x0000);
1423 
1424 }
1425 
1426 
1427 /*
1428  * Set the volume of a given voice.  Called at splaudio().
1429  */
1430 void
1431 gus_set_volume(struct gus_softc *sc, int voice, int volume)
1432 {
1433 	bus_space_tag_t iot = sc->sc_iot;
1434 	bus_space_handle_t ioh2 = sc->sc_ioh2;
1435 	unsigned int gusvol;
1436 
1437 	gusvol = gus_log_volumes[volume < 512 ? volume : 511];
1438 
1439 	sc->sc_voc[voice].current_volume = gusvol;
1440 
1441 	bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, (unsigned char) voice);
1442 
1443 	SELECT_GUS_REG(iot, ioh2, GUSREG_START_VOLUME);
1444 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, (unsigned char) (gusvol >> 4));
1445 
1446 	SELECT_GUS_REG(iot, ioh2, GUSREG_END_VOLUME);
1447 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, (unsigned char) (gusvol >> 4));
1448 
1449 	SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_VOLUME);
1450 	bus_space_write_2(iot, ioh2, GUS_DATA_LOW, gusvol << 4);
1451 	delay(500);
1452 	bus_space_write_2(iot, ioh2, GUS_DATA_LOW, gusvol << 4);
1453 
1454 }
1455 
1456 /*
1457  * Interface to the audio layer.
1458  */
1459 
1460 int
1461 gusmax_set_params(void *addr, int setmode, int usemode, struct audio_params *p,
1462     struct audio_params *r)
1463 {
1464 	struct ad1848_softc *ac = addr;
1465 	struct gus_softc *sc = ac->parent;
1466 	int error;
1467 
1468 	error = ad1848_set_params(ac, setmode, usemode, p, r);
1469 	if (error)
1470 		return error;
1471 	error = gus_set_params(sc, setmode, usemode, p, r);
1472 	return error;
1473 }
1474 
1475 int
1476 gus_set_params(void *addr, int setmode, int usemode, struct audio_params *p,
1477     struct audio_params *r)
1478 {
1479 	struct gus_softc *sc = addr;
1480 
1481 	switch (p->encoding) {
1482 	case AUDIO_ENCODING_SLINEAR_LE:
1483 	case AUDIO_ENCODING_ULINEAR_LE:
1484 		break;
1485 	default:
1486 		return (EINVAL);
1487 	}
1488 
1489 	/* XXX: why?! this is called with interrupts disabled */
1490 	mtx_enter(&audio_lock);
1491 
1492 	if (p->precision == 8) {
1493 		sc->sc_voc[GUS_VOICE_LEFT].voccntl &= ~GUSMASK_DATA_SIZE16;
1494 		sc->sc_voc[GUS_VOICE_RIGHT].voccntl &= ~GUSMASK_DATA_SIZE16;
1495 	} else {
1496 		sc->sc_voc[GUS_VOICE_LEFT].voccntl |= GUSMASK_DATA_SIZE16;
1497 		sc->sc_voc[GUS_VOICE_RIGHT].voccntl |= GUSMASK_DATA_SIZE16;
1498 	}
1499 
1500 	sc->sc_encoding = p->encoding;
1501 	sc->sc_precision = p->precision;
1502 	sc->sc_channels = p->channels;
1503 
1504 	mtx_leave(&audio_lock);
1505 
1506 	if (p->sample_rate > gus_max_frequency[sc->sc_voices - GUS_MIN_VOICES])
1507 		p->sample_rate = gus_max_frequency[sc->sc_voices - GUS_MIN_VOICES];
1508 	if (setmode & AUMODE_RECORD)
1509 		sc->sc_irate = p->sample_rate;
1510 	if (setmode & AUMODE_PLAY)
1511 		sc->sc_orate = p->sample_rate;
1512 
1513 	p->bps = AUDIO_BPS(p->precision);
1514 	r->bps = AUDIO_BPS(r->precision);
1515 	p->msb = r->msb = 1;
1516 
1517 	return 0;
1518 }
1519 
1520 /*
1521  * Interface to the audio layer - set the blocksize to the correct number
1522  * of units
1523  */
1524 
1525 int
1526 gusmax_round_blocksize(void *addr, int blocksize)
1527 {
1528 	struct ad1848_softc *ac = addr;
1529 	struct gus_softc *sc = ac->parent;
1530 
1531 /*	blocksize = ad1848_round_blocksize(ac, blocksize);*/
1532 	return gus_round_blocksize(sc, blocksize);
1533 }
1534 
1535 int
1536 gus_round_blocksize(addr, blocksize)
1537 	void * addr;
1538 	int blocksize;
1539 {
1540 	struct gus_softc *sc = addr;
1541 
1542 	DPRINTF(("gus_round_blocksize called\n"));
1543 
1544 	if ((sc->sc_encoding == AUDIO_ENCODING_ULAW ||
1545 	     sc->sc_encoding == AUDIO_ENCODING_ALAW) && blocksize > 32768)
1546 		blocksize = 32768;
1547 	else if (blocksize > 65536)
1548 		blocksize = 65536;
1549 
1550 	if ((blocksize % GUS_BUFFER_MULTIPLE) != 0)
1551 		blocksize = (blocksize / GUS_BUFFER_MULTIPLE + 1) *
1552 			GUS_BUFFER_MULTIPLE;
1553 
1554 	/* set up temporary buffer to hold the deinterleave, if necessary
1555 	   for stereo output */
1556 	if (sc->sc_deintr_buf) {
1557 		free(sc->sc_deintr_buf, M_DEVBUF, 0);
1558 		sc->sc_deintr_buf = NULL;
1559 	}
1560 	sc->sc_deintr_buf = malloc(blocksize/2, M_DEVBUF, M_WAITOK);
1561 
1562 	sc->sc_blocksize = blocksize;
1563 	/* multi-buffering not quite working yet. */
1564 	sc->sc_nbufs = /*GUS_MEM_FOR_BUFFERS / blocksize*/ 2;
1565 
1566 	gus_set_chan_addrs(sc);
1567 
1568 	return blocksize;
1569 }
1570 
1571 int
1572 gus_get_out_gain(caddr_t addr)
1573 {
1574 	struct gus_softc *sc = (struct gus_softc *) addr;
1575 
1576 	DPRINTF(("gus_get_out_gain called\n"));
1577 	return sc->sc_ogain / 2;
1578 }
1579 
1580 inline void
1581 gus_set_voices(struct gus_softc *sc, int voices)
1582 {
1583 	bus_space_tag_t iot = sc->sc_iot;
1584 	bus_space_handle_t ioh2 = sc->sc_ioh2;
1585 	/*
1586 	 * Select the active number of voices
1587 	 */
1588 
1589 	SELECT_GUS_REG(iot, ioh2, GUSREG_ACTIVE_VOICES);
1590 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, (voices-1) | 0xc0);
1591 
1592 	sc->sc_voices = voices;
1593 }
1594 
1595 /*
1596  * Actually set the settings of various values on the card
1597  */
1598 
1599 int
1600 gusmax_commit_settings(void *addr)
1601 {
1602 	struct ad1848_softc *ac = addr;
1603 	struct gus_softc *sc = ac->parent;
1604 	int error;
1605 
1606 	error = ad1848_commit_settings(ac);
1607 	if (error)
1608 		return error;
1609 	return gus_commit_settings(sc);
1610 }
1611 
1612 /*
1613  * Commit the settings.  Called at normal IPL.
1614  */
1615 int
1616 gus_commit_settings(void *addr)
1617 {
1618 	struct gus_softc *sc = addr;
1619 
1620 	DPRINTF(("gus_commit_settings called (gain = %d)\n",sc->sc_ogain));
1621 
1622 
1623 	/* XXX: why?! this is called with interrupts disabled */
1624 	mtx_enter(&audio_lock);
1625 
1626 	gus_set_recrate(sc, sc->sc_irate);
1627 	gus_set_volume(sc, GUS_VOICE_LEFT, sc->sc_ogain);
1628 	gus_set_volume(sc, GUS_VOICE_RIGHT, sc->sc_ogain);
1629 	gus_set_samprate(sc, GUS_VOICE_LEFT, sc->sc_orate);
1630 	gus_set_samprate(sc, GUS_VOICE_RIGHT, sc->sc_orate);
1631 	mtx_leave(&audio_lock);
1632 	gus_set_chan_addrs(sc);
1633 
1634 	return 0;
1635 }
1636 
1637 void
1638 gus_set_chan_addrs(struct gus_softc *sc)
1639 {
1640 	/*
1641 	 * We use sc_nbufs * blocksize bytes of storage in the on-board GUS
1642 	 * ram.
1643 	 * For mono, each of the sc_nbufs buffers is DMA'd to in one chunk,
1644 	 * and both left & right channels play the same buffer.
1645 	 *
1646 	 * For stereo, each channel gets a contiguous half of the memory,
1647 	 * and each has sc_nbufs buffers of size blocksize/2.
1648 	 * Stereo data are deinterleaved in main memory before the DMA out
1649 	 * routines are called to queue the output.
1650 	 *
1651 	 * The blocksize per channel is kept in sc_chanblocksize.
1652 	 */
1653 	if (sc->sc_channels == 2)
1654 	    sc->sc_chanblocksize = sc->sc_blocksize/2;
1655 	else
1656 	    sc->sc_chanblocksize = sc->sc_blocksize;
1657 
1658 	sc->sc_voc[GUS_VOICE_LEFT].start_addr = GUS_MEM_OFFSET - 1;
1659 	sc->sc_voc[GUS_VOICE_RIGHT].start_addr =
1660 	    (gus_dostereo && sc->sc_channels == 2 ? GUS_LEFT_RIGHT_OFFSET : 0)
1661 	      + GUS_MEM_OFFSET - 1;
1662 	sc->sc_voc[GUS_VOICE_RIGHT].current_addr =
1663 	    sc->sc_voc[GUS_VOICE_RIGHT].start_addr + 1;
1664 	sc->sc_voc[GUS_VOICE_RIGHT].end_addr =
1665 	    sc->sc_voc[GUS_VOICE_RIGHT].start_addr +
1666 	    sc->sc_nbufs * sc->sc_chanblocksize;
1667 
1668 }
1669 
1670 /*
1671  * Set the sample rate of the given voice.  Called at splaudio().
1672  */
1673 
1674 void
1675 gus_set_samprate(struct gus_softc *sc, int voice, int freq)
1676 {
1677 	bus_space_tag_t iot = sc->sc_iot;
1678 	bus_space_handle_t ioh2 = sc->sc_ioh2;
1679 	unsigned int fc;
1680 	u_long temp, f = (u_long) freq;
1681 
1682 	/*
1683 	 * calculate fc based on the number of active voices;
1684 	 * we need to use longs to preserve enough bits
1685 	 */
1686 
1687 	temp = (u_long) gus_max_frequency[sc->sc_voices-GUS_MIN_VOICES];
1688 
1689 	fc = (unsigned int)(((f << 9L) + (temp >> 1L)) / temp);
1690 
1691 	fc <<= 1;
1692 
1693 
1694 	/*
1695 	 * Program the voice frequency, and set it in the voice data record
1696 	 */
1697 
1698 	bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, (unsigned char) voice);
1699 	SELECT_GUS_REG(iot, ioh2, GUSREG_FREQ_CONTROL);
1700 	bus_space_write_2(iot, ioh2, GUS_DATA_LOW, fc);
1701 
1702 	sc->sc_voc[voice].rate = freq;
1703 
1704 }
1705 
1706 /*
1707  * Set the sample rate of the recording frequency.  Formula is from the GUS
1708  * SDK.  Called at splaudio().
1709  */
1710 
1711 void
1712 gus_set_recrate(struct gus_softc *sc, u_long rate)
1713 {
1714 	bus_space_tag_t iot = sc->sc_iot;
1715 	bus_space_handle_t ioh2 = sc->sc_ioh2;
1716 	u_char realrate;
1717 	DPRINTF(("gus_set_recrate %lu\n", rate));
1718 
1719 #if 0
1720 	realrate = 9878400/(16*(rate+2)); /* formula from GUS docs */
1721 #endif
1722 	realrate = (9878400 >> 4)/rate - 2; /* formula from code, sigh. */
1723 
1724 	SELECT_GUS_REG(iot, ioh2, GUSREG_SAMPLE_FREQ);
1725 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, realrate);
1726 }
1727 
1728 /*
1729  * Interface to the audio layer - turn the output on or off.  Note that some
1730  * of these bits are flipped in the register
1731  */
1732 
1733 int
1734 gusmax_speaker_ctl(void *addr, int newstate)
1735 {
1736 	struct ad1848_softc *sc = addr;
1737 	return gus_speaker_ctl(sc->parent, newstate);
1738 }
1739 
1740 int
1741 gus_speaker_ctl(void *addr, int newstate)
1742 {
1743 	struct gus_softc *sc = (struct gus_softc *) addr;
1744 	bus_space_tag_t iot = sc->sc_iot;
1745 	bus_space_handle_t ioh1 = sc->sc_ioh1;
1746 
1747 	/* Line out bit is flipped: 0 enables, 1 disables */
1748 	if ((newstate == SPKR_ON) &&
1749 	    (sc->sc_mixcontrol & GUSMASK_LINE_OUT)) {
1750 		sc->sc_mixcontrol &= ~GUSMASK_LINE_OUT;
1751 		bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL, sc->sc_mixcontrol);
1752 	}
1753 	if ((newstate == SPKR_OFF) &&
1754 	    (sc->sc_mixcontrol & GUSMASK_LINE_OUT) == 0) {
1755 		sc->sc_mixcontrol |= GUSMASK_LINE_OUT;
1756 		bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL, sc->sc_mixcontrol);
1757 	}
1758 
1759 	return 0;
1760 }
1761 
1762 int
1763 gus_linein_ctl(void *addr, int newstate)
1764 {
1765 	struct gus_softc *sc = (struct gus_softc *) addr;
1766 	bus_space_tag_t iot = sc->sc_iot;
1767 	bus_space_handle_t ioh1 = sc->sc_ioh1;
1768 
1769 	/* Line in bit is flipped: 0 enables, 1 disables */
1770 	if ((newstate == SPKR_ON) &&
1771 	    (sc->sc_mixcontrol & GUSMASK_LINE_IN)) {
1772 		sc->sc_mixcontrol &= ~GUSMASK_LINE_IN;
1773 		bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL, sc->sc_mixcontrol);
1774 	}
1775 	if ((newstate == SPKR_OFF) &&
1776 	    (sc->sc_mixcontrol & GUSMASK_LINE_IN) == 0) {
1777 		sc->sc_mixcontrol |= GUSMASK_LINE_IN;
1778 		bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL, sc->sc_mixcontrol);
1779 	}
1780 
1781 	return 0;
1782 }
1783 
1784 int
1785 gus_mic_ctl(void *addr, int newstate)
1786 {
1787 	struct gus_softc *sc = (struct gus_softc *) addr;
1788 	bus_space_tag_t iot = sc->sc_iot;
1789 	bus_space_handle_t ioh1 = sc->sc_ioh1;
1790 
1791 	/* Mic bit is normal: 1 enables, 0 disables */
1792 	if ((newstate == SPKR_ON) &&
1793 	    (sc->sc_mixcontrol & GUSMASK_MIC_IN) == 0) {
1794 		sc->sc_mixcontrol |= GUSMASK_MIC_IN;
1795 		bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL, sc->sc_mixcontrol);
1796 	}
1797 	if ((newstate == SPKR_OFF) &&
1798 	    (sc->sc_mixcontrol & GUSMASK_MIC_IN)) {
1799 		sc->sc_mixcontrol &= ~GUSMASK_MIC_IN;
1800 		bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL, sc->sc_mixcontrol);
1801 	}
1802 
1803 	return 0;
1804 }
1805 
1806 /*
1807  * Set the end address of a give voice.  Called at splaudio().
1808  */
1809 
1810 void
1811 gus_set_endaddr(struct gus_softc *sc, int voice, u_long addr)
1812 {
1813 	bus_space_tag_t iot = sc->sc_iot;
1814 	bus_space_handle_t ioh2 = sc->sc_ioh2;
1815 
1816 	sc->sc_voc[voice].end_addr = addr;
1817 
1818 	if (sc->sc_voc[voice].voccntl & GUSMASK_DATA_SIZE16)
1819 		addr = convert_to_16bit(addr);
1820 
1821 	SELECT_GUS_REG(iot, ioh2, GUSREG_END_ADDR_HIGH);
1822 	bus_space_write_2(iot, ioh2, GUS_DATA_LOW, ADDR_HIGH(addr));
1823 	SELECT_GUS_REG(iot, ioh2, GUSREG_END_ADDR_LOW);
1824 	bus_space_write_2(iot, ioh2, GUS_DATA_LOW, ADDR_LOW(addr));
1825 
1826 }
1827 
1828 #ifdef GUSPLAYDEBUG
1829 /*
1830  * Set current address.  Called at splaudio().
1831  */
1832 void
1833 gus_set_curaddr(struct gus_softc *sc, int voice, u_long addr)
1834 {
1835 	bus_space_tag_t iot = sc->sc_iot;
1836 	bus_space_handle_t ioh2 = sc->sc_ioh2;
1837 
1838 	sc->sc_voc[voice].current_addr = addr;
1839 
1840 	if (sc->sc_voc[voice].voccntl & GUSMASK_DATA_SIZE16)
1841 		addr = convert_to_16bit(addr);
1842 
1843 	bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, (unsigned char) voice);
1844 
1845 	SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_ADDR_HIGH);
1846 	bus_space_write_2(iot, ioh2, GUS_DATA_LOW, ADDR_HIGH(addr));
1847 	SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_ADDR_LOW);
1848 	bus_space_write_2(iot, ioh2, GUS_DATA_LOW, ADDR_LOW(addr));
1849 
1850 }
1851 
1852 /*
1853  * Get current GUS playback address.  Called at splaudio().
1854  */
1855 u_long
1856 gus_get_curaddr(struct gus_softc *sc, int voice)
1857 {
1858 	bus_space_tag_t iot = sc->sc_iot;
1859 	bus_space_handle_t ioh2 = sc->sc_ioh2;
1860 	u_long addr;
1861 
1862 	bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, (unsigned char) voice);
1863 	SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_ADDR_HIGH|GUSREG_READ);
1864 	addr = (bus_space_read_2(iot, ioh2, GUS_DATA_LOW) & 0x1fff) << 7;
1865 	SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_ADDR_LOW|GUSREG_READ);
1866 	addr |= (bus_space_read_2(iot, ioh2, GUS_DATA_LOW) >> 9L) & 0x7f;
1867 
1868 	if (sc->sc_voc[voice].voccntl & GUSMASK_DATA_SIZE16)
1869 	    addr = (addr & 0xc0000) | ((addr & 0x1ffff) << 1); /* undo 16-bit change */
1870 	DPRINTF(("gus voice %d curaddr %ld end_addr %ld\n",
1871 		 voice, addr, sc->sc_voc[voice].end_addr));
1872 	/* XXX sanity check the address? */
1873 
1874 	return(addr);
1875 }
1876 #endif
1877 
1878 /*
1879  * Convert an address value to a "16 bit" value - why this is necessary I
1880  * have NO idea
1881  */
1882 
1883 u_long
1884 convert_to_16bit(u_long address)
1885 {
1886 	u_long old_address;
1887 
1888 	old_address = address;
1889 	address >>= 1;
1890 	address &= 0x0001ffffL;
1891 	address |= (old_address & 0x000c0000L);
1892 
1893 	return (address);
1894 }
1895 
1896 /*
1897  * Write a value into the GUS's DRAM
1898  */
1899 
1900 void
1901 guspoke(bus_space_tag_t iot, bus_space_handle_t ioh2, long address,
1902     unsigned char value)
1903 {
1904 
1905 	/*
1906 	 * Select the DRAM address
1907 	 */
1908 
1909 	SELECT_GUS_REG(iot, ioh2, GUSREG_DRAM_ADDR_LOW);
1910 	bus_space_write_2(iot, ioh2, GUS_DATA_LOW, (unsigned int) (address & 0xffff));
1911 	SELECT_GUS_REG(iot, ioh2, GUSREG_DRAM_ADDR_HIGH);
1912 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, (unsigned char) ((address >> 16) & 0xff));
1913 
1914 	/*
1915 	 * Actually write the data
1916 	 */
1917 
1918 	bus_space_write_1(iot, ioh2, GUS_DRAM_DATA, value);
1919 }
1920 
1921 /*
1922  * Read a value from the GUS's DRAM
1923  */
1924 
1925 unsigned char
1926 guspeek(bus_space_tag_t iot, bus_space_handle_t ioh2, u_long address)
1927 {
1928 
1929 	/*
1930 	 * Select the DRAM address
1931 	 */
1932 
1933 	SELECT_GUS_REG(iot, ioh2, GUSREG_DRAM_ADDR_LOW);
1934 	bus_space_write_2(iot, ioh2, GUS_DATA_LOW, (unsigned int) (address & 0xffff));
1935 	SELECT_GUS_REG(iot, ioh2, GUSREG_DRAM_ADDR_HIGH);
1936 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, (unsigned char) ((address >> 16) & 0xff));
1937 
1938 	/*
1939 	 * Read in the data from the board
1940 	 */
1941 
1942 	return (unsigned char) bus_space_read_1(iot, ioh2, GUS_DRAM_DATA);
1943 }
1944 
1945 /*
1946  * Reset the Gravis UltraSound card, completely
1947  */
1948 
1949 void
1950 gusreset(struct gus_softc *sc, int voices)
1951 {
1952 	bus_space_tag_t iot = sc->sc_iot;
1953 	bus_space_handle_t ioh1 = sc->sc_ioh1;
1954 	bus_space_handle_t ioh2 = sc->sc_ioh2;
1955 	bus_space_handle_t ioh4 = sc->sc_ioh4;
1956 	int i;
1957 
1958 	mtx_enter(&audio_lock);
1959 
1960 	/*
1961 	 * Reset the GF1 chip
1962 	 */
1963 
1964 	SELECT_GUS_REG(iot, ioh2, GUSREG_RESET);
1965 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x00);
1966 
1967 	delay(500);
1968 
1969 	/*
1970 	 * Release reset
1971 	 */
1972 
1973 	SELECT_GUS_REG(iot, ioh2, GUSREG_RESET);
1974 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, GUSMASK_MASTER_RESET);
1975 
1976 	delay(500);
1977 
1978 	/*
1979 	 * Reset MIDI port as well, if applicable
1980 	 */
1981 
1982 	if (ioh4 != (bus_space_handle_t)NULL) {
1983 		bus_space_write_1(iot, ioh4, GUS_MIDI_CONTROL, MIDI_RESET);
1984 
1985 		delay(500);
1986 
1987 		bus_space_write_1(iot, ioh4, GUS_MIDI_CONTROL, 0x00);
1988 	}
1989 
1990 	/*
1991 	 * Clear interrupts
1992 	 */
1993 
1994 	SELECT_GUS_REG(iot, ioh2, GUSREG_DMA_CONTROL);
1995 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x00);
1996 	SELECT_GUS_REG(iot, ioh2, GUSREG_TIMER_CONTROL);
1997 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x00);
1998 	SELECT_GUS_REG(iot, ioh2, GUSREG_SAMPLE_CONTROL);
1999 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x00);
2000 
2001 	gus_set_voices(sc, voices);
2002 
2003 	bus_space_read_1(iot, ioh1, GUS_IRQ_STATUS);
2004 	SELECT_GUS_REG(iot, ioh2, GUSREG_DMA_CONTROL);
2005 	bus_space_read_1(iot, ioh2, GUS_DATA_HIGH);
2006 	SELECT_GUS_REG(iot, ioh2, GUSREG_SAMPLE_CONTROL);
2007 	bus_space_read_1(iot, ioh2, GUS_DATA_HIGH);
2008 	SELECT_GUS_REG(iot, ioh2, GUSREG_IRQ_STATUS);
2009 	bus_space_read_1(iot, ioh2, GUS_DATA_HIGH);
2010 
2011 	/*
2012 	 * Reset voice specific information
2013 	 */
2014 
2015 	for(i = 0; i < voices; i++) {
2016 		bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, (unsigned char) i);
2017 
2018 		SELECT_GUS_REG(iot, ioh2, GUSREG_VOICE_CNTL);
2019 
2020 		sc->sc_voc[i].voccntl = GUSMASK_VOICE_STOPPED |
2021 			GUSMASK_STOP_VOICE;
2022 
2023 		bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[i].voccntl);
2024 
2025 		sc->sc_voc[i].volcntl = GUSMASK_VOLUME_STOPPED |
2026 				GUSMASK_STOP_VOLUME;
2027 
2028 		SELECT_GUS_REG(iot, ioh2, GUSREG_VOLUME_CONTROL);
2029 		bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[i].volcntl);
2030 
2031 		delay(100);
2032 
2033 		gus_set_samprate(sc, i, 8000);
2034 		SELECT_GUS_REG(iot, ioh2, GUSREG_START_ADDR_HIGH);
2035 		bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x0000);
2036 		SELECT_GUS_REG(iot, ioh2, GUSREG_START_ADDR_LOW);
2037 		bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x0000);
2038 		SELECT_GUS_REG(iot, ioh2, GUSREG_END_ADDR_HIGH);
2039 		bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x0000);
2040 		SELECT_GUS_REG(iot, ioh2, GUSREG_END_ADDR_LOW);
2041 		bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x0000);
2042 		SELECT_GUS_REG(iot, ioh2, GUSREG_VOLUME_RATE);
2043 		bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x01);
2044 		SELECT_GUS_REG(iot, ioh2, GUSREG_START_VOLUME);
2045 		bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x10);
2046 		SELECT_GUS_REG(iot, ioh2, GUSREG_END_VOLUME);
2047 		bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0xe0);
2048 		SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_VOLUME);
2049 		bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x0000);
2050 
2051 		SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_ADDR_HIGH);
2052 		bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x0000);
2053 		SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_ADDR_LOW);
2054 		bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x0000);
2055 		SELECT_GUS_REG(iot, ioh2, GUSREG_PAN_POS);
2056 		bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x07);
2057 	}
2058 
2059 	/*
2060 	 * Clear out any pending IRQs
2061 	 */
2062 
2063 	bus_space_read_1(iot, ioh1, GUS_IRQ_STATUS);
2064 	SELECT_GUS_REG(iot, ioh2, GUSREG_DMA_CONTROL);
2065 	bus_space_read_1(iot, ioh2, GUS_DATA_HIGH);
2066 	SELECT_GUS_REG(iot, ioh2, GUSREG_SAMPLE_CONTROL);
2067 	bus_space_read_1(iot, ioh2, GUS_DATA_HIGH);
2068 	SELECT_GUS_REG(iot, ioh2, GUSREG_IRQ_STATUS);
2069 	bus_space_read_1(iot, ioh2, GUS_DATA_HIGH);
2070 
2071 	SELECT_GUS_REG(iot, ioh2, GUSREG_RESET);
2072 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, GUSMASK_MASTER_RESET | GUSMASK_DAC_ENABLE |
2073 		GUSMASK_IRQ_ENABLE);
2074 
2075 	mtx_leave(&audio_lock);
2076 }
2077 
2078 
2079 int
2080 gus_init_cs4231(struct gus_softc *sc)
2081 {
2082 	bus_space_tag_t iot = sc->sc_iot;
2083 	bus_space_handle_t ioh1 = sc->sc_ioh1;
2084 	int port = sc->sc_iobase;
2085 	u_char ctrl;
2086 
2087 	ctrl = (port & 0xf0) >> 4;	/* set port address middle nibble */
2088 	/*
2089 	 * The codec is a bit weird--swapped dma channels.
2090 	 */
2091 	ctrl |= GUS_MAX_CODEC_ENABLE;
2092 	if (sc->sc_drq >= 4)
2093 		ctrl |= GUS_MAX_RECCHAN16;
2094 	if (sc->sc_recdrq >= 4)
2095 		ctrl |= GUS_MAX_PLAYCHAN16;
2096 
2097 	bus_space_write_1(iot, ioh1, GUS_MAX_CTRL, ctrl);
2098 
2099 	sc->sc_codec.sc_iot = sc->sc_iot;
2100 	sc->sc_codec.sc_iobase = port+GUS_MAX_CODEC_BASE;
2101 
2102 	if (ad1848_mapprobe(&sc->sc_codec, sc->sc_codec.sc_iobase) == 0) {
2103 		sc->sc_flags &= ~GUS_CODEC_INSTALLED;
2104 		return (0);
2105 	} else {
2106 		struct ad1848_volume vol = {AUDIO_MAX_GAIN, AUDIO_MAX_GAIN};
2107 		sc->sc_flags |= GUS_CODEC_INSTALLED;
2108 		sc->sc_codec.parent = sc;
2109 		sc->sc_codec.sc_drq = sc->sc_recdrq;
2110 		sc->sc_codec.sc_recdrq = sc->sc_drq;
2111 		gus_hw_if = gusmax_hw_if;
2112 		/* enable line in and mic in the GUS mixer; the codec chip
2113 		   will do the real mixing for them. */
2114 		sc->sc_mixcontrol &= ~GUSMASK_LINE_IN; /* 0 enables. */
2115 		sc->sc_mixcontrol |= GUSMASK_MIC_IN; /* 1 enables. */
2116 		bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL, sc->sc_mixcontrol);
2117 
2118 		ad1848_attach(&sc->sc_codec);
2119 		/* turn on pre-MUX microphone gain. */
2120 		ad1848_set_mic_gain(&sc->sc_codec, &vol);
2121 
2122 		return (1);
2123 	}
2124 }
2125 
2126 
2127 /*
2128  * Return info about the audio device, for the AUDIO_GETINFO ioctl
2129  */
2130 
2131 int
2132 gus_getdev(void *addr, struct audio_device *dev)
2133 {
2134 	*dev = gus_device;
2135 	return 0;
2136 }
2137 
2138 /*
2139  * stubs (XXX)
2140  */
2141 
2142 int
2143 gus_set_in_gain(caddr_t addr, u_int gain,  u_char balance)
2144 {
2145 	DPRINTF(("gus_set_in_gain called\n"));
2146 	return 0;
2147 }
2148 
2149 int
2150 gus_get_in_gain(caddr_t addr)
2151 {
2152 	DPRINTF(("gus_get_in_gain called\n"));
2153 	return 0;
2154 }
2155 
2156 int
2157 gusmax_dma_input(void *addr, void *buf, int size, void (*callback)(void *),
2158     void *arg)
2159 {
2160 	struct ad1848_softc *sc = addr;
2161 	return gus_dma_input(sc->parent, buf, size, callback, arg);
2162 }
2163 
2164 /*
2165  * Start sampling the input source into the requested DMA buffer.
2166  * Called at splaudio(), either from top-half or from interrupt handler.
2167  */
2168 int
2169 gus_dma_input(void *addr, void *buf, int size, void (*callback)(void *),
2170     void *arg)
2171 {
2172 	struct gus_softc *sc = addr;
2173 	bus_space_tag_t iot = sc->sc_iot;
2174 	bus_space_handle_t ioh2 = sc->sc_ioh2;
2175 	u_char dmac;
2176 	DMAPRINTF(("gus_dma_input called\n"));
2177 
2178 	/*
2179 	 * Sample SIZE bytes of data from the card, into buffer at BUF.
2180 	 */
2181 	if (sc->sc_precision == 16) {
2182 	    return EINVAL;		/* XXX */
2183 	}
2184 
2185 	/* set DMA modes */
2186 	dmac = GUSMASK_SAMPLE_IRQ|GUSMASK_SAMPLE_START;
2187 	if (sc->sc_recdrq >= 4)
2188 		dmac |= GUSMASK_SAMPLE_DATA16;
2189 	if (sc->sc_encoding == AUDIO_ENCODING_ULAW ||
2190 	    sc->sc_encoding == AUDIO_ENCODING_ALAW ||
2191 	    sc->sc_encoding == AUDIO_ENCODING_ULINEAR_LE ||
2192 	    sc->sc_encoding == AUDIO_ENCODING_ULINEAR_BE)
2193 	    dmac |= GUSMASK_SAMPLE_INVBIT;
2194 	if (sc->sc_channels == 2)
2195 	    dmac |= GUSMASK_SAMPLE_STEREO;
2196 	isa_dmastart(sc->sc_dev.dv_parent, sc->sc_recdrq, buf, size,
2197 	    NULL, DMAMODE_READ, BUS_DMA_NOWAIT);
2198 
2199 	DMAPRINTF(("gus_dma_input isadma_started\n"));
2200 	sc->sc_flags |= GUS_DMAIN_ACTIVE;
2201 	sc->sc_dmainintr = callback;
2202 	sc->sc_inarg = arg;
2203 	sc->sc_dmaincnt = size;
2204 	sc->sc_dmainaddr = buf;
2205 
2206 	SELECT_GUS_REG(iot, ioh2, GUSREG_SAMPLE_CONTROL);
2207 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, dmac);	/* Go! */
2208 
2209 
2210 	DMAPRINTF(("gus_dma_input returning\n"));
2211 	return 0;
2212 }
2213 
2214 int
2215 gus_dmain_intr(struct gus_softc *sc)
2216 {
2217         void (*callback)(void *);
2218 	void *arg;
2219 
2220 	DMAPRINTF(("gus_dmain_intr called\n"));
2221 	if (sc->sc_dmainintr) {
2222 	    isa_dmadone(sc->sc_dev.dv_parent, sc->sc_recdrq);
2223 	    callback = sc->sc_dmainintr;
2224 	    arg = sc->sc_inarg;
2225 
2226 	    sc->sc_dmainaddr = 0;
2227 	    sc->sc_dmaincnt = 0;
2228 	    sc->sc_dmainintr = 0;
2229 	    sc->sc_inarg = 0;
2230 
2231 	    sc->sc_flags &= ~GUS_DMAIN_ACTIVE;
2232 	    DMAPRINTF(("calling dmain_intr callback %p(%p)\n", callback, arg));
2233 	    (*callback)(arg);
2234 	    return 1;
2235 	} else {
2236 	    DMAPRINTF(("gus_dmain_intr false?\n"));
2237 	    return 0;			/* XXX ??? */
2238 	}
2239 }
2240 
2241 int
2242 gusmax_halt_out_dma(void *addr)
2243 {
2244 	struct ad1848_softc *sc = addr;
2245 	return gus_halt_out_dma(sc->parent);
2246 }
2247 
2248 
2249 int
2250 gusmax_halt_in_dma(void *addr)
2251 {
2252 	struct ad1848_softc *sc = addr;
2253 	return gus_halt_in_dma(sc->parent);
2254 }
2255 
2256 /*
2257  * Stop any DMA output.  Called at splaudio().
2258  */
2259 int
2260 gus_halt_out_dma(void *addr)
2261 {
2262 	struct gus_softc *sc = addr;
2263 	bus_space_tag_t iot = sc->sc_iot;
2264 	bus_space_handle_t ioh2 = sc->sc_ioh2;
2265 
2266 	mtx_enter(&audio_lock);
2267 	DMAPRINTF(("gus_halt_out_dma called\n"));
2268 	/*
2269 	 * Make sure the GUS _isn't_ setup for DMA
2270 	 */
2271 
2272 	SELECT_GUS_REG(iot, ioh2, GUSREG_DMA_CONTROL);
2273 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0);
2274 
2275 	timeout_del(&sc->sc_dma_tmo);
2276 	isa_dmaabort(sc->sc_dev.dv_parent, sc->sc_drq);
2277 	sc->sc_flags &= ~(GUS_DMAOUT_ACTIVE|GUS_LOCKED);
2278 	sc->sc_dmaoutintr = 0;
2279 	sc->sc_outarg = 0;
2280 	sc->sc_dmaoutaddr = 0;
2281 	sc->sc_dmaoutcnt = 0;
2282 	sc->sc_dmabuf = 0;
2283 	sc->sc_bufcnt = 0;
2284 	sc->sc_playbuf = -1;
2285 	/* also stop playing */
2286 	gus_stop_voice(sc, GUS_VOICE_LEFT, 1);
2287 	gus_stop_voice(sc, GUS_VOICE_RIGHT, 0);
2288 	mtx_leave(&audio_lock);
2289 	return 0;
2290 }
2291 
2292 /*
2293  * Stop any DMA output.  Called at splaudio().
2294  */
2295 int
2296 gus_halt_in_dma(void *addr)
2297 {
2298 	struct gus_softc *sc = addr;
2299 	bus_space_tag_t iot = sc->sc_iot;
2300 	bus_space_handle_t ioh2 = sc->sc_ioh2;
2301 
2302 	mtx_enter(&audio_lock);
2303 	DMAPRINTF(("gus_halt_in_dma called\n"));
2304 
2305 	/*
2306 	 * Make sure the GUS _isn't_ setup for DMA
2307 	 */
2308 
2309 	SELECT_GUS_REG(iot, ioh2, GUSREG_SAMPLE_CONTROL);
2310 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH,
2311 	     bus_space_read_1(iot, ioh2, GUS_DATA_HIGH) & ~(GUSMASK_SAMPLE_START|GUSMASK_SAMPLE_IRQ));
2312 
2313 	isa_dmaabort(sc->sc_dev.dv_parent, sc->sc_recdrq);
2314 	sc->sc_flags &= ~GUS_DMAIN_ACTIVE;
2315 	sc->sc_dmainintr = 0;
2316 	sc->sc_inarg = 0;
2317 	sc->sc_dmainaddr = 0;
2318 	sc->sc_dmaincnt = 0;
2319 	mtx_leave(&audio_lock);
2320 	return 0;
2321 }
2322 
2323 
2324 ad1848_devmap_t gusmapping[] = {
2325   {GUSMAX_DAC_LVL, AD1848_KIND_LVL, AD1848_AUX1_CHANNEL},
2326   {GUSMAX_LINE_IN_LVL, AD1848_KIND_LVL, AD1848_LINE_CHANNEL},
2327   {GUSMAX_MONO_LVL, AD1848_KIND_LVL, AD1848_MONO_CHANNEL},
2328   {GUSMAX_CD_LVL, AD1848_KIND_LVL, AD1848_AUX2_CHANNEL},
2329   {GUSMAX_MONITOR_LVL, AD1848_KIND_LVL, AD1848_MONITOR_CHANNEL},
2330   {GUSMAX_OUT_LVL, AD1848_KIND_LVL, AD1848_DAC_CHANNEL},
2331   {GUSMAX_DAC_MUTE, AD1848_KIND_MUTE, AD1848_AUX1_CHANNEL},
2332   {GUSMAX_LINE_IN_MUTE, AD1848_KIND_MUTE, AD1848_LINE_CHANNEL},
2333   {GUSMAX_MONO_MUTE, AD1848_KIND_MUTE, AD1848_MONO_CHANNEL},
2334   {GUSMAX_CD_MUTE, AD1848_KIND_MUTE, AD1848_AUX2_CHANNEL},
2335   {GUSMAX_MONITOR_MUTE, AD1848_KIND_MUTE, AD1848_MONITOR_CHANNEL},
2336   {GUSMAX_REC_LVL, AD1848_KIND_RECORDGAIN, -1},
2337   {GUSMAX_RECORD_SOURCE, AD1848_KIND_RECORDSOURCE, -1}
2338 };
2339 
2340 int nummap = sizeof(gusmapping) / sizeof(gusmapping[0]);
2341 
2342 int
2343 gusmax_mixer_get_port(void *addr, mixer_ctrl_t *cp)
2344 {
2345 	struct ad1848_softc *ac = addr;
2346 	struct gus_softc *sc = ac->parent;
2347 	struct ad1848_volume vol;
2348 	int error = ad1848_mixer_get_port(ac, gusmapping, nummap, cp);
2349 
2350 	if (error != ENXIO)
2351 	  return (error);
2352 
2353 	error = EINVAL;
2354 
2355 	switch (cp->dev) {
2356 	case GUSMAX_SPEAKER_LVL:	/* fake speaker for mute naming */
2357 		if (cp->type == AUDIO_MIXER_VALUE) {
2358 			if (sc->sc_mixcontrol & GUSMASK_LINE_OUT)
2359 				vol.left = vol.right = AUDIO_MAX_GAIN;
2360 			else
2361 				vol.left = vol.right = AUDIO_MIN_GAIN;
2362 			error = 0;
2363 			ad1848_from_vol(cp, &vol);
2364 		}
2365 		break;
2366 
2367 	case GUSMAX_SPEAKER_MUTE:
2368 		if (cp->type == AUDIO_MIXER_ENUM) {
2369 			cp->un.ord = sc->sc_mixcontrol & GUSMASK_LINE_OUT ? 1 : 0;
2370 			error = 0;
2371 		}
2372 		break;
2373 	default:
2374 		error = ENXIO;
2375 		break;
2376 	}
2377 
2378 	return(error);
2379 }
2380 
2381 int
2382 gus_mixer_get_port(void *addr, mixer_ctrl_t *cp)
2383 {
2384 	struct gus_softc *sc = addr;
2385 	struct ics2101_softc *ic = &sc->sc_mixer;
2386 	struct ad1848_volume vol;
2387 	int error = EINVAL;
2388 
2389 	DPRINTF(("gus_mixer_get_port: dev=%d type=%d\n", cp->dev, cp->type));
2390 
2391 	if (!HAS_MIXER(sc) && cp->dev > GUSICS_MASTER_MUTE)
2392 		return ENXIO;
2393 
2394 	switch (cp->dev) {
2395 
2396 	case GUSICS_MIC_IN_MUTE:	/* Microphone */
2397 		if (cp->type == AUDIO_MIXER_ENUM) {
2398 			if (HAS_MIXER(sc))
2399 				cp->un.ord = ic->sc_mute[GUSMIX_CHAN_MIC][ICSMIX_LEFT];
2400 			else
2401 				cp->un.ord =
2402 				    sc->sc_mixcontrol & GUSMASK_MIC_IN ? 0 : 1;
2403 			error = 0;
2404 		}
2405 		break;
2406 
2407 	case GUSICS_LINE_IN_MUTE:
2408 		if (cp->type == AUDIO_MIXER_ENUM) {
2409 			if (HAS_MIXER(sc))
2410 				cp->un.ord = ic->sc_mute[GUSMIX_CHAN_LINE][ICSMIX_LEFT];
2411 			else
2412 				cp->un.ord =
2413 				    sc->sc_mixcontrol & GUSMASK_LINE_IN ? 1 : 0;
2414 			error = 0;
2415 		}
2416 		break;
2417 
2418 	case GUSICS_MASTER_MUTE:
2419 		if (cp->type == AUDIO_MIXER_ENUM) {
2420 			if (HAS_MIXER(sc))
2421 				cp->un.ord = ic->sc_mute[GUSMIX_CHAN_MASTER][ICSMIX_LEFT];
2422 			else
2423 				cp->un.ord =
2424 				    sc->sc_mixcontrol & GUSMASK_LINE_OUT ? 1 : 0;
2425 			error = 0;
2426 		}
2427 		break;
2428 
2429 	case GUSICS_DAC_MUTE:
2430 		if (cp->type == AUDIO_MIXER_ENUM) {
2431 			cp->un.ord = ic->sc_mute[GUSMIX_CHAN_DAC][ICSMIX_LEFT];
2432 			error = 0;
2433 		}
2434 		break;
2435 
2436 	case GUSICS_CD_MUTE:
2437 		if (cp->type == AUDIO_MIXER_ENUM) {
2438 			cp->un.ord = ic->sc_mute[GUSMIX_CHAN_CD][ICSMIX_LEFT];
2439 			error = 0;
2440 		}
2441 		break;
2442 
2443 	case GUSICS_MASTER_LVL:
2444 		if (cp->type == AUDIO_MIXER_VALUE) {
2445 			vol.left = ic->sc_setting[GUSMIX_CHAN_MASTER][ICSMIX_LEFT];
2446 			vol.right = ic->sc_setting[GUSMIX_CHAN_MASTER][ICSMIX_RIGHT];
2447 			if (ad1848_from_vol(cp, &vol))
2448 				error = 0;
2449 		}
2450 		break;
2451 
2452 	case GUSICS_MIC_IN_LVL:	/* Microphone */
2453 		if (cp->type == AUDIO_MIXER_VALUE) {
2454 			vol.left = ic->sc_setting[GUSMIX_CHAN_MIC][ICSMIX_LEFT];
2455 			vol.right = ic->sc_setting[GUSMIX_CHAN_MIC][ICSMIX_RIGHT];
2456 			if (ad1848_from_vol(cp, &vol))
2457 				error = 0;
2458 		}
2459 		break;
2460 
2461 	case GUSICS_LINE_IN_LVL:	/* line in */
2462 		if (cp->type == AUDIO_MIXER_VALUE) {
2463 			vol.left = ic->sc_setting[GUSMIX_CHAN_LINE][ICSMIX_LEFT];
2464 			vol.right = ic->sc_setting[GUSMIX_CHAN_LINE][ICSMIX_RIGHT];
2465 			if (ad1848_from_vol(cp, &vol))
2466 				error = 0;
2467 		}
2468 		break;
2469 
2470 
2471 	case GUSICS_CD_LVL:
2472 		if (cp->type == AUDIO_MIXER_VALUE) {
2473 			vol.left = ic->sc_setting[GUSMIX_CHAN_CD][ICSMIX_LEFT];
2474 			vol.right = ic->sc_setting[GUSMIX_CHAN_CD][ICSMIX_RIGHT];
2475 			if (ad1848_from_vol(cp, &vol))
2476 				error = 0;
2477 		}
2478 		break;
2479 
2480 	case GUSICS_DAC_LVL:		/* dac out */
2481 		if (cp->type == AUDIO_MIXER_VALUE) {
2482 			vol.left = ic->sc_setting[GUSMIX_CHAN_DAC][ICSMIX_LEFT];
2483 			vol.right = ic->sc_setting[GUSMIX_CHAN_DAC][ICSMIX_RIGHT];
2484 			if (ad1848_from_vol(cp, &vol))
2485 				error = 0;
2486 		}
2487 		break;
2488 
2489 
2490 	case GUSICS_RECORD_SOURCE:
2491 		if (cp->type == AUDIO_MIXER_ENUM) {
2492 			/* Can't set anything else useful, sigh. */
2493 			 cp->un.ord = 0;
2494 		}
2495 		break;
2496 
2497 	default:
2498 		return ENXIO;
2499 	    /*NOTREACHED*/
2500 	}
2501 	return error;
2502 }
2503 
2504 void
2505 gusics_master_mute(struct ics2101_softc *ic, int mute)
2506 {
2507 	ics2101_mix_mute(ic, GUSMIX_CHAN_MASTER, ICSMIX_LEFT, mute);
2508 	ics2101_mix_mute(ic, GUSMIX_CHAN_MASTER, ICSMIX_RIGHT, mute);
2509 }
2510 
2511 void
2512 gusics_mic_mute(struct ics2101_softc *ic, int mute)
2513 {
2514 	ics2101_mix_mute(ic, GUSMIX_CHAN_MIC, ICSMIX_LEFT, mute);
2515 	ics2101_mix_mute(ic, GUSMIX_CHAN_MIC, ICSMIX_RIGHT, mute);
2516 }
2517 
2518 void
2519 gusics_linein_mute(struct ics2101_softc *ic, int mute)
2520 {
2521 	ics2101_mix_mute(ic, GUSMIX_CHAN_LINE, ICSMIX_LEFT, mute);
2522 	ics2101_mix_mute(ic, GUSMIX_CHAN_LINE, ICSMIX_RIGHT, mute);
2523 }
2524 
2525 void
2526 gusics_cd_mute(struct ics2101_softc *ic, int mute)
2527 {
2528 	ics2101_mix_mute(ic, GUSMIX_CHAN_CD, ICSMIX_LEFT, mute);
2529 	ics2101_mix_mute(ic, GUSMIX_CHAN_CD, ICSMIX_RIGHT, mute);
2530 }
2531 
2532 void
2533 gusics_dac_mute(struct ics2101_softc *ic, int mute)
2534 {
2535 	ics2101_mix_mute(ic, GUSMIX_CHAN_DAC, ICSMIX_LEFT, mute);
2536 	ics2101_mix_mute(ic, GUSMIX_CHAN_DAC, ICSMIX_RIGHT, mute);
2537 }
2538 
2539 int
2540 gusmax_mixer_set_port(void *addr, mixer_ctrl_t *cp)
2541 {
2542 	struct ad1848_softc *ac = addr;
2543 	struct gus_softc *sc = ac->parent;
2544 	struct ad1848_volume vol;
2545 	int error = ad1848_mixer_set_port(ac, gusmapping, nummap, cp);
2546 
2547 	if (error != ENXIO)
2548 	  return (error);
2549 
2550 	DPRINTF(("gusmax_mixer_set_port: dev=%d type=%d\n", cp->dev, cp->type));
2551 
2552 	switch (cp->dev) {
2553 	case GUSMAX_SPEAKER_LVL:
2554 		if (cp->type == AUDIO_MIXER_VALUE &&
2555 		    cp->un.value.num_channels == 1) {
2556 			if (ad1848_to_vol(cp, &vol)) {
2557 				gus_speaker_ctl(sc, vol.left > AUDIO_MIN_GAIN ?
2558 						SPKR_ON : SPKR_OFF);
2559 				error = 0;
2560 			}
2561 		}
2562 		break;
2563 
2564 	case GUSMAX_SPEAKER_MUTE:
2565 		if (cp->type == AUDIO_MIXER_ENUM) {
2566 			gus_speaker_ctl(sc, cp->un.ord ? SPKR_OFF : SPKR_ON);
2567 			error = 0;
2568 		}
2569 		break;
2570 
2571 	default:
2572 		return ENXIO;
2573 	    /*NOTREACHED*/
2574     }
2575     return error;
2576 }
2577 
2578 int
2579 gus_mixer_set_port(void *addr, mixer_ctrl_t *cp)
2580 {
2581 	struct gus_softc *sc = addr;
2582 	struct ics2101_softc *ic = &sc->sc_mixer;
2583 	struct ad1848_volume vol;
2584 	int error = EINVAL;
2585 
2586 	DPRINTF(("gus_mixer_set_port: dev=%d type=%d\n", cp->dev, cp->type));
2587 
2588 	if (!HAS_MIXER(sc) && cp->dev > GUSICS_MASTER_MUTE)
2589 		return ENXIO;
2590 
2591 	switch (cp->dev) {
2592 
2593 	case GUSICS_MIC_IN_MUTE:	/* Microphone */
2594 		if (cp->type == AUDIO_MIXER_ENUM) {
2595 			DPRINTF(("mic mute %d\n", cp->un.ord));
2596 			if (HAS_MIXER(sc)) {
2597 				gusics_mic_mute(ic, cp->un.ord);
2598 			}
2599 			gus_mic_ctl(sc, cp->un.ord ? SPKR_OFF : SPKR_ON);
2600 			error = 0;
2601 		}
2602 		break;
2603 
2604 	case GUSICS_LINE_IN_MUTE:
2605 		if (cp->type == AUDIO_MIXER_ENUM) {
2606 			DPRINTF(("linein mute %d\n", cp->un.ord));
2607 			if (HAS_MIXER(sc)) {
2608 				gusics_linein_mute(ic, cp->un.ord);
2609 			}
2610 			gus_linein_ctl(sc, cp->un.ord ? SPKR_OFF : SPKR_ON);
2611 			error = 0;
2612 		}
2613 		break;
2614 
2615 	case GUSICS_MASTER_MUTE:
2616 		if (cp->type == AUDIO_MIXER_ENUM) {
2617 			DPRINTF(("master mute %d\n", cp->un.ord));
2618 			if (HAS_MIXER(sc)) {
2619 				gusics_master_mute(ic, cp->un.ord);
2620 			}
2621 			gus_speaker_ctl(sc, cp->un.ord ? SPKR_OFF : SPKR_ON);
2622 			error = 0;
2623 		}
2624 		break;
2625 
2626 	case GUSICS_DAC_MUTE:
2627 		if (cp->type == AUDIO_MIXER_ENUM) {
2628 			gusics_dac_mute(ic, cp->un.ord);
2629 			error = 0;
2630 		}
2631 		break;
2632 
2633 	case GUSICS_CD_MUTE:
2634 		if (cp->type == AUDIO_MIXER_ENUM) {
2635 			gusics_cd_mute(ic, cp->un.ord);
2636 			error = 0;
2637 		}
2638 		break;
2639 
2640 	case GUSICS_MASTER_LVL:
2641 		if (cp->type == AUDIO_MIXER_VALUE) {
2642 			if (ad1848_to_vol(cp, &vol)) {
2643 				ics2101_mix_attenuate(ic,
2644 						      GUSMIX_CHAN_MASTER,
2645 						      ICSMIX_LEFT,
2646 						      vol.left);
2647 				ics2101_mix_attenuate(ic,
2648 						      GUSMIX_CHAN_MASTER,
2649 						      ICSMIX_RIGHT,
2650 						      vol.right);
2651 				error = 0;
2652 			}
2653 		}
2654 		break;
2655 
2656 	case GUSICS_MIC_IN_LVL:	/* Microphone */
2657 		if (cp->type == AUDIO_MIXER_VALUE) {
2658 			if (ad1848_to_vol(cp, &vol)) {
2659 				ics2101_mix_attenuate(ic,
2660 						      GUSMIX_CHAN_MIC,
2661 						      ICSMIX_LEFT,
2662 						      vol.left);
2663 				ics2101_mix_attenuate(ic,
2664 						      GUSMIX_CHAN_MIC,
2665 						      ICSMIX_RIGHT,
2666 						      vol.right);
2667 				error = 0;
2668 			}
2669 		}
2670 		break;
2671 
2672 	case GUSICS_LINE_IN_LVL:	/* line in */
2673 		if (cp->type == AUDIO_MIXER_VALUE) {
2674 			if (ad1848_to_vol(cp, &vol)) {
2675 				ics2101_mix_attenuate(ic,
2676 						      GUSMIX_CHAN_LINE,
2677 						      ICSMIX_LEFT,
2678 						      vol.left);
2679 				ics2101_mix_attenuate(ic,
2680 						      GUSMIX_CHAN_LINE,
2681 						      ICSMIX_RIGHT,
2682 						      vol.right);
2683 				error = 0;
2684 			}
2685 		}
2686 		break;
2687 
2688 
2689 	case GUSICS_CD_LVL:
2690 		if (cp->type == AUDIO_MIXER_VALUE) {
2691 			if (ad1848_to_vol(cp, &vol)) {
2692 				ics2101_mix_attenuate(ic,
2693 						      GUSMIX_CHAN_CD,
2694 						      ICSMIX_LEFT,
2695 						      vol.left);
2696 				ics2101_mix_attenuate(ic,
2697 						      GUSMIX_CHAN_CD,
2698 						      ICSMIX_RIGHT,
2699 						      vol.right);
2700 				error = 0;
2701 			}
2702 		}
2703 		break;
2704 
2705 	case GUSICS_DAC_LVL:		/* dac out */
2706 		if (cp->type == AUDIO_MIXER_VALUE) {
2707 			if (ad1848_to_vol(cp, &vol)) {
2708 				ics2101_mix_attenuate(ic,
2709 						      GUSMIX_CHAN_DAC,
2710 						      ICSMIX_LEFT,
2711 						      vol.left);
2712 				ics2101_mix_attenuate(ic,
2713 						      GUSMIX_CHAN_DAC,
2714 						      ICSMIX_RIGHT,
2715 						      vol.right);
2716 				error = 0;
2717 			}
2718 		}
2719 		break;
2720 
2721 
2722 	case GUSICS_RECORD_SOURCE:
2723 		if (cp->type == AUDIO_MIXER_ENUM && cp->un.ord == 0) {
2724 			/* Can't set anything else useful, sigh. */
2725 			error = 0;
2726 		}
2727 		break;
2728 
2729 	default:
2730 		return ENXIO;
2731 	    /*NOTREACHED*/
2732 	}
2733 	return error;
2734 }
2735 
2736 int
2737 gus_get_props(void *addr)
2738 {
2739 	struct gus_softc *sc = addr;
2740 	return AUDIO_PROP_MMAP |
2741 		(sc->sc_recdrq == sc->sc_drq ? 0 : AUDIO_PROP_FULLDUPLEX);
2742 }
2743 
2744 int
2745 gusmax_get_props(void *addr)
2746 {
2747 	struct ad1848_softc *ac = addr;
2748 	return gus_get_props(ac->parent);
2749 }
2750 
2751 int
2752 gusmax_mixer_query_devinfo(void *addr, mixer_devinfo_t *dip)
2753 {
2754 	DPRINTF(("gusmax_query_devinfo: index=%d\n", dip->index));
2755 
2756 	switch(dip->index) {
2757 #if 0
2758     case GUSMAX_MIC_IN_LVL:	/* Microphone */
2759 	dip->type = AUDIO_MIXER_VALUE;
2760 	dip->mixer_class = GUSMAX_INPUT_CLASS;
2761 	dip->prev = AUDIO_MIXER_LAST;
2762 	dip->next = GUSMAX_MIC_IN_MUTE;
2763 	strlcpy(dip->label.name, AudioNmicrophone, sizeof dip->label.name);
2764 	dip->un.v.num_channels = 2;
2765 	strlcpy(dip->un.v.units.name, AudioNvolume,
2766 	    sizeof dip->un.v.units.name);
2767 	break;
2768 #endif
2769 
2770     case GUSMAX_MONO_LVL:	/* mono/microphone mixer */
2771 	dip->type = AUDIO_MIXER_VALUE;
2772 	dip->mixer_class = GUSMAX_INPUT_CLASS;
2773 	dip->prev = AUDIO_MIXER_LAST;
2774 	dip->next = GUSMAX_MONO_MUTE;
2775 	strlcpy(dip->label.name, AudioNmicrophone, sizeof dip->label.name);
2776 	dip->un.v.num_channels = 1;
2777 	strlcpy(dip->un.v.units.name, AudioNvolume,
2778 	    sizeof dip->un.v.units.name);
2779 	break;
2780 
2781     case GUSMAX_DAC_LVL:		/*  dacout */
2782 	dip->type = AUDIO_MIXER_VALUE;
2783 	dip->mixer_class = GUSMAX_INPUT_CLASS;
2784 	dip->prev = AUDIO_MIXER_LAST;
2785 	dip->next = GUSMAX_DAC_MUTE;
2786 	strlcpy(dip->label.name, AudioNdac, sizeof dip->label.name);
2787 	dip->un.v.num_channels = 2;
2788 	strlcpy(dip->un.v.units.name, AudioNvolume,
2789 	    sizeof dip->un.v.units.name);
2790 	break;
2791 
2792     case GUSMAX_LINE_IN_LVL:	/* line */
2793 	dip->type = AUDIO_MIXER_VALUE;
2794 	dip->mixer_class = GUSMAX_INPUT_CLASS;
2795 	dip->prev = AUDIO_MIXER_LAST;
2796 	dip->next = GUSMAX_LINE_IN_MUTE;
2797 	strlcpy(dip->label.name, AudioNline, sizeof dip->label.name);
2798 	dip->un.v.num_channels = 2;
2799 	strlcpy(dip->un.v.units.name, AudioNvolume,
2800 	    sizeof dip->un.v.units.name);
2801 	break;
2802 
2803     case GUSMAX_CD_LVL:		/* cd */
2804 	dip->type = AUDIO_MIXER_VALUE;
2805 	dip->mixer_class = GUSMAX_INPUT_CLASS;
2806 	dip->prev = AUDIO_MIXER_LAST;
2807 	dip->next = GUSMAX_CD_MUTE;
2808 	strlcpy(dip->label.name, AudioNcd, sizeof dip->label.name);
2809 	dip->un.v.num_channels = 2;
2810 	strlcpy(dip->un.v.units.name, AudioNvolume,
2811 	    sizeof dip->un.v.units.name);
2812 	break;
2813 
2814 
2815     case GUSMAX_MONITOR_LVL:	/* monitor level */
2816 	dip->type = AUDIO_MIXER_VALUE;
2817 	dip->mixer_class = GUSMAX_MONITOR_CLASS;
2818 	dip->next = GUSMAX_MONITOR_MUTE;
2819 	dip->prev = AUDIO_MIXER_LAST;
2820 	strlcpy(dip->label.name, AudioNmonitor, sizeof dip->label.name);
2821 	dip->un.v.num_channels = 1;
2822 	strlcpy(dip->un.v.units.name, AudioNvolume,
2823 	    sizeof dip->un.v.units.name);
2824 	break;
2825 
2826     case GUSMAX_OUT_LVL:		/* cs4231 output volume: not useful? */
2827 	dip->type = AUDIO_MIXER_VALUE;
2828 	dip->mixer_class = GUSMAX_MONITOR_CLASS;
2829 	dip->prev = dip->next = AUDIO_MIXER_LAST;
2830 	strlcpy(dip->label.name, AudioNoutput, sizeof dip->label.name);
2831 	dip->un.v.num_channels = 2;
2832 	strlcpy(dip->un.v.units.name, AudioNvolume,
2833 	    sizeof dip->un.v.units.name);
2834 	break;
2835 
2836     case GUSMAX_SPEAKER_LVL:		/* fake speaker volume */
2837 	dip->type = AUDIO_MIXER_VALUE;
2838 	dip->mixer_class = GUSMAX_MONITOR_CLASS;
2839 	dip->prev = AUDIO_MIXER_LAST;
2840 	dip->next = GUSMAX_SPEAKER_MUTE;
2841 	strlcpy(dip->label.name, AudioNmaster, sizeof dip->label.name);
2842 	dip->un.v.num_channels = 2;
2843 	strlcpy(dip->un.v.units.name, AudioNvolume,
2844 	    sizeof dip->un.v.units.name);
2845 	break;
2846 
2847     case GUSMAX_LINE_IN_MUTE:
2848 	dip->mixer_class = GUSMAX_INPUT_CLASS;
2849 	dip->type = AUDIO_MIXER_ENUM;
2850 	dip->prev = GUSMAX_LINE_IN_LVL;
2851 	dip->next = AUDIO_MIXER_LAST;
2852 	goto mute;
2853 
2854     case GUSMAX_DAC_MUTE:
2855 	dip->mixer_class = GUSMAX_INPUT_CLASS;
2856 	dip->type = AUDIO_MIXER_ENUM;
2857 	dip->prev = GUSMAX_DAC_LVL;
2858 	dip->next = AUDIO_MIXER_LAST;
2859 	goto mute;
2860 
2861     case GUSMAX_CD_MUTE:
2862 	dip->mixer_class = GUSMAX_INPUT_CLASS;
2863 	dip->type = AUDIO_MIXER_ENUM;
2864 	dip->prev = GUSMAX_CD_LVL;
2865 	dip->next = AUDIO_MIXER_LAST;
2866 	goto mute;
2867 
2868     case GUSMAX_MONO_MUTE:
2869 	dip->mixer_class = GUSMAX_INPUT_CLASS;
2870 	dip->type = AUDIO_MIXER_ENUM;
2871 	dip->prev = GUSMAX_MONO_LVL;
2872 	dip->next = AUDIO_MIXER_LAST;
2873 	goto mute;
2874 
2875     case GUSMAX_MONITOR_MUTE:
2876 	dip->mixer_class = GUSMAX_OUTPUT_CLASS;
2877 	dip->type = AUDIO_MIXER_ENUM;
2878 	dip->prev = GUSMAX_MONITOR_LVL;
2879 	dip->next = AUDIO_MIXER_LAST;
2880 	goto mute;
2881 
2882     case GUSMAX_SPEAKER_MUTE:
2883 	dip->mixer_class = GUSMAX_OUTPUT_CLASS;
2884 	dip->type = AUDIO_MIXER_ENUM;
2885 	dip->prev = GUSMAX_SPEAKER_LVL;
2886 	dip->next = AUDIO_MIXER_LAST;
2887     mute:
2888 	strlcpy(dip->label.name, AudioNmute, sizeof dip->label.name);
2889 	dip->un.e.num_mem = 2;
2890 	strlcpy(dip->un.e.member[0].label.name, AudioNoff,
2891 	    sizeof dip->un.e.member[0].label.name);
2892 	dip->un.e.member[0].ord = 0;
2893 	strlcpy(dip->un.e.member[1].label.name, AudioNon,
2894 	    sizeof dip->un.e.member[1].label.name);
2895 	dip->un.e.member[1].ord = 1;
2896 	break;
2897 
2898     case GUSMAX_REC_LVL:	/* record level */
2899 	dip->type = AUDIO_MIXER_VALUE;
2900 	dip->mixer_class = GUSMAX_RECORD_CLASS;
2901 	dip->prev = AUDIO_MIXER_LAST;
2902 	dip->next = GUSMAX_RECORD_SOURCE;
2903 	strlcpy(dip->label.name, AudioNrecord, sizeof dip->label.name);
2904 	dip->un.v.num_channels = 2;
2905 	strlcpy(dip->un.v.units.name, AudioNvolume, sizeof dip->un.v.units.name);
2906 	break;
2907 
2908     case GUSMAX_RECORD_SOURCE:
2909 	dip->mixer_class = GUSMAX_RECORD_CLASS;
2910 	dip->type = AUDIO_MIXER_ENUM;
2911 	dip->prev = GUSMAX_REC_LVL;
2912 	dip->next = AUDIO_MIXER_LAST;
2913 	strlcpy(dip->label.name, AudioNsource, sizeof dip->label.name);
2914 	dip->un.e.num_mem = 4;
2915 	strlcpy(dip->un.e.member[0].label.name, AudioNoutput,
2916 	    sizeof dip->un.e.member[0].label.name);
2917 	dip->un.e.member[0].ord = DAC_IN_PORT;
2918 	strlcpy(dip->un.e.member[1].label.name, AudioNmicrophone,
2919 	    sizeof dip->un.e.member[1].label.name);
2920 	dip->un.e.member[1].ord = MIC_IN_PORT;
2921 	strlcpy(dip->un.e.member[2].label.name, AudioNdac,
2922 	    sizeof dip->un.e.member[2].label.name);
2923 	dip->un.e.member[2].ord = AUX1_IN_PORT;
2924 	strlcpy(dip->un.e.member[3].label.name, AudioNline,
2925 	    sizeof dip->un.e.member[3].label.name);
2926 	dip->un.e.member[3].ord = LINE_IN_PORT;
2927 	break;
2928 
2929     case GUSMAX_INPUT_CLASS:			/* input class descriptor */
2930 	dip->type = AUDIO_MIXER_CLASS;
2931 	dip->mixer_class = GUSMAX_INPUT_CLASS;
2932 	dip->next = dip->prev = AUDIO_MIXER_LAST;
2933 	strlcpy(dip->label.name, AudioCinputs, sizeof dip->label.name);
2934 	break;
2935 
2936     case GUSMAX_OUTPUT_CLASS:			/* output class descriptor */
2937 	dip->type = AUDIO_MIXER_CLASS;
2938 	dip->mixer_class = GUSMAX_OUTPUT_CLASS;
2939 	dip->next = dip->prev = AUDIO_MIXER_LAST;
2940 	strlcpy(dip->label.name, AudioCoutputs, sizeof dip->label.name);
2941 	break;
2942 
2943     case GUSMAX_MONITOR_CLASS:			/* monitor class descriptor */
2944 	dip->type = AUDIO_MIXER_CLASS;
2945 	dip->mixer_class = GUSMAX_MONITOR_CLASS;
2946 	dip->next = dip->prev = AUDIO_MIXER_LAST;
2947 	strlcpy(dip->label.name, AudioCmonitor, sizeof dip->label.name);
2948 	break;
2949 
2950     case GUSMAX_RECORD_CLASS:			/* record source class */
2951 	dip->type = AUDIO_MIXER_CLASS;
2952 	dip->mixer_class = GUSMAX_RECORD_CLASS;
2953 	dip->next = dip->prev = AUDIO_MIXER_LAST;
2954 	strlcpy(dip->label.name, AudioCrecord, sizeof dip->label.name);
2955 	break;
2956 
2957     default:
2958 	return ENXIO;
2959 	/*NOTREACHED*/
2960     }
2961     DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name));
2962 	return 0;
2963 }
2964 
2965 int
2966 gus_mixer_query_devinfo(void *addr, mixer_devinfo_t *dip)
2967 {
2968 	struct gus_softc *sc = addr;
2969 
2970 	DPRINTF(("gusmax_query_devinfo: index=%d\n", dip->index));
2971 
2972 	if (!HAS_MIXER(sc) && dip->index > GUSICS_MASTER_MUTE)
2973 		return ENXIO;
2974 
2975 	switch(dip->index) {
2976 
2977 	case GUSICS_MIC_IN_LVL:	/* Microphone */
2978 		dip->type = AUDIO_MIXER_VALUE;
2979 		dip->mixer_class = GUSICS_INPUT_CLASS;
2980 		dip->prev = AUDIO_MIXER_LAST;
2981 		dip->next = GUSICS_MIC_IN_MUTE;
2982 		strlcpy(dip->label.name, AudioNmicrophone,
2983 		    sizeof dip->label.name);
2984 		dip->un.v.num_channels = 2;
2985 		strlcpy(dip->un.v.units.name, AudioNvolume,
2986 		    sizeof dip->un.v.units.name);
2987 		break;
2988 
2989 	case GUSICS_LINE_IN_LVL:	/* line */
2990 		dip->type = AUDIO_MIXER_VALUE;
2991 		dip->mixer_class = GUSICS_INPUT_CLASS;
2992 		dip->prev = AUDIO_MIXER_LAST;
2993 		dip->next = GUSICS_LINE_IN_MUTE;
2994 		strlcpy(dip->label.name, AudioNline, sizeof dip->label.name);
2995 		dip->un.v.num_channels = 2;
2996 		strlcpy(dip->un.v.units.name, AudioNvolume,
2997 		    sizeof dip->un.v.units.name);
2998 		break;
2999 
3000 	case GUSICS_CD_LVL:		/* cd */
3001 		dip->type = AUDIO_MIXER_VALUE;
3002 		dip->mixer_class = GUSICS_INPUT_CLASS;
3003 		dip->prev = AUDIO_MIXER_LAST;
3004 		dip->next = GUSICS_CD_MUTE;
3005 		strlcpy(dip->label.name, AudioNcd, sizeof dip->label.name);
3006 		dip->un.v.num_channels = 2;
3007 		strlcpy(dip->un.v.units.name, AudioNvolume,
3008 		    sizeof dip->un.v.units.name);
3009 		break;
3010 
3011 	case GUSICS_DAC_LVL:		/*  dacout */
3012 		dip->type = AUDIO_MIXER_VALUE;
3013 		dip->mixer_class = GUSICS_INPUT_CLASS;
3014 		dip->prev = AUDIO_MIXER_LAST;
3015 		dip->next = GUSICS_DAC_MUTE;
3016 		strlcpy(dip->label.name, AudioNdac, sizeof dip->label.name);
3017 		dip->un.v.num_channels = 2;
3018 		strlcpy(dip->un.v.units.name, AudioNvolume,
3019 		    sizeof dip->un.v.units.name);
3020 		break;
3021 
3022 	case GUSICS_MASTER_LVL:		/*  master output */
3023 		dip->type = AUDIO_MIXER_VALUE;
3024 		dip->mixer_class = GUSICS_OUTPUT_CLASS;
3025 		dip->prev = AUDIO_MIXER_LAST;
3026 		dip->next = GUSICS_MASTER_MUTE;
3027 		strlcpy(dip->label.name, AudioNmaster, sizeof dip->label.name);
3028 		dip->un.v.num_channels = 2;
3029 		strlcpy(dip->un.v.units.name, AudioNvolume,
3030 		    sizeof dip->un.v.units.name);
3031 		break;
3032 
3033 
3034 	case GUSICS_LINE_IN_MUTE:
3035 		dip->mixer_class = GUSICS_INPUT_CLASS;
3036 		dip->type = AUDIO_MIXER_ENUM;
3037 		dip->prev = GUSICS_LINE_IN_LVL;
3038 		dip->next = AUDIO_MIXER_LAST;
3039 		goto mute;
3040 
3041 	case GUSICS_DAC_MUTE:
3042 		dip->mixer_class = GUSICS_INPUT_CLASS;
3043 		dip->type = AUDIO_MIXER_ENUM;
3044 		dip->prev = GUSICS_DAC_LVL;
3045 		dip->next = AUDIO_MIXER_LAST;
3046 		goto mute;
3047 
3048 	case GUSICS_CD_MUTE:
3049 		dip->mixer_class = GUSICS_INPUT_CLASS;
3050 		dip->type = AUDIO_MIXER_ENUM;
3051 		dip->prev = GUSICS_CD_LVL;
3052 		dip->next = AUDIO_MIXER_LAST;
3053 		goto mute;
3054 
3055 	case GUSICS_MIC_IN_MUTE:
3056 		dip->mixer_class = GUSICS_INPUT_CLASS;
3057 		dip->type = AUDIO_MIXER_ENUM;
3058 		dip->prev = GUSICS_MIC_IN_LVL;
3059 		dip->next = AUDIO_MIXER_LAST;
3060 		goto mute;
3061 
3062 	case GUSICS_MASTER_MUTE:
3063 		dip->mixer_class = GUSICS_OUTPUT_CLASS;
3064 		dip->type = AUDIO_MIXER_ENUM;
3065 		dip->prev = GUSICS_MASTER_LVL;
3066 		dip->next = AUDIO_MIXER_LAST;
3067 mute:
3068 		strlcpy(dip->label.name, AudioNmute, sizeof dip->label.name);
3069 		dip->un.e.num_mem = 2;
3070 		strlcpy(dip->un.e.member[0].label.name, AudioNoff,
3071 		    sizeof dip->un.e.member[0].label.name);
3072 		dip->un.e.member[0].ord = 0;
3073 		strlcpy(dip->un.e.member[1].label.name, AudioNon,
3074 		    sizeof dip->un.e.member[1].label.name);
3075 		dip->un.e.member[1].ord = 1;
3076 		break;
3077 
3078 	case GUSICS_RECORD_SOURCE:
3079 		dip->mixer_class = GUSICS_RECORD_CLASS;
3080 		dip->type = AUDIO_MIXER_ENUM;
3081 		dip->prev = dip->next = AUDIO_MIXER_LAST;
3082 		strlcpy(dip->label.name, AudioNsource, sizeof dip->label.name);
3083 		dip->un.e.num_mem = 1;
3084 		strlcpy(dip->un.e.member[0].label.name, AudioNoutput,
3085 		    sizeof dip->un.e.member[0].label.name);
3086 		dip->un.e.member[0].ord = GUSICS_MASTER_LVL;
3087 		break;
3088 
3089 	case GUSICS_INPUT_CLASS:
3090 		dip->type = AUDIO_MIXER_CLASS;
3091 		dip->mixer_class = GUSICS_INPUT_CLASS;
3092 		dip->next = dip->prev = AUDIO_MIXER_LAST;
3093 		strlcpy(dip->label.name, AudioCinputs, sizeof dip->label.name);
3094 		break;
3095 
3096 	case GUSICS_OUTPUT_CLASS:
3097 		dip->type = AUDIO_MIXER_CLASS;
3098 		dip->mixer_class = GUSICS_OUTPUT_CLASS;
3099 		dip->next = dip->prev = AUDIO_MIXER_LAST;
3100 		strlcpy(dip->label.name, AudioCoutputs, sizeof dip->label.name);
3101 		break;
3102 
3103 	case GUSICS_RECORD_CLASS:
3104 		dip->type = AUDIO_MIXER_CLASS;
3105 		dip->mixer_class = GUSICS_RECORD_CLASS;
3106 		dip->next = dip->prev = AUDIO_MIXER_LAST;
3107 		strlcpy(dip->label.name, AudioCrecord, sizeof dip->label.name);
3108 		break;
3109 
3110 	default:
3111 		return ENXIO;
3112 	/*NOTREACHED*/
3113 	}
3114 	DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name));
3115 	return 0;
3116 }
3117 
3118 int
3119 gus_query_encoding(void *addr, struct audio_encoding *fp)
3120 {
3121 	switch (fp->index) {
3122 	case 0:
3123 		strlcpy(fp->name, AudioEslinear, sizeof fp->name);
3124 		fp->encoding = AUDIO_ENCODING_SLINEAR;
3125 		fp->precision = 8;
3126 		fp->flags = 0;
3127 		break;
3128 	case 1:
3129 		strlcpy(fp->name, AudioEslinear_le, sizeof fp->name);
3130 		fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
3131 		fp->precision = 16;
3132 		fp->flags = 0;
3133 		break;
3134 	case 2:
3135 		strlcpy(fp->name, AudioEulinear, sizeof fp->name);
3136 		fp->encoding = AUDIO_ENCODING_ULINEAR;
3137 		fp->precision = 8;
3138 		fp->flags = 0;
3139 		break;
3140 	case 3:
3141 		strlcpy(fp->name, AudioEulinear_le, sizeof fp->name);
3142 		fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
3143 		fp->precision = 16;
3144 		fp->flags = 0;
3145 		break;
3146 	default:
3147 		return(EINVAL);
3148 		/*NOTREACHED*/
3149 	}
3150 	fp->bps = AUDIO_BPS(fp->precision);
3151 	fp->msb = 1;
3152 
3153 	return (0);
3154 }
3155 
3156 void *
3157 gus_malloc(void *addr, int direction, size_t size, int pool, int flags)
3158 {
3159 	struct gus_softc *sc = addr;
3160 	int drq;
3161 
3162 	if (direction == AUMODE_PLAY)
3163 		drq = sc->sc_drq;
3164 	else
3165 		drq = sc->sc_recdrq;
3166 
3167 	return isa_malloc(sc->sc_isa, drq, size, pool, flags);
3168 }
3169 
3170 void
3171 gus_free(void *addr, void *ptr, int pool)
3172 {
3173 	isa_free(ptr, pool);
3174 }
3175 
3176 size_t
3177 gus_round(void *addr, int direction, size_t size)
3178 {
3179 	if (size > MAX_ISADMA)
3180 		size = MAX_ISADMA;
3181 	return size;
3182 }
3183 
3184 paddr_t
3185 gus_mappage(void *addr, void *mem, off_t off, int prot)
3186 {
3187 	return isa_mappage(mem, off, prot);
3188 }
3189 
3190 /*
3191  * Setup the ICS mixer in "transparent" mode: reset everything to a sensible
3192  * level.  Levels as suggested by GUS SDK code.
3193  */
3194 
3195 void
3196 gus_init_ics2101(struct gus_softc *sc)
3197 {
3198 	struct ics2101_softc *ic = &sc->sc_mixer;
3199 	sc->sc_mixer.sc_iot = sc->sc_iot;
3200 	sc->sc_mixer.sc_selio = GUS_MIXER_SELECT;
3201 	sc->sc_mixer.sc_selio_ioh = sc->sc_ioh3;
3202 	sc->sc_mixer.sc_dataio = GUS_MIXER_DATA;
3203 	sc->sc_mixer.sc_dataio_ioh = sc->sc_ioh2;
3204 	sc->sc_mixer.sc_flags = (sc->sc_revision == 5) ? ICS_FLIP : 0;
3205 
3206 	ics2101_mix_attenuate(ic,
3207 			      GUSMIX_CHAN_MIC,
3208 			      ICSMIX_LEFT,
3209 			      ICSMIX_MIN_ATTN);
3210 	ics2101_mix_attenuate(ic,
3211 			      GUSMIX_CHAN_MIC,
3212 			      ICSMIX_RIGHT,
3213 			      ICSMIX_MIN_ATTN);
3214 	/*
3215 	 * Start with microphone muted by the mixer...
3216 	 */
3217 	gusics_mic_mute(ic, 1);
3218 
3219 	/* ... and enabled by the GUS master mix control */
3220 	gus_mic_ctl(sc, SPKR_ON);
3221 
3222 	ics2101_mix_attenuate(ic,
3223 			      GUSMIX_CHAN_LINE,
3224 			      ICSMIX_LEFT,
3225 			      ICSMIX_MIN_ATTN);
3226 	ics2101_mix_attenuate(ic,
3227 			      GUSMIX_CHAN_LINE,
3228 			      ICSMIX_RIGHT,
3229 			      ICSMIX_MIN_ATTN);
3230 
3231 	ics2101_mix_attenuate(ic,
3232 			      GUSMIX_CHAN_CD,
3233 			      ICSMIX_LEFT,
3234 			      ICSMIX_MIN_ATTN);
3235 	ics2101_mix_attenuate(ic,
3236 			      GUSMIX_CHAN_CD,
3237 			      ICSMIX_RIGHT,
3238 			      ICSMIX_MIN_ATTN);
3239 
3240 	ics2101_mix_attenuate(ic,
3241 			      GUSMIX_CHAN_DAC,
3242 			      ICSMIX_LEFT,
3243 			      ICSMIX_MIN_ATTN);
3244 	ics2101_mix_attenuate(ic,
3245 			      GUSMIX_CHAN_DAC,
3246 			      ICSMIX_RIGHT,
3247 			      ICSMIX_MIN_ATTN);
3248 
3249 	ics2101_mix_attenuate(ic,
3250 			      ICSMIX_CHAN_4,
3251 			      ICSMIX_LEFT,
3252 			      ICSMIX_MAX_ATTN);
3253 	ics2101_mix_attenuate(ic,
3254 			      ICSMIX_CHAN_4,
3255 			      ICSMIX_RIGHT,
3256 			      ICSMIX_MAX_ATTN);
3257 
3258 	ics2101_mix_attenuate(ic,
3259 			      GUSMIX_CHAN_MASTER,
3260 			      ICSMIX_LEFT,
3261 			      ICSMIX_MIN_ATTN);
3262 	ics2101_mix_attenuate(ic,
3263 			      GUSMIX_CHAN_MASTER,
3264 			      ICSMIX_RIGHT,
3265 			      ICSMIX_MIN_ATTN);
3266 	/* unmute other stuff: */
3267 	gusics_cd_mute(ic, 0);
3268 	gusics_dac_mute(ic, 0);
3269 	gusics_linein_mute(ic, 0);
3270 	return;
3271 }
3272 
3273 
3274 
3275 void
3276 gus_subattach(struct gus_softc *sc, struct isa_attach_args *ia)
3277 {
3278 	int		i;
3279 	bus_space_tag_t iot;
3280 	unsigned char	c,d,m;
3281 
3282 	iot = sc->sc_iot;
3283 
3284 	/*
3285 	 * Figure out our board rev, and see if we need to initialize the
3286 	 * mixer
3287 	 */
3288 
3289 	c = bus_space_read_1(iot, sc->sc_ioh3, GUS_BOARD_REV);
3290 	if (c != 0xff)
3291 		sc->sc_revision = c;
3292 	else
3293 		sc->sc_revision = 0;
3294 
3295 	SELECT_GUS_REG(iot, sc->sc_ioh2, GUSREG_RESET);
3296 	bus_space_write_1(iot, sc->sc_ioh2, GUS_DATA_HIGH, 0x00);
3297 
3298 	gusreset(sc, GUS_MAX_VOICES); /* initialize all voices */
3299 	gusreset(sc, GUS_MIN_VOICES); /* then set to just the ones we use */
3300 
3301 	/*
3302 	 * Setup the IRQ and DRQ lines in software, using values from
3303 	 * config file
3304 	 */
3305 
3306 	m = GUSMASK_LINE_IN|GUSMASK_LINE_OUT;		/* disable all */
3307 
3308 	c = ((unsigned char) gus_irq_map[ia->ia_irq]) | GUSMASK_BOTH_RQ;
3309 
3310 	if (sc->sc_recdrq == sc->sc_drq)
3311 		d = (unsigned char) (gus_drq_map[sc->sc_drq] |
3312 				GUSMASK_BOTH_RQ);
3313 	else
3314 		d = (unsigned char) (gus_drq_map[sc->sc_drq] |
3315 				gus_drq_map[sc->sc_recdrq] << 3);
3316 
3317 	/*
3318 	 * Program the IRQ and DMA channels on the GUS.  Note that we hardwire
3319 	 * the GUS to only use one IRQ channel, but we give the user the
3320 	 * option of using two DMA channels (the other one given by the drq2
3321 	 * option in the config file).  Two DMA channels are needed for full-
3322 	 * duplex operation.
3323 	 *
3324 	 * The order of these operations is very magical.
3325 	 */
3326 
3327 	disable_intr();		/* XXX needed? */
3328 
3329 	bus_space_write_1(iot, sc->sc_ioh1, GUS_REG_CONTROL, GUS_REG_IRQCTL);
3330 	bus_space_write_1(iot, sc->sc_ioh1, GUS_MIX_CONTROL, m);
3331 	bus_space_write_1(iot, sc->sc_ioh1, GUS_IRQCTL_CONTROL, 0x00);
3332 	bus_space_write_1(iot, sc->sc_ioh1, 0x0f, 0x00);
3333 
3334 	bus_space_write_1(iot, sc->sc_ioh1, GUS_MIX_CONTROL, m);
3335 
3336 	/* magic reset? */
3337 	bus_space_write_1(iot, sc->sc_ioh1, GUS_DMA_CONTROL, d | 0x80);
3338 
3339 	bus_space_write_1(iot, sc->sc_ioh1, GUS_MIX_CONTROL,
3340 	    m | GUSMASK_CONTROL_SEL);
3341 	bus_space_write_1(iot, sc->sc_ioh1, GUS_IRQ_CONTROL, c);
3342 
3343 	bus_space_write_1(iot, sc->sc_ioh1, GUS_MIX_CONTROL, m);
3344 	bus_space_write_1(iot, sc->sc_ioh1, GUS_DMA_CONTROL, d);
3345 
3346 	bus_space_write_1(iot, sc->sc_ioh1, GUS_MIX_CONTROL,
3347 	    m | GUSMASK_CONTROL_SEL);
3348 	bus_space_write_1(iot, sc->sc_ioh1, GUS_IRQ_CONTROL, c);
3349 
3350 	bus_space_write_1(iot, sc->sc_ioh2, GUS_VOICE_SELECT, 0x00);
3351 
3352 	/* enable line in, line out.  leave mic disabled. */
3353 	bus_space_write_1(iot, sc->sc_ioh1, GUS_MIX_CONTROL,
3354 	     (m | GUSMASK_LATCHES) & ~(GUSMASK_LINE_OUT|GUSMASK_LINE_IN));
3355 	bus_space_write_1(iot, sc->sc_ioh2, GUS_VOICE_SELECT, 0x00);
3356 
3357 	enable_intr();
3358 
3359 	sc->sc_mixcontrol =
3360 		(m | GUSMASK_LATCHES) & ~(GUSMASK_LINE_OUT|GUSMASK_LINE_IN);
3361 
3362 	sc->sc_codec.sc_isa = sc->sc_isa;
3363 
3364 	if (sc->sc_revision >= 5 && sc->sc_revision <= 9) {
3365 		sc->sc_flags |= GUS_MIXER_INSTALLED;
3366 		gus_init_ics2101(sc);
3367 	}
3368 	if (sc->sc_revision < 10 || !gus_init_cs4231(sc)) {
3369 		/* Not using the CS4231, so create our DMA maps. */
3370 		if (sc->sc_drq != -1) {
3371 			if (isa_dmamap_create(sc->sc_isa, sc->sc_drq,
3372 			    MAX_ISADMA, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW)) {
3373 				printf("%s: can't create map for drq %d\n",
3374 				       sc->sc_dev.dv_xname, sc->sc_drq);
3375 				return;
3376 			}
3377 		}
3378 		if (sc->sc_recdrq != -1 && sc->sc_recdrq != sc->sc_drq) {
3379 			if (isa_dmamap_create(sc->sc_isa, sc->sc_recdrq,
3380 			    MAX_ISADMA, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW)) {
3381 				printf("%s: can't create map for drq %d\n",
3382 				       sc->sc_dev.dv_xname, sc->sc_recdrq);
3383 				return;
3384 			}
3385 		}
3386 	}
3387 
3388 	timeout_set(&sc->sc_dma_tmo, gus_dmaout_timeout, sc);
3389 
3390 	SELECT_GUS_REG(iot, sc->sc_ioh2, GUSREG_RESET);
3391 	/*
3392 	 * Check to see how much memory we have on this card; see if any
3393 	 * "mirroring" occurs.  We're assuming at least 256K already exists
3394 	 * on the card; otherwise the initial probe would have failed
3395 	 */
3396 
3397 	guspoke(iot, sc->sc_ioh2, 0L, 0x00);
3398 	for(i = 1; i < 1024; i++) {
3399 		u_long loc;
3400 
3401 		/*
3402 		 * See if we've run into mirroring yet
3403 		 */
3404 
3405 		if (guspeek(iot, sc->sc_ioh2, 0L) != 0)
3406 			break;
3407 
3408 		loc = i << 10;
3409 
3410 		guspoke(iot, sc->sc_ioh2, loc, 0xaa);
3411 		if (guspeek(iot, sc->sc_ioh2, loc) != 0xaa)
3412 			break;
3413 	}
3414 
3415 	sc->sc_dsize = i;
3416 	/*
3417 	 * The "official" (3.x) version number cannot easily be obtained.
3418 	 * The revision register does not correspond to the minor number
3419 	 * of the board version. Simply use the revision register as
3420 	 * identification.
3421 	 */
3422 	snprintf(gus_device.version, sizeof gus_device.version, "%d",
3423 	    sc->sc_revision);
3424 
3425 	printf(": ver %d", sc->sc_revision);
3426 	if (sc->sc_revision >= 10)
3427 		printf(", MAX");
3428 	else {
3429 		if (HAS_MIXER(sc))
3430 			printf(", ICS2101 mixer");
3431 		if (HAS_CODEC(sc))
3432 			printf(", %s codec/mixer", sc->sc_codec.chip_name);
3433 	}
3434 	printf(", %dKB DRAM, ", sc->sc_dsize);
3435 	if (sc->sc_recdrq == sc->sc_drq) {
3436 		printf("half-duplex");
3437 	} else {
3438 		printf("full-duplex, record drq %d", sc->sc_recdrq);
3439 	}
3440 
3441 	printf("\n");
3442 
3443 	/*
3444 	 * Setup a default interrupt handler
3445 	 */
3446 
3447 	sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq,
3448 	    IST_EDGE, IPL_AUDIO | IPL_MPSAFE,
3449 	    gusintr, sc /* sc->sc_gusdsp */, sc->sc_dev.dv_xname);
3450 
3451 	/*
3452 	 * Set some default values
3453 	 * XXX others start with 8kHz mono mulaw
3454 	 */
3455 
3456 	sc->sc_irate = sc->sc_orate = 44100;
3457 	sc->sc_encoding = AUDIO_ENCODING_SLINEAR_LE;
3458 	sc->sc_precision = 16;
3459 	sc->sc_voc[GUS_VOICE_LEFT].voccntl |= GUSMASK_DATA_SIZE16;
3460 	sc->sc_voc[GUS_VOICE_RIGHT].voccntl |= GUSMASK_DATA_SIZE16;
3461 	sc->sc_channels = 1;
3462 	sc->sc_ogain = 340;
3463 	gus_commit_settings(sc);
3464 
3465 	/*
3466 	 * We always put the left channel full left & right channel
3467 	 * full right.
3468 	 * For mono playback, we set up both voices playing the same buffer.
3469 	 */
3470 	bus_space_write_1(iot, sc->sc_ioh2, GUS_VOICE_SELECT,
3471 	    (u_char)GUS_VOICE_LEFT);
3472 	SELECT_GUS_REG(iot, sc->sc_ioh2, GUSREG_PAN_POS);
3473 	bus_space_write_1(iot, sc->sc_ioh2, GUS_DATA_HIGH, GUS_PAN_FULL_LEFT);
3474 
3475 	bus_space_write_1(iot, sc->sc_ioh2, GUS_VOICE_SELECT,
3476 	    (u_char)GUS_VOICE_RIGHT);
3477 	SELECT_GUS_REG(iot, sc->sc_ioh2, GUSREG_PAN_POS);
3478 	bus_space_write_1(iot, sc->sc_ioh2, GUS_DATA_HIGH, GUS_PAN_FULL_RIGHT);
3479 
3480 	/*
3481 	 * Attach to the generic audio layer
3482 	 */
3483 
3484 	audio_attach_mi(&gus_hw_if, HAS_CODEC(sc) ? (void *)&sc->sc_codec :
3485 	    (void *)sc, &sc->sc_dev);
3486 }
3487 
3488 /*
3489  * Test to see if a particular I/O base is valid for the GUS.  Return true
3490  * if it is.
3491  */
3492 
3493 int
3494 gus_test_iobase (bus_space_tag_t iot, int iobase)
3495 {
3496 	bus_space_handle_t ioh1, ioh2, ioh3, ioh4;
3497 	u_char s1, s2;
3498 	int rv = 0;
3499 
3500 	/* Map i/o space */
3501 	if (bus_space_map(iot, iobase, GUS_NPORT1, 0, &ioh1))
3502 		return 0;
3503 	if (bus_space_map(iot, iobase+GUS_IOH2_OFFSET, GUS_NPORT2, 0, &ioh2))
3504 		goto bad1;
3505 
3506 	/* XXX Maybe we shouldn't fail on mapping this, but just assume
3507 	 * the card is of revision 0? */
3508 	if (bus_space_map(iot, iobase+GUS_IOH3_OFFSET, GUS_NPORT3, 0, &ioh3))
3509 		goto bad2;
3510 
3511 	if (bus_space_map(iot, iobase+GUS_IOH4_OFFSET, GUS_NPORT4, 0, &ioh4))
3512 		goto bad3;
3513 
3514 	/*
3515 	 * Reset GUS to an initial state before we do anything.
3516 	 */
3517 
3518 	mtx_enter(&audio_lock);
3519 	delay(500);
3520 
3521 	SELECT_GUS_REG(iot, ioh2, GUSREG_RESET);
3522 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x00);
3523 
3524 	delay(500);
3525 
3526 	SELECT_GUS_REG(iot, ioh2, GUSREG_RESET);
3527 	bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, GUSMASK_MASTER_RESET);
3528 
3529 	delay(500);
3530 
3531 	mtx_leave(&audio_lock);
3532 
3533 	/*
3534 	 * See if we can write to the board's memory
3535 	 */
3536 
3537 	s1 = guspeek(iot, ioh2, 0L);
3538 	s2 = guspeek(iot, ioh2, 1L);
3539 
3540 	guspoke(iot, ioh2, 0L, 0xaa);
3541 	guspoke(iot, ioh2, 1L, 0x55);
3542 
3543 	if (guspeek(iot, ioh2, 0L) != 0xaa)
3544 		goto bad;
3545 
3546 	guspoke(iot, ioh2, 0L, s1);
3547 	guspoke(iot, ioh2, 1L, s2);
3548 
3549 	rv = 1;
3550 
3551 bad:
3552 	bus_space_unmap(iot, ioh4, GUS_NPORT4);
3553 bad3:
3554 	bus_space_unmap(iot, ioh3, GUS_NPORT3);
3555 bad2:
3556 	bus_space_unmap(iot, ioh2, GUS_NPORT2);
3557 bad1:
3558 	bus_space_unmap(iot, ioh1, GUS_NPORT1);
3559 	return rv;
3560 }
3561