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