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