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