gus.c revision 1.42
1/*	$NetBSD: gus.c,v 1.42 1997/08/26 19:27:21 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, int, struct audio_params *, struct audio_params *));
361int 	gusmax_set_params __P((void *, int, 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	int iobase = ia->ia_iobase;
662	int recdrq = ia->ia_drq2;
663
664	sc->sc_iot = ia->ia_iot;
665	/*
666	 * Before we do anything else, make sure requested IRQ and DRQ are
667	 * valid for this card.
668	 */
669
670	if (ia->ia_irq == IRQUNK || gus_irq_map[ia->ia_irq] == IRQUNK) {
671		printf("gus: invalid irq %d, card not probed\n", ia->ia_irq);
672		return(0);
673	}
674
675	if (ia->ia_drq == DRQUNK || gus_drq_map[ia->ia_drq] == DRQUNK) {
676		printf("gus: invalid drq %d, card not probed\n", ia->ia_drq);
677		return(0);
678	}
679
680	if (recdrq != DRQUNK) {
681		if (recdrq > 7 || gus_drq_map[recdrq] == DRQUNK) {
682		   printf("gus: invalid second DMA channel (%d), card not probed\n", recdrq);
683		   return(0);
684	        }
685	} else
686		recdrq = ia->ia_drq;
687
688	if (iobase == IOBASEUNK) {
689		int i;
690		for(i = 0; i < gus_addrs; i++)
691			if (gus_test_iobase(gus_base_addrs[i])) {
692				iobase = gus_base_addrs[i];
693				goto done;
694			}
695		return 0;
696	} else if (! gus_test_iobase(iobase))
697			return 0;
698
699done:
700	sc->sc_iobase = iobase;
701	sc->sc_irq = ia->ia_irq;
702	sc->sc_drq = ia->ia_drq;
703	sc->sc_recdrq = recdrq;
704
705	ia->ia_iobase = sc->sc_iobase;
706	ia->ia_iosize = 16;		/* XXX */
707	return(1);
708}
709
710/*
711 * Test to see if a particular I/O base is valid for the GUS.  Return true
712 * if it is.
713 */
714
715STATIC int
716gus_test_iobase (int iobase)
717{
718	int i = splgus();
719	u_char s1, s2;
720
721	/*
722	 * Reset GUS to an initial state before we do anything.
723	 */
724
725	delay(500);
726
727 	SELECT_GUS_REG(iobase, GUSREG_RESET);
728 	outb(iobase+GUS_DATA_HIGH, 0x00);
729
730 	delay(500);
731
732	SELECT_GUS_REG(iobase, GUSREG_RESET);
733 	outb(iobase+GUS_DATA_HIGH, GUSMASK_MASTER_RESET);
734
735 	delay(500);
736
737	splx(i);
738
739	/*
740	 * See if we can write to the board's memory
741	 */
742
743 	s1 = guspeek(iobase, 0L);
744 	s2 = guspeek(iobase, 1L);
745
746 	guspoke(iobase, 0L, 0xaa);
747 	guspoke(iobase, 1L, 0x55);
748
749 	if ((i=(int)guspeek(iobase, 0L)) != 0xaa) {
750		return(0);
751	}
752
753	guspoke(iobase, 0L, s1);
754	guspoke(iobase, 1L, s2);
755
756	return 1;
757}
758
759/*
760 * Setup the GUS for use; called shortly after probe
761 */
762
763void
764gusattach(parent, self, aux)
765	struct device *parent, *self;
766	void *aux;
767{
768	struct gus_softc *sc = (void *) self;
769	struct isa_attach_args *ia = aux;
770	int port = ia->ia_iobase;
771	int		i;
772	unsigned char	c,d,m;
773
774	/*
775	 * Figure out our board rev, and see if we need to initialize the
776	 * mixer
777	 */
778
779 	delay(500);
780
781 	c = inb(port+GUS_BOARD_REV);
782	if (c != 0xff)
783		sc->sc_revision = c;
784	else
785		sc->sc_revision = 0;
786
787
788 	SELECT_GUS_REG(port, GUSREG_RESET);
789 	outb(port+GUS_DATA_HIGH, 0x00);
790
791	gusreset(sc, GUS_MAX_VOICES); /* initialize all voices */
792	gusreset(sc, GUS_MIN_VOICES); /* then set to just the ones we use */
793
794	/*
795	 * Setup the IRQ and DRQ lines in software, using values from
796	 * config file
797	 */
798
799	m = GUSMASK_LINE_IN|GUSMASK_LINE_OUT;		/* disable all */
800
801	c = ((unsigned char) gus_irq_map[ia->ia_irq]) | GUSMASK_BOTH_RQ;
802
803	if (sc->sc_recdrq == sc->sc_drq)
804		d = (unsigned char) (gus_drq_map[sc->sc_drq] |
805				GUSMASK_BOTH_RQ);
806	else
807		d = (unsigned char) (gus_drq_map[sc->sc_drq] |
808				gus_drq_map[sc->sc_recdrq] << 3);
809
810	/*
811	 * Program the IRQ and DMA channels on the GUS.  Note that we hardwire
812	 * the GUS to only use one IRQ channel, but we give the user the
813	 * option of using two DMA channels (the other one given by the flags
814	 * option in the config file).  Two DMA channels are needed for full-
815	 * duplex operation.
816	 *
817	 * The order of these operations is very magical.
818	 */
819
820	disable_intr();
821
822	outb(port+GUS_REG_CONTROL, GUS_REG_IRQCTL);
823	outb(port+GUS_MIX_CONTROL, m);
824	outb(port+GUS_IRQCTL_CONTROL, 0x00);
825	outb(port+0x0f, 0x00);
826
827	outb(port+GUS_MIX_CONTROL, m);
828	outb(port+GUS_DMA_CONTROL, d | 0x80); /* magic reset? */
829
830	outb(port+GUS_MIX_CONTROL, m | GUSMASK_CONTROL_SEL);
831	outb(port+GUS_IRQ_CONTROL, c);
832
833	outb(port+GUS_MIX_CONTROL, m);
834	outb(port+GUS_DMA_CONTROL, d);
835
836	outb(port+GUS_MIX_CONTROL, m | GUSMASK_CONTROL_SEL);
837	outb(port+GUS_IRQ_CONTROL, c);
838
839	outb(port+GUS_VOICE_SELECT, 0x00);
840
841	/* enable line in, line out.  leave mic disabled. */
842	outb(port+GUS_MIX_CONTROL,
843	     (m | GUSMASK_LATCHES) & ~(GUSMASK_LINE_OUT|GUSMASK_LINE_IN));
844	outb(port+GUS_VOICE_SELECT, 0x00);
845
846	enable_intr();
847
848	sc->sc_mixcontrol =
849		(m | GUSMASK_LATCHES) & ~(GUSMASK_LINE_OUT|GUSMASK_LINE_IN);
850
851	/* XXX WILL THIS ALWAYS WORK THE WAY THEY'RE OVERLAYED?! */
852	sc->sc_codec.sc_isa = sc->sc_dev.dv_parent;
853
854 	if (sc->sc_revision >= 5 && sc->sc_revision <= 9) {
855 		sc->sc_flags |= GUS_MIXER_INSTALLED;
856 		gus_init_ics2101(sc);
857	}
858	if (sc->sc_revision >= 0xa) {
859		gus_init_cs4231(sc);
860	}
861
862 	SELECT_GUS_REG(port, GUSREG_RESET);
863 	/*
864 	 * Check to see how much memory we have on this card; see if any
865 	 * "mirroring" occurs.  We're assuming at least 256K already exists
866 	 * on the card; otherwise the initial probe would have failed
867 	 */
868
869	guspoke(port, 0L, 0x00);
870	for(i = 1; i < 1024; i++) {
871		u_long loc;
872
873		/*
874		 * See if we've run into mirroring yet
875		 */
876
877		if (guspeek(port, 0L) != 0)
878			break;
879
880		loc = i << 10;
881
882		guspoke(port, loc, 0xaa);
883		if (guspeek(port, loc) != 0xaa)
884			break;
885	}
886
887	sc->sc_dsize = i;
888	sprintf(gus_device.version, "3.%d", sc->sc_revision);
889
890	printf("\n <Gravis UltraSound version 3.%d, %dKB DRAM, ",
891	       sc->sc_revision, sc->sc_dsize);
892	if (HAS_MIXER(sc))
893		printf("ICS2101 mixer, ");
894	if (HAS_CODEC(sc))
895		printf("%s codec/mixer, ", sc->sc_codec.chip_name);
896	if (sc->sc_recdrq == sc->sc_drq) {
897		printf("half-duplex");
898	} else {
899		printf("full-duplex, record drq %d", sc->sc_recdrq);
900	}
901
902	printf(">\n");
903
904	/*
905	 * Setup a default interrupt handler
906	 */
907
908	/* XXX we shouldn't have to use splgus == splclock, nor should
909	 * we use IPL_CLOCK.
910	 */
911	sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
912	    IPL_AUDIO, gusintr, sc /* sc->sc_gusdsp */);
913
914	/*
915	 * Set some default values
916	 */
917
918	sc->sc_irate = sc->sc_orate = 44100;
919	sc->sc_encoding = AUDIO_ENCODING_SLINEAR_LE;
920	sc->sc_precision = 16;
921	sc->sc_voc[GUS_VOICE_LEFT].voccntl |= GUSMASK_DATA_SIZE16;
922	sc->sc_voc[GUS_VOICE_RIGHT].voccntl |= GUSMASK_DATA_SIZE16;
923	sc->sc_channels = 1;
924	sc->sc_ogain = 340;
925	gus_commit_settings(sc);
926
927	/*
928	 * We always put the left channel full left & right channel
929	 * full right.
930	 * For mono playback, we set up both voices playing the same buffer.
931	 */
932	outb(sc->sc_iobase+GUS_VOICE_SELECT, (unsigned char) GUS_VOICE_LEFT);
933	SELECT_GUS_REG(sc->sc_iobase, GUSREG_PAN_POS);
934	outb(sc->sc_iobase+GUS_DATA_HIGH, GUS_PAN_FULL_LEFT);
935
936	outb(sc->sc_iobase+GUS_VOICE_SELECT, (unsigned char) GUS_VOICE_RIGHT);
937	SELECT_GUS_REG(sc->sc_iobase, GUSREG_PAN_POS);
938	outb(sc->sc_iobase+GUS_DATA_HIGH, GUS_PAN_FULL_RIGHT);
939
940	/*
941	 * Attach to the generic audio layer
942	 */
943
944	audio_attach_mi(&gus_hw_if, 0, HAS_CODEC(sc) ? (void *)&sc->sc_codec : (void *)sc, &sc->sc_dev);
945}
946
947int
948gusopen(addr, flags)
949	void *addr;
950	int flags;
951{
952	struct gus_softc *sc = addr;
953
954	DPRINTF(("gusopen() called\n"));
955
956	if (sc->sc_flags & GUS_OPEN)
957		return EBUSY;
958
959	/*
960	 * Some initialization
961	 */
962
963	sc->sc_flags |= GUS_OPEN;
964	sc->sc_dmabuf = 0;
965	sc->sc_playbuf = -1;
966	sc->sc_bufcnt = 0;
967	sc->sc_voc[GUS_VOICE_LEFT].start_addr = GUS_MEM_OFFSET - 1;
968	sc->sc_voc[GUS_VOICE_LEFT].current_addr = GUS_MEM_OFFSET;
969
970	if (HAS_CODEC(sc)) {
971		ad1848_open(&sc->sc_codec, flags);
972		sc->sc_codec.aux1_mute = 0;
973		ad1848_mute_aux1(&sc->sc_codec, 0); /* turn on DAC output */
974		if (flags & FREAD) {
975			sc->sc_codec.mono_mute = 0;
976			cs4231_mute_mono(&sc->sc_codec, 0);
977		}
978	} else if (flags & FREAD) {
979		/* enable/unmute the microphone */
980		if (HAS_MIXER(sc)) {
981			gusics_mic_mute(&sc->sc_mixer, 0);
982		} else
983			gus_mic_ctl(sc, SPKR_ON);
984	}
985	if (sc->sc_nbufs == 0)
986	    gus_round_blocksize(sc, GUS_BUFFER_MULTIPLE); /* default blksiz */
987	return 0;
988}
989
990int
991gusmaxopen(addr, flags)
992	void *addr;
993	int flags;
994{
995	struct ad1848_softc *ac = addr;
996	return gusopen(ac->parent, flags);
997}
998
999STATIC void
1000gus_deinterleave(sc, buf, size)
1001	struct gus_softc *sc;
1002	void *buf;
1003	int size;
1004{
1005	/* deinterleave the stereo data.  We can use sc->sc_deintr_buf
1006	   for scratch space. */
1007	int i;
1008
1009	if (size > sc->sc_blocksize) {
1010		printf("gus: deinterleave %d > %d\n", size, sc->sc_blocksize);
1011		return;
1012	} else if (size < sc->sc_blocksize) {
1013		DPRINTF(("gus: deinterleave %d < %d\n", size, sc->sc_blocksize));
1014	}
1015
1016	/*
1017	 * size is in bytes.
1018	 */
1019	if (sc->sc_precision == 16) {
1020		u_short *dei = sc->sc_deintr_buf;
1021		u_short *sbuf = buf;
1022		size >>= 1;		/* bytecnt to shortcnt */
1023		/* copy 2nd of each pair of samples to the staging area, while
1024		   compacting the 1st of each pair into the original area. */
1025		for (i = 0; i < size/2-1; i++)  {
1026			dei[i] = sbuf[i*2+1];
1027			sbuf[i+1] = sbuf[i*2+2];
1028		}
1029		/*
1030		 * this has copied one less sample than half of the
1031		 * buffer.  The first sample of the 1st stream was
1032		 * already in place and didn't need copying.
1033		 * Therefore, we've moved all of the 1st stream's
1034		 * samples into place.  We have one sample from 2nd
1035		 * stream in the last slot of original area, not
1036		 * copied to the staging area (But we don't need to!).
1037		 * Copy the remainder of the original stream into place.
1038		 */
1039		bcopy(dei, &sbuf[size/2], i * sizeof(short));
1040	} else {
1041		u_char *dei = sc->sc_deintr_buf;
1042		u_char *sbuf = buf;
1043		for (i = 0; i < size/2-1; i++)  {
1044			dei[i] = sbuf[i*2+1];
1045			sbuf[i+1] = sbuf[i*2+2];
1046		}
1047		bcopy(dei, &sbuf[size/2], i);
1048	}
1049}
1050
1051/*
1052 * Actually output a buffer to the DSP chip
1053 */
1054
1055int
1056gusmax_dma_output(addr, buf, size, intr, arg)
1057	void * addr;
1058	void *buf;
1059	int size;
1060	void (*intr) __P((void *));
1061	void *arg;
1062{
1063	struct ad1848_softc *ac = addr;
1064	return gus_dma_output(ac->parent, buf, size, intr, arg);
1065}
1066
1067/*
1068 * called at splgus() from interrupt handler.
1069 */
1070void
1071stereo_dmaintr(arg)
1072	void *arg;
1073{
1074    struct gus_softc *sc = arg;
1075    struct stereo_dma_intr *sa = &sc->sc_stereo;
1076
1077    DMAPRINTF(("stereo_dmaintr"));
1078
1079    /*
1080     * Put other half in its place, then call the real interrupt routine :)
1081     */
1082
1083    sc->sc_dmaoutintr = sa->intr;
1084    sc->sc_outarg = sa->arg;
1085
1086#ifdef GUSPLAYDEBUG
1087    if (gusstats) {
1088      microtime(&dmarecords[dmarecord_index].tv);
1089      dmarecords[dmarecord_index].gusaddr = sa->dmabuf;
1090      dmarecords[dmarecord_index].bsdaddr = sa->buffer;
1091      dmarecords[dmarecord_index].count = sa->size;
1092      dmarecords[dmarecord_index].channel = 1;
1093      dmarecords[dmarecord_index].direction = 1;
1094      dmarecord_index = ++dmarecord_index % NDMARECS;
1095    }
1096#endif
1097
1098    gusdmaout(sc, sa->flags, sa->dmabuf, (caddr_t) sa->buffer, sa->size);
1099
1100    sa->flags = 0;
1101    sa->dmabuf = 0;
1102    sa->buffer = 0;
1103    sa->size = 0;
1104    sa->intr = 0;
1105    sa->arg = 0;
1106}
1107
1108/*
1109 * Start up DMA output to the card.
1110 * Called at splgus/splaudio already, either from intr handler or from
1111 * generic audio code.
1112 */
1113int
1114gus_dma_output(addr, buf, size, intr, arg)
1115	void * addr;
1116	void *buf;
1117	int size;
1118	void (*intr) __P((void *));
1119	void *arg;
1120{
1121	struct gus_softc *sc = addr;
1122	u_char *buffer = buf;
1123	u_long boarddma;
1124	int flags;
1125
1126	DMAPRINTF(("gus_dma_output %d @ %p\n", size, buf));
1127
1128	if (size != sc->sc_blocksize) {
1129	    DPRINTF(("gus_dma_output reqsize %d not sc_blocksize %d\n",
1130		     size, sc->sc_blocksize));
1131	    return EINVAL;
1132	}
1133
1134	flags = GUSMASK_DMA_WRITE;
1135	if (sc->sc_precision == 16)
1136	    flags |= GUSMASK_DMA_DATA_SIZE;
1137	if (sc->sc_encoding == AUDIO_ENCODING_ULAW ||
1138	    sc->sc_encoding == AUDIO_ENCODING_ALAW ||
1139	    sc->sc_encoding == AUDIO_ENCODING_ULINEAR_BE ||
1140	    sc->sc_encoding == AUDIO_ENCODING_ULINEAR_LE)
1141	    flags |= GUSMASK_DMA_INVBIT;
1142
1143	if (sc->sc_channels == 2) {
1144		if (sc->sc_precision == 16) {
1145			if (size & 3) {
1146				DPRINTF(("gus_dma_output: unpaired 16bit samples"));
1147				size &= 3;
1148			}
1149		} else if (size & 1) {
1150			DPRINTF(("gus_dma_output: unpaired samples"));
1151			size &= 1;
1152		}
1153		if (size == 0)
1154			return 0;
1155
1156		gus_deinterleave(sc, (void *)buffer, size);
1157
1158		size >>= 1;
1159
1160 		boarddma = size * sc->sc_dmabuf + GUS_MEM_OFFSET;
1161
1162		sc->sc_stereo.intr = intr;
1163		sc->sc_stereo.arg = arg;
1164		sc->sc_stereo.size = size;
1165		sc->sc_stereo.dmabuf = boarddma + GUS_LEFT_RIGHT_OFFSET;
1166		sc->sc_stereo.buffer = buffer + size;
1167		sc->sc_stereo.flags = flags;
1168		if (gus_dostereo) {
1169		  intr = stereo_dmaintr;
1170		  arg = sc;
1171		}
1172	} else
1173		boarddma = size * sc->sc_dmabuf + GUS_MEM_OFFSET;
1174
1175
1176	sc->sc_flags |= GUS_LOCKED;
1177	sc->sc_dmaoutintr = intr;
1178	sc->sc_outarg = arg;
1179
1180#ifdef GUSPLAYDEBUG
1181	if (gusstats) {
1182	  microtime(&dmarecords[dmarecord_index].tv);
1183	  dmarecords[dmarecord_index].gusaddr = boarddma;
1184	  dmarecords[dmarecord_index].bsdaddr = buffer;
1185	  dmarecords[dmarecord_index].count = size;
1186	  dmarecords[dmarecord_index].channel = 0;
1187	  dmarecords[dmarecord_index].direction = 1;
1188	  dmarecord_index = ++dmarecord_index % NDMARECS;
1189	}
1190#endif
1191
1192	gusdmaout(sc, flags, boarddma, (caddr_t) buffer, size);
1193
1194	return 0;
1195}
1196
1197void
1198gusmax_close(addr)
1199	void *addr;
1200{
1201	struct ad1848_softc *ac = addr;
1202	struct gus_softc *sc = ac->parent;
1203#if 0
1204	ac->aux1_mute = 1;
1205	ad1848_mute_aux1(ac, 1);	/* turn off DAC output */
1206#endif
1207	ad1848_close(ac);
1208	gusclose(sc);
1209}
1210
1211/*
1212 * Close out device stuff.  Called at splgus() from generic audio layer.
1213 */
1214void
1215gusclose(addr)
1216	void *addr;
1217{
1218	struct gus_softc *sc = addr;
1219
1220        DPRINTF(("gus_close: sc=%p\n", sc));
1221
1222
1223/*	if (sc->sc_flags & GUS_DMAOUT_ACTIVE) */ {
1224		gus_halt_out_dma(sc);
1225	}
1226/*	if (sc->sc_flags & GUS_DMAIN_ACTIVE) */ {
1227		gus_halt_in_dma(sc);
1228	}
1229	sc->sc_flags &= ~(GUS_OPEN|GUS_LOCKED|GUS_DMAOUT_ACTIVE|GUS_DMAIN_ACTIVE);
1230
1231	if (sc->sc_deintr_buf) {
1232		FREE(sc->sc_deintr_buf, M_DEVBUF);
1233		sc->sc_deintr_buf = NULL;
1234	}
1235	/* turn off speaker, etc. */
1236
1237	/* make sure the voices shut up: */
1238	gus_stop_voice(sc, GUS_VOICE_LEFT, 1);
1239	gus_stop_voice(sc, GUS_VOICE_RIGHT, 0);
1240}
1241
1242/*
1243 * Service interrupts.  Farm them off to helper routines if we are using the
1244 * GUS for simple playback/record
1245 */
1246
1247#ifdef DIAGNOSTIC
1248int gusintrcnt;
1249int gusdmaintrcnt;
1250int gusvocintrcnt;
1251#endif
1252
1253int
1254gusintr(arg)
1255	void *arg;
1256{
1257	struct gus_softc *sc = arg;
1258	unsigned char intr;
1259	int port = sc->sc_iobase;
1260	int retval = 0;
1261
1262	DPRINTF(("gusintr\n"));
1263#ifdef DIAGNOSTIC
1264	gusintrcnt++;
1265#endif
1266	if (HAS_CODEC(sc))
1267		retval = ad1848_intr(&sc->sc_codec);
1268	if ((intr = inb(port+GUS_IRQ_STATUS)) & GUSMASK_IRQ_DMATC) {
1269		DMAPRINTF(("gusintr dma flags=%x\n", sc->sc_flags));
1270#ifdef DIAGNOSTIC
1271		gusdmaintrcnt++;
1272#endif
1273		retval += gus_dmaout_intr(sc);
1274		if (sc->sc_flags & GUS_DMAIN_ACTIVE) {
1275		    SELECT_GUS_REG(port, GUSREG_SAMPLE_CONTROL);
1276		    intr = inb(port+GUS_DATA_HIGH);
1277		    if (intr & GUSMASK_SAMPLE_DMATC) {
1278			retval += gus_dmain_intr(sc);
1279		    }
1280		}
1281	}
1282	if (intr & (GUSMASK_IRQ_VOICE | GUSMASK_IRQ_VOLUME)) {
1283		DMAPRINTF(("gusintr voice flags=%x\n", sc->sc_flags));
1284#ifdef DIAGNOSTIC
1285		gusvocintrcnt++;
1286#endif
1287		retval += gus_voice_intr(sc);
1288	}
1289	if (retval)
1290		return 1;
1291	return retval;
1292}
1293
1294int gus_bufcnt[GUS_MEM_FOR_BUFFERS / GUS_BUFFER_MULTIPLE];
1295int gus_restart;				/* how many restarts? */
1296int gus_stops;				/* how many times did voice stop? */
1297int gus_falsestops;			/* stopped but not done? */
1298int gus_continues;
1299
1300struct playcont {
1301	struct timeval tv;
1302	u_int playbuf;
1303	u_int dmabuf;
1304	u_char bufcnt;
1305	u_char vaction;
1306	u_char voccntl;
1307	u_char volcntl;
1308	u_long curaddr;
1309	u_long endaddr;
1310} playstats[NDMARECS];
1311
1312int playcntr;
1313
1314STATIC void
1315gus_dmaout_timeout(arg)
1316     void *arg;
1317{
1318    struct gus_softc *sc = arg;
1319    int port = sc->sc_iobase;
1320    int s;
1321
1322    printf("%s: dmaout timeout\n", sc->sc_dev.dv_xname);
1323    /*
1324     * Stop any DMA.
1325     */
1326
1327    s = splgus();
1328    SELECT_GUS_REG(port, GUSREG_DMA_CONTROL);
1329    outb(sc->sc_iobase+GUS_DATA_HIGH, 0);
1330
1331#if 0
1332    /* XXX we will dmadone below? */
1333    isa_dmaabort(sc->sc_dev.dv_parent, sc->sc_drq);
1334#endif
1335
1336    gus_dmaout_dointr(sc);
1337    splx(s);
1338}
1339
1340
1341/*
1342 * Service DMA interrupts.  This routine will only get called if we're doing
1343 * a DMA transfer for playback/record requests from the audio layer.
1344 */
1345
1346STATIC int
1347gus_dmaout_intr(sc)
1348	struct gus_softc *sc;
1349{
1350	int port = sc->sc_iobase;
1351
1352	/*
1353	 * If we got a DMA transfer complete from the GUS DRAM, then deal
1354	 * with it.
1355	 */
1356
1357	SELECT_GUS_REG(port, GUSREG_DMA_CONTROL);
1358 	if (inb(port+GUS_DATA_HIGH) & GUSMASK_DMA_IRQPEND) {
1359	    untimeout(gus_dmaout_timeout, sc);
1360	    gus_dmaout_dointr(sc);
1361	    return 1;
1362	}
1363	return 0;
1364}
1365
1366STATIC void
1367gus_dmaout_dointr(sc)
1368	struct gus_softc *sc;
1369{
1370	int port = sc->sc_iobase;
1371
1372	/* sc->sc_dmaoutcnt - 1 because DMA controller counts from zero?. */
1373	isa_dmadone(sc->sc_dev.dv_parent, sc->sc_drq);
1374	sc->sc_flags &= ~GUS_DMAOUT_ACTIVE;  /* pending DMA is done */
1375	DMAPRINTF(("gus_dmaout_dointr %d @ %p\n", sc->sc_dmaoutcnt,
1376		   sc->sc_dmaoutaddr));
1377
1378	/*
1379	 * to prevent clicking, we need to copy last sample
1380	 * from last buffer to scratch area just before beginning of
1381	 * buffer.  However, if we're doing formats that are converted by
1382	 * the card during the DMA process, we need to pick up the converted
1383	 * byte rather than the one we have in memory.
1384	 */
1385	if (sc->sc_dmabuf == sc->sc_nbufs - 1) {
1386	  int i;
1387	  switch (sc->sc_encoding) {
1388	  case AUDIO_ENCODING_SLINEAR_LE:
1389	  case AUDIO_ENCODING_SLINEAR_BE:
1390	    if (sc->sc_precision == 8)
1391	      goto byte;
1392	    /* we have the native format */
1393	    for (i = 1; i <= 2; i++)
1394	      guspoke(port, sc->sc_gusaddr -
1395		      (sc->sc_nbufs - 1) * sc->sc_chanblocksize - i,
1396		      sc->sc_dmaoutaddr[sc->sc_dmaoutcnt-i]);
1397	    break;
1398	  case AUDIO_ENCODING_ULINEAR_LE:
1399	  case AUDIO_ENCODING_ULINEAR_BE:
1400	    guspoke(port, sc->sc_gusaddr -
1401		    (sc->sc_nbufs - 1) * sc->sc_chanblocksize - 2,
1402		    guspeek(port,
1403			    sc->sc_gusaddr + sc->sc_chanblocksize - 2));
1404	  case AUDIO_ENCODING_ALAW:
1405	  case AUDIO_ENCODING_ULAW:
1406	  byte:
1407	    /* we need to fetch the translated byte, then stuff it. */
1408	    guspoke(port, sc->sc_gusaddr -
1409		    (sc->sc_nbufs - 1) * sc->sc_chanblocksize - 1,
1410		    guspeek(port,
1411			    sc->sc_gusaddr + sc->sc_chanblocksize - 1));
1412	    break;
1413	  }
1414	}
1415	/*
1416	 * If this is the first half of stereo, "ignore" this one
1417	 * and copy out the second half.
1418	 */
1419	if (sc->sc_dmaoutintr == stereo_dmaintr) {
1420	    (*sc->sc_dmaoutintr)(sc->sc_outarg);
1421	    return;
1422	}
1423	/*
1424	 * If the voice is stopped, then start it.  Reset the loop
1425	 * and roll bits.  Call the audio layer routine, since if
1426	 * we're starting a stopped voice, that means that the next
1427	 * buffer can be filled
1428	 */
1429
1430	sc->sc_flags &= ~GUS_LOCKED;
1431	if (sc->sc_voc[GUS_VOICE_LEFT].voccntl &
1432	    GUSMASK_VOICE_STOPPED) {
1433	    if (sc->sc_flags & GUS_PLAYING) {
1434		printf("%s: playing yet stopped?\n", sc->sc_dev.dv_xname);
1435	    }
1436	    sc->sc_bufcnt++; /* another yet to be played */
1437	    gus_start_playing(sc, sc->sc_dmabuf);
1438	    gus_restart++;
1439	} else {
1440	    /*
1441	     * set the sound action based on which buffer we
1442	     * just transferred.  If we just transferred buffer 0
1443	     * we want the sound to loop when it gets to the nth
1444	     * buffer; if we just transferred
1445	     * any other buffer, we want the sound to roll over
1446	     * at least one more time.  The voice interrupt
1447	     * handlers will take care of accounting &
1448	     * setting control bits if it's not caught up to us
1449	     * yet.
1450	     */
1451	    if (++sc->sc_bufcnt == 2) {
1452		/*
1453		 * XXX
1454		 * If we're too slow in reaction here,
1455		 * the voice could be just approaching the
1456		 * end of its run.  It should be set to stop,
1457		 * so these adjustments might not DTRT.
1458		 */
1459		if (sc->sc_dmabuf == 0 &&
1460		    sc->sc_playbuf == sc->sc_nbufs - 1) {
1461		    /* player is just at the last buf, we're at the
1462		       first.  Turn on looping, turn off rolling. */
1463		    sc->sc_voc[GUS_VOICE_LEFT].voccntl |= GUSMASK_LOOP_ENABLE;
1464		    sc->sc_voc[GUS_VOICE_LEFT].volcntl &= ~GUSMASK_VOICE_ROLL;
1465		    playstats[playcntr].vaction = 3;
1466		} else {
1467		    /* player is at previous buf:
1468		       turn on rolling, turn off looping */
1469		    sc->sc_voc[GUS_VOICE_LEFT].voccntl &= ~GUSMASK_LOOP_ENABLE;
1470		    sc->sc_voc[GUS_VOICE_LEFT].volcntl |= GUSMASK_VOICE_ROLL;
1471		    playstats[playcntr].vaction = 4;
1472		}
1473#ifdef GUSPLAYDEBUG
1474		if (gusstats) {
1475		  microtime(&playstats[playcntr].tv);
1476		  playstats[playcntr].endaddr = sc->sc_voc[GUS_VOICE_LEFT].end_addr;
1477		  playstats[playcntr].voccntl = sc->sc_voc[GUS_VOICE_LEFT].voccntl;
1478		  playstats[playcntr].volcntl = sc->sc_voc[GUS_VOICE_LEFT].volcntl;
1479		  playstats[playcntr].playbuf = sc->sc_playbuf;
1480		  playstats[playcntr].dmabuf = sc->sc_dmabuf;
1481		  playstats[playcntr].bufcnt = sc->sc_bufcnt;
1482		  playstats[playcntr].curaddr = gus_get_curaddr(sc, GUS_VOICE_LEFT);
1483		  playcntr = ++playcntr % NDMARECS;
1484		}
1485#endif
1486		outb(port+GUS_VOICE_SELECT, GUS_VOICE_LEFT);
1487		SELECT_GUS_REG(port, GUSREG_VOICE_CNTL);
1488		outb(port+GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_LEFT].voccntl);
1489		SELECT_GUS_REG(port, GUSREG_VOLUME_CONTROL);
1490		outb(port+GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_LEFT].volcntl);
1491	    }
1492	}
1493	gus_bufcnt[sc->sc_bufcnt-1]++;
1494	/*
1495	 * flip to the next DMA buffer
1496	 */
1497
1498	sc->sc_dmabuf = ++sc->sc_dmabuf % sc->sc_nbufs;
1499	/*
1500	 * See comments below about DMA admission control strategy.
1501	 * We can call the upper level here if we have an
1502	 * idle buffer (not currently playing) to DMA into.
1503	 */
1504	if (sc->sc_dmaoutintr && sc->sc_bufcnt < sc->sc_nbufs) {
1505	    /* clean out to prevent double calls */
1506	    void (*pfunc) __P((void *)) = sc->sc_dmaoutintr;
1507	    void *arg = sc->sc_outarg;
1508
1509	    sc->sc_outarg = 0;
1510	    sc->sc_dmaoutintr = 0;
1511	    (*pfunc)(arg);
1512	}
1513}
1514
1515/*
1516 * Service voice interrupts
1517 */
1518
1519STATIC int
1520gus_voice_intr(sc)
1521	struct gus_softc *sc;
1522{
1523	int port = sc->sc_iobase;
1524	int ignore = 0, voice, rval = 0;
1525	unsigned char intr, status;
1526
1527	/*
1528	 * The point of this may not be obvious at first.  A voice can
1529	 * interrupt more than once; according to the GUS SDK we are supposed
1530	 * to ignore multiple interrupts for the same voice.
1531	 */
1532
1533	while(1) {
1534		SELECT_GUS_REG(port, GUSREG_IRQ_STATUS);
1535		intr = inb(port+GUS_DATA_HIGH);
1536
1537		if ((intr & (GUSMASK_WIRQ_VOLUME | GUSMASK_WIRQ_VOICE))
1538			== (GUSMASK_WIRQ_VOLUME | GUSMASK_WIRQ_VOICE))
1539			/*
1540			 * No more interrupts, time to return
1541			 */
1542		 	return rval;
1543
1544		if ((intr & GUSMASK_WIRQ_VOICE) == 0) {
1545
1546		    /*
1547		     * We've got a voice interrupt.  Ignore previous
1548		     * interrupts by the same voice.
1549		     */
1550
1551		    rval = 1;
1552		    voice = intr & GUSMASK_WIRQ_VOICEMASK;
1553
1554		    if ((1 << voice) & ignore)
1555			break;
1556
1557		    ignore |= 1 << voice;
1558
1559		    /*
1560		     * If the voice is stopped, then force it to stop
1561		     * (this stops it from continuously generating IRQs)
1562		     */
1563
1564		    SELECT_GUS_REG(port, GUSREG_VOICE_CNTL+0x80);
1565		    status = inb(port+GUS_DATA_HIGH);
1566		    if (status & GUSMASK_VOICE_STOPPED) {
1567			if (voice != GUS_VOICE_LEFT) {
1568			    DMAPRINTF(("%s: spurious voice %d stop?\n",
1569				       sc->sc_dev.dv_xname, voice));
1570			    gus_stop_voice(sc, voice, 0);
1571			    continue;
1572			}
1573			gus_stop_voice(sc, voice, 1);
1574			/* also kill right voice */
1575			gus_stop_voice(sc, GUS_VOICE_RIGHT, 0);
1576			sc->sc_bufcnt--; /* it finished a buffer */
1577			if (sc->sc_bufcnt > 0) {
1578			    /*
1579			     * probably a race to get here: the voice
1580			     * stopped while the DMA code was just trying to
1581			     * get the next buffer in place.
1582			     * Start the voice again.
1583			     */
1584			    printf("%s: stopped voice not drained? (%x)\n",
1585				   sc->sc_dev.dv_xname, sc->sc_bufcnt);
1586			    gus_falsestops++;
1587
1588			    sc->sc_playbuf = ++sc->sc_playbuf % sc->sc_nbufs;
1589			    gus_start_playing(sc, sc->sc_playbuf);
1590			} else if (sc->sc_bufcnt < 0) {
1591#ifdef DDB
1592			    printf("%s: negative bufcnt in stopped voice\n",
1593				   sc->sc_dev.dv_xname);
1594			    Debugger();
1595#else
1596			    panic("%s: negative bufcnt in stopped voice",
1597				  sc->sc_dev.dv_xname);
1598#endif
1599			} else {
1600			    sc->sc_playbuf = -1; /* none are active */
1601			    gus_stops++;
1602			}
1603			/* fall through to callback and admit another
1604			   buffer.... */
1605		    } else if (sc->sc_bufcnt != 0) {
1606			/*
1607			 * This should always be taken if the voice
1608			 * is not stopped.
1609			 */
1610			gus_continues++;
1611			if (gus_continue_playing(sc, voice)) {
1612				/*
1613				 * we shouldn't have continued--active DMA
1614				 * is in the way in the ring, for
1615				 * some as-yet undebugged reason.
1616				 */
1617				gus_stop_voice(sc, GUS_VOICE_LEFT, 1);
1618				/* also kill right voice */
1619				gus_stop_voice(sc, GUS_VOICE_RIGHT, 0);
1620				sc->sc_playbuf = -1;
1621				gus_stops++;
1622			}
1623		    }
1624		    /*
1625		     * call the upper level to send on down another
1626		     * block. We do admission rate control as follows:
1627		     *
1628		     * When starting up output (in the first N
1629		     * blocks), call the upper layer after the DMA is
1630		     * complete (see above in gus_dmaout_intr()).
1631		     *
1632		     * When output is already in progress and we have
1633		     * no more GUS buffers to use for DMA, the DMA
1634		     * output routines do not call the upper layer.
1635		     * Instead, we call the DMA completion routine
1636		     * here, after the voice interrupts indicating
1637		     * that it's finished with a buffer.
1638		     *
1639		     * However, don't call anything here if the DMA
1640		     * output flag is set, (which shouldn't happen)
1641		     * because we'll squish somebody else's DMA if
1642		     * that's the case.  When DMA is done, it will
1643		     * call back if there is a spare buffer.
1644		     */
1645		    if (sc->sc_dmaoutintr && !(sc->sc_flags & GUS_LOCKED)) {
1646			if (sc->sc_dmaoutintr == stereo_dmaintr)
1647			    printf("gusdmaout botch?\n");
1648			else {
1649			    /* clean out to avoid double calls */
1650			    void (*pfunc) __P((void *)) = sc->sc_dmaoutintr;
1651			    void *arg = sc->sc_outarg;
1652
1653			    sc->sc_outarg = 0;
1654			    sc->sc_dmaoutintr = 0;
1655			    (*pfunc)(arg);
1656			}
1657		    }
1658		}
1659
1660		/*
1661		 * Ignore other interrupts for now
1662		 */
1663	}
1664	return 0;
1665}
1666
1667STATIC void
1668gus_start_playing(sc, bufno)
1669struct gus_softc *sc;
1670int bufno;
1671{
1672    int port = sc->sc_iobase;
1673    /*
1674     * Start the voices playing, with buffer BUFNO.
1675     */
1676
1677    /*
1678     * Loop or roll if we have buffers ready.
1679     */
1680
1681    if (sc->sc_bufcnt == 1) {
1682	sc->sc_voc[GUS_VOICE_LEFT].voccntl &= ~(GUSMASK_LOOP_ENABLE);
1683	sc->sc_voc[GUS_VOICE_LEFT].volcntl &= ~(GUSMASK_VOICE_ROLL);
1684    } else {
1685	if (bufno == sc->sc_nbufs - 1) {
1686	    sc->sc_voc[GUS_VOICE_LEFT].voccntl |= GUSMASK_LOOP_ENABLE;
1687	    sc->sc_voc[GUS_VOICE_LEFT].volcntl &= ~(GUSMASK_VOICE_ROLL);
1688	} else {
1689	    sc->sc_voc[GUS_VOICE_LEFT].voccntl &= ~GUSMASK_LOOP_ENABLE;
1690	    sc->sc_voc[GUS_VOICE_LEFT].volcntl |= GUSMASK_VOICE_ROLL;
1691	}
1692    }
1693
1694    outb(port+GUS_VOICE_SELECT, GUS_VOICE_LEFT);
1695
1696    SELECT_GUS_REG(port, GUSREG_VOICE_CNTL);
1697    outb(port+GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_LEFT].voccntl);
1698
1699    SELECT_GUS_REG(port, GUSREG_VOLUME_CONTROL);
1700    outb(port+GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_LEFT].volcntl);
1701
1702    sc->sc_voc[GUS_VOICE_LEFT].current_addr =
1703	GUS_MEM_OFFSET + sc->sc_chanblocksize * bufno;
1704    sc->sc_voc[GUS_VOICE_LEFT].end_addr =
1705	sc->sc_voc[GUS_VOICE_LEFT].current_addr + sc->sc_chanblocksize - 1;
1706    sc->sc_voc[GUS_VOICE_RIGHT].current_addr =
1707	sc->sc_voc[GUS_VOICE_LEFT].current_addr +
1708	(gus_dostereo && sc->sc_channels == 2 ? GUS_LEFT_RIGHT_OFFSET : 0);
1709    /*
1710     * set up right channel to just loop forever, no interrupts,
1711     * starting at the buffer we just filled.  We'll feed it data
1712     * at the same time as left channel.
1713     */
1714    sc->sc_voc[GUS_VOICE_RIGHT].voccntl |= GUSMASK_LOOP_ENABLE;
1715    sc->sc_voc[GUS_VOICE_RIGHT].volcntl &= ~(GUSMASK_VOICE_ROLL);
1716
1717#ifdef GUSPLAYDEBUG
1718    if (gusstats) {
1719      microtime(&playstats[playcntr].tv);
1720      playstats[playcntr].curaddr = sc->sc_voc[GUS_VOICE_LEFT].current_addr;
1721
1722      playstats[playcntr].voccntl = sc->sc_voc[GUS_VOICE_LEFT].voccntl;
1723      playstats[playcntr].volcntl = sc->sc_voc[GUS_VOICE_LEFT].volcntl;
1724      playstats[playcntr].endaddr = sc->sc_voc[GUS_VOICE_LEFT].end_addr;
1725      playstats[playcntr].playbuf = bufno;
1726      playstats[playcntr].dmabuf = sc->sc_dmabuf;
1727      playstats[playcntr].bufcnt = sc->sc_bufcnt;
1728      playstats[playcntr].vaction = 5;
1729      playcntr = ++playcntr % NDMARECS;
1730    }
1731#endif
1732
1733    outb(port+GUS_VOICE_SELECT, GUS_VOICE_RIGHT);
1734    SELECT_GUS_REG(port, GUSREG_VOICE_CNTL);
1735    outb(port+GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_RIGHT].voccntl);
1736    SELECT_GUS_REG(port, GUSREG_VOLUME_CONTROL);
1737    outb(port+GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_RIGHT].volcntl);
1738
1739    gus_start_voice(sc, GUS_VOICE_RIGHT, 0);
1740    gus_start_voice(sc, GUS_VOICE_LEFT, 1);
1741    if (sc->sc_playbuf == -1)
1742	/* mark start of playing */
1743	sc->sc_playbuf = bufno;
1744}
1745
1746STATIC int
1747gus_continue_playing(sc, voice)
1748struct gus_softc *sc;
1749int voice;
1750{
1751    int port = sc->sc_iobase;
1752
1753    /*
1754     * stop this voice from interrupting while we work.
1755     */
1756
1757    SELECT_GUS_REG(port, GUSREG_VOICE_CNTL);
1758    outb(port+GUS_DATA_HIGH, sc->sc_voc[voice].voccntl & ~(GUSMASK_VOICE_IRQ));
1759
1760    /*
1761     * update playbuf to point to the buffer the hardware just started
1762     * playing
1763     */
1764    sc->sc_playbuf = ++sc->sc_playbuf % sc->sc_nbufs;
1765
1766    /*
1767     * account for buffer just finished
1768     */
1769    if (--sc->sc_bufcnt == 0) {
1770	DPRINTF(("gus: bufcnt 0 on continuing voice?\n"));
1771    }
1772    if (sc->sc_playbuf == sc->sc_dmabuf && (sc->sc_flags & GUS_LOCKED)) {
1773	printf("%s: continue into active dmabuf?\n", sc->sc_dev.dv_xname);
1774	return 1;
1775    }
1776
1777    /*
1778     * Select the end of the buffer based on the currently active
1779     * buffer, [plus extra contiguous buffers (if ready)].
1780     */
1781
1782    /*
1783     * set endpoint at end of buffer we just started playing.
1784     *
1785     * The total gets -1 because end addrs are one less than you might
1786     * think (the end_addr is the address of the last sample to play)
1787     */
1788    gus_set_endaddr(sc, voice, GUS_MEM_OFFSET +
1789		    sc->sc_chanblocksize * (sc->sc_playbuf + 1) - 1);
1790
1791    if (sc->sc_bufcnt < 2) {
1792	/*
1793	 * Clear out the loop and roll flags, and rotate the currently
1794	 * playing buffer.  That way, if we don't manage to get more
1795	 * data before this buffer finishes, we'll just stop.
1796	 */
1797	sc->sc_voc[voice].voccntl &= ~GUSMASK_LOOP_ENABLE;
1798	sc->sc_voc[voice].volcntl &= ~GUSMASK_VOICE_ROLL;
1799	playstats[playcntr].vaction = 0;
1800    } else {
1801	/*
1802	 * We have some buffers to play.  set LOOP if we're on the
1803	 * last buffer in the ring, otherwise set ROLL.
1804	 */
1805	if (sc->sc_playbuf == sc->sc_nbufs - 1) {
1806	    sc->sc_voc[voice].voccntl |= GUSMASK_LOOP_ENABLE;
1807	    sc->sc_voc[voice].volcntl &= ~GUSMASK_VOICE_ROLL;
1808	    playstats[playcntr].vaction = 1;
1809	} else {
1810	    sc->sc_voc[voice].voccntl &= ~GUSMASK_LOOP_ENABLE;
1811	    sc->sc_voc[voice].volcntl |= GUSMASK_VOICE_ROLL;
1812	    playstats[playcntr].vaction = 2;
1813	}
1814    }
1815#ifdef GUSPLAYDEBUG
1816    if (gusstats) {
1817      microtime(&playstats[playcntr].tv);
1818      playstats[playcntr].curaddr = gus_get_curaddr(sc, voice);
1819
1820      playstats[playcntr].voccntl = sc->sc_voc[voice].voccntl;
1821      playstats[playcntr].volcntl = sc->sc_voc[voice].volcntl;
1822      playstats[playcntr].endaddr = sc->sc_voc[voice].end_addr;
1823      playstats[playcntr].playbuf = sc->sc_playbuf;
1824      playstats[playcntr].dmabuf = sc->sc_dmabuf;
1825      playstats[playcntr].bufcnt = sc->sc_bufcnt;
1826      playcntr = ++playcntr % NDMARECS;
1827    }
1828#endif
1829
1830    /*
1831     * (re-)set voice parameters.  This will reenable interrupts from this
1832     * voice.
1833     */
1834
1835    SELECT_GUS_REG(port, GUSREG_VOICE_CNTL);
1836    outb(port+GUS_DATA_HIGH, sc->sc_voc[voice].voccntl);
1837    SELECT_GUS_REG(port, GUSREG_VOLUME_CONTROL);
1838    outb(port+GUS_DATA_HIGH, sc->sc_voc[voice].volcntl);
1839    return 0;
1840}
1841
1842/*
1843 * Send/receive data into GUS's DRAM using DMA.  Called at splgus()
1844 */
1845
1846STATIC void
1847gusdmaout(sc, flags, gusaddr, buffaddr, length)
1848	struct gus_softc *sc;
1849	int flags, length;
1850	u_long gusaddr;
1851	caddr_t buffaddr;
1852{
1853	unsigned char c = (unsigned char) flags;
1854	int port = sc->sc_iobase;
1855
1856	DMAPRINTF(("gusdmaout flags=%x scflags=%x\n", flags, sc->sc_flags));
1857
1858	sc->sc_gusaddr = gusaddr;
1859
1860	/*
1861	 * If we're using a 16 bit DMA channel, we have to jump through some
1862	 * extra hoops; this includes translating the DRAM address a bit
1863	 */
1864
1865	if (sc->sc_drq >= 4) {
1866		c |= GUSMASK_DMA_WIDTH;
1867		gusaddr = convert_to_16bit(gusaddr);
1868	}
1869
1870	/*
1871	 * Add flag bits that we always set - fast DMA, enable IRQ
1872	 */
1873
1874	c |= GUSMASK_DMA_ENABLE | GUSMASK_DMA_R0 | GUSMASK_DMA_IRQ;
1875
1876	/*
1877	 * Make sure the GUS _isn't_ setup for DMA
1878	 */
1879
1880 	SELECT_GUS_REG(port, GUSREG_DMA_CONTROL);
1881	outb(port+GUS_DATA_HIGH, 0);
1882
1883	/*
1884	 * Tell the PC DMA controller to start doing DMA
1885	 */
1886
1887	sc->sc_dmaoutaddr = (u_char *) buffaddr;
1888	sc->sc_dmaoutcnt = length;
1889	isa_dmastart(sc->sc_dev.dv_parent, sc->sc_drq, buffaddr, length,
1890	    NULL, DMAMODE_WRITE, BUS_DMA_NOWAIT);
1891
1892	/*
1893	 * Set up DMA address - use the upper 16 bits ONLY
1894	 */
1895
1896	sc->sc_flags |= GUS_DMAOUT_ACTIVE;
1897
1898 	SELECT_GUS_REG(port, GUSREG_DMA_START);
1899 	outw(port+GUS_DATA_LOW, (int) (gusaddr >> 4));
1900
1901 	/*
1902 	 * Tell the GUS to start doing DMA
1903 	 */
1904
1905 	SELECT_GUS_REG(port, GUSREG_DMA_CONTROL);
1906	outb(port+GUS_DATA_HIGH, c);
1907
1908	/*
1909	 * XXX If we don't finish in one second, give up...
1910	 */
1911	untimeout(gus_dmaout_timeout, sc); /* flush old one, if there is one */
1912	timeout(gus_dmaout_timeout, sc, hz);
1913}
1914
1915/*
1916 * Start a voice playing on the GUS.  Called from interrupt handler at
1917 * splgus().
1918 */
1919
1920STATIC void
1921gus_start_voice(sc, voice, intrs)
1922	struct gus_softc *sc;
1923	int voice;
1924	int intrs;
1925{
1926	int port = sc->sc_iobase;
1927	u_long start;
1928	u_long current;
1929	u_long end;
1930
1931	/*
1932	 * Pick all the values for the voice out of the gus_voice struct
1933	 * and use those to program the voice
1934	 */
1935
1936 	start = sc->sc_voc[voice].start_addr;
1937 	current = sc->sc_voc[voice].current_addr;
1938 	end = sc->sc_voc[voice].end_addr;
1939
1940 	/*
1941	 * If we're using 16 bit data, mangle the addresses a bit
1942	 */
1943
1944	if (sc->sc_voc[voice].voccntl & GUSMASK_DATA_SIZE16) {
1945	        /* -1 on start so that we get onto sample boundary--other
1946		   code always sets it for 1-byte rollover protection */
1947		start = convert_to_16bit(start-1);
1948		current = convert_to_16bit(current);
1949		end = convert_to_16bit(end);
1950	}
1951
1952	/*
1953	 * Select the voice we want to use, and program the data addresses
1954	 */
1955
1956	outb(port+GUS_VOICE_SELECT, (unsigned char) voice);
1957
1958	SELECT_GUS_REG(port, GUSREG_START_ADDR_HIGH);
1959	outw(port+GUS_DATA_LOW, ADDR_HIGH(start));
1960	SELECT_GUS_REG(port, GUSREG_START_ADDR_LOW);
1961	outw(port+GUS_DATA_LOW, ADDR_LOW(start));
1962
1963	SELECT_GUS_REG(port, GUSREG_CUR_ADDR_HIGH);
1964	outw(port+GUS_DATA_LOW, ADDR_HIGH(current));
1965	SELECT_GUS_REG(port, GUSREG_CUR_ADDR_LOW);
1966	outw(port+GUS_DATA_LOW, ADDR_LOW(current));
1967
1968	SELECT_GUS_REG(port, GUSREG_END_ADDR_HIGH);
1969	outw(port+GUS_DATA_LOW, ADDR_HIGH(end));
1970	SELECT_GUS_REG(port, GUSREG_END_ADDR_LOW);
1971	outw(port+GUS_DATA_LOW, ADDR_LOW(end));
1972
1973	/*
1974	 * (maybe) enable interrupts, disable voice stopping
1975	 */
1976
1977	if (intrs) {
1978		sc->sc_flags |= GUS_PLAYING; /* playing is about to start */
1979		sc->sc_voc[voice].voccntl |= GUSMASK_VOICE_IRQ;
1980		DMAPRINTF(("gus voice playing=%x\n", sc->sc_flags));
1981	} else
1982		sc->sc_voc[voice].voccntl &= ~GUSMASK_VOICE_IRQ;
1983	sc->sc_voc[voice].voccntl &= ~(GUSMASK_VOICE_STOPPED |
1984		GUSMASK_STOP_VOICE);
1985
1986	/*
1987	 * Tell the GUS about it.  Note that we're doing volume ramping here
1988	 * from 0 up to the set volume to help reduce clicks.
1989	 */
1990
1991	SELECT_GUS_REG(port, GUSREG_START_VOLUME);
1992	outb(port+GUS_DATA_HIGH, 0x00);
1993	SELECT_GUS_REG(port, GUSREG_END_VOLUME);
1994	outb(port+GUS_DATA_HIGH, sc->sc_voc[voice].current_volume >> 4);
1995	SELECT_GUS_REG(port, GUSREG_CUR_VOLUME);
1996	outw(port+GUS_DATA_LOW, 0x00);
1997	SELECT_GUS_REG(port, GUSREG_VOLUME_RATE);
1998	outb(port+GUS_DATA_HIGH, 63);
1999
2000	SELECT_GUS_REG(port, GUSREG_VOICE_CNTL);
2001	outb(port+GUS_DATA_HIGH, sc->sc_voc[voice].voccntl);
2002	SELECT_GUS_REG(port, GUSREG_VOLUME_CONTROL);
2003	outb(port+GUS_DATA_HIGH, 0x00);
2004	delay(50);
2005	SELECT_GUS_REG(port, GUSREG_VOICE_CNTL);
2006	outb(port+GUS_DATA_HIGH, sc->sc_voc[voice].voccntl);
2007	SELECT_GUS_REG(port, GUSREG_VOLUME_CONTROL);
2008	outb(port+GUS_DATA_HIGH, 0x00);
2009
2010}
2011
2012/*
2013 * Stop a given voice.  called at splgus()
2014 */
2015
2016STATIC void
2017gus_stop_voice(sc, voice, intrs_too)
2018	struct gus_softc *sc;
2019	int voice;
2020	int intrs_too;
2021{
2022	int port = sc->sc_iobase;
2023
2024	sc->sc_voc[voice].voccntl |= GUSMASK_VOICE_STOPPED |
2025		GUSMASK_STOP_VOICE;
2026	if (intrs_too) {
2027	  sc->sc_voc[voice].voccntl &= ~(GUSMASK_VOICE_IRQ);
2028	  /* no more DMA to do */
2029	  sc->sc_flags &= ~GUS_PLAYING;
2030	}
2031	DMAPRINTF(("gusintr voice notplaying=%x\n", sc->sc_flags));
2032
2033	guspoke(port, 0L, 0);
2034
2035	outb(port+GUS_VOICE_SELECT, (unsigned char) voice);
2036
2037	SELECT_GUS_REG(port, GUSREG_CUR_VOLUME);
2038	outw(port+GUS_DATA_LOW, 0x0000);
2039	SELECT_GUS_REG(port, GUSREG_VOICE_CNTL);
2040	outb(port+GUS_DATA_HIGH, sc->sc_voc[voice].voccntl);
2041	delay(100);
2042	SELECT_GUS_REG(port, GUSREG_CUR_VOLUME);
2043	outw(port+GUS_DATA_LOW, 0x0000);
2044	SELECT_GUS_REG(port, GUSREG_VOICE_CNTL);
2045	outb(port+GUS_DATA_HIGH, sc->sc_voc[voice].voccntl);
2046
2047	SELECT_GUS_REG(port, GUSREG_CUR_ADDR_HIGH);
2048	outw(port+GUS_DATA_LOW, 0x0000);
2049	SELECT_GUS_REG(port, GUSREG_CUR_ADDR_LOW);
2050	outw(port+GUS_DATA_LOW, 0x0000);
2051
2052}
2053
2054
2055/*
2056 * Set the volume of a given voice.  Called at splgus().
2057 */
2058STATIC void
2059gus_set_volume(sc, voice, volume)
2060	struct gus_softc *sc;
2061	int voice, volume;
2062{
2063	int port = sc->sc_iobase;
2064	unsigned int gusvol;
2065
2066	gusvol = gus_log_volumes[volume < 512 ? volume : 511];
2067
2068	sc->sc_voc[voice].current_volume = gusvol;
2069
2070	outb(port+GUS_VOICE_SELECT, (unsigned char) voice);
2071
2072	SELECT_GUS_REG(port, GUSREG_START_VOLUME);
2073	outb(port+GUS_DATA_HIGH, (unsigned char) (gusvol >> 4));
2074
2075	SELECT_GUS_REG(port, GUSREG_END_VOLUME);
2076	outb(port+GUS_DATA_HIGH, (unsigned char) (gusvol >> 4));
2077
2078	SELECT_GUS_REG(port, GUSREG_CUR_VOLUME);
2079	outw(port+GUS_DATA_LOW, gusvol << 4);
2080	delay(500);
2081	outw(port+GUS_DATA_LOW, gusvol << 4);
2082
2083}
2084
2085/*
2086 * Interface to the audio layer.
2087 */
2088
2089int
2090gusmax_set_params(addr, setmode, usemode, p, r)
2091	void *addr;
2092	int setmode, usemode;
2093	struct audio_params *p, *r;
2094{
2095	struct ad1848_softc *ac = addr;
2096	struct gus_softc *sc = ac->parent;
2097	int error;
2098
2099	error = ad1848_set_params(ac, setmode, usemode, p, r);
2100	if (error)
2101		return error;
2102	error = gus_set_params(sc, setmode, usemode, p, r);
2103	return error;
2104}
2105
2106int
2107gus_set_params(addr, setmode, usemode, p, r)
2108	void *addr;
2109	int setmode, usemode;
2110	struct audio_params *p, *r;
2111{
2112	struct gus_softc *sc = addr;
2113	int s;
2114
2115	switch (p->encoding) {
2116	case AUDIO_ENCODING_ULAW:
2117	case AUDIO_ENCODING_ALAW:
2118	case AUDIO_ENCODING_SLINEAR_LE:
2119	case AUDIO_ENCODING_ULINEAR_LE:
2120	case AUDIO_ENCODING_SLINEAR_BE:
2121	case AUDIO_ENCODING_ULINEAR_BE:
2122		break;
2123	default:
2124		return (EINVAL);
2125	}
2126
2127	s = splaudio();
2128
2129	if (p->precision == 8) {
2130		sc->sc_voc[GUS_VOICE_LEFT].voccntl &= ~GUSMASK_DATA_SIZE16;
2131		sc->sc_voc[GUS_VOICE_RIGHT].voccntl &= ~GUSMASK_DATA_SIZE16;
2132	} else {
2133		sc->sc_voc[GUS_VOICE_LEFT].voccntl |= GUSMASK_DATA_SIZE16;
2134		sc->sc_voc[GUS_VOICE_RIGHT].voccntl |= GUSMASK_DATA_SIZE16;
2135	}
2136
2137	sc->sc_encoding = p->encoding;
2138	sc->sc_precision = p->precision;
2139	sc->sc_channels = p->channels;
2140
2141	splx(s);
2142
2143	if (p->sample_rate > gus_max_frequency[sc->sc_voices - GUS_MIN_VOICES])
2144		p->sample_rate = gus_max_frequency[sc->sc_voices - GUS_MIN_VOICES];
2145	if (setmode & AUMODE_RECORD)
2146		sc->sc_irate = p->sample_rate;
2147	if (setmode & AUMODE_PLAY)
2148		sc->sc_orate = p->sample_rate;
2149
2150	switch (p->encoding) {
2151	case AUDIO_ENCODING_ULAW:
2152		p->sw_code = mulaw_to_ulinear8;
2153		r->sw_code = ulinear8_to_mulaw;
2154		break;
2155	case AUDIO_ENCODING_ALAW:
2156		p->sw_code = alaw_to_ulinear8;
2157		r->sw_code = ulinear8_to_alaw;
2158		break;
2159	case AUDIO_ENCODING_ULINEAR_BE:
2160	case AUDIO_ENCODING_SLINEAR_BE:
2161		r->sw_code = p->sw_code = swap_bytes;
2162		break;
2163	}
2164
2165	return 0;
2166}
2167
2168/*
2169 * Interface to the audio layer - set the blocksize to the correct number
2170 * of units
2171 */
2172
2173int
2174gusmax_round_blocksize(addr, blocksize)
2175	void * addr;
2176	int blocksize;
2177{
2178	struct ad1848_softc *ac = addr;
2179	struct gus_softc *sc = ac->parent;
2180
2181/*	blocksize = ad1848_round_blocksize(ac, blocksize);*/
2182	return gus_round_blocksize(sc, blocksize);
2183}
2184
2185int
2186gus_round_blocksize(addr, blocksize)
2187	void * addr;
2188	int blocksize;
2189{
2190	struct gus_softc *sc = addr;
2191
2192	DPRINTF(("gus_round_blocksize called\n"));
2193
2194	if ((sc->sc_encoding == AUDIO_ENCODING_ULAW ||
2195	     sc->sc_encoding == AUDIO_ENCODING_ALAW) && blocksize > 32768)
2196		blocksize = 32768;
2197	else if (blocksize > 65536)
2198		blocksize = 65536;
2199
2200	if ((blocksize % GUS_BUFFER_MULTIPLE) != 0)
2201		blocksize = (blocksize / GUS_BUFFER_MULTIPLE + 1) *
2202			GUS_BUFFER_MULTIPLE;
2203
2204	/* set up temporary buffer to hold the deinterleave, if necessary
2205	   for stereo output */
2206	if (sc->sc_deintr_buf) {
2207		FREE(sc->sc_deintr_buf, M_DEVBUF);
2208		sc->sc_deintr_buf = NULL;
2209	}
2210	MALLOC(sc->sc_deintr_buf, void *, blocksize>>1, M_DEVBUF, M_WAITOK);
2211
2212	sc->sc_blocksize = blocksize;
2213	/* multi-buffering not quite working yet. */
2214	sc->sc_nbufs = /*GUS_MEM_FOR_BUFFERS / blocksize*/ 2;
2215
2216	gus_set_chan_addrs(sc);
2217
2218	return blocksize;
2219}
2220
2221int
2222gus_get_out_gain(addr)
2223	caddr_t addr;
2224{
2225	struct gus_softc *sc = (struct gus_softc *) addr;
2226
2227	DPRINTF(("gus_get_out_gain called\n"));
2228	return sc->sc_ogain / 2;
2229}
2230
2231STATIC inline void gus_set_voices(sc, voices)
2232struct gus_softc *sc;
2233int voices;
2234{
2235	int port = sc->sc_iobase;
2236	/*
2237	 * Select the active number of voices
2238	 */
2239
2240	SELECT_GUS_REG(port, GUSREG_ACTIVE_VOICES);
2241	outb(port+GUS_DATA_HIGH, (voices-1) | 0xc0);
2242
2243	sc->sc_voices = voices;
2244}
2245
2246/*
2247 * Actually set the settings of various values on the card
2248 */
2249
2250int
2251gusmax_commit_settings(addr)
2252	void * addr;
2253{
2254	struct ad1848_softc *ac = addr;
2255	struct gus_softc *sc = ac->parent;
2256	int error;
2257
2258	error = ad1848_commit_settings(ac);
2259	if (error)
2260		return error;
2261	return gus_commit_settings(sc);
2262}
2263
2264/*
2265 * Commit the settings.  Called at normal IPL.
2266 */
2267int
2268gus_commit_settings(addr)
2269	void * addr;
2270{
2271	struct gus_softc *sc = addr;
2272	int s;
2273
2274	DPRINTF(("gus_commit_settings called (gain = %d)\n",sc->sc_ogain));
2275
2276
2277	s = splgus();
2278
2279	gus_set_recrate(sc, sc->sc_irate);
2280	gus_set_volume(sc, GUS_VOICE_LEFT, sc->sc_ogain);
2281	gus_set_volume(sc, GUS_VOICE_RIGHT, sc->sc_ogain);
2282	gus_set_samprate(sc, GUS_VOICE_LEFT, sc->sc_orate);
2283	gus_set_samprate(sc, GUS_VOICE_RIGHT, sc->sc_orate);
2284	splx(s);
2285	gus_set_chan_addrs(sc);
2286
2287	return 0;
2288}
2289
2290STATIC void
2291gus_set_chan_addrs(sc)
2292struct gus_softc *sc;
2293{
2294	/*
2295	 * We use sc_nbufs * blocksize bytes of storage in the on-board GUS
2296	 * ram.
2297	 * For mono, each of the sc_nbufs buffers is DMA'd to in one chunk,
2298	 * and both left & right channels play the same buffer.
2299	 *
2300	 * For stereo, each channel gets a contiguous half of the memory,
2301	 * and each has sc_nbufs buffers of size blocksize/2.
2302	 * Stereo data are deinterleaved in main memory before the DMA out
2303	 * routines are called to queue the output.
2304	 *
2305	 * The blocksize per channel is kept in sc_chanblocksize.
2306	 */
2307	if (sc->sc_channels == 2)
2308	    sc->sc_chanblocksize = sc->sc_blocksize/2;
2309	else
2310	    sc->sc_chanblocksize = sc->sc_blocksize;
2311
2312	sc->sc_voc[GUS_VOICE_LEFT].start_addr = GUS_MEM_OFFSET - 1;
2313	sc->sc_voc[GUS_VOICE_RIGHT].start_addr =
2314	    (gus_dostereo && sc->sc_channels == 2 ? GUS_LEFT_RIGHT_OFFSET : 0)
2315	      + GUS_MEM_OFFSET - 1;
2316	sc->sc_voc[GUS_VOICE_RIGHT].current_addr =
2317	    sc->sc_voc[GUS_VOICE_RIGHT].start_addr + 1;
2318	sc->sc_voc[GUS_VOICE_RIGHT].end_addr =
2319	    sc->sc_voc[GUS_VOICE_RIGHT].start_addr +
2320	    sc->sc_nbufs * sc->sc_chanblocksize;
2321
2322}
2323
2324/*
2325 * Set the sample rate of the given voice.  Called at splgus().
2326 */
2327
2328STATIC void
2329gus_set_samprate(sc, voice, freq)
2330	struct gus_softc *sc;
2331	int voice, freq;
2332{
2333	int port = sc->sc_iobase;
2334	unsigned int fc;
2335	u_long temp, f = (u_long) freq;
2336
2337	/*
2338	 * calculate fc based on the number of active voices;
2339	 * we need to use longs to preserve enough bits
2340	 */
2341
2342	temp = (u_long) gus_max_frequency[sc->sc_voices-GUS_MIN_VOICES];
2343
2344 	fc = (unsigned int)(((f << 9L) + (temp >> 1L)) / temp);
2345
2346 	fc <<= 1;
2347
2348
2349	/*
2350	 * Program the voice frequency, and set it in the voice data record
2351	 */
2352
2353	outb(port+GUS_VOICE_SELECT, (unsigned char) voice);
2354	SELECT_GUS_REG(port, GUSREG_FREQ_CONTROL);
2355	outw(port+GUS_DATA_LOW, fc);
2356
2357	sc->sc_voc[voice].rate = freq;
2358
2359}
2360
2361/*
2362 * Set the sample rate of the recording frequency.  Formula is from the GUS
2363 * SDK.  Called at splgus().
2364 */
2365
2366STATIC void
2367gus_set_recrate(sc, rate)
2368	struct gus_softc *sc;
2369	u_long rate;
2370{
2371	int port = sc->sc_iobase;
2372	u_char realrate;
2373	DPRINTF(("gus_set_recrate %lu\n", rate));
2374
2375#if 0
2376	realrate = 9878400/(16*(rate+2)); /* formula from GUS docs */
2377#endif
2378	realrate = (9878400 >> 4)/rate - 2; /* formula from code, sigh. */
2379
2380	SELECT_GUS_REG(port, GUSREG_SAMPLE_FREQ);
2381 	outb(port+GUS_DATA_HIGH, realrate);
2382}
2383
2384/*
2385 * Interface to the audio layer - turn the output on or off.  Note that some
2386 * of these bits are flipped in the register
2387 */
2388
2389int
2390gusmax_speaker_ctl(addr, newstate)
2391	void * addr;
2392	int newstate;
2393{
2394	struct ad1848_softc *sc = addr;
2395	return gus_speaker_ctl(sc->parent, newstate);
2396}
2397
2398int
2399gus_speaker_ctl(addr, newstate)
2400	void * addr;
2401	int newstate;
2402{
2403	struct gus_softc *sc = (struct gus_softc *) addr;
2404
2405	/* Line out bit is flipped: 0 enables, 1 disables */
2406	if ((newstate == SPKR_ON) &&
2407	    (sc->sc_mixcontrol & GUSMASK_LINE_OUT)) {
2408		sc->sc_mixcontrol &= ~GUSMASK_LINE_OUT;
2409		outb(sc->sc_iobase+GUS_MIX_CONTROL, sc->sc_mixcontrol);
2410	}
2411	if ((newstate == SPKR_OFF) &&
2412	    (sc->sc_mixcontrol & GUSMASK_LINE_OUT) == 0) {
2413		sc->sc_mixcontrol |= GUSMASK_LINE_OUT;
2414		outb(sc->sc_iobase+GUS_MIX_CONTROL, sc->sc_mixcontrol);
2415	}
2416
2417	return 0;
2418}
2419
2420STATIC int
2421gus_linein_ctl(addr, newstate)
2422	void * addr;
2423	int newstate;
2424{
2425	struct gus_softc *sc = (struct gus_softc *) addr;
2426
2427	/* Line in bit is flipped: 0 enables, 1 disables */
2428	if ((newstate == SPKR_ON) &&
2429	    (sc->sc_mixcontrol & GUSMASK_LINE_IN)) {
2430		sc->sc_mixcontrol &= ~GUSMASK_LINE_IN;
2431		outb(sc->sc_iobase+GUS_MIX_CONTROL, sc->sc_mixcontrol);
2432	}
2433	if ((newstate == SPKR_OFF) &&
2434	    (sc->sc_mixcontrol & GUSMASK_LINE_IN) == 0) {
2435		sc->sc_mixcontrol |= GUSMASK_LINE_IN;
2436		outb(sc->sc_iobase+GUS_MIX_CONTROL, sc->sc_mixcontrol);
2437	}
2438
2439	return 0;
2440}
2441
2442STATIC int
2443gus_mic_ctl(addr, newstate)
2444	void * addr;
2445	int newstate;
2446{
2447	struct gus_softc *sc = (struct gus_softc *) addr;
2448
2449	/* Mic bit is normal: 1 enables, 0 disables */
2450	if ((newstate == SPKR_ON) &&
2451	    (sc->sc_mixcontrol & GUSMASK_MIC_IN) == 0) {
2452		sc->sc_mixcontrol |= GUSMASK_MIC_IN;
2453		outb(sc->sc_iobase+GUS_MIX_CONTROL, sc->sc_mixcontrol);
2454	}
2455	if ((newstate == SPKR_OFF) &&
2456	    (sc->sc_mixcontrol & GUSMASK_MIC_IN)) {
2457		sc->sc_mixcontrol &= ~GUSMASK_MIC_IN;
2458		outb(sc->sc_iobase+GUS_MIX_CONTROL, sc->sc_mixcontrol);
2459	}
2460
2461	return 0;
2462}
2463
2464/*
2465 * Set the end address of a give voice.  Called at splgus()
2466 */
2467
2468STATIC void
2469gus_set_endaddr(sc, voice, addr)
2470	struct gus_softc *sc;
2471	int voice;
2472	u_long addr;
2473{
2474	int port = sc->sc_iobase;
2475
2476	sc->sc_voc[voice].end_addr = addr;
2477
2478	if (sc->sc_voc[voice].voccntl & GUSMASK_DATA_SIZE16)
2479		addr = convert_to_16bit(addr);
2480
2481	SELECT_GUS_REG(port, GUSREG_END_ADDR_HIGH);
2482	outw(port+GUS_DATA_LOW, ADDR_HIGH(addr));
2483	SELECT_GUS_REG(port, GUSREG_END_ADDR_LOW);
2484	outw(port+GUS_DATA_LOW, ADDR_LOW(addr));
2485
2486}
2487
2488#ifdef GUSPLAYDEBUG
2489/*
2490 * Set current address.  called at splgus()
2491 */
2492STATIC void
2493gus_set_curaddr(sc, voice, addr)
2494	struct gus_softc *sc;
2495	int voice;
2496	u_long addr;
2497{
2498	int port = sc->sc_iobase;
2499
2500	sc->sc_voc[voice].current_addr = addr;
2501
2502	if (sc->sc_voc[voice].voccntl & GUSMASK_DATA_SIZE16)
2503		addr = convert_to_16bit(addr);
2504
2505	outb(port+GUS_VOICE_SELECT, (unsigned char) voice);
2506
2507	SELECT_GUS_REG(port, GUSREG_CUR_ADDR_HIGH);
2508	outw(port+GUS_DATA_LOW, ADDR_HIGH(addr));
2509	SELECT_GUS_REG(port, GUSREG_CUR_ADDR_LOW);
2510	outw(port+GUS_DATA_LOW, ADDR_LOW(addr));
2511
2512}
2513
2514/*
2515 * Get current GUS playback address.  Called at splgus().
2516 */
2517STATIC u_long
2518gus_get_curaddr(sc, voice)
2519	struct gus_softc *sc;
2520	int voice;
2521{
2522	int port = sc->sc_iobase;
2523	u_long addr;
2524
2525	outb(port+GUS_VOICE_SELECT, (unsigned char) voice);
2526	SELECT_GUS_REG(port, GUSREG_CUR_ADDR_HIGH|GUSREG_READ);
2527	addr = (inw(port+GUS_DATA_LOW) & 0x1fff) << 7;
2528	SELECT_GUS_REG(port, GUSREG_CUR_ADDR_LOW|GUSREG_READ);
2529	addr |= (inw(port+GUS_DATA_LOW) >> 9L) & 0x7f;
2530
2531	if (sc->sc_voc[voice].voccntl & GUSMASK_DATA_SIZE16)
2532	    addr = (addr & 0xc0000) | ((addr & 0x1ffff) << 1); /* undo 16-bit change */
2533	DPRINTF(("gus voice %d curaddr %ld end_addr %ld\n",
2534		 voice, addr, sc->sc_voc[voice].end_addr));
2535	/* XXX sanity check the address? */
2536
2537	return(addr);
2538}
2539#endif
2540
2541/*
2542 * Convert an address value to a "16 bit" value - why this is necessary I
2543 * have NO idea
2544 */
2545
2546STATIC u_long
2547convert_to_16bit(address)
2548	u_long address;
2549{
2550	u_long old_address;
2551
2552	old_address = address;
2553	address >>= 1;
2554	address &= 0x0001ffffL;
2555	address |= (old_address & 0x000c0000L);
2556
2557	return (address);
2558}
2559
2560/*
2561 * Write a value into the GUS's DRAM
2562 */
2563
2564STATIC void
2565guspoke(port, address, value)
2566	int port;
2567	long address;
2568	unsigned char value;
2569{
2570
2571	/*
2572	 * Select the DRAM address
2573	 */
2574
2575 	SELECT_GUS_REG(port, GUSREG_DRAM_ADDR_LOW);
2576 	outw(port+GUS_DATA_LOW, (unsigned int) (address & 0xffff));
2577 	SELECT_GUS_REG(port, GUSREG_DRAM_ADDR_HIGH);
2578 	outb(port+GUS_DATA_HIGH, (unsigned char) ((address >> 16) & 0xff));
2579
2580	/*
2581	 * Actually write the data
2582	 */
2583
2584	outb(port+GUS_DRAM_DATA, value);
2585}
2586
2587/*
2588 * Read a value from the GUS's DRAM
2589 */
2590
2591STATIC unsigned char
2592guspeek(port, address)
2593	int port;
2594	u_long address;
2595{
2596
2597	/*
2598	 * Select the DRAM address
2599	 */
2600
2601 	SELECT_GUS_REG(port, GUSREG_DRAM_ADDR_LOW);
2602 	outw(port+GUS_DATA_LOW, (unsigned int) (address & 0xffff));
2603 	SELECT_GUS_REG(port, GUSREG_DRAM_ADDR_HIGH);
2604 	outb(port+GUS_DATA_HIGH, (unsigned char) ((address >> 16) & 0xff));
2605
2606	/*
2607	 * Read in the data from the board
2608	 */
2609
2610	return (unsigned char) inb(port+GUS_DRAM_DATA);
2611}
2612
2613/*
2614 * Reset the Gravis UltraSound card, completely
2615 */
2616
2617STATIC void
2618gusreset(sc, voices)
2619	struct gus_softc *sc;
2620	int voices;
2621{
2622	int port = sc->sc_iobase;
2623	int i,s;
2624
2625	s = splgus();
2626
2627	/*
2628	 * Reset the GF1 chip
2629	 */
2630
2631	SELECT_GUS_REG(port, GUSREG_RESET);
2632	outb(port+GUS_DATA_HIGH, 0x00);
2633
2634	delay(500);
2635
2636	/*
2637	 * Release reset
2638	 */
2639
2640	SELECT_GUS_REG(port, GUSREG_RESET);
2641	outb(port+GUS_DATA_HIGH, GUSMASK_MASTER_RESET);
2642
2643	delay(500);
2644
2645	/*
2646	 * Reset MIDI port as well
2647	 */
2648
2649	outb(GUS_MIDI_CONTROL,MIDI_RESET);
2650
2651	delay(500);
2652
2653	outb(GUS_MIDI_CONTROL,0x00);
2654
2655	/*
2656	 * Clear interrupts
2657	 */
2658
2659	SELECT_GUS_REG(port, GUSREG_DMA_CONTROL);
2660	outb(port+GUS_DATA_HIGH, 0x00);
2661	SELECT_GUS_REG(port, GUSREG_TIMER_CONTROL);
2662	outb(port+GUS_DATA_HIGH, 0x00);
2663	SELECT_GUS_REG(port, GUSREG_SAMPLE_CONTROL);
2664	outb(port+GUS_DATA_HIGH, 0x00);
2665
2666	gus_set_voices(sc, voices);
2667
2668	inb(port+GUS_IRQ_STATUS);
2669	SELECT_GUS_REG(port, GUSREG_DMA_CONTROL);
2670	inb(port+GUS_DATA_HIGH);
2671	SELECT_GUS_REG(port, GUSREG_SAMPLE_CONTROL);
2672	inb(port+GUS_DATA_HIGH);
2673	SELECT_GUS_REG(port, GUSREG_IRQ_STATUS);
2674	inb(port+GUS_DATA_HIGH);
2675
2676	/*
2677	 * Reset voice specific information
2678	 */
2679
2680	for(i = 0; i < voices; i++) {
2681		outb(port+GUS_VOICE_SELECT, (unsigned char) i);
2682
2683		SELECT_GUS_REG(port, GUSREG_VOICE_CNTL);
2684
2685		sc->sc_voc[i].voccntl = GUSMASK_VOICE_STOPPED |
2686			GUSMASK_STOP_VOICE;
2687
2688		outb(port+GUS_DATA_HIGH, sc->sc_voc[i].voccntl);
2689
2690		sc->sc_voc[i].volcntl = GUSMASK_VOLUME_STOPPED |
2691				GUSMASK_STOP_VOLUME;
2692
2693		SELECT_GUS_REG(port, GUSREG_VOLUME_CONTROL);
2694		outb(port+GUS_DATA_HIGH, sc->sc_voc[i].volcntl);
2695
2696		delay(100);
2697
2698		gus_set_samprate(sc, i, 8000);
2699		SELECT_GUS_REG(port, GUSREG_START_ADDR_HIGH);
2700		outw(port+GUS_DATA_LOW, 0x0000);
2701		SELECT_GUS_REG(port, GUSREG_START_ADDR_LOW);
2702		outw(port+GUS_DATA_LOW, 0x0000);
2703		SELECT_GUS_REG(port, GUSREG_END_ADDR_HIGH);
2704		outw(port+GUS_DATA_LOW, 0x0000);
2705		SELECT_GUS_REG(port, GUSREG_END_ADDR_LOW);
2706		outw(port+GUS_DATA_LOW, 0x0000);
2707		SELECT_GUS_REG(port, GUSREG_VOLUME_RATE);
2708		outb(port+GUS_DATA_HIGH, 0x01);
2709		SELECT_GUS_REG(port, GUSREG_START_VOLUME);
2710		outb(port+GUS_DATA_HIGH, 0x10);
2711		SELECT_GUS_REG(port, GUSREG_END_VOLUME);
2712		outb(port+GUS_DATA_HIGH, 0xe0);
2713		SELECT_GUS_REG(port, GUSREG_CUR_VOLUME);
2714		outw(port+GUS_DATA_LOW, 0x0000);
2715
2716		SELECT_GUS_REG(port, GUSREG_CUR_ADDR_HIGH);
2717		outw(port+GUS_DATA_LOW, 0x0000);
2718		SELECT_GUS_REG(port, GUSREG_CUR_ADDR_LOW);
2719		outw(port+GUS_DATA_LOW, 0x0000);
2720		SELECT_GUS_REG(port, GUSREG_PAN_POS);
2721		outb(port+GUS_DATA_HIGH, 0x07);
2722	}
2723
2724	/*
2725	 * Clear out any pending IRQs
2726	 */
2727
2728	inb(port+GUS_IRQ_STATUS);
2729	SELECT_GUS_REG(port, GUSREG_DMA_CONTROL);
2730	inb(port+GUS_DATA_HIGH);
2731	SELECT_GUS_REG(port, GUSREG_SAMPLE_CONTROL);
2732	inb(port+GUS_DATA_HIGH);
2733	SELECT_GUS_REG(port, GUSREG_IRQ_STATUS);
2734	inb(port+GUS_DATA_HIGH);
2735
2736	SELECT_GUS_REG(port, GUSREG_RESET);
2737	outb(port+GUS_DATA_HIGH, GUSMASK_MASTER_RESET | GUSMASK_DAC_ENABLE |
2738		GUSMASK_IRQ_ENABLE);
2739
2740	splx(s);
2741}
2742
2743
2744STATIC void
2745gus_init_cs4231(sc)
2746	struct gus_softc *sc;
2747{
2748	int port = sc->sc_iobase;
2749	u_char ctrl;
2750
2751	ctrl = (port & 0xf0) >> 4;	/* set port address middle nibble */
2752	/*
2753	 * The codec is a bit weird--swapped dma channels.
2754	 */
2755	ctrl |= GUS_MAX_CODEC_ENABLE;
2756	if (sc->sc_drq >= 4)
2757		ctrl |= GUS_MAX_RECCHAN16;
2758	if (sc->sc_recdrq >= 4)
2759		ctrl |= GUS_MAX_PLAYCHAN16;
2760
2761	outb(port+GUS_MAX_CTRL, ctrl);
2762
2763	sc->sc_codec.sc_iot = sc->sc_iot;
2764	sc->sc_codec.sc_iobase = port+GUS_MAX_CODEC_BASE;
2765
2766	if (ad1848_probe(&sc->sc_codec) == 0) {
2767		sc->sc_flags &= ~GUS_CODEC_INSTALLED;
2768	} else {
2769		struct ad1848_volume vol = {AUDIO_MAX_GAIN, AUDIO_MAX_GAIN};
2770		static struct audio_hw_if gusmax_hw_if = {
2771			gusmaxopen,
2772			gusmax_close,
2773			NULL,				/* drain */
2774
2775			gus_query_encoding, /* query encoding */
2776
2777			gusmax_set_params,
2778
2779			gusmax_round_blocksize,
2780
2781			gusmax_set_out_port,
2782			gusmax_get_out_port,
2783			gusmax_set_in_port,
2784			gusmax_get_in_port,
2785
2786			gusmax_commit_settings,
2787
2788			NULL,
2789			NULL,
2790
2791			gusmax_dma_output,
2792			gusmax_dma_input,
2793			gusmax_halt_out_dma,
2794			gusmax_halt_in_dma,
2795			gusmax_cont_out_dma,
2796			gusmax_cont_in_dma,
2797
2798			gusmax_speaker_ctl,
2799
2800			gus_getdev,
2801			NULL,
2802			gusmax_mixer_set_port,
2803			gusmax_mixer_get_port,
2804			gusmax_mixer_query_devinfo,
2805			NULL,
2806			NULL,
2807			NULL,
2808                        NULL,
2809			gusmax_get_props,
2810		};
2811		sc->sc_flags |= GUS_CODEC_INSTALLED;
2812		sc->sc_codec.parent = sc;
2813		sc->sc_codec.sc_drq = sc->sc_recdrq;
2814		sc->sc_codec.sc_recdrq = sc->sc_drq;
2815		gus_hw_if = gusmax_hw_if;
2816		/* enable line in and mic in the GUS mixer; the codec chip
2817		   will do the real mixing for them. */
2818		sc->sc_mixcontrol &= ~GUSMASK_LINE_IN; /* 0 enables. */
2819		sc->sc_mixcontrol |= GUSMASK_MIC_IN; /* 1 enables. */
2820		outb(sc->sc_iobase+GUS_MIX_CONTROL, sc->sc_mixcontrol);
2821
2822		ad1848_attach(&sc->sc_codec);
2823		/* turn on pre-MUX microphone gain. */
2824		ad1848_set_mic_gain(&sc->sc_codec, &vol);
2825	}
2826}
2827
2828
2829/*
2830 * Return info about the audio device, for the AUDIO_GETINFO ioctl
2831 */
2832
2833int
2834gus_getdev(addr, dev)
2835	void * addr;
2836	struct audio_device *dev;
2837{
2838	*dev = gus_device;
2839	return 0;
2840}
2841
2842/*
2843 * stubs (XXX)
2844 */
2845
2846int
2847gus_set_in_gain(addr, gain, balance)
2848	caddr_t addr;
2849	u_int gain;
2850	u_char balance;
2851{
2852	DPRINTF(("gus_set_in_gain called\n"));
2853	return 0;
2854}
2855
2856int
2857gus_get_in_gain(addr)
2858	caddr_t addr;
2859{
2860	DPRINTF(("gus_get_in_gain called\n"));
2861	return 0;
2862}
2863
2864int
2865gusmax_set_out_port(addr, port)
2866	void * addr;
2867	int port;
2868{
2869	struct ad1848_softc *sc = addr;
2870	return gus_set_out_port(sc->parent, port);
2871}
2872
2873int
2874gus_set_out_port(addr, port)
2875	void * addr;
2876	int port;
2877{
2878	struct gus_softc *sc = addr;
2879	DPRINTF(("gus_set_out_port called\n"));
2880	sc->sc_out_port = port;
2881
2882	return 0;
2883}
2884
2885int
2886gusmax_get_out_port(addr)
2887	void * addr;
2888{
2889	struct ad1848_softc *sc = addr;
2890	return gus_get_out_port(sc->parent);
2891}
2892
2893int
2894gus_get_out_port(addr)
2895	void * addr;
2896{
2897	struct gus_softc *sc = addr;
2898	DPRINTF(("gus_get_out_port() called\n"));
2899	return sc->sc_out_port;
2900}
2901
2902int
2903gusmax_set_in_port(addr, port)
2904	void * addr;
2905	int port;
2906{
2907	struct ad1848_softc *sc = addr;
2908	DPRINTF(("gusmax_set_in_port: %d\n", port));
2909
2910	switch(port) {
2911	case MIC_IN_PORT:
2912	case LINE_IN_PORT:
2913	case AUX1_IN_PORT:
2914	case DAC_IN_PORT:
2915		break;
2916	default:
2917		return(EINVAL);
2918		/*NOTREACHED*/
2919	}
2920	return(ad1848_set_rec_port(sc, port));
2921}
2922
2923int
2924gusmax_get_in_port(addr)
2925	void * addr;
2926{
2927	struct ad1848_softc *sc = addr;
2928	int port;
2929
2930	port = ad1848_get_rec_port(sc);
2931	DPRINTF(("gusmax_get_in_port: %d\n", port));
2932
2933	return(port);
2934}
2935
2936int
2937gus_set_in_port(addr, port)
2938	void * addr;
2939	int port;
2940{
2941	struct gus_softc *sc = addr;
2942	DPRINTF(("gus_set_in_port called\n"));
2943	/*
2944	 * On the GUS with ICS mixer, the ADC input is after the mixer stage,
2945	 * so we can't set the input port.
2946	 *
2947	 * On the GUS with CS4231 codec/mixer, see gusmax_set_in_port().
2948	 */
2949	sc->sc_in_port = port;
2950
2951	return 0;
2952}
2953
2954
2955int
2956gus_get_in_port(addr)
2957	void * addr;
2958{
2959	struct gus_softc *sc = addr;
2960	DPRINTF(("gus_get_in_port called\n"));
2961	return sc->sc_in_port;
2962}
2963
2964
2965int
2966gusmax_dma_input(addr, buf, size, callback, arg)
2967	void * addr;
2968	void *buf;
2969	int size;
2970	void (*callback) __P((void *));
2971	void *arg;
2972{
2973	struct ad1848_softc *sc = addr;
2974	return gus_dma_input(sc->parent, buf, size, callback, arg);
2975}
2976
2977/*
2978 * Start sampling the input source into the requested DMA buffer.
2979 * Called at splgus(), either from top-half or from interrupt handler.
2980 */
2981int
2982gus_dma_input(addr, buf, size, callback, arg)
2983	void * addr;
2984	void *buf;
2985	int size;
2986	void (*callback) __P((void *));
2987	void *arg;
2988{
2989	struct gus_softc *sc = addr;
2990	int port = sc->sc_iobase;
2991	u_char dmac;
2992	DMAPRINTF(("gus_dma_input called\n"));
2993
2994	/*
2995	 * Sample SIZE bytes of data from the card, into buffer at BUF.
2996	 */
2997
2998	if (sc->sc_precision == 16)
2999	    return EINVAL;		/* XXX */
3000
3001	/* set DMA modes */
3002	dmac = GUSMASK_SAMPLE_IRQ|GUSMASK_SAMPLE_START;
3003	if (sc->sc_recdrq >= 4)
3004		dmac |= GUSMASK_SAMPLE_DATA16;
3005	if (sc->sc_encoding == AUDIO_ENCODING_ULAW ||
3006	    sc->sc_encoding == AUDIO_ENCODING_ALAW ||
3007	    sc->sc_encoding == AUDIO_ENCODING_ULINEAR_LE ||
3008	    sc->sc_encoding == AUDIO_ENCODING_ULINEAR_BE)
3009	    dmac |= GUSMASK_SAMPLE_INVBIT;
3010	if (sc->sc_channels == 2)
3011	    dmac |= GUSMASK_SAMPLE_STEREO;
3012	isa_dmastart(sc->sc_dev.dv_parent, sc->sc_recdrq, buf, size,
3013	    NULL, DMAMODE_READ, BUS_DMA_NOWAIT);
3014
3015	DMAPRINTF(("gus_dma_input isa_dmastarted\n"));
3016	sc->sc_flags |= GUS_DMAIN_ACTIVE;
3017	sc->sc_dmainintr = callback;
3018	sc->sc_inarg = arg;
3019	sc->sc_dmaincnt = size;
3020	sc->sc_dmainaddr = buf;
3021
3022	SELECT_GUS_REG(port, GUSREG_SAMPLE_CONTROL);
3023	outb(port+GUS_DATA_HIGH, dmac);	/* Go! */
3024
3025
3026	DMAPRINTF(("gus_dma_input returning\n"));
3027
3028	return 0;
3029}
3030
3031STATIC int
3032gus_dmain_intr(sc)
3033	struct gus_softc *sc;
3034{
3035        void (*callback) __P((void *));
3036	void *arg;
3037
3038	DMAPRINTF(("gus_dmain_intr called\n"));
3039	if (sc->sc_dmainintr) {
3040	    isa_dmadone(sc->sc_dev.dv_parent, sc->sc_recdrq);
3041	    callback = sc->sc_dmainintr;
3042	    arg = sc->sc_inarg;
3043
3044	    sc->sc_dmainaddr = 0;
3045	    sc->sc_dmaincnt = 0;
3046	    sc->sc_dmainintr = 0;
3047	    sc->sc_inarg = 0;
3048
3049	    sc->sc_flags &= ~GUS_DMAIN_ACTIVE;
3050	    DMAPRINTF(("calling dmain_intr callback %p(%p)\n", callback, arg));
3051	    (*callback)(arg);
3052	    return 1;
3053	} else {
3054	    DMAPRINTF(("gus_dmain_intr false?\n"));
3055	    return 0;			/* XXX ??? */
3056	}
3057}
3058
3059int
3060gusmax_halt_out_dma(addr)
3061	void * addr;
3062{
3063	struct ad1848_softc *sc = addr;
3064	return gus_halt_out_dma(sc->parent);
3065}
3066
3067
3068int
3069gusmax_halt_in_dma(addr)
3070	void * addr;
3071{
3072	struct ad1848_softc *sc = addr;
3073	return gus_halt_in_dma(sc->parent);
3074}
3075
3076int
3077gusmax_cont_out_dma(addr)
3078	void * addr;
3079{
3080	struct ad1848_softc *sc = addr;
3081	return gus_cont_out_dma(sc->parent);
3082}
3083
3084int
3085gusmax_cont_in_dma(addr)
3086	void * addr;
3087{
3088	struct ad1848_softc *sc = addr;
3089	return gus_cont_in_dma(sc->parent);
3090}
3091
3092/*
3093 * Stop any DMA output.  Called at splgus().
3094 */
3095int
3096gus_halt_out_dma(addr)
3097	void * addr;
3098{
3099	struct gus_softc *sc = addr;
3100	int port = sc->sc_iobase;
3101
3102	DMAPRINTF(("gus_halt_out_dma called\n"));
3103	/*
3104	 * Make sure the GUS _isn't_ setup for DMA
3105	 */
3106
3107 	SELECT_GUS_REG(port, GUSREG_DMA_CONTROL);
3108	outb(sc->sc_iobase+GUS_DATA_HIGH, 0);
3109
3110	untimeout(gus_dmaout_timeout, sc);
3111	isa_dmaabort(sc->sc_dev.dv_parent, sc->sc_drq);
3112	sc->sc_flags &= ~(GUS_DMAOUT_ACTIVE|GUS_LOCKED);
3113	sc->sc_dmaoutintr = 0;
3114	sc->sc_outarg = 0;
3115	sc->sc_dmaoutaddr = 0;
3116	sc->sc_dmaoutcnt = 0;
3117	sc->sc_dmabuf = 0;
3118	sc->sc_bufcnt = 0;
3119	sc->sc_playbuf = -1;
3120	/* also stop playing */
3121	gus_stop_voice(sc, GUS_VOICE_LEFT, 1);
3122	gus_stop_voice(sc, GUS_VOICE_RIGHT, 0);
3123
3124	return 0;
3125}
3126
3127/*
3128 * Stop any DMA output.  Called at splgus().
3129 */
3130int
3131gus_halt_in_dma(addr)
3132	void * addr;
3133{
3134	struct gus_softc *sc = addr;
3135	int port = sc->sc_iobase;
3136	DMAPRINTF(("gus_halt_in_dma called\n"));
3137
3138	/*
3139	 * Make sure the GUS _isn't_ setup for DMA
3140	 */
3141
3142 	SELECT_GUS_REG(port, GUSREG_SAMPLE_CONTROL);
3143	outb(port+GUS_DATA_HIGH,
3144	     inb(port+GUS_DATA_HIGH) & ~(GUSMASK_SAMPLE_START|GUSMASK_SAMPLE_IRQ));
3145
3146	isa_dmaabort(sc->sc_dev.dv_parent, sc->sc_recdrq);
3147	sc->sc_flags &= ~GUS_DMAIN_ACTIVE;
3148	sc->sc_dmainintr = 0;
3149	sc->sc_inarg = 0;
3150	sc->sc_dmainaddr = 0;
3151	sc->sc_dmaincnt = 0;
3152
3153	return 0;
3154}
3155
3156int
3157gus_cont_out_dma(addr)
3158	void * addr;
3159{
3160	DPRINTF(("gus_cont_out_dma called\n"));
3161	return EOPNOTSUPP;
3162}
3163
3164int
3165gus_cont_in_dma(addr)
3166	void * addr;
3167{
3168	DPRINTF(("gus_cont_in_dma called\n"));
3169	return EOPNOTSUPP;
3170}
3171
3172
3173STATIC __inline int
3174gus_to_vol(cp, vol)
3175	mixer_ctrl_t *cp;
3176	struct ad1848_volume *vol;
3177{
3178	if (cp->un.value.num_channels == 1) {
3179		vol->left = vol->right = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
3180		return(1);
3181	}
3182	else if (cp->un.value.num_channels == 2) {
3183		vol->left  = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
3184		vol->right = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
3185		return(1);
3186	}
3187	return(0);
3188}
3189
3190STATIC __inline int
3191gus_from_vol(cp, vol)
3192	mixer_ctrl_t *cp;
3193	struct ad1848_volume *vol;
3194{
3195	if (cp->un.value.num_channels == 1) {
3196		cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = vol->left;
3197		return(1);
3198	}
3199	else if (cp->un.value.num_channels == 2) {
3200		cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = vol->left;
3201		cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = vol->right;
3202		return(1);
3203	}
3204	return(0);
3205}
3206
3207STATIC int
3208gusmax_mixer_get_port(addr, cp)
3209	void *addr;
3210	mixer_ctrl_t *cp;
3211{
3212	struct ad1848_softc *ac = addr;
3213	struct gus_softc *sc = ac->parent;
3214	struct ad1848_volume vol;
3215	int error = EINVAL;
3216
3217	DPRINTF(("gusmax_mixer_get_port: port=%d\n", cp->dev));
3218
3219	switch (cp->dev) {
3220#if 0 /* use mono level instead */
3221	case GUSMAX_MIC_IN_LVL:	/* Microphone */
3222		if (cp->type == AUDIO_MIXER_VALUE) {
3223			error = ad1848_get_mic_gain(ac, &vol);
3224			if (!error)
3225				gus_from_vol(cp, &vol);
3226		}
3227		break;
3228#endif
3229
3230	case GUSMAX_DAC_LVL:		/* dac out */
3231		if (cp->type == AUDIO_MIXER_VALUE) {
3232			error = ad1848_get_aux1_gain(ac, &vol);
3233			if (!error)
3234				gus_from_vol(cp, &vol);
3235		}
3236		break;
3237
3238	case GUSMAX_LINE_IN_LVL:	/* line in */
3239		if (cp->type == AUDIO_MIXER_VALUE) {
3240			error = cs4231_get_linein_gain(ac, &vol);
3241			if (!error)
3242				gus_from_vol(cp, &vol);
3243		}
3244		break;
3245
3246	case GUSMAX_MONO_LVL:	/* mono */
3247		if (cp->type == AUDIO_MIXER_VALUE &&
3248		    cp->un.value.num_channels == 1) {
3249			error = cs4231_get_mono_gain(ac, &vol);
3250			if (!error)
3251				gus_from_vol(cp, &vol);
3252		}
3253		break;
3254
3255	case GUSMAX_CD_LVL:	/* CD */
3256		if (cp->type == AUDIO_MIXER_VALUE) {
3257			error = ad1848_get_aux2_gain(ac, &vol);
3258			if (!error)
3259				gus_from_vol(cp, &vol);
3260		}
3261		break;
3262
3263	case GUSMAX_MONITOR_LVL:	/* monitor level */
3264		if (cp->type == AUDIO_MIXER_VALUE &&
3265		    cp->un.value.num_channels == 1) {
3266			error = ad1848_get_mon_gain(ac, &vol);
3267			if (!error)
3268				cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
3269					vol.left;
3270		}
3271		break;
3272
3273	case GUSMAX_OUT_LVL:	/* output level */
3274		if (cp->type == AUDIO_MIXER_VALUE) {
3275			error = ad1848_get_out_gain(ac, &vol);
3276			if (!error)
3277				gus_from_vol(cp, &vol);
3278		}
3279		break;
3280
3281	case GUSMAX_SPEAKER_LVL:	/* fake speaker for mute naming */
3282		if (cp->type == AUDIO_MIXER_VALUE) {
3283			if (sc->sc_mixcontrol & GUSMASK_LINE_OUT)
3284				vol.left = vol.right = AUDIO_MAX_GAIN;
3285			else
3286				vol.left = vol.right = AUDIO_MIN_GAIN;
3287			error = 0;
3288			gus_from_vol(cp, &vol);
3289		}
3290		break;
3291
3292	case GUSMAX_LINE_IN_MUTE:
3293		if (cp->type == AUDIO_MIXER_ENUM) {
3294			cp->un.ord = ac->line_mute;
3295			error = 0;
3296		}
3297		break;
3298
3299
3300	case GUSMAX_DAC_MUTE:
3301		if (cp->type == AUDIO_MIXER_ENUM) {
3302			cp->un.ord = ac->aux1_mute;
3303			error = 0;
3304		}
3305		break;
3306
3307	case GUSMAX_CD_MUTE:
3308		if (cp->type == AUDIO_MIXER_ENUM) {
3309			cp->un.ord = ac->aux2_mute;
3310			error = 0;
3311		}
3312		break;
3313
3314	case GUSMAX_MONO_MUTE:
3315		if (cp->type == AUDIO_MIXER_ENUM) {
3316			cp->un.ord = ac->mono_mute;
3317			error = 0;
3318		}
3319		break;
3320
3321	case GUSMAX_MONITOR_MUTE:
3322		if (cp->type == AUDIO_MIXER_ENUM) {
3323			cp->un.ord = ac->mon_mute;
3324			error = 0;
3325		}
3326		break;
3327
3328	case GUSMAX_SPEAKER_MUTE:
3329		if (cp->type == AUDIO_MIXER_ENUM) {
3330			cp->un.ord = sc->sc_mixcontrol & GUSMASK_LINE_OUT ? 1 : 0;
3331			error = 0;
3332		}
3333		break;
3334
3335	case GUSMAX_REC_LVL:		/* record level */
3336		if (cp->type == AUDIO_MIXER_VALUE) {
3337			error = ad1848_get_rec_gain(ac, &vol);
3338			if (!error)
3339				gus_from_vol(cp, &vol);
3340		}
3341		break;
3342
3343	case GUSMAX_RECORD_SOURCE:
3344		if (cp->type == AUDIO_MIXER_ENUM) {
3345			cp->un.ord = ad1848_get_rec_port(ac);
3346			error = 0;
3347		}
3348		break;
3349
3350	default:
3351		error = ENXIO;
3352		break;
3353	}
3354
3355	return(error);
3356}
3357
3358STATIC int
3359gus_mixer_get_port(addr, cp)
3360	void *addr;
3361	mixer_ctrl_t *cp;
3362{
3363	struct gus_softc *sc = addr;
3364	struct ics2101_softc *ic = &sc->sc_mixer;
3365	struct ad1848_volume vol;
3366	int error = EINVAL;
3367
3368	DPRINTF(("gus_mixer_get_port: dev=%d type=%d\n", cp->dev, cp->type));
3369
3370	if (!HAS_MIXER(sc) && cp->dev > GUSICS_MASTER_MUTE)
3371		return ENXIO;
3372
3373	switch (cp->dev) {
3374
3375	case GUSICS_MIC_IN_MUTE:	/* Microphone */
3376		if (cp->type == AUDIO_MIXER_ENUM) {
3377			if (HAS_MIXER(sc))
3378				cp->un.ord = ic->sc_mute[GUSMIX_CHAN_MIC][ICSMIX_LEFT];
3379			else
3380				cp->un.ord =
3381				    sc->sc_mixcontrol & GUSMASK_MIC_IN ? 0 : 1;
3382			error = 0;
3383		}
3384		break;
3385
3386	case GUSICS_LINE_IN_MUTE:
3387		if (cp->type == AUDIO_MIXER_ENUM) {
3388			if (HAS_MIXER(sc))
3389				cp->un.ord = ic->sc_mute[GUSMIX_CHAN_LINE][ICSMIX_LEFT];
3390			else
3391				cp->un.ord =
3392				    sc->sc_mixcontrol & GUSMASK_LINE_IN ? 1 : 0;
3393			error = 0;
3394		}
3395		break;
3396
3397	case GUSICS_MASTER_MUTE:
3398		if (cp->type == AUDIO_MIXER_ENUM) {
3399			if (HAS_MIXER(sc))
3400				cp->un.ord = ic->sc_mute[GUSMIX_CHAN_MASTER][ICSMIX_LEFT];
3401			else
3402				cp->un.ord =
3403				    sc->sc_mixcontrol & GUSMASK_LINE_OUT ? 1 : 0;
3404			error = 0;
3405		}
3406		break;
3407
3408	case GUSICS_DAC_MUTE:
3409		if (cp->type == AUDIO_MIXER_ENUM) {
3410			cp->un.ord = ic->sc_mute[GUSMIX_CHAN_DAC][ICSMIX_LEFT];
3411			error = 0;
3412		}
3413		break;
3414
3415	case GUSICS_CD_MUTE:
3416		if (cp->type == AUDIO_MIXER_ENUM) {
3417			cp->un.ord = ic->sc_mute[GUSMIX_CHAN_CD][ICSMIX_LEFT];
3418			error = 0;
3419		}
3420		break;
3421
3422	case GUSICS_MASTER_LVL:
3423		if (cp->type == AUDIO_MIXER_VALUE) {
3424			vol.left = ic->sc_setting[GUSMIX_CHAN_MASTER][ICSMIX_LEFT];
3425			vol.right = ic->sc_setting[GUSMIX_CHAN_MASTER][ICSMIX_RIGHT];
3426			if (gus_from_vol(cp, &vol))
3427				error = 0;
3428		}
3429		break;
3430
3431	case GUSICS_MIC_IN_LVL:	/* Microphone */
3432		if (cp->type == AUDIO_MIXER_VALUE) {
3433			vol.left = ic->sc_setting[GUSMIX_CHAN_MIC][ICSMIX_LEFT];
3434			vol.right = ic->sc_setting[GUSMIX_CHAN_MIC][ICSMIX_RIGHT];
3435			if (gus_from_vol(cp, &vol))
3436				error = 0;
3437		}
3438		break;
3439
3440	case GUSICS_LINE_IN_LVL:	/* line in */
3441		if (cp->type == AUDIO_MIXER_VALUE) {
3442			vol.left = ic->sc_setting[GUSMIX_CHAN_LINE][ICSMIX_LEFT];
3443			vol.right = ic->sc_setting[GUSMIX_CHAN_LINE][ICSMIX_RIGHT];
3444			if (gus_from_vol(cp, &vol))
3445				error = 0;
3446		}
3447		break;
3448
3449
3450	case GUSICS_CD_LVL:
3451		if (cp->type == AUDIO_MIXER_VALUE) {
3452			vol.left = ic->sc_setting[GUSMIX_CHAN_CD][ICSMIX_LEFT];
3453			vol.right = ic->sc_setting[GUSMIX_CHAN_CD][ICSMIX_RIGHT];
3454			if (gus_from_vol(cp, &vol))
3455				error = 0;
3456		}
3457		break;
3458
3459	case GUSICS_DAC_LVL:		/* dac out */
3460		if (cp->type == AUDIO_MIXER_VALUE) {
3461			vol.left = ic->sc_setting[GUSMIX_CHAN_DAC][ICSMIX_LEFT];
3462			vol.right = ic->sc_setting[GUSMIX_CHAN_DAC][ICSMIX_RIGHT];
3463			if (gus_from_vol(cp, &vol))
3464				error = 0;
3465		}
3466		break;
3467
3468
3469	case GUSICS_RECORD_SOURCE:
3470		if (cp->type == AUDIO_MIXER_ENUM) {
3471			/* Can't set anything else useful, sigh. */
3472			 cp->un.ord = 0;
3473		}
3474		break;
3475
3476	default:
3477		return ENXIO;
3478	    /*NOTREACHED*/
3479	}
3480	return error;
3481}
3482
3483STATIC void
3484gusics_master_mute(ic, mute)
3485	struct ics2101_softc *ic;
3486	int mute;
3487{
3488	ics2101_mix_mute(ic, GUSMIX_CHAN_MASTER, ICSMIX_LEFT, mute);
3489	ics2101_mix_mute(ic, GUSMIX_CHAN_MASTER, ICSMIX_RIGHT, mute);
3490}
3491
3492STATIC void
3493gusics_mic_mute(ic, mute)
3494	struct ics2101_softc *ic;
3495	int mute;
3496{
3497	ics2101_mix_mute(ic, GUSMIX_CHAN_MIC, ICSMIX_LEFT, mute);
3498	ics2101_mix_mute(ic, GUSMIX_CHAN_MIC, ICSMIX_RIGHT, mute);
3499}
3500
3501STATIC void
3502gusics_linein_mute(ic, mute)
3503	struct ics2101_softc *ic;
3504	int mute;
3505{
3506	ics2101_mix_mute(ic, GUSMIX_CHAN_LINE, ICSMIX_LEFT, mute);
3507	ics2101_mix_mute(ic, GUSMIX_CHAN_LINE, ICSMIX_RIGHT, mute);
3508}
3509
3510STATIC void
3511gusics_cd_mute(ic, mute)
3512	struct ics2101_softc *ic;
3513	int mute;
3514{
3515	ics2101_mix_mute(ic, GUSMIX_CHAN_CD, ICSMIX_LEFT, mute);
3516	ics2101_mix_mute(ic, GUSMIX_CHAN_CD, ICSMIX_RIGHT, mute);
3517}
3518
3519STATIC void
3520gusics_dac_mute(ic, mute)
3521	struct ics2101_softc *ic;
3522	int mute;
3523{
3524	ics2101_mix_mute(ic, GUSMIX_CHAN_DAC, ICSMIX_LEFT, mute);
3525	ics2101_mix_mute(ic, GUSMIX_CHAN_DAC, ICSMIX_RIGHT, mute);
3526}
3527
3528STATIC int
3529gusmax_mixer_set_port(addr, cp)
3530	void *addr;
3531	mixer_ctrl_t *cp;
3532{
3533	struct ad1848_softc *ac = addr;
3534	struct gus_softc *sc = ac->parent;
3535	struct ad1848_volume vol;
3536	int error = EINVAL;
3537
3538	DPRINTF(("gusmax_mixer_set_port: dev=%d type=%d\n", cp->dev, cp->type));
3539
3540	switch (cp->dev) {
3541#if 0
3542	case GUSMAX_MIC_IN_LVL:	/* Microphone */
3543		if (cp->type == AUDIO_MIXER_VALUE &&
3544		    cp->un.value.num_channels == 1) {
3545			/* XXX enable/disable pre-MUX fixed gain */
3546			if (gus_to_vol(cp, &vol))
3547				error = ad1848_set_mic_gain(ac, &vol);
3548		}
3549		break;
3550#endif
3551
3552	case GUSMAX_DAC_LVL:		/* dac out */
3553		if (cp->type == AUDIO_MIXER_VALUE) {
3554			if (gus_to_vol(cp, &vol))
3555				error = ad1848_set_aux1_gain(ac, &vol);
3556		}
3557		break;
3558
3559	case GUSMAX_LINE_IN_LVL:	/* line in */
3560		if (cp->type == AUDIO_MIXER_VALUE) {
3561			if (gus_to_vol(cp, &vol))
3562				error = cs4231_set_linein_gain(ac, &vol);
3563		}
3564		break;
3565
3566	case GUSMAX_MONO_LVL:	/* mic/mono in */
3567		if (cp->type == AUDIO_MIXER_VALUE &&
3568		    cp->un.value.num_channels == 1) {
3569			if (gus_to_vol(cp, &vol))
3570				error = cs4231_set_mono_gain(ac, &vol);
3571		}
3572		break;
3573
3574	case GUSMAX_CD_LVL:	/* CD: AUX2 */
3575		if (cp->type == AUDIO_MIXER_VALUE) {
3576			if (gus_to_vol(cp, &vol))
3577				error = ad1848_set_aux2_gain(ac, &vol);
3578		}
3579		break;
3580
3581	case GUSMAX_MONITOR_LVL:
3582		if (cp->type == AUDIO_MIXER_VALUE &&
3583		    cp->un.value.num_channels == 1) {
3584			vol.left  = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
3585			error = ad1848_set_mon_gain(ac, &vol);
3586		}
3587		break;
3588
3589	case GUSMAX_OUT_LVL:	/* output volume */
3590		if (cp->type == AUDIO_MIXER_VALUE) {
3591			if (gus_to_vol(cp, &vol))
3592				error = ad1848_set_out_gain(ac, &vol);
3593		}
3594		break;
3595
3596	case GUSMAX_SPEAKER_LVL:
3597		if (cp->type == AUDIO_MIXER_VALUE &&
3598		    cp->un.value.num_channels == 1) {
3599			if (gus_to_vol(cp, &vol)) {
3600				gus_speaker_ctl(sc, vol.left > AUDIO_MIN_GAIN ?
3601						SPKR_ON : SPKR_OFF);
3602				error = 0;
3603			}
3604		}
3605		break;
3606
3607	case GUSMAX_LINE_IN_MUTE:
3608		if (cp->type == AUDIO_MIXER_ENUM) {
3609			ac->line_mute = cp->un.ord ? 1 : 0;
3610			DPRINTF(("line mute %d\n", cp->un.ord));
3611			cs4231_mute_line(ac, ac->line_mute);
3612			gus_linein_ctl(sc, ac->line_mute ? SPKR_OFF : SPKR_ON);
3613			error = 0;
3614		}
3615		break;
3616
3617	case GUSMAX_DAC_MUTE:
3618		if (cp->type == AUDIO_MIXER_ENUM) {
3619			ac->aux1_mute = cp->un.ord ? 1 : 0;
3620			DPRINTF(("dac mute %d\n", cp->un.ord));
3621			ad1848_mute_aux1(ac, ac->aux1_mute);
3622			error = 0;
3623		}
3624		break;
3625
3626	case GUSMAX_CD_MUTE:
3627		if (cp->type == AUDIO_MIXER_ENUM) {
3628			ac->aux2_mute = cp->un.ord ? 1 : 0;
3629			DPRINTF(("cd mute %d\n", cp->un.ord));
3630			ad1848_mute_aux2(ac, ac->aux2_mute);
3631			error = 0;
3632		}
3633		break;
3634
3635	case GUSMAX_MONO_MUTE:	/* Microphone */
3636		if (cp->type == AUDIO_MIXER_ENUM) {
3637			ac->mono_mute = cp->un.ord ? 1 : 0;
3638			DPRINTF(("mono mute %d\n", cp->un.ord));
3639			cs4231_mute_mono(ac, ac->mono_mute);
3640			gus_mic_ctl(sc, ac->mono_mute ? SPKR_OFF : SPKR_ON);
3641			error = 0;
3642		}
3643		break;
3644
3645	case GUSMAX_MONITOR_MUTE:
3646		if (cp->type == AUDIO_MIXER_ENUM) {
3647			ac->mon_mute = cp->un.ord ? 1 : 0;
3648			DPRINTF(("mono mute %d\n", cp->un.ord));
3649			cs4231_mute_monitor(ac, ac->mon_mute);
3650			error = 0;
3651		}
3652		break;
3653
3654	case GUSMAX_SPEAKER_MUTE:
3655		if (cp->type == AUDIO_MIXER_ENUM) {
3656			gus_speaker_ctl(sc, cp->un.ord ? SPKR_OFF : SPKR_ON);
3657			error = 0;
3658		}
3659		break;
3660
3661	case GUSMAX_REC_LVL:		/* record level */
3662		if (cp->type == AUDIO_MIXER_VALUE) {
3663			if (gus_to_vol(cp, &vol))
3664				error = ad1848_set_rec_gain(ac, &vol);
3665		}
3666		break;
3667
3668	case GUSMAX_RECORD_SOURCE:
3669		if (cp->type == AUDIO_MIXER_ENUM) {
3670			error = ad1848_set_rec_port(ac, cp->un.ord);
3671		}
3672		break;
3673
3674	default:
3675		return ENXIO;
3676	    /*NOTREACHED*/
3677    }
3678    return error;
3679}
3680
3681STATIC int
3682gus_mixer_set_port(addr, cp)
3683	void *addr;
3684	mixer_ctrl_t *cp;
3685{
3686	struct gus_softc *sc = addr;
3687	struct ics2101_softc *ic = &sc->sc_mixer;
3688	struct ad1848_volume vol;
3689	int error = EINVAL;
3690
3691	DPRINTF(("gus_mixer_set_port: dev=%d type=%d\n", cp->dev, cp->type));
3692
3693	if (!HAS_MIXER(sc) && cp->dev > GUSICS_MASTER_MUTE)
3694		return ENXIO;
3695
3696	switch (cp->dev) {
3697
3698	case GUSICS_MIC_IN_MUTE:	/* Microphone */
3699		if (cp->type == AUDIO_MIXER_ENUM) {
3700			DPRINTF(("mic mute %d\n", cp->un.ord));
3701			if (HAS_MIXER(sc)) {
3702				gusics_mic_mute(ic, cp->un.ord);
3703			}
3704			gus_mic_ctl(sc, cp->un.ord ? SPKR_OFF : SPKR_ON);
3705			error = 0;
3706		}
3707		break;
3708
3709	case GUSICS_LINE_IN_MUTE:
3710		if (cp->type == AUDIO_MIXER_ENUM) {
3711			DPRINTF(("linein mute %d\n", cp->un.ord));
3712			if (HAS_MIXER(sc)) {
3713				gusics_linein_mute(ic, cp->un.ord);
3714			}
3715			gus_linein_ctl(sc, cp->un.ord ? SPKR_OFF : SPKR_ON);
3716			error = 0;
3717		}
3718		break;
3719
3720	case GUSICS_MASTER_MUTE:
3721		if (cp->type == AUDIO_MIXER_ENUM) {
3722			DPRINTF(("master mute %d\n", cp->un.ord));
3723			if (HAS_MIXER(sc)) {
3724				gusics_master_mute(ic, cp->un.ord);
3725			}
3726			gus_speaker_ctl(sc, cp->un.ord ? SPKR_OFF : SPKR_ON);
3727			error = 0;
3728		}
3729		break;
3730
3731	case GUSICS_DAC_MUTE:
3732		if (cp->type == AUDIO_MIXER_ENUM) {
3733			gusics_dac_mute(ic, cp->un.ord);
3734			error = 0;
3735		}
3736		break;
3737
3738	case GUSICS_CD_MUTE:
3739		if (cp->type == AUDIO_MIXER_ENUM) {
3740			gusics_cd_mute(ic, cp->un.ord);
3741			error = 0;
3742		}
3743		break;
3744
3745	case GUSICS_MASTER_LVL:
3746		if (cp->type == AUDIO_MIXER_VALUE) {
3747			if (gus_to_vol(cp, &vol)) {
3748				ics2101_mix_attenuate(ic,
3749						      GUSMIX_CHAN_MASTER,
3750						      ICSMIX_LEFT,
3751						      vol.left);
3752				ics2101_mix_attenuate(ic,
3753						      GUSMIX_CHAN_MASTER,
3754						      ICSMIX_RIGHT,
3755						      vol.right);
3756				error = 0;
3757			}
3758		}
3759		break;
3760
3761	case GUSICS_MIC_IN_LVL:	/* Microphone */
3762		if (cp->type == AUDIO_MIXER_VALUE) {
3763			if (gus_to_vol(cp, &vol)) {
3764				ics2101_mix_attenuate(ic,
3765						      GUSMIX_CHAN_MIC,
3766						      ICSMIX_LEFT,
3767						      vol.left);
3768				ics2101_mix_attenuate(ic,
3769						      GUSMIX_CHAN_MIC,
3770						      ICSMIX_RIGHT,
3771						      vol.right);
3772				error = 0;
3773			}
3774		}
3775		break;
3776
3777	case GUSICS_LINE_IN_LVL:	/* line in */
3778		if (cp->type == AUDIO_MIXER_VALUE) {
3779			if (gus_to_vol(cp, &vol)) {
3780				ics2101_mix_attenuate(ic,
3781						      GUSMIX_CHAN_LINE,
3782						      ICSMIX_LEFT,
3783						      vol.left);
3784				ics2101_mix_attenuate(ic,
3785						      GUSMIX_CHAN_LINE,
3786						      ICSMIX_RIGHT,
3787						      vol.right);
3788				error = 0;
3789			}
3790		}
3791		break;
3792
3793
3794	case GUSICS_CD_LVL:
3795		if (cp->type == AUDIO_MIXER_VALUE) {
3796			if (gus_to_vol(cp, &vol)) {
3797				ics2101_mix_attenuate(ic,
3798						      GUSMIX_CHAN_CD,
3799						      ICSMIX_LEFT,
3800						      vol.left);
3801				ics2101_mix_attenuate(ic,
3802						      GUSMIX_CHAN_CD,
3803						      ICSMIX_RIGHT,
3804						      vol.right);
3805				error = 0;
3806			}
3807		}
3808		break;
3809
3810	case GUSICS_DAC_LVL:		/* dac out */
3811		if (cp->type == AUDIO_MIXER_VALUE) {
3812			if (gus_to_vol(cp, &vol)) {
3813				ics2101_mix_attenuate(ic,
3814						      GUSMIX_CHAN_DAC,
3815						      ICSMIX_LEFT,
3816						      vol.left);
3817				ics2101_mix_attenuate(ic,
3818						      GUSMIX_CHAN_DAC,
3819						      ICSMIX_RIGHT,
3820						      vol.right);
3821				error = 0;
3822			}
3823		}
3824		break;
3825
3826
3827	case GUSICS_RECORD_SOURCE:
3828		if (cp->type == AUDIO_MIXER_ENUM && cp->un.ord == 0) {
3829			/* Can't set anything else useful, sigh. */
3830			error = 0;
3831		}
3832		break;
3833
3834	default:
3835		return ENXIO;
3836	    /*NOTREACHED*/
3837	}
3838	return error;
3839}
3840
3841STATIC int
3842gus_get_props(addr)
3843	void *addr;
3844{
3845	struct gus_softc *sc = addr;
3846	return sc->sc_recdrq == sc->sc_drq ? 0 : AUDIO_PROP_FULLDUPLEX;
3847}
3848
3849STATIC int
3850gusmax_get_props(addr)
3851	void *addr;
3852{
3853	struct ad1848_softc *ac = addr;
3854	return gus_get_props(ac->parent);
3855}
3856
3857STATIC int
3858gusmax_mixer_query_devinfo(addr, dip)
3859	void *addr;
3860	mixer_devinfo_t *dip;
3861{
3862	DPRINTF(("gusmax_query_devinfo: index=%d\n", dip->index));
3863
3864	switch(dip->index) {
3865#if 0
3866    case GUSMAX_MIC_IN_LVL:	/* Microphone */
3867	dip->type = AUDIO_MIXER_VALUE;
3868	dip->mixer_class = GUSMAX_INPUT_CLASS;
3869	dip->prev = AUDIO_MIXER_LAST;
3870	dip->next = GUSMAX_MIC_IN_MUTE;
3871	strcpy(dip->label.name, AudioNmicrophone);
3872	dip->un.v.num_channels = 2;
3873	strcpy(dip->un.v.units.name, AudioNvolume);
3874	break;
3875#endif
3876
3877    case GUSMAX_MONO_LVL:	/* mono/microphone mixer */
3878	dip->type = AUDIO_MIXER_VALUE;
3879	dip->mixer_class = GUSMAX_INPUT_CLASS;
3880	dip->prev = AUDIO_MIXER_LAST;
3881	dip->next = GUSMAX_MONO_MUTE;
3882	strcpy(dip->label.name, AudioNmicrophone);
3883	dip->un.v.num_channels = 1;
3884	strcpy(dip->un.v.units.name, AudioNvolume);
3885	break;
3886
3887    case GUSMAX_DAC_LVL:		/*  dacout */
3888	dip->type = AUDIO_MIXER_VALUE;
3889	dip->mixer_class = GUSMAX_INPUT_CLASS;
3890	dip->prev = AUDIO_MIXER_LAST;
3891	dip->next = GUSMAX_DAC_MUTE;
3892	strcpy(dip->label.name, AudioNdac);
3893	dip->un.v.num_channels = 2;
3894	strcpy(dip->un.v.units.name, AudioNvolume);
3895	break;
3896
3897    case GUSMAX_LINE_IN_LVL:	/* line */
3898	dip->type = AUDIO_MIXER_VALUE;
3899	dip->mixer_class = GUSMAX_INPUT_CLASS;
3900	dip->prev = AUDIO_MIXER_LAST;
3901	dip->next = GUSMAX_LINE_IN_MUTE;
3902	strcpy(dip->label.name, AudioNline);
3903	dip->un.v.num_channels = 2;
3904	strcpy(dip->un.v.units.name, AudioNvolume);
3905	break;
3906
3907    case GUSMAX_CD_LVL:		/* cd */
3908	dip->type = AUDIO_MIXER_VALUE;
3909	dip->mixer_class = GUSMAX_INPUT_CLASS;
3910	dip->prev = AUDIO_MIXER_LAST;
3911	dip->next = GUSMAX_CD_MUTE;
3912	strcpy(dip->label.name, AudioNcd);
3913	dip->un.v.num_channels = 2;
3914	strcpy(dip->un.v.units.name, AudioNvolume);
3915	break;
3916
3917
3918    case GUSMAX_MONITOR_LVL:	/* monitor level */
3919	dip->type = AUDIO_MIXER_VALUE;
3920	dip->mixer_class = GUSMAX_MONITOR_CLASS;
3921	dip->next = GUSMAX_MONITOR_MUTE;
3922	dip->prev = AUDIO_MIXER_LAST;
3923	strcpy(dip->label.name, AudioNmonitor);
3924	dip->un.v.num_channels = 1;
3925	strcpy(dip->un.v.units.name, AudioNvolume);
3926	break;
3927
3928    case GUSMAX_OUT_LVL:		/* cs4231 output volume: not useful? */
3929	dip->type = AUDIO_MIXER_VALUE;
3930	dip->mixer_class = GUSMAX_MONITOR_CLASS;
3931	dip->prev = dip->next = AUDIO_MIXER_LAST;
3932	strcpy(dip->label.name, AudioNoutput);
3933	dip->un.v.num_channels = 2;
3934	strcpy(dip->un.v.units.name, AudioNvolume);
3935	break;
3936
3937    case GUSMAX_SPEAKER_LVL:		/* fake speaker volume */
3938	dip->type = AUDIO_MIXER_VALUE;
3939	dip->mixer_class = GUSMAX_MONITOR_CLASS;
3940	dip->prev = AUDIO_MIXER_LAST;
3941	dip->next = GUSMAX_SPEAKER_MUTE;
3942	strcpy(dip->label.name, AudioNspeaker);
3943	dip->un.v.num_channels = 2;
3944	strcpy(dip->un.v.units.name, AudioNvolume);
3945	break;
3946
3947    case GUSMAX_LINE_IN_MUTE:
3948	dip->mixer_class = GUSMAX_INPUT_CLASS;
3949	dip->type = AUDIO_MIXER_ENUM;
3950	dip->prev = GUSMAX_LINE_IN_LVL;
3951	dip->next = AUDIO_MIXER_LAST;
3952	goto mute;
3953
3954    case GUSMAX_DAC_MUTE:
3955	dip->mixer_class = GUSMAX_INPUT_CLASS;
3956	dip->type = AUDIO_MIXER_ENUM;
3957	dip->prev = GUSMAX_DAC_LVL;
3958	dip->next = AUDIO_MIXER_LAST;
3959	goto mute;
3960
3961    case GUSMAX_CD_MUTE:
3962	dip->mixer_class = GUSMAX_INPUT_CLASS;
3963	dip->type = AUDIO_MIXER_ENUM;
3964	dip->prev = GUSMAX_CD_LVL;
3965	dip->next = AUDIO_MIXER_LAST;
3966	goto mute;
3967
3968    case GUSMAX_MONO_MUTE:
3969	dip->mixer_class = GUSMAX_INPUT_CLASS;
3970	dip->type = AUDIO_MIXER_ENUM;
3971	dip->prev = GUSMAX_MONO_LVL;
3972	dip->next = AUDIO_MIXER_LAST;
3973	goto mute;
3974
3975    case GUSMAX_MONITOR_MUTE:
3976	dip->mixer_class = GUSMAX_OUTPUT_CLASS;
3977	dip->type = AUDIO_MIXER_ENUM;
3978	dip->prev = GUSMAX_MONITOR_LVL;
3979	dip->next = AUDIO_MIXER_LAST;
3980	goto mute;
3981
3982    case GUSMAX_SPEAKER_MUTE:
3983	dip->mixer_class = GUSMAX_OUTPUT_CLASS;
3984	dip->type = AUDIO_MIXER_ENUM;
3985	dip->prev = GUSMAX_SPEAKER_LVL;
3986	dip->next = AUDIO_MIXER_LAST;
3987    mute:
3988	strcpy(dip->label.name, AudioNmute);
3989	dip->un.e.num_mem = 2;
3990	strcpy(dip->un.e.member[0].label.name, AudioNoff);
3991	dip->un.e.member[0].ord = 0;
3992	strcpy(dip->un.e.member[1].label.name, AudioNon);
3993	dip->un.e.member[1].ord = 1;
3994	break;
3995
3996    case GUSMAX_REC_LVL:	/* record level */
3997	dip->type = AUDIO_MIXER_VALUE;
3998	dip->mixer_class = GUSMAX_RECORD_CLASS;
3999	dip->prev = AUDIO_MIXER_LAST;
4000	dip->next = GUSMAX_RECORD_SOURCE;
4001	strcpy(dip->label.name, AudioNrecord);
4002	dip->un.v.num_channels = 2;
4003	strcpy(dip->un.v.units.name, AudioNvolume);
4004	break;
4005
4006    case GUSMAX_RECORD_SOURCE:
4007	dip->mixer_class = GUSMAX_RECORD_CLASS;
4008	dip->type = AUDIO_MIXER_ENUM;
4009	dip->prev = GUSMAX_REC_LVL;
4010	dip->next = AUDIO_MIXER_LAST;
4011	strcpy(dip->label.name, AudioNsource);
4012	dip->un.e.num_mem = 4;
4013	strcpy(dip->un.e.member[0].label.name, AudioNoutput);
4014	dip->un.e.member[0].ord = DAC_IN_PORT;
4015	strcpy(dip->un.e.member[1].label.name, AudioNmicrophone);
4016	dip->un.e.member[1].ord = MIC_IN_PORT;
4017	strcpy(dip->un.e.member[2].label.name, AudioNdac);
4018	dip->un.e.member[2].ord = AUX1_IN_PORT;
4019	strcpy(dip->un.e.member[3].label.name, AudioNline);
4020	dip->un.e.member[3].ord = LINE_IN_PORT;
4021	break;
4022
4023    case GUSMAX_INPUT_CLASS:			/* input class descriptor */
4024	dip->type = AUDIO_MIXER_CLASS;
4025	dip->mixer_class = GUSMAX_INPUT_CLASS;
4026	dip->next = dip->prev = AUDIO_MIXER_LAST;
4027	strcpy(dip->label.name, AudioCInputs);
4028	break;
4029
4030    case GUSMAX_OUTPUT_CLASS:			/* output class descriptor */
4031	dip->type = AUDIO_MIXER_CLASS;
4032	dip->mixer_class = GUSMAX_OUTPUT_CLASS;
4033	dip->next = dip->prev = AUDIO_MIXER_LAST;
4034	strcpy(dip->label.name, AudioCOutputs);
4035	break;
4036
4037    case GUSMAX_MONITOR_CLASS:			/* monitor class descriptor */
4038	dip->type = AUDIO_MIXER_CLASS;
4039	dip->mixer_class = GUSMAX_MONITOR_CLASS;
4040	dip->next = dip->prev = AUDIO_MIXER_LAST;
4041	strcpy(dip->label.name, AudioCMonitor);
4042	break;
4043
4044    case GUSMAX_RECORD_CLASS:			/* record source class */
4045	dip->type = AUDIO_MIXER_CLASS;
4046	dip->mixer_class = GUSMAX_RECORD_CLASS;
4047	dip->next = dip->prev = AUDIO_MIXER_LAST;
4048	strcpy(dip->label.name, AudioCRecord);
4049	break;
4050
4051    default:
4052	return ENXIO;
4053	/*NOTREACHED*/
4054    }
4055    DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name));
4056	return 0;
4057}
4058
4059STATIC int
4060gus_mixer_query_devinfo(addr, dip)
4061	void *addr;
4062	mixer_devinfo_t *dip;
4063{
4064	struct gus_softc *sc = addr;
4065
4066	DPRINTF(("gusmax_query_devinfo: index=%d\n", dip->index));
4067
4068	if (!HAS_MIXER(sc) && dip->index > GUSICS_MASTER_MUTE)
4069		return ENXIO;
4070
4071	switch(dip->index) {
4072
4073	case GUSICS_MIC_IN_LVL:	/* Microphone */
4074		dip->type = AUDIO_MIXER_VALUE;
4075		dip->mixer_class = GUSICS_INPUT_CLASS;
4076		dip->prev = AUDIO_MIXER_LAST;
4077		dip->next = GUSICS_MIC_IN_MUTE;
4078		strcpy(dip->label.name, AudioNmicrophone);
4079		dip->un.v.num_channels = 2;
4080		strcpy(dip->un.v.units.name, AudioNvolume);
4081		break;
4082
4083	case GUSICS_LINE_IN_LVL:	/* line */
4084		dip->type = AUDIO_MIXER_VALUE;
4085		dip->mixer_class = GUSICS_INPUT_CLASS;
4086		dip->prev = AUDIO_MIXER_LAST;
4087		dip->next = GUSICS_LINE_IN_MUTE;
4088		strcpy(dip->label.name, AudioNline);
4089		dip->un.v.num_channels = 2;
4090		strcpy(dip->un.v.units.name, AudioNvolume);
4091		break;
4092
4093	case GUSICS_CD_LVL:		/* cd */
4094		dip->type = AUDIO_MIXER_VALUE;
4095		dip->mixer_class = GUSICS_INPUT_CLASS;
4096		dip->prev = AUDIO_MIXER_LAST;
4097		dip->next = GUSICS_CD_MUTE;
4098		strcpy(dip->label.name, AudioNcd);
4099		dip->un.v.num_channels = 2;
4100		strcpy(dip->un.v.units.name, AudioNvolume);
4101		break;
4102
4103	case GUSICS_DAC_LVL:		/*  dacout */
4104		dip->type = AUDIO_MIXER_VALUE;
4105		dip->mixer_class = GUSICS_INPUT_CLASS;
4106		dip->prev = AUDIO_MIXER_LAST;
4107		dip->next = GUSICS_DAC_MUTE;
4108		strcpy(dip->label.name, AudioNdac);
4109		dip->un.v.num_channels = 2;
4110		strcpy(dip->un.v.units.name, AudioNvolume);
4111		break;
4112
4113	case GUSICS_MASTER_LVL:		/*  master output */
4114		dip->type = AUDIO_MIXER_VALUE;
4115		dip->mixer_class = GUSICS_OUTPUT_CLASS;
4116		dip->prev = AUDIO_MIXER_LAST;
4117		dip->next = GUSICS_MASTER_MUTE;
4118		strcpy(dip->label.name, AudioNvolume);
4119		dip->un.v.num_channels = 2;
4120		strcpy(dip->un.v.units.name, AudioNvolume);
4121		break;
4122
4123
4124	case GUSICS_LINE_IN_MUTE:
4125		dip->mixer_class = GUSICS_INPUT_CLASS;
4126		dip->type = AUDIO_MIXER_ENUM;
4127		dip->prev = GUSICS_LINE_IN_LVL;
4128		dip->next = AUDIO_MIXER_LAST;
4129		goto mute;
4130
4131	case GUSICS_DAC_MUTE:
4132		dip->mixer_class = GUSICS_INPUT_CLASS;
4133		dip->type = AUDIO_MIXER_ENUM;
4134		dip->prev = GUSICS_DAC_LVL;
4135		dip->next = AUDIO_MIXER_LAST;
4136		goto mute;
4137
4138	case GUSICS_CD_MUTE:
4139		dip->mixer_class = GUSICS_INPUT_CLASS;
4140		dip->type = AUDIO_MIXER_ENUM;
4141		dip->prev = GUSICS_CD_LVL;
4142		dip->next = AUDIO_MIXER_LAST;
4143		goto mute;
4144
4145	case GUSICS_MIC_IN_MUTE:
4146		dip->mixer_class = GUSICS_INPUT_CLASS;
4147		dip->type = AUDIO_MIXER_ENUM;
4148		dip->prev = GUSICS_MIC_IN_LVL;
4149		dip->next = AUDIO_MIXER_LAST;
4150		goto mute;
4151
4152	case GUSICS_MASTER_MUTE:
4153		dip->mixer_class = GUSICS_OUTPUT_CLASS;
4154		dip->type = AUDIO_MIXER_ENUM;
4155		dip->prev = GUSICS_MASTER_LVL;
4156		dip->next = AUDIO_MIXER_LAST;
4157mute:
4158		strcpy(dip->label.name, AudioNmute);
4159		dip->un.e.num_mem = 2;
4160		strcpy(dip->un.e.member[0].label.name, AudioNoff);
4161		dip->un.e.member[0].ord = 0;
4162		strcpy(dip->un.e.member[1].label.name, AudioNon);
4163		dip->un.e.member[1].ord = 1;
4164		break;
4165
4166	case GUSICS_RECORD_SOURCE:
4167		dip->mixer_class = GUSICS_RECORD_CLASS;
4168		dip->type = AUDIO_MIXER_ENUM;
4169		dip->prev = dip->next = AUDIO_MIXER_LAST;
4170		strcpy(dip->label.name, AudioNsource);
4171		dip->un.e.num_mem = 1;
4172		strcpy(dip->un.e.member[0].label.name, AudioNoutput);
4173		dip->un.e.member[0].ord = GUSICS_MASTER_LVL;
4174		break;
4175
4176	case GUSICS_INPUT_CLASS:
4177		dip->type = AUDIO_MIXER_CLASS;
4178		dip->mixer_class = GUSICS_INPUT_CLASS;
4179		dip->next = dip->prev = AUDIO_MIXER_LAST;
4180		strcpy(dip->label.name, AudioCInputs);
4181		break;
4182
4183	case GUSICS_OUTPUT_CLASS:
4184		dip->type = AUDIO_MIXER_CLASS;
4185		dip->mixer_class = GUSICS_OUTPUT_CLASS;
4186		dip->next = dip->prev = AUDIO_MIXER_LAST;
4187		strcpy(dip->label.name, AudioCOutputs);
4188		break;
4189
4190	case GUSICS_RECORD_CLASS:
4191		dip->type = AUDIO_MIXER_CLASS;
4192		dip->mixer_class = GUSICS_RECORD_CLASS;
4193		dip->next = dip->prev = AUDIO_MIXER_LAST;
4194		strcpy(dip->label.name, AudioCRecord);
4195		break;
4196
4197	default:
4198		return ENXIO;
4199	/*NOTREACHED*/
4200	}
4201	DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name));
4202	return 0;
4203}
4204
4205STATIC int
4206gus_query_encoding(addr, fp)
4207	void *addr;
4208	struct audio_encoding *fp;
4209{
4210	switch (fp->index) {
4211	case 0:
4212		strcpy(fp->name, AudioEmulaw);
4213		fp->encoding = AUDIO_ENCODING_ULAW;
4214		fp->precision = 8;
4215		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
4216		break;
4217	case 1:
4218		strcpy(fp->name, AudioElinear);
4219		fp->encoding = AUDIO_ENCODING_SLINEAR;
4220		fp->precision = 8;
4221		fp->flags = 0;
4222		break;
4223	case 2:
4224		strcpy(fp->name, AudioElinear_le);
4225		fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
4226		fp->precision = 16;
4227		fp->flags = 0;
4228		break;
4229	case 3:
4230		strcpy(fp->name, AudioEulinear);
4231		fp->encoding = AUDIO_ENCODING_ULINEAR;
4232		fp->precision = 8;
4233		fp->flags = 0;
4234		break;
4235	case 4:
4236		strcpy(fp->name, AudioEulinear_le);
4237		fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
4238		fp->precision = 16;
4239		fp->flags = 0;
4240		break;
4241	case 5:
4242		strcpy(fp->name, AudioElinear_be);
4243		fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
4244		fp->precision = 16;
4245		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
4246		break;
4247	case 6:
4248		strcpy(fp->name, AudioEulinear_be);
4249		fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
4250		fp->precision = 16;
4251		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
4252		break;
4253	case 7:
4254		strcpy(fp->name, AudioEalaw);
4255		fp->encoding = AUDIO_ENCODING_ALAW;
4256		fp->precision = 8;
4257		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
4258		break;
4259
4260	default:
4261		return(EINVAL);
4262		/*NOTREACHED*/
4263	}
4264	return (0);
4265}
4266
4267/*
4268 * Setup the ICS mixer in "transparent" mode: reset everything to a sensible
4269 * level.  Levels as suggested by GUS SDK code.
4270 */
4271
4272STATIC void
4273gus_init_ics2101(sc)
4274	struct gus_softc *sc;
4275{
4276	int port = sc->sc_iobase;
4277	struct ics2101_softc *ic = &sc->sc_mixer;
4278	sc->sc_mixer.sc_selio = port+GUS_MIXER_SELECT;
4279	sc->sc_mixer.sc_dataio = port+GUS_MIXER_DATA;
4280	sc->sc_mixer.sc_flags = (sc->sc_revision == 5) ? ICS_FLIP : 0;
4281
4282	ics2101_mix_attenuate(ic,
4283			      GUSMIX_CHAN_MIC,
4284			      ICSMIX_LEFT,
4285			      ICSMIX_MIN_ATTN);
4286	ics2101_mix_attenuate(ic,
4287			      GUSMIX_CHAN_MIC,
4288			      ICSMIX_RIGHT,
4289			      ICSMIX_MIN_ATTN);
4290	/*
4291	 * Start with microphone muted by the mixer...
4292	 */
4293	gusics_mic_mute(ic, 1);
4294
4295	/* ... and enabled by the GUS master mix control */
4296	gus_mic_ctl(sc, SPKR_ON);
4297
4298	ics2101_mix_attenuate(ic,
4299			      GUSMIX_CHAN_LINE,
4300			      ICSMIX_LEFT,
4301			      ICSMIX_MIN_ATTN);
4302	ics2101_mix_attenuate(ic,
4303			      GUSMIX_CHAN_LINE,
4304			      ICSMIX_RIGHT,
4305			      ICSMIX_MIN_ATTN);
4306
4307	ics2101_mix_attenuate(ic,
4308			      GUSMIX_CHAN_CD,
4309			      ICSMIX_LEFT,
4310			      ICSMIX_MIN_ATTN);
4311	ics2101_mix_attenuate(ic,
4312			      GUSMIX_CHAN_CD,
4313			      ICSMIX_RIGHT,
4314			      ICSMIX_MIN_ATTN);
4315
4316	ics2101_mix_attenuate(ic,
4317			      GUSMIX_CHAN_DAC,
4318			      ICSMIX_LEFT,
4319			      ICSMIX_MIN_ATTN);
4320	ics2101_mix_attenuate(ic,
4321			      GUSMIX_CHAN_DAC,
4322			      ICSMIX_RIGHT,
4323			      ICSMIX_MIN_ATTN);
4324
4325	ics2101_mix_attenuate(ic,
4326			      ICSMIX_CHAN_4,
4327			      ICSMIX_LEFT,
4328			      ICSMIX_MAX_ATTN);
4329	ics2101_mix_attenuate(ic,
4330			      ICSMIX_CHAN_4,
4331			      ICSMIX_RIGHT,
4332			      ICSMIX_MAX_ATTN);
4333
4334	ics2101_mix_attenuate(ic,
4335			      GUSMIX_CHAN_MASTER,
4336			      ICSMIX_LEFT,
4337			      ICSMIX_MIN_ATTN);
4338	ics2101_mix_attenuate(ic,
4339			      GUSMIX_CHAN_MASTER,
4340			      ICSMIX_RIGHT,
4341			      ICSMIX_MIN_ATTN);
4342	/* unmute other stuff: */
4343	gusics_cd_mute(ic, 0);
4344	gusics_dac_mute(ic, 0);
4345	gusics_linein_mute(ic, 0);
4346	return;
4347}
4348
4349
4350#endif /* NGUS */
4351