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