gus.c revision 1.34
1193323Sed/*	$NetBSD: gus.c,v 1.34 1997/07/27 23:51:55 augustss Exp $	*/
2193323Sed
3193323Sed/*-
4193323Sed * Copyright (c) 1996 The NetBSD Foundation, Inc.
5193323Sed * All rights reserved.
6193323Sed *
7193323Sed * This code is derived from software contributed to The NetBSD Foundation
8193323Sed * by Ken Hornstein and John Kohl.
9193323Sed *
10193323Sed * Redistribution and use in source and binary forms, with or without
11193323Sed * modification, are permitted provided that the following conditions
12193323Sed * are met:
13193323Sed * 1. Redistributions of source code must retain the above copyright
14193323Sed *    notice, this list of conditions and the following disclaimer.
15193323Sed * 2. Redistributions in binary form must reproduce the above copyright
16193323Sed *    notice, this list of conditions and the following disclaimer in the
17193323Sed *    documentation and/or other materials provided with the distribution.
18193323Sed * 3. All advertising materials mentioning features or use of this software
19193323Sed *    must display the following acknowledgement:
20193323Sed *        This product includes software developed by the NetBSD
21193323Sed *	  Foundation, Inc. and its contributors.
22193323Sed * 4. Neither the name of The NetBSD Foundation nor the names of its
23193323Sed *    contributors may be used to endorse or promote products derived
24193323Sed *    from this software without specific prior written permission.
25193323Sed *
26193323Sed * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27193323Sed * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28193323Sed * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29193323Sed * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
30193323Sed * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31193323Sed * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32193323Sed * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33193323Sed * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34193323Sed * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35193323Sed * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36193323Sed * POSSIBILITY OF SUCH DAMAGE.
37193323Sed */
38193323Sed
39193323Sed/*
40193323Sed *
41193323Sed * TODO:
42193323Sed *	. figure out why mixer activity while sound is playing causes problems
43193323Sed *	  (phantom interrupts?)
44193323Sed *  	. figure out a better deinterleave strategy that avoids sucking up
45193323Sed *	  CPU, memory and cache bandwidth.  (Maybe a special encoding?
46193323Sed *	  Maybe use the double-speed sampling/hardware deinterleave trick
47193323Sed *	  from the GUS SDK?)  A 486/33 isn't quite fast enough to keep
48193323Sed *	  up with 44.1kHz 16-bit stereo output without some drop-outs.
49193323Sed *	. use CS4231 for 16-bit sampling, for a-law and mu-law playback.
50193323Sed *	. actually test full-duplex sampling(recording) and playback.
51193323Sed */
52193323Sed
53193323Sed/*
54193323Sed * Gravis UltraSound driver
55193323Sed *
56193323Sed * For more detailed information, see the GUS developers' kit
57193323Sed * available on the net at:
58193323Sed *
59193323Sed * ftp://freedom.nmsu.edu/pub/ultrasound/gravis/util/
60193323Sed * 	gusdkXXX.zip (developers' kit--get rev 2.22 or later)
61193323Sed *		See ultrawrd.doc inside--it's MS Word (ick), but it's the bible
62193323Sed *
63193323Sed */
64193323Sed
65193323Sed/*
66193323Sed * The GUS Max has a slightly strange set of connections between the CS4231
67193323Sed * and the GF1 and the DMA interconnects.  It's set up so that the CS4231 can
68193323Sed * be playing while the GF1 is loading patches from the system.
69193323Sed *
70193323Sed * Here's a recreation of the DMA interconnect diagram:
71193323Sed *
72193323Sed *       GF1
73193323Sed *   +---------+				 digital
74193323Sed *   |         |  record			 ASIC
75193323Sed *   |         |--------------+
76193323Sed *   |         |              |		       +--------+
77193323Sed *   |         | play (dram)  |      +----+    |	|
78193323Sed *   |         |--------------(------|-\  |    |   +-+  |
79193323Sed *   +---------+              |      |  >-|----|---|C|--|------  dma chan 1
80193323Sed *                            |  +---|-/  |    |   +-+ 	|
81193323Sed *                            |  |   +----+    |    |   |
82193323Sed *                            |	 |   +----+    |    |   |
83193323Sed *   +---------+        +-+   +--(---|-\  |    |    |   |
84193323Sed *   |         | play   |8|      |   |  >-|----|----+---|------  dma chan 2
85193323Sed *   | ---C----|--------|/|------(---|-/  |    |        |
86193323Sed *   |    ^    |record  |1|      |   +----+    |	|
87193323Sed *   |    |    |   /----|6|------+   	       +--------+
88193323Sed *   | ---+----|--/     +-+
89193323Sed *   +---------+
90193323Sed *     CS4231   	8-to-16 bit bus conversion, if needed
91193323Sed *
92193323Sed *
93193323Sed * "C" is an optional combiner.
94193323Sed *
95193323Sed */
96193323Sed
97193323Sed#include "gus.h"
98193323Sed#if NGUS > 0
99193323Sed
100193323Sed#include <sys/param.h>
101193323Sed#include <sys/systm.h>
102193323Sed#include <sys/errno.h>
103193323Sed#include <sys/ioctl.h>
104193323Sed#include <sys/syslog.h>
105193323Sed#include <sys/device.h>
106193323Sed#include <sys/proc.h>
107193323Sed#include <sys/buf.h>
108193323Sed#include <sys/fcntl.h>
109193323Sed#include <sys/malloc.h>
110193323Sed#include <sys/kernel.h>
111193323Sed
112193323Sed#include <machine/cpu.h>
113193323Sed#include <machine/intr.h>
114193323Sed#include <machine/bus.h>
115193323Sed#include <machine/pio.h>
116193323Sed#include <machine/cpufunc.h>
117193323Sed#include <sys/audioio.h>
118193323Sed#include <dev/audio_if.h>
119193323Sed#include <dev/mulaw.h>
120193323Sed
121193323Sed#include <dev/isa/isavar.h>
122193323Sed#include <dev/isa/isadmavar.h>
123193323Sed#include <i386/isa/icu.h>
124193323Sed
125193323Sed#include <dev/ic/ics2101reg.h>
126193323Sed#include <dev/ic/cs4231reg.h>
127193323Sed#include <dev/ic/ad1848reg.h>
128193323Sed#include <dev/isa/ics2101var.h>
129193323Sed#include <dev/isa/ad1848var.h>
130193323Sed#include <dev/isa/cs4231var.h>
131193323Sed#include "gusreg.h"
132193323Sed
133193323Sed#ifdef AUDIO_DEBUG
134193323Sed#define STATIC /* empty; for debugging symbols */
135193323Sed#else
136193323Sed#define STATIC static
137193323Sed#endif
138193323Sed
139193323Sed/*
140193323Sed * Software state of a single "voice" on the GUS
141193323Sed */
142193323Sed
143193323Sedstruct gus_voice {
144193323Sed
145193323Sed	/*
146193323Sed	 * Various control bits
147193323Sed	 */
148193323Sed
149193323Sed	unsigned char voccntl;	/* State of voice control register */
150193323Sed	unsigned char volcntl;	/* State of volume control register */
151193323Sed	unsigned char pan_pos;	/* Position of volume panning (4 bits) */
152193323Sed	int rate;		/* Sample rate of voice being played back */
153193323Sed
154193323Sed	/*
155193323Sed	 * Address of the voice data into the GUS's DRAM.  20 bits each
156193323Sed	 */
157193323Sed
158193323Sed	u_long start_addr;	/* Starting address of voice data loop area */
159193323Sed	u_long end_addr;	/* Ending address of voice data loop */
160193323Sed	u_long current_addr;	/* Beginning address of voice data
161193323Sed				   (start playing here) */
162193323Sed
163193323Sed	/*
164193323Sed	 * linear volume values for the GUS's volume ramp.  0-511 (9 bits).
165193323Sed	 * These values must be translated into the logarithmic values using
166193323Sed	 * gus_log_volumes[]
167193323Sed	 */
168193323Sed
169193323Sed	int start_volume;	/* Starting position of volume ramp */
170193323Sed	int current_volume;	/* Current position of volume on volume ramp */
171193323Sed	int end_volume;		/* Ending position of volume on volume ramp */
172193323Sed};
173193323Sed
174193323Sed/*
175193323Sed * Software state of GUS
176193323Sed */
177193323Sed
178193323Sedstruct gus_softc {
179193323Sed	struct device sc_dev;		/* base device */
180193323Sed	struct isadev sc_id;		/* ISA device */
181193323Sed	void *sc_ih;			/* interrupt vector */
182193323Sed	bus_space_tag_t sc_iot;		/* tag */
183193323Sed	bus_space_handle_t sc_ioh;	/* handle */
184193323Sed
185193323Sed	int sc_iobase;			/* I/O base address */
186193323Sed	int sc_irq;			/* IRQ used */
187193323Sed	int sc_drq;			/* DMA channel for play */
188193323Sed	int sc_recdrq;			/* DMA channel for recording */
189193323Sed
190193323Sed	int sc_flags;			/* Various flags about the GUS */
191193323Sed#define GUS_MIXER_INSTALLED	0x01	/* An ICS mixer is installed */
192193323Sed#define GUS_LOCKED		0x02	/* GUS is busy doing multi-phase DMA */
193193323Sed#define GUS_CODEC_INSTALLED	0x04	/* CS4231 installed/MAX */
194193323Sed#define GUS_PLAYING		0x08	/* GUS is playing a voice */
195193323Sed#define GUS_DMAOUT_ACTIVE	0x10	/* GUS is busy doing audio DMA */
196193323Sed#define GUS_DMAIN_ACTIVE	0x20	/* GUS is busy sampling  */
197193323Sed#define GUS_OPEN		0x100	/* GUS is open */
198193323Sed	int sc_dsize;			/* Size of GUS DRAM */
199193323Sed	int sc_voices;			/* Number of active voices */
200193323Sed	u_char sc_revision;		/* Board revision of GUS */
201193323Sed	u_char sc_mixcontrol;		/* Value of GUS_MIX_CONTROL register */
202193323Sed
203193323Sed	u_long sc_orate;		/* Output sampling rate */
204193323Sed	u_long sc_irate;		/* Input sampling rate */
205193323Sed
206193323Sed	int sc_encoding;		/* Current data encoding type */
207193323Sed	int sc_precision;		/* # of bits of precision */
208193323Sed	int sc_channels;		/* Number of active channels */
209193323Sed	int sc_blocksize;		/* Current blocksize */
210193323Sed	int sc_chanblocksize;		/* Current blocksize for each in-use
211193323Sed					   channel */
212193323Sed	short sc_nbufs;			/* how many on-GUS bufs per-channel */
213193323Sed	short sc_bufcnt;		/* how many need to be played */
214193323Sed	void *sc_deintr_buf;		/* deinterleave buffer for stereo */
215193323Sed
216193323Sed	int sc_ogain;			/* Output gain control */
217193323Sed	u_char sc_out_port;		/* Current out port (generic only) */
218193323Sed	u_char sc_in_port;		/* keep track of it when no codec */
219193323Sed
220193323Sed	void (*sc_dmaoutintr) __P((void*)); /* DMA completion intr handler */
221193323Sed	void *sc_outarg;		/* argument for sc_dmaoutintr() */
222193323Sed	u_char *sc_dmaoutaddr;		/* for isa_dmadone */
223193323Sed	u_long sc_gusaddr;		/* where did we just put it? */
224193323Sed	int sc_dmaoutcnt;		/* for isa_dmadone */
225193323Sed
226193323Sed	void (*sc_dmainintr) __P((void*)); /* DMA completion intr handler */
227193323Sed	void *sc_inarg;			/* argument for sc_dmaoutintr() */
228193323Sed	u_char *sc_dmainaddr;		/* for isa_dmadone */
229193323Sed	int sc_dmaincnt;		/* for isa_dmadone */
230193323Sed
231193323Sed	struct stereo_dma_intr {
232193323Sed		void (*intr)__P((void *));
233193323Sed		void *arg;
234193323Sed		u_char *buffer;
235193323Sed		u_long dmabuf;
236193323Sed		int size;
237193323Sed		int flags;
238193323Sed	} sc_stereo;
239193323Sed
240193323Sed	/*
241193323Sed	 * State information for linear audio layer
242193323Sed	 */
243193323Sed
244193323Sed	int sc_dmabuf;			/* Which ring buffer we're DMA'ing to */
245193323Sed	int sc_playbuf;			/* Which ring buffer we're playing */
246193323Sed
247193323Sed	/*
248193323Sed	 * Voice information array.  All voice-specific information is stored
249193323Sed	 * here
250193323Sed	 */
251193323Sed
252193323Sed	struct gus_voice sc_voc[32];	/* Voice data for each voice */
253193323Sed	union {
254193323Sed		struct ics2101_softc sc_mixer_u;
255193323Sed		struct ad1848_softc sc_codec_u;
256193323Sed	} u;
257193323Sed#define sc_mixer u.sc_mixer_u
258193323Sed#define sc_codec u.sc_codec_u
259193323Sed};
260193323Sed
261193323Sedstruct ics2101_volume {
262193323Sed	u_char left;
263193323Sed	u_char right;
264193323Sed};
265193323Sed
266193323Sed#define HAS_CODEC(sc) ((sc)->sc_flags & GUS_CODEC_INSTALLED)
267193323Sed#define HAS_MIXER(sc) ((sc)->sc_flags & GUS_MIXER_INSTALLED)
268193323Sed
269193323Sed/*
270193323Sed * Mixer devices for ICS2101
271193323Sed */
272193323Sed/* MIC IN mute, line in mute, line out mute are first since they can be done
273193323Sed   even if no ICS mixer. */
274193323Sed#define GUSICS_MIC_IN_MUTE		0
275193323Sed#define GUSICS_LINE_IN_MUTE		1
276193323Sed#define GUSICS_MASTER_MUTE		2
277193323Sed#define GUSICS_CD_MUTE			3
278193323Sed#define GUSICS_DAC_MUTE			4
279193323Sed#define GUSICS_MIC_IN_LVL		5
280193323Sed#define GUSICS_LINE_IN_LVL		6
281193323Sed#define GUSICS_CD_LVL			7
282193323Sed#define GUSICS_DAC_LVL			8
283193323Sed#define GUSICS_MASTER_LVL		9
284193323Sed
285193323Sed#define GUSICS_RECORD_SOURCE		10
286193323Sed
287193323Sed/* Classes */
288193323Sed#define GUSICS_INPUT_CLASS		11
289193323Sed#define GUSICS_OUTPUT_CLASS		12
290193323Sed#define GUSICS_RECORD_CLASS		13
291193323Sed
292193323Sed/*
293193323Sed * Mixer & MUX devices for CS4231
294193323Sed */
295193323Sed#define GUSMAX_MONO_LVL			0 /* mic input to MUX;
296193323Sed					     also mono mixer input */
297193323Sed#define GUSMAX_DAC_LVL			1 /* input to MUX; also mixer input */
298193323Sed#define GUSMAX_LINE_IN_LVL		2 /* input to MUX; also mixer input */
299193323Sed#define GUSMAX_CD_LVL			3 /* mixer input only */
300193323Sed#define GUSMAX_MONITOR_LVL		4 /* digital mix (?) */
301193323Sed#define GUSMAX_OUT_LVL			5 /* output level. (?) */
302193323Sed#define GUSMAX_SPEAKER_LVL		6 /* pseudo-device for mute */
303193323Sed#define GUSMAX_LINE_IN_MUTE		7 /* pre-mixer */
304193323Sed#define GUSMAX_DAC_MUTE			8 /* pre-mixer */
305193323Sed#define GUSMAX_CD_MUTE			9 /* pre-mixer */
306193323Sed#define GUSMAX_MONO_MUTE		10 /* pre-mixer--microphone/mono */
307193323Sed#define GUSMAX_MONITOR_MUTE		11 /* post-mixer level/mute */
308193323Sed#define GUSMAX_SPEAKER_MUTE		12 /* speaker mute */
309193323Sed
310193323Sed#define GUSMAX_REC_LVL			13 /* post-MUX gain */
311193323Sed
312193323Sed#define GUSMAX_RECORD_SOURCE		14
313193323Sed
314193323Sed/* Classes */
315193323Sed#define GUSMAX_INPUT_CLASS		15
316193323Sed#define GUSMAX_RECORD_CLASS		16
317193323Sed#define GUSMAX_MONITOR_CLASS		17
318193323Sed#define GUSMAX_OUTPUT_CLASS		18
319193323Sed
320193323Sed#ifdef AUDIO_DEBUG
321193323Sed#define GUSPLAYDEBUG	/*XXX*/
322193323Sed#define DPRINTF(x)	if (gusdebug) printf x
323193323Sed#define DMAPRINTF(x)	if (gusdmadebug) printf x
324193323Sedint	gusdebug = 0;
325193323Sedint	gusdmadebug = 0;
326193323Sed#else
327193323Sed#define DPRINTF(x)
328193323Sed#define DMAPRINTF(x)
329193323Sed#endif
330193323Sedint	gus_dostereo = 1;
331193323Sed
332193323Sed#define NDMARECS 2048
333193323Sed#ifdef GUSPLAYDEBUG
334193323Sedint	gusstats = 0;
335193323Sedstruct dma_record {
336193323Sed    struct timeval tv;
337193323Sed    u_long gusaddr;
338193323Sed    caddr_t bsdaddr;
339193323Sed    u_short count;
340193323Sed    u_char channel;
341193323Sed    u_char direction;
342193323Sed} dmarecords[NDMARECS];
343193323Sed
344193323Sedint dmarecord_index = 0;
345193323Sed#endif
346193323Sed
347193323Sed/*
348193323Sed * local routines
349193323Sed */
350193323Sed
351193323Sedint	gusopen __P((dev_t, int));
352193323Sedvoid	gusclose __P((void *));
353193323Sedvoid	gusmax_close __P((void *));
354193323Sedint	gusintr __P((void *));
355193323Sedint	gus_set_in_gain __P((caddr_t, u_int, u_char));
356193323Sedint	gus_get_in_gain __P((caddr_t));
357193323Sedint	gus_set_out_gain __P((caddr_t, u_int, u_char));
358193323Sedint	gus_get_out_gain __P((caddr_t));
359193323Sedint 	gus_set_params __P((void *, int, struct audio_params *, struct audio_params *));
360193323Sedint 	gusmax_set_params __P((void *, int, struct audio_params *, struct audio_params *));
361193323Sedint	gus_round_blocksize __P((void *, int));
362193323Sedint	gus_set_out_port __P((void *, int));
363193323Sedint	gus_get_out_port __P((void *));
364193323Sedint	gus_set_in_port __P((void *, int));
365193323Sedint	gus_get_in_port __P((void *));
366193323Sedint	gus_commit_settings __P((void *));
367193323Sedint	gus_dma_output __P((void *, void *, int, void (*)(void *), void *));
368193323Sedint	gus_dma_input __P((void *, void *, int, void (*)(void *), void *));
369193323Sedint	gus_halt_out_dma __P((void *));
370193323Sedint	gus_halt_in_dma __P((void *));
371193323Sedint	gus_cont_out_dma __P((void *));
372193323Sedint	gus_cont_in_dma __P((void *));
373193323Sedint	gus_speaker_ctl __P((void *, int));
374193323Sedint	gusmax_round_blocksize __P((void *, int));
375193323Sedint	gusmax_commit_settings __P((void *));
376193323Sedint	gusmax_dma_output __P((void *, void *, int, void (*)(void *), void *));
377193323Sedint	gusmax_dma_input __P((void *, void *, int, void (*)(void *), void *));
378193323Sedint	gusmax_halt_out_dma __P((void *));
379193323Sedint	gusmax_halt_in_dma __P((void *));
380193323Sedint	gusmax_cont_out_dma __P((void *));
381193323Sedint	gusmax_cont_in_dma __P((void *));
382193323Sedint	gusmax_speaker_ctl __P((void *, int));
383193323Sedint	gusmax_set_out_port __P((void *, int));
384193323Sedint	gusmax_get_out_port __P((void *));
385193323Sedint	gusmax_set_in_port __P((void *, int));
386193323Sedint	gusmax_get_in_port __P((void *));
387193323Sedint	gus_getdev __P((void *, struct audio_device *));
388193323Sed
389193323SedSTATIC void	gus_deinterleave __P((struct gus_softc *, void *, int));
390193323Sed
391193323SedSTATIC int	gus_mic_ctl __P((void *, int));
392193323SedSTATIC int	gus_linein_ctl __P((void *, int));
393193323SedSTATIC int	gus_test_iobase __P((int));
394193323SedSTATIC void	guspoke __P((int, long, u_char));
395193323SedSTATIC void	gusdmaout __P((struct gus_softc *, int, u_long, caddr_t, int));
396193323SedSTATIC void	gus_init_cs4231 __P((struct gus_softc *));
397193323SedSTATIC void	gus_init_ics2101 __P((struct gus_softc *));
398193323Sed
399193323SedSTATIC void	gus_set_chan_addrs __P((struct gus_softc *));
400193323SedSTATIC void	gusreset __P((struct gus_softc *, int));
401193323SedSTATIC void	gus_set_voices __P((struct gus_softc *, int));
402193323SedSTATIC void	gus_set_volume __P((struct gus_softc *, int, int));
403193323SedSTATIC void	gus_set_samprate __P((struct gus_softc *, int, int));
404193323SedSTATIC void	gus_set_recrate __P((struct gus_softc *, u_long));
405193323SedSTATIC void	gus_start_voice __P((struct gus_softc *, int, int));
406193323SedSTATIC void	gus_stop_voice __P((struct gus_softc *, int, int));
407193323SedSTATIC void	gus_set_endaddr __P((struct gus_softc *, int, u_long));
408193323Sed#ifdef GUSPLAYDEBUG
409193323SedSTATIC void	gus_set_curaddr __P((struct gus_softc *, int, u_long));
410193323SedSTATIC u_long	gus_get_curaddr __P((struct gus_softc *, int));
411193323Sed#endif
412193323SedSTATIC int	gus_dmaout_intr __P((struct gus_softc *));
413193323SedSTATIC void	gus_dmaout_dointr __P((struct gus_softc *));
414193323SedSTATIC void	gus_dmaout_timeout __P((void *));
415193323SedSTATIC int	gus_dmain_intr __P((struct gus_softc *));
416193323SedSTATIC int	gus_voice_intr __P((struct gus_softc *));
417193323SedSTATIC void	gus_start_playing __P((struct gus_softc *, int));
418193323SedSTATIC int	gus_continue_playing __P((struct gus_softc *, int));
419193323SedSTATIC u_char guspeek __P((int, u_long));
420193323SedSTATIC u_long convert_to_16bit __P((u_long));
421193323SedSTATIC int	gus_mixer_set_port __P((void *, mixer_ctrl_t *));
422193323SedSTATIC int	gus_mixer_get_port __P((void *, mixer_ctrl_t *));
423193323SedSTATIC int	gusmax_mixer_set_port __P((void *, mixer_ctrl_t *));
424193323SedSTATIC int	gusmax_mixer_get_port __P((void *, mixer_ctrl_t *));
425193323SedSTATIC int	gus_mixer_query_devinfo __P((void *, mixer_devinfo_t *));
426193323SedSTATIC int	gusmax_mixer_query_devinfo __P((void *, mixer_devinfo_t *));
427193323SedSTATIC int	gus_query_encoding __P((void *, struct audio_encoding *));
428193323Sed
429193323SedSTATIC void	gusics_master_mute __P((struct ics2101_softc *, int));
430193323SedSTATIC void	gusics_dac_mute __P((struct ics2101_softc *, int));
431193323SedSTATIC void	gusics_mic_mute __P((struct ics2101_softc *, int));
432193323SedSTATIC void	gusics_linein_mute __P((struct ics2101_softc *, int));
433193323SedSTATIC void	gusics_cd_mute __P((struct ics2101_softc *, int));
434193323Sed
435193323SedSTATIC __inline int gus_to_vol __P((mixer_ctrl_t *, struct ad1848_volume *));
436193323SedSTATIC __inline int gus_from_vol __P((mixer_ctrl_t *, struct ad1848_volume *));
437193323Sed
438193323Sedvoid	stereo_dmaintr __P((void *));
439193323Sed
440193323Sed/*
441193323Sed * ISA bus driver routines
442193323Sed */
443193323Sed
444193323Sedint	gusprobe __P((struct device *, void *, void *));
445193323Sedvoid	gusattach __P((struct device *, struct device *, void *));
446193323Sed
447193323Sedstruct cfattach gus_ca = {
448193323Sed	sizeof(struct gus_softc), gusprobe, gusattach,
449193323Sed};
450193323Sed
451193323Sedstruct cfdriver gus_cd = {
452193323Sed	NULL, "gus", DV_DULL
453193323Sed};
454193323Sed
455193323Sed
456193323Sed/*
457193323Sed * A mapping from IRQ/DRQ values to the values used in the GUS's internal
458193323Sed * registers.  A zero means that the referenced IRQ/DRQ is invalid
459193323Sed */
460193323Sed
461193323Sedstatic int gus_irq_map[] = {
462193323Sed	IRQUNK, IRQUNK, 1, 3, IRQUNK, 2, IRQUNK, 4, IRQUNK, 1, IRQUNK, 5, 6,
463193323Sed	IRQUNK, IRQUNK, 7
464193323Sed};
465193323Sedstatic int gus_drq_map[] = {
466193323Sed	DRQUNK, 1, DRQUNK, 2, DRQUNK, 3, 4, 5
467193323Sed};
468193323Sed
469193323Sed/*
470193323Sed * A list of valid base addresses for the GUS
471193323Sed */
472193323Sed
473193323Sedstatic int gus_base_addrs[] = {
474193323Sed	0x210, 0x220, 0x230, 0x240, 0x250, 0x260
475193323Sed};
476193323Sedstatic int gus_addrs = sizeof(gus_base_addrs) / sizeof(gus_base_addrs[0]);
477193323Sed
478193323Sed/*
479193323Sed * Maximum frequency values of the GUS based on the number of currently active
480193323Sed * voices.  Since the GUS samples a voice every 1.6 us, the maximum frequency
481193323Sed * is dependent on the number of active voices.  Yes, it is pretty weird.
482193323Sed */
483193323Sed
484193323Sedstatic int gus_max_frequency[] = {
485193323Sed		44100,		/* 14 voices */
486193323Sed		41160,		/* 15 voices */
487193323Sed		38587,		/* 16 voices */
488193323Sed		36317,		/* 17 voices */
489193323Sed		34300,		/* 18 voices */
490193323Sed		32494,		/* 19 voices */
491193323Sed		30870,		/* 20 voices */
492193323Sed		29400,		/* 21 voices */
493193323Sed		28063,		/* 22 voices */
494193323Sed		26843,		/* 23 voices */
495193323Sed		25725,		/* 24 voices */
496193323Sed		24696,		/* 25 voices */
497193323Sed		23746,		/* 26 voices */
498193323Sed		22866,		/* 27 voices */
499193323Sed		22050,		/* 28 voices */
500193323Sed		21289,		/* 29 voices */
501193323Sed		20580,		/* 30 voices */
502193323Sed		19916,		/* 31 voices */
503193323Sed		19293		/* 32 voices */
504193323Sed};
505193323Sed/*
506193323Sed * A mapping of linear volume levels to the logarithmic volume values used
507193323Sed * by the GF1 chip on the GUS.  From GUS SDK vol1.c.
508193323Sed */
509193323Sed
510193323Sedstatic unsigned short gus_log_volumes[512] = {
511193323Sed 0x0000,
512193323Sed 0x0700, 0x07ff, 0x0880, 0x08ff, 0x0940, 0x0980, 0x09c0, 0x09ff, 0x0a20,
513193323Sed 0x0a40, 0x0a60, 0x0a80, 0x0aa0, 0x0ac0, 0x0ae0, 0x0aff, 0x0b10, 0x0b20,
514193323Sed 0x0b30, 0x0b40, 0x0b50, 0x0b60, 0x0b70, 0x0b80, 0x0b90, 0x0ba0, 0x0bb0,
515193323Sed 0x0bc0, 0x0bd0, 0x0be0, 0x0bf0, 0x0bff, 0x0c08, 0x0c10, 0x0c18, 0x0c20,
516193323Sed 0x0c28, 0x0c30, 0x0c38, 0x0c40, 0x0c48, 0x0c50, 0x0c58, 0x0c60, 0x0c68,
517193323Sed 0x0c70, 0x0c78, 0x0c80, 0x0c88, 0x0c90, 0x0c98, 0x0ca0, 0x0ca8, 0x0cb0,
518193323Sed 0x0cb8, 0x0cc0, 0x0cc8, 0x0cd0, 0x0cd8, 0x0ce0, 0x0ce8, 0x0cf0, 0x0cf8,
519193323Sed 0x0cff, 0x0d04, 0x0d08, 0x0d0c, 0x0d10, 0x0d14, 0x0d18, 0x0d1c, 0x0d20,
520193323Sed 0x0d24, 0x0d28, 0x0d2c, 0x0d30, 0x0d34, 0x0d38, 0x0d3c, 0x0d40, 0x0d44,
521193323Sed 0x0d48, 0x0d4c, 0x0d50, 0x0d54, 0x0d58, 0x0d5c, 0x0d60, 0x0d64, 0x0d68,
522193323Sed 0x0d6c, 0x0d70, 0x0d74, 0x0d78, 0x0d7c, 0x0d80, 0x0d84, 0x0d88, 0x0d8c,
523193323Sed 0x0d90, 0x0d94, 0x0d98, 0x0d9c, 0x0da0, 0x0da4, 0x0da8, 0x0dac, 0x0db0,
524193323Sed 0x0db4, 0x0db8, 0x0dbc, 0x0dc0, 0x0dc4, 0x0dc8, 0x0dcc, 0x0dd0, 0x0dd4,
525193323Sed 0x0dd8, 0x0ddc, 0x0de0, 0x0de4, 0x0de8, 0x0dec, 0x0df0, 0x0df4, 0x0df8,
526193323Sed 0x0dfc, 0x0dff, 0x0e02, 0x0e04, 0x0e06, 0x0e08, 0x0e0a, 0x0e0c, 0x0e0e,
527193323Sed 0x0e10, 0x0e12, 0x0e14, 0x0e16, 0x0e18, 0x0e1a, 0x0e1c, 0x0e1e, 0x0e20,
528193323Sed 0x0e22, 0x0e24, 0x0e26, 0x0e28, 0x0e2a, 0x0e2c, 0x0e2e, 0x0e30, 0x0e32,
529193323Sed 0x0e34, 0x0e36, 0x0e38, 0x0e3a, 0x0e3c, 0x0e3e, 0x0e40, 0x0e42, 0x0e44,
530193323Sed 0x0e46, 0x0e48, 0x0e4a, 0x0e4c, 0x0e4e, 0x0e50, 0x0e52, 0x0e54, 0x0e56,
531193323Sed 0x0e58, 0x0e5a, 0x0e5c, 0x0e5e, 0x0e60, 0x0e62, 0x0e64, 0x0e66, 0x0e68,
532193323Sed 0x0e6a, 0x0e6c, 0x0e6e, 0x0e70, 0x0e72, 0x0e74, 0x0e76, 0x0e78, 0x0e7a,
533193323Sed 0x0e7c, 0x0e7e, 0x0e80, 0x0e82, 0x0e84, 0x0e86, 0x0e88, 0x0e8a, 0x0e8c,
534193323Sed 0x0e8e, 0x0e90, 0x0e92, 0x0e94, 0x0e96, 0x0e98, 0x0e9a, 0x0e9c, 0x0e9e,
535193323Sed 0x0ea0, 0x0ea2, 0x0ea4, 0x0ea6, 0x0ea8, 0x0eaa, 0x0eac, 0x0eae, 0x0eb0,
536193323Sed 0x0eb2, 0x0eb4, 0x0eb6, 0x0eb8, 0x0eba, 0x0ebc, 0x0ebe, 0x0ec0, 0x0ec2,
537193323Sed 0x0ec4, 0x0ec6, 0x0ec8, 0x0eca, 0x0ecc, 0x0ece, 0x0ed0, 0x0ed2, 0x0ed4,
538193323Sed 0x0ed6, 0x0ed8, 0x0eda, 0x0edc, 0x0ede, 0x0ee0, 0x0ee2, 0x0ee4, 0x0ee6,
539193323Sed 0x0ee8, 0x0eea, 0x0eec, 0x0eee, 0x0ef0, 0x0ef2, 0x0ef4, 0x0ef6, 0x0ef8,
540193323Sed 0x0efa, 0x0efc, 0x0efe, 0x0eff, 0x0f01, 0x0f02, 0x0f03, 0x0f04, 0x0f05,
541193323Sed 0x0f06, 0x0f07, 0x0f08, 0x0f09, 0x0f0a, 0x0f0b, 0x0f0c, 0x0f0d, 0x0f0e,
542193323Sed 0x0f0f, 0x0f10, 0x0f11, 0x0f12, 0x0f13, 0x0f14, 0x0f15, 0x0f16, 0x0f17,
543193323Sed 0x0f18, 0x0f19, 0x0f1a, 0x0f1b, 0x0f1c, 0x0f1d, 0x0f1e, 0x0f1f, 0x0f20,
544193323Sed 0x0f21, 0x0f22, 0x0f23, 0x0f24, 0x0f25, 0x0f26, 0x0f27, 0x0f28, 0x0f29,
545193323Sed 0x0f2a, 0x0f2b, 0x0f2c, 0x0f2d, 0x0f2e, 0x0f2f, 0x0f30, 0x0f31, 0x0f32,
546193323Sed 0x0f33, 0x0f34, 0x0f35, 0x0f36, 0x0f37, 0x0f38, 0x0f39, 0x0f3a, 0x0f3b,
547193323Sed 0x0f3c, 0x0f3d, 0x0f3e, 0x0f3f, 0x0f40, 0x0f41, 0x0f42, 0x0f43, 0x0f44,
548193323Sed 0x0f45, 0x0f46, 0x0f47, 0x0f48, 0x0f49, 0x0f4a, 0x0f4b, 0x0f4c, 0x0f4d,
549193323Sed 0x0f4e, 0x0f4f, 0x0f50, 0x0f51, 0x0f52, 0x0f53, 0x0f54, 0x0f55, 0x0f56,
550193323Sed 0x0f57, 0x0f58, 0x0f59, 0x0f5a, 0x0f5b, 0x0f5c, 0x0f5d, 0x0f5e, 0x0f5f,
551193323Sed 0x0f60, 0x0f61, 0x0f62, 0x0f63, 0x0f64, 0x0f65, 0x0f66, 0x0f67, 0x0f68,
552193323Sed 0x0f69, 0x0f6a, 0x0f6b, 0x0f6c, 0x0f6d, 0x0f6e, 0x0f6f, 0x0f70, 0x0f71,
553193323Sed 0x0f72, 0x0f73, 0x0f74, 0x0f75, 0x0f76, 0x0f77, 0x0f78, 0x0f79, 0x0f7a,
554193323Sed 0x0f7b, 0x0f7c, 0x0f7d, 0x0f7e, 0x0f7f, 0x0f80, 0x0f81, 0x0f82, 0x0f83,
555193323Sed 0x0f84, 0x0f85, 0x0f86, 0x0f87, 0x0f88, 0x0f89, 0x0f8a, 0x0f8b, 0x0f8c,
556193323Sed 0x0f8d, 0x0f8e, 0x0f8f, 0x0f90, 0x0f91, 0x0f92, 0x0f93, 0x0f94, 0x0f95,
557193323Sed 0x0f96, 0x0f97, 0x0f98, 0x0f99, 0x0f9a, 0x0f9b, 0x0f9c, 0x0f9d, 0x0f9e,
558193323Sed 0x0f9f, 0x0fa0, 0x0fa1, 0x0fa2, 0x0fa3, 0x0fa4, 0x0fa5, 0x0fa6, 0x0fa7,
559193323Sed 0x0fa8, 0x0fa9, 0x0faa, 0x0fab, 0x0fac, 0x0fad, 0x0fae, 0x0faf, 0x0fb0,
560193323Sed 0x0fb1, 0x0fb2, 0x0fb3, 0x0fb4, 0x0fb5, 0x0fb6, 0x0fb7, 0x0fb8, 0x0fb9,
561193323Sed 0x0fba, 0x0fbb, 0x0fbc, 0x0fbd, 0x0fbe, 0x0fbf, 0x0fc0, 0x0fc1, 0x0fc2,
562193323Sed 0x0fc3, 0x0fc4, 0x0fc5, 0x0fc6, 0x0fc7, 0x0fc8, 0x0fc9, 0x0fca, 0x0fcb,
563193323Sed 0x0fcc, 0x0fcd, 0x0fce, 0x0fcf, 0x0fd0, 0x0fd1, 0x0fd2, 0x0fd3, 0x0fd4,
564193323Sed 0x0fd5, 0x0fd6, 0x0fd7, 0x0fd8, 0x0fd9, 0x0fda, 0x0fdb, 0x0fdc, 0x0fdd,
565193323Sed 0x0fde, 0x0fdf, 0x0fe0, 0x0fe1, 0x0fe2, 0x0fe3, 0x0fe4, 0x0fe5, 0x0fe6,
566193323Sed 0x0fe7, 0x0fe8, 0x0fe9, 0x0fea, 0x0feb, 0x0fec, 0x0fed, 0x0fee, 0x0fef,
567193323Sed 0x0ff0, 0x0ff1, 0x0ff2, 0x0ff3, 0x0ff4, 0x0ff5, 0x0ff6, 0x0ff7, 0x0ff8,
568193323Sed 0x0ff9, 0x0ffa, 0x0ffb, 0x0ffc, 0x0ffd, 0x0ffe, 0x0fff};
569193323Sed
570193323Sed#define SELECT_GUS_REG(port,x) outb(port+GUS_REG_SELECT,x)
571193323Sed#define WHICH_GUS_REG(port) inb(port+GUS_REG_SELECT)
572193323Sed#define ADDR_HIGH(x) (unsigned int) ((x >> 7L) & 0x1fffL)
573193323Sed#define ADDR_LOW(x) (unsigned int) ((x & 0x7fL) << 9L)
574193323Sed
575193323Sed#define GUS_MIN_VOICES 14	/* Minimum possible number of voices */
576193323Sed#define GUS_MAX_VOICES 32	/* Maximum possible number of voices */
577193323Sed#define GUS_VOICE_LEFT 0	/* Voice used for left (and mono) playback */
578193323Sed#define GUS_VOICE_RIGHT 1	/* Voice used for right playback */
579193323Sed#define GUS_MEM_OFFSET 32	/* Offset into GUS memory to begin of buffer */
580193323Sed#define GUS_BUFFER_MULTIPLE 1024	/* Audio buffers are multiples of this */
581193323Sed#define	GUS_MEM_FOR_BUFFERS	131072	/* use this many bytes on-GUS */
582193323Sed#define	GUS_LEFT_RIGHT_OFFSET	(sc->sc_nbufs * sc->sc_chanblocksize + GUS_MEM_OFFSET)
583193323Sed
584193323Sed#define GUS_PREC_BYTES (sc->sc_precision >> 3) /* precision to bytes */
585193323Sed
586193323Sed/* splgus() must be splaudio() */
587193323Sed
588193323Sed#define splgus splaudio
589193323Sed
590193323Sed/*
591193323Sed * Interface to higher level audio driver
592193323Sed */
593193323Sed
594193323Sedstruct audio_hw_if gus_hw_if = {
595193323Sed	gusopen,
596193323Sed	gusclose,
597193323Sed	NULL,				/* drain */
598193323Sed
599193323Sed	gus_query_encoding,
600193323Sed
601193323Sed	gus_set_params,
602193323Sed
603193323Sed	gus_round_blocksize,
604193323Sed
605193323Sed	gus_set_out_port,
606193323Sed	gus_get_out_port,
607193323Sed	gus_set_in_port,
608193323Sed	gus_get_in_port,
609193323Sed
610193323Sed	gus_commit_settings,
611193323Sed
612193323Sed	NULL,
613193323Sed	NULL,
614193323Sed
615193323Sed	gus_dma_output,
616193323Sed	gus_dma_input,
617193323Sed	gus_halt_out_dma,
618193323Sed	gus_halt_in_dma,
619193323Sed	gus_cont_out_dma,
620193323Sed	gus_cont_in_dma,
621193323Sed
622193323Sed	gus_speaker_ctl,
623193323Sed
624193323Sed	gus_getdev,
625193323Sed	NULL,
626193323Sed	gus_mixer_set_port,
627193323Sed	gus_mixer_get_port,
628193323Sed	gus_mixer_query_devinfo,
629193323Sed	NULL,
630193323Sed	NULL,
631193323Sed	NULL,
632193323Sed	AUDIO_PROP_FULLDUPLEX,
633193323Sed	0,
634193323Sed};
635193323Sed
636193323Sed
637193323Sed/*
638193323Sed * Some info about the current audio device
639193323Sed */
640193323Sed
641193323Sedstruct audio_device gus_device = {
642193323Sed	"UltraSound",
643193323Sed	"",
644193323Sed	"gus",
645193323Sed};
646193323Sed
647193323Sed#define FLIP_REV	5		/* This rev has flipped mixer chans */
648193323Sed
649193323Sed
650193323Sedint
651193323Sedgusprobe(parent, match, aux)
652193323Sed	struct device *parent;
653193323Sed	void *match, *aux;
654193323Sed{
655193323Sed	register struct gus_softc *sc = match;
656193323Sed	register struct isa_attach_args *ia = aux;
657193323Sed	struct cfdata *cf = sc->sc_dev.dv_cfdata;
658193323Sed	register int iobase = ia->ia_iobase;
659193323Sed	int recdrq = cf->cf_flags;
660193323Sed
661193323Sed	sc->sc_iot = ia->ia_iot;
662193323Sed	/*
663193323Sed	 * Before we do anything else, make sure requested IRQ and DRQ are
664193323Sed	 * valid for this card.
665193323Sed	 */
666193323Sed
667193323Sed	if (gus_irq_map[ia->ia_irq] == IRQUNK) {
668193323Sed		printf("gus: invalid irq %d, card not probed\n", ia->ia_irq);
669193323Sed		return(0);
670193323Sed	}
671193323Sed
672193323Sed	if (gus_drq_map[ia->ia_drq] == DRQUNK) {
673193323Sed		printf("gus: invalid drq %d, card not probed\n", ia->ia_drq);
674193323Sed		return(0);
675193323Sed	}
676193323Sed
677193323Sed	if (recdrq != 0x00) {
678193323Sed		if (recdrq > 7 || gus_drq_map[recdrq] == DRQUNK) {
679193323Sed		   printf("gus: invalid flag given for second DMA channel (0x%x), card not probed\n", recdrq);
680193323Sed		   return(0);
681193323Sed	        }
682193323Sed	} else
683193323Sed		recdrq = ia->ia_drq;
684193323Sed
685193323Sed	if (iobase == IOBASEUNK) {
686193323Sed		int i;
687193323Sed		for(i = 0; i < gus_addrs; i++)
688193323Sed			if (gus_test_iobase(gus_base_addrs[i])) {
689193323Sed				iobase = gus_base_addrs[i];
690193323Sed				goto done;
691193323Sed			}
692193323Sed		return 0;
693193323Sed	} else if (! gus_test_iobase(iobase))
694193323Sed			return 0;
695193323Sed
696193323Seddone:
697193323Sed	sc->sc_iobase = iobase;
698193323Sed	sc->sc_irq = ia->ia_irq;
699193323Sed	sc->sc_drq = ia->ia_drq;
700193323Sed	sc->sc_recdrq = recdrq;
701193323Sed
702193323Sed	ia->ia_iobase = sc->sc_iobase;
703193323Sed	ia->ia_iosize = 16;		/* XXX */
704193323Sed	return(1);
705193323Sed}
706
707/*
708 * Test to see if a particular I/O base is valid for the GUS.  Return true
709 * if it is.
710 */
711
712STATIC int
713gus_test_iobase (int iobase)
714{
715	int i = splgus();
716	u_char s1, s2;
717
718	/*
719	 * Reset GUS to an initial state before we do anything.
720	 */
721
722	delay(500);
723
724 	SELECT_GUS_REG(iobase, GUSREG_RESET);
725 	outb(iobase+GUS_DATA_HIGH, 0x00);
726
727 	delay(500);
728
729	SELECT_GUS_REG(iobase, GUSREG_RESET);
730 	outb(iobase+GUS_DATA_HIGH, GUSMASK_MASTER_RESET);
731
732 	delay(500);
733
734	splx(i);
735
736	/*
737	 * See if we can write to the board's memory
738	 */
739
740 	s1 = guspeek(iobase, 0L);
741 	s2 = guspeek(iobase, 1L);
742
743 	guspoke(iobase, 0L, 0xaa);
744 	guspoke(iobase, 1L, 0x55);
745
746 	if ((i=(int)guspeek(iobase, 0L)) != 0xaa) {
747		return(0);
748	}
749
750	guspoke(iobase, 0L, s1);
751	guspoke(iobase, 1L, s2);
752
753	return 1;
754}
755
756/*
757 * Setup the GUS for use; called shortly after probe
758 */
759
760void
761gusattach(parent, self, aux)
762	struct device *parent, *self;
763	void *aux;
764{
765	register struct gus_softc *sc = (void *) self;
766	register struct isa_attach_args *ia = aux;
767	register int port = ia->ia_iobase;
768	int		i;
769	register unsigned char	c,d,m;
770
771	/*
772	 * Figure out our board rev, and see if we need to initialize the
773	 * mixer
774	 */
775
776 	delay(500);
777
778 	c = inb(port+GUS_BOARD_REV);
779	if (c != 0xff)
780		sc->sc_revision = c;
781	else
782		sc->sc_revision = 0;
783
784
785 	SELECT_GUS_REG(port, GUSREG_RESET);
786 	outb(port+GUS_DATA_HIGH, 0x00);
787
788	gusreset(sc, GUS_MAX_VOICES); /* initialize all voices */
789	gusreset(sc, GUS_MIN_VOICES); /* then set to just the ones we use */
790
791	/*
792	 * Setup the IRQ and DRQ lines in software, using values from
793	 * config file
794	 */
795
796	m = GUSMASK_LINE_IN|GUSMASK_LINE_OUT;		/* disable all */
797
798	c = ((unsigned char) gus_irq_map[ia->ia_irq]) | GUSMASK_BOTH_RQ;
799
800	if (sc->sc_recdrq == sc->sc_drq)
801		d = (unsigned char) (gus_drq_map[sc->sc_drq] |
802				GUSMASK_BOTH_RQ);
803	else
804		d = (unsigned char) (gus_drq_map[sc->sc_drq] |
805				gus_drq_map[sc->sc_recdrq] << 3);
806
807	/*
808	 * Program the IRQ and DMA channels on the GUS.  Note that we hardwire
809	 * the GUS to only use one IRQ channel, but we give the user the
810	 * option of using two DMA channels (the other one given by the flags
811	 * option in the config file).  Two DMA channels are needed for full-
812	 * duplex operation.
813	 *
814	 * The order of these operations is very magical.
815	 */
816
817	disable_intr();
818
819	outb(port+GUS_REG_CONTROL, GUS_REG_IRQCTL);
820	outb(port+GUS_MIX_CONTROL, m);
821	outb(port+GUS_IRQCTL_CONTROL, 0x00);
822	outb(port+0x0f, 0x00);
823
824	outb(port+GUS_MIX_CONTROL, m);
825	outb(port+GUS_DMA_CONTROL, d | 0x80); /* magic reset? */
826
827	outb(port+GUS_MIX_CONTROL, m | GUSMASK_CONTROL_SEL);
828	outb(port+GUS_IRQ_CONTROL, c);
829
830	outb(port+GUS_MIX_CONTROL, m);
831	outb(port+GUS_DMA_CONTROL, d);
832
833	outb(port+GUS_MIX_CONTROL, m | GUSMASK_CONTROL_SEL);
834	outb(port+GUS_IRQ_CONTROL, c);
835
836	outb(port+GUS_VOICE_SELECT, 0x00);
837
838	/* enable line in, line out.  leave mic disabled. */
839	outb(port+GUS_MIX_CONTROL,
840	     (m | GUSMASK_LATCHES) & ~(GUSMASK_LINE_OUT|GUSMASK_LINE_IN));
841	outb(port+GUS_VOICE_SELECT, 0x00);
842
843	enable_intr();
844
845	sc->sc_mixcontrol =
846		(m | GUSMASK_LATCHES) & ~(GUSMASK_LINE_OUT|GUSMASK_LINE_IN);
847
848	/* XXX WILL THIS ALWAYS WORK THE WAY THEY'RE OVERLAYED?! */
849	sc->sc_codec.sc_isa = sc->sc_dev.dv_parent;
850
851 	if (sc->sc_revision >= 5 && sc->sc_revision <= 9) {
852 		sc->sc_flags |= GUS_MIXER_INSTALLED;
853 		gus_init_ics2101(sc);
854	}
855	if (sc->sc_revision >= 0xa) {
856		gus_init_cs4231(sc);
857	}
858
859 	SELECT_GUS_REG(port, GUSREG_RESET);
860 	/*
861 	 * Check to see how much memory we have on this card; see if any
862 	 * "mirroring" occurs.  We're assuming at least 256K already exists
863 	 * on the card; otherwise the initial probe would have failed
864 	 */
865
866	guspoke(port, 0L, 0x00);
867	for(i = 1; i < 1024; i++) {
868		u_long loc;
869
870		/*
871		 * See if we've run into mirroring yet
872		 */
873
874		if (guspeek(port, 0L) != 0)
875			break;
876
877		loc = i << 10;
878
879		guspoke(port, loc, 0xaa);
880		if (guspeek(port, loc) != 0xaa)
881			break;
882	}
883
884	sc->sc_dsize = i;
885	sprintf(gus_device.version, "3.%d", sc->sc_revision);
886
887	printf("\n <Gravis UltraSound version 3.%d, %dKB DRAM, ",
888	       sc->sc_revision, sc->sc_dsize);
889	if (HAS_MIXER(sc))
890		printf("ICS2101 mixer, ");
891	if (HAS_CODEC(sc))
892		printf("%s codec/mixer, ", sc->sc_codec.chip_name);
893	if (sc->sc_recdrq == sc->sc_drq) {
894		printf("half-duplex");
895		gus_hw_if.props &= ~AUDIO_PROP_FULLDUPLEX;
896	} else {
897		printf("full-duplex, record drq %d", sc->sc_recdrq);
898		gus_hw_if.props |= AUDIO_PROP_FULLDUPLEX;
899	}
900
901	printf(">\n");
902
903	/*
904	 * Setup a default interrupt handler
905	 */
906
907	/* XXX we shouldn't have to use splgus == splclock, nor should
908	 * we use IPL_CLOCK.
909	 */
910	sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
911	    IPL_AUDIO, gusintr, sc /* sc->sc_gusdsp */);
912
913	/*
914	 * Set some default values
915	 */
916
917	sc->sc_irate = sc->sc_orate = 44100;
918	sc->sc_encoding = AUDIO_ENCODING_SLINEAR_LE;
919	sc->sc_precision = 16;
920	sc->sc_voc[GUS_VOICE_LEFT].voccntl |= GUSMASK_DATA_SIZE16;
921	sc->sc_voc[GUS_VOICE_RIGHT].voccntl |= GUSMASK_DATA_SIZE16;
922	sc->sc_channels = 1;
923	sc->sc_ogain = 340;
924	gus_commit_settings(sc);
925
926	/*
927	 * We always put the left channel full left & right channel
928	 * full right.
929	 * For mono playback, we set up both voices playing the same buffer.
930	 */
931	outb(sc->sc_iobase+GUS_VOICE_SELECT, (unsigned char) GUS_VOICE_LEFT);
932	SELECT_GUS_REG(sc->sc_iobase, GUSREG_PAN_POS);
933	outb(sc->sc_iobase+GUS_DATA_HIGH, GUS_PAN_FULL_LEFT);
934
935	outb(sc->sc_iobase+GUS_VOICE_SELECT, (unsigned char) GUS_VOICE_RIGHT);
936	SELECT_GUS_REG(sc->sc_iobase, GUSREG_PAN_POS);
937	outb(sc->sc_iobase+GUS_DATA_HIGH, GUS_PAN_FULL_RIGHT);
938
939	/*
940	 * Attach to the generic audio layer
941	 */
942
943	if (audio_hardware_attach(&gus_hw_if, HAS_CODEC(sc) ? (void *)&sc->sc_codec : (void *)sc) != 0)
944		printf("gus: could not attach to audio pseudo-device driver\n");
945}
946
947int
948gusopen(dev, flags)
949	dev_t dev;
950	int flags;
951{
952	int unit = AUDIOUNIT(dev);
953	struct gus_softc *sc;
954
955	DPRINTF(("gusopen() called\n"));
956
957	if (unit >= gus_cd.cd_ndevs)
958		return ENXIO;
959	sc = gus_cd.cd_devs[unit];
960	if (!sc)
961		return ENXIO;
962
963	if (sc->sc_flags & GUS_OPEN)
964		return EBUSY;
965
966	/*
967	 * Some initialization
968	 */
969
970	sc->sc_flags |= GUS_OPEN;
971	sc->sc_dmabuf = 0;
972	sc->sc_playbuf = -1;
973	sc->sc_bufcnt = 0;
974	sc->sc_voc[GUS_VOICE_LEFT].start_addr = GUS_MEM_OFFSET - 1;
975	sc->sc_voc[GUS_VOICE_LEFT].current_addr = GUS_MEM_OFFSET;
976
977	if (HAS_CODEC(sc)) {
978		ad1848_open(&sc->sc_codec, dev, flags);
979		sc->sc_codec.aux1_mute = 0;
980		ad1848_mute_aux1(&sc->sc_codec, 0); /* turn on DAC output */
981		if (flags & FREAD) {
982			sc->sc_codec.mono_mute = 0;
983			cs4231_mute_mono(&sc->sc_codec, 0);
984		}
985	} else if (flags & FREAD) {
986		/* enable/unmute the microphone */
987		if (HAS_MIXER(sc)) {
988			gusics_mic_mute(&sc->sc_mixer, 0);
989		} else
990			gus_mic_ctl(sc, SPKR_ON);
991	}
992	if (sc->sc_nbufs == 0)
993	    gus_round_blocksize(sc, GUS_BUFFER_MULTIPLE); /* default blksiz */
994	return 0;
995}
996
997STATIC void
998gus_deinterleave(sc, buf, size)
999	register struct gus_softc *sc;
1000	void *buf;
1001	int size;
1002{
1003	/* deinterleave the stereo data.  We can use sc->sc_deintr_buf
1004	   for scratch space. */
1005	register int i;
1006
1007	if (size > sc->sc_blocksize) {
1008		printf("gus: deinterleave %d > %d\n", size, sc->sc_blocksize);
1009		return;
1010	} else if (size < sc->sc_blocksize) {
1011		DPRINTF(("gus: deinterleave %d < %d\n", size, sc->sc_blocksize));
1012	}
1013
1014	/*
1015	 * size is in bytes.
1016	 */
1017	if (sc->sc_precision == 16) {
1018		register u_short *dei = sc->sc_deintr_buf;
1019		register u_short *sbuf = buf;
1020		size >>= 1;		/* bytecnt to shortcnt */
1021		/* copy 2nd of each pair of samples to the staging area, while
1022		   compacting the 1st of each pair into the original area. */
1023		for (i = 0; i < size/2-1; i++)  {
1024			dei[i] = sbuf[i*2+1];
1025			sbuf[i+1] = sbuf[i*2+2];
1026		}
1027		/*
1028		 * this has copied one less sample than half of the
1029		 * buffer.  The first sample of the 1st stream was
1030		 * already in place and didn't need copying.
1031		 * Therefore, we've moved all of the 1st stream's
1032		 * samples into place.  We have one sample from 2nd
1033		 * stream in the last slot of original area, not
1034		 * copied to the staging area (But we don't need to!).
1035		 * Copy the remainder of the original stream into place.
1036		 */
1037		bcopy(dei, &sbuf[size/2], i * sizeof(short));
1038	} else {
1039		register u_char *dei = sc->sc_deintr_buf;
1040		register u_char *sbuf = buf;
1041		for (i = 0; i < size/2-1; i++)  {
1042			dei[i] = sbuf[i*2+1];
1043			sbuf[i+1] = sbuf[i*2+2];
1044		}
1045		bcopy(dei, &sbuf[size/2], i);
1046	}
1047}
1048
1049/*
1050 * Actually output a buffer to the DSP chip
1051 */
1052
1053int
1054gusmax_dma_output(addr, buf, size, intr, arg)
1055	void * addr;
1056	void *buf;
1057	int size;
1058	void (*intr) __P((void *));
1059	void *arg;
1060{
1061	register struct ad1848_softc *ac = addr;
1062	return gus_dma_output(ac->parent, buf, size, intr, arg);
1063}
1064
1065/*
1066 * called at splgus() from interrupt handler.
1067 */
1068void
1069stereo_dmaintr(arg)
1070	void *arg;
1071{
1072    struct gus_softc *sc = arg;
1073    struct stereo_dma_intr *sa = &sc->sc_stereo;
1074
1075    DMAPRINTF(("stereo_dmaintr"));
1076
1077    /*
1078     * Put other half in its place, then call the real interrupt routine :)
1079     */
1080
1081    sc->sc_dmaoutintr = sa->intr;
1082    sc->sc_outarg = sa->arg;
1083
1084#ifdef GUSPLAYDEBUG
1085    if (gusstats) {
1086      microtime(&dmarecords[dmarecord_index].tv);
1087      dmarecords[dmarecord_index].gusaddr = sa->dmabuf;
1088      dmarecords[dmarecord_index].bsdaddr = sa->buffer;
1089      dmarecords[dmarecord_index].count = sa->size;
1090      dmarecords[dmarecord_index].channel = 1;
1091      dmarecords[dmarecord_index].direction = 1;
1092      dmarecord_index = ++dmarecord_index % NDMARECS;
1093    }
1094#endif
1095
1096    gusdmaout(sc, sa->flags, sa->dmabuf, (caddr_t) sa->buffer, sa->size);
1097
1098    sa->flags = 0;
1099    sa->dmabuf = 0;
1100    sa->buffer = 0;
1101    sa->size = 0;
1102    sa->intr = 0;
1103    sa->arg = 0;
1104}
1105
1106/*
1107 * Start up DMA output to the card.
1108 * Called at splgus/splaudio already, either from intr handler or from
1109 * generic audio code.
1110 */
1111int
1112gus_dma_output(addr, buf, size, intr, arg)
1113	void * addr;
1114	void *buf;
1115	int size;
1116	void (*intr) __P((void *));
1117	void *arg;
1118{
1119	struct gus_softc *sc = addr;
1120	u_char *buffer = buf;
1121	u_long boarddma;
1122	int flags;
1123
1124	DMAPRINTF(("gus_dma_output %d @ %p\n", size, buf));
1125
1126	if (size != sc->sc_blocksize) {
1127	    DPRINTF(("gus_dma_output reqsize %d not sc_blocksize %d\n",
1128		     size, sc->sc_blocksize));
1129	    return EINVAL;
1130	}
1131
1132	flags = GUSMASK_DMA_WRITE;
1133	if (sc->sc_precision == 16)
1134	    flags |= GUSMASK_DMA_DATA_SIZE;
1135	if (sc->sc_encoding == AUDIO_ENCODING_ULAW ||
1136	    sc->sc_encoding == AUDIO_ENCODING_ULINEAR_BE ||
1137	    sc->sc_encoding == AUDIO_ENCODING_ULINEAR_LE)
1138	    flags |= GUSMASK_DMA_INVBIT;
1139
1140	if (sc->sc_channels == 2) {
1141		if (sc->sc_precision == 16) {
1142			if (size & 3) {
1143				DPRINTF(("gus_dma_output: unpaired 16bit samples"));
1144				size &= 3;
1145			}
1146		} else if (size & 1) {
1147			DPRINTF(("gus_dma_output: unpaired samples"));
1148			size &= 1;
1149		}
1150		if (size == 0)
1151			return 0;
1152
1153		gus_deinterleave(sc, (void *)buffer, size);
1154
1155		size >>= 1;
1156
1157 		boarddma = size * sc->sc_dmabuf + GUS_MEM_OFFSET;
1158
1159		sc->sc_stereo.intr = intr;
1160		sc->sc_stereo.arg = arg;
1161		sc->sc_stereo.size = size;
1162		sc->sc_stereo.dmabuf = boarddma + GUS_LEFT_RIGHT_OFFSET;
1163		sc->sc_stereo.buffer = buffer + size;
1164		sc->sc_stereo.flags = flags;
1165		if (gus_dostereo) {
1166		  intr = stereo_dmaintr;
1167		  arg = sc;
1168		}
1169	} else
1170		boarddma = size * sc->sc_dmabuf + GUS_MEM_OFFSET;
1171
1172
1173	sc->sc_flags |= GUS_LOCKED;
1174	sc->sc_dmaoutintr = intr;
1175	sc->sc_outarg = arg;
1176
1177#ifdef GUSPLAYDEBUG
1178	if (gusstats) {
1179	  microtime(&dmarecords[dmarecord_index].tv);
1180	  dmarecords[dmarecord_index].gusaddr = boarddma;
1181	  dmarecords[dmarecord_index].bsdaddr = buffer;
1182	  dmarecords[dmarecord_index].count = size;
1183	  dmarecords[dmarecord_index].channel = 0;
1184	  dmarecords[dmarecord_index].direction = 1;
1185	  dmarecord_index = ++dmarecord_index % NDMARECS;
1186	}
1187#endif
1188
1189	gusdmaout(sc, flags, boarddma, (caddr_t) buffer, size);
1190
1191	return 0;
1192}
1193
1194void
1195gusmax_close(addr)
1196	void *addr;
1197{
1198	register struct ad1848_softc *ac = addr;
1199	register struct gus_softc *sc = ac->parent;
1200#if 0
1201	ac->aux1_mute = 1;
1202	ad1848_mute_aux1(ac, 1);	/* turn off DAC output */
1203#endif
1204	ad1848_close(ac);
1205	gusclose(sc);
1206}
1207
1208/*
1209 * Close out device stuff.  Called at splgus() from generic audio layer.
1210 */
1211void
1212gusclose(addr)
1213	void *addr;
1214{
1215	struct gus_softc *sc = addr;
1216
1217        DPRINTF(("gus_close: sc=%p\n", sc));
1218
1219
1220/*	if (sc->sc_flags & GUS_DMAOUT_ACTIVE) */ {
1221		gus_halt_out_dma(sc);
1222	}
1223/*	if (sc->sc_flags & GUS_DMAIN_ACTIVE) */ {
1224		gus_halt_in_dma(sc);
1225	}
1226	sc->sc_flags &= ~(GUS_OPEN|GUS_LOCKED|GUS_DMAOUT_ACTIVE|GUS_DMAIN_ACTIVE);
1227
1228	if (sc->sc_deintr_buf) {
1229		FREE(sc->sc_deintr_buf, M_DEVBUF);
1230		sc->sc_deintr_buf = NULL;
1231	}
1232	/* turn off speaker, etc. */
1233
1234	/* make sure the voices shut up: */
1235	gus_stop_voice(sc, GUS_VOICE_LEFT, 1);
1236	gus_stop_voice(sc, GUS_VOICE_RIGHT, 0);
1237}
1238
1239/*
1240 * Service interrupts.  Farm them off to helper routines if we are using the
1241 * GUS for simple playback/record
1242 */
1243
1244#ifdef DIAGNOSTIC
1245int gusintrcnt;
1246int gusdmaintrcnt;
1247int gusvocintrcnt;
1248#endif
1249
1250int
1251gusintr(arg)
1252	void *arg;
1253{
1254	register struct gus_softc *sc = arg;
1255	unsigned char intr;
1256	register int port = sc->sc_iobase;
1257	int retval = 0;
1258
1259	DPRINTF(("gusintr\n"));
1260#ifdef DIAGNOSTIC
1261	gusintrcnt++;
1262#endif
1263	if (HAS_CODEC(sc))
1264		retval = ad1848_intr(&sc->sc_codec);
1265	if ((intr = inb(port+GUS_IRQ_STATUS)) & GUSMASK_IRQ_DMATC) {
1266		DMAPRINTF(("gusintr dma flags=%x\n", sc->sc_flags));
1267#ifdef DIAGNOSTIC
1268		gusdmaintrcnt++;
1269#endif
1270		retval += gus_dmaout_intr(sc);
1271		if (sc->sc_flags & GUS_DMAIN_ACTIVE) {
1272		    SELECT_GUS_REG(port, GUSREG_SAMPLE_CONTROL);
1273		    intr = inb(port+GUS_DATA_HIGH);
1274		    if (intr & GUSMASK_SAMPLE_DMATC) {
1275			retval += gus_dmain_intr(sc);
1276		    }
1277		}
1278	}
1279	if (intr & (GUSMASK_IRQ_VOICE | GUSMASK_IRQ_VOLUME)) {
1280		DMAPRINTF(("gusintr voice flags=%x\n", sc->sc_flags));
1281#ifdef DIAGNOSTIC
1282		gusvocintrcnt++;
1283#endif
1284		retval += gus_voice_intr(sc);
1285	}
1286	if (retval)
1287		return 1;
1288	return retval;
1289}
1290
1291int gus_bufcnt[GUS_MEM_FOR_BUFFERS / GUS_BUFFER_MULTIPLE];
1292int gus_restart;				/* how many restarts? */
1293int gus_stops;				/* how many times did voice stop? */
1294int gus_falsestops;			/* stopped but not done? */
1295int gus_continues;
1296
1297struct playcont {
1298	struct timeval tv;
1299	u_int playbuf;
1300	u_int dmabuf;
1301	u_char bufcnt;
1302	u_char vaction;
1303	u_char voccntl;
1304	u_char volcntl;
1305	u_long curaddr;
1306	u_long endaddr;
1307} playstats[NDMARECS];
1308
1309int playcntr;
1310
1311STATIC void
1312gus_dmaout_timeout(arg)
1313     void *arg;
1314{
1315    register struct gus_softc *sc = arg;
1316    register int port = sc->sc_iobase;
1317    int s;
1318
1319    printf("%s: dmaout timeout\n", sc->sc_dev.dv_xname);
1320    /*
1321     * Stop any DMA.
1322     */
1323
1324    s = splgus();
1325    SELECT_GUS_REG(port, GUSREG_DMA_CONTROL);
1326    outb(sc->sc_iobase+GUS_DATA_HIGH, 0);
1327
1328#if 0
1329    /* XXX we will dmadone below? */
1330    isa_dmaabort(sc->sc_dev.dv_parent, sc->sc_drq);
1331#endif
1332
1333    gus_dmaout_dointr(sc);
1334    splx(s);
1335}
1336
1337
1338/*
1339 * Service DMA interrupts.  This routine will only get called if we're doing
1340 * a DMA transfer for playback/record requests from the audio layer.
1341 */
1342
1343STATIC int
1344gus_dmaout_intr(sc)
1345	struct gus_softc *sc;
1346{
1347	register int port = sc->sc_iobase;
1348
1349	/*
1350	 * If we got a DMA transfer complete from the GUS DRAM, then deal
1351	 * with it.
1352	 */
1353
1354	SELECT_GUS_REG(port, GUSREG_DMA_CONTROL);
1355 	if (inb(port+GUS_DATA_HIGH) & GUSMASK_DMA_IRQPEND) {
1356	    untimeout(gus_dmaout_timeout, sc);
1357	    gus_dmaout_dointr(sc);
1358	    return 1;
1359	}
1360	return 0;
1361}
1362
1363STATIC void
1364gus_dmaout_dointr(sc)
1365	struct gus_softc *sc;
1366{
1367	register int port = sc->sc_iobase;
1368
1369	/* sc->sc_dmaoutcnt - 1 because DMA controller counts from zero?. */
1370	isa_dmadone(sc->sc_dev.dv_parent, sc->sc_drq);
1371	sc->sc_flags &= ~GUS_DMAOUT_ACTIVE;  /* pending DMA is done */
1372	DMAPRINTF(("gus_dmaout_dointr %d @ %p\n", sc->sc_dmaoutcnt,
1373		   sc->sc_dmaoutaddr));
1374
1375	/*
1376	 * to prevent clicking, we need to copy last sample
1377	 * from last buffer to scratch area just before beginning of
1378	 * buffer.  However, if we're doing formats that are converted by
1379	 * the card during the DMA process, we need to pick up the converted
1380	 * byte rather than the one we have in memory.
1381	 */
1382	if (sc->sc_dmabuf == sc->sc_nbufs - 1) {
1383	  register int i;
1384	  switch (sc->sc_encoding) {
1385	  case AUDIO_ENCODING_SLINEAR_LE:
1386	  case AUDIO_ENCODING_SLINEAR_BE:
1387	    if (sc->sc_precision == 8)
1388	      goto byte;
1389	    /* we have the native format */
1390	    for (i = 1; i <= 2; i++)
1391	      guspoke(port, sc->sc_gusaddr -
1392		      (sc->sc_nbufs - 1) * sc->sc_chanblocksize - i,
1393		      sc->sc_dmaoutaddr[sc->sc_dmaoutcnt-i]);
1394	    break;
1395	  case AUDIO_ENCODING_ULINEAR_LE:
1396	  case AUDIO_ENCODING_ULINEAR_BE:
1397	    guspoke(port, sc->sc_gusaddr -
1398		    (sc->sc_nbufs - 1) * sc->sc_chanblocksize - 2,
1399		    guspeek(port,
1400			    sc->sc_gusaddr + sc->sc_chanblocksize - 2));
1401	  case AUDIO_ENCODING_ULAW:
1402	  byte:
1403	    /* we need to fetch the translated byte, then stuff it. */
1404	    guspoke(port, sc->sc_gusaddr -
1405		    (sc->sc_nbufs - 1) * sc->sc_chanblocksize - 1,
1406		    guspeek(port,
1407			    sc->sc_gusaddr + sc->sc_chanblocksize - 1));
1408	    break;
1409	  }
1410	}
1411	/*
1412	 * If this is the first half of stereo, "ignore" this one
1413	 * and copy out the second half.
1414	 */
1415	if (sc->sc_dmaoutintr == stereo_dmaintr) {
1416	    (*sc->sc_dmaoutintr)(sc->sc_outarg);
1417	    return;
1418	}
1419	/*
1420	 * If the voice is stopped, then start it.  Reset the loop
1421	 * and roll bits.  Call the audio layer routine, since if
1422	 * we're starting a stopped voice, that means that the next
1423	 * buffer can be filled
1424	 */
1425
1426	sc->sc_flags &= ~GUS_LOCKED;
1427	if (sc->sc_voc[GUS_VOICE_LEFT].voccntl &
1428	    GUSMASK_VOICE_STOPPED) {
1429	    if (sc->sc_flags & GUS_PLAYING) {
1430		printf("%s: playing yet stopped?\n", sc->sc_dev.dv_xname);
1431	    }
1432	    sc->sc_bufcnt++; /* another yet to be played */
1433	    gus_start_playing(sc, sc->sc_dmabuf);
1434	    gus_restart++;
1435	} else {
1436	    /*
1437	     * set the sound action based on which buffer we
1438	     * just transferred.  If we just transferred buffer 0
1439	     * we want the sound to loop when it gets to the nth
1440	     * buffer; if we just transferred
1441	     * any other buffer, we want the sound to roll over
1442	     * at least one more time.  The voice interrupt
1443	     * handlers will take care of accounting &
1444	     * setting control bits if it's not caught up to us
1445	     * yet.
1446	     */
1447	    if (++sc->sc_bufcnt == 2) {
1448		/*
1449		 * XXX
1450		 * If we're too slow in reaction here,
1451		 * the voice could be just approaching the
1452		 * end of its run.  It should be set to stop,
1453		 * so these adjustments might not DTRT.
1454		 */
1455		if (sc->sc_dmabuf == 0 &&
1456		    sc->sc_playbuf == sc->sc_nbufs - 1) {
1457		    /* player is just at the last buf, we're at the
1458		       first.  Turn on looping, turn off rolling. */
1459		    sc->sc_voc[GUS_VOICE_LEFT].voccntl |= GUSMASK_LOOP_ENABLE;
1460		    sc->sc_voc[GUS_VOICE_LEFT].volcntl &= ~GUSMASK_VOICE_ROLL;
1461		    playstats[playcntr].vaction = 3;
1462		} else {
1463		    /* player is at previous buf:
1464		       turn on rolling, turn off looping */
1465		    sc->sc_voc[GUS_VOICE_LEFT].voccntl &= ~GUSMASK_LOOP_ENABLE;
1466		    sc->sc_voc[GUS_VOICE_LEFT].volcntl |= GUSMASK_VOICE_ROLL;
1467		    playstats[playcntr].vaction = 4;
1468		}
1469#ifdef GUSPLAYDEBUG
1470		if (gusstats) {
1471		  microtime(&playstats[playcntr].tv);
1472		  playstats[playcntr].endaddr = sc->sc_voc[GUS_VOICE_LEFT].end_addr;
1473		  playstats[playcntr].voccntl = sc->sc_voc[GUS_VOICE_LEFT].voccntl;
1474		  playstats[playcntr].volcntl = sc->sc_voc[GUS_VOICE_LEFT].volcntl;
1475		  playstats[playcntr].playbuf = sc->sc_playbuf;
1476		  playstats[playcntr].dmabuf = sc->sc_dmabuf;
1477		  playstats[playcntr].bufcnt = sc->sc_bufcnt;
1478		  playstats[playcntr].curaddr = gus_get_curaddr(sc, GUS_VOICE_LEFT);
1479		  playcntr = ++playcntr % NDMARECS;
1480		}
1481#endif
1482		outb(port+GUS_VOICE_SELECT, GUS_VOICE_LEFT);
1483		SELECT_GUS_REG(port, GUSREG_VOICE_CNTL);
1484		outb(port+GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_LEFT].voccntl);
1485		SELECT_GUS_REG(port, GUSREG_VOLUME_CONTROL);
1486		outb(port+GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_LEFT].volcntl);
1487	    }
1488	}
1489	gus_bufcnt[sc->sc_bufcnt-1]++;
1490	/*
1491	 * flip to the next DMA buffer
1492	 */
1493
1494	sc->sc_dmabuf = ++sc->sc_dmabuf % sc->sc_nbufs;
1495	/*
1496	 * See comments below about DMA admission control strategy.
1497	 * We can call the upper level here if we have an
1498	 * idle buffer (not currently playing) to DMA into.
1499	 */
1500	if (sc->sc_dmaoutintr && sc->sc_bufcnt < sc->sc_nbufs) {
1501	    /* clean out to prevent double calls */
1502	    void (*pfunc) __P((void *)) = sc->sc_dmaoutintr;
1503	    void *arg = sc->sc_outarg;
1504
1505	    sc->sc_outarg = 0;
1506	    sc->sc_dmaoutintr = 0;
1507	    (*pfunc)(arg);
1508	}
1509}
1510
1511/*
1512 * Service voice interrupts
1513 */
1514
1515STATIC int
1516gus_voice_intr(sc)
1517	struct gus_softc *sc;
1518{
1519	register int port = sc->sc_iobase;
1520	int ignore = 0, voice, rval = 0;
1521	unsigned char intr, status;
1522
1523	/*
1524	 * The point of this may not be obvious at first.  A voice can
1525	 * interrupt more than once; according to the GUS SDK we are supposed
1526	 * to ignore multiple interrupts for the same voice.
1527	 */
1528
1529	while(1) {
1530		SELECT_GUS_REG(port, GUSREG_IRQ_STATUS);
1531		intr = inb(port+GUS_DATA_HIGH);
1532
1533		if ((intr & (GUSMASK_WIRQ_VOLUME | GUSMASK_WIRQ_VOICE))
1534			== (GUSMASK_WIRQ_VOLUME | GUSMASK_WIRQ_VOICE))
1535			/*
1536			 * No more interrupts, time to return
1537			 */
1538		 	return rval;
1539
1540		if ((intr & GUSMASK_WIRQ_VOICE) == 0) {
1541
1542		    /*
1543		     * We've got a voice interrupt.  Ignore previous
1544		     * interrupts by the same voice.
1545		     */
1546
1547		    rval = 1;
1548		    voice = intr & GUSMASK_WIRQ_VOICEMASK;
1549
1550		    if ((1 << voice) & ignore)
1551			break;
1552
1553		    ignore |= 1 << voice;
1554
1555		    /*
1556		     * If the voice is stopped, then force it to stop
1557		     * (this stops it from continuously generating IRQs)
1558		     */
1559
1560		    SELECT_GUS_REG(port, GUSREG_VOICE_CNTL+0x80);
1561		    status = inb(port+GUS_DATA_HIGH);
1562		    if (status & GUSMASK_VOICE_STOPPED) {
1563			if (voice != GUS_VOICE_LEFT) {
1564			    DMAPRINTF(("%s: spurious voice %d stop?\n",
1565				       sc->sc_dev.dv_xname, voice));
1566			    gus_stop_voice(sc, voice, 0);
1567			    continue;
1568			}
1569			gus_stop_voice(sc, voice, 1);
1570			/* also kill right voice */
1571			gus_stop_voice(sc, GUS_VOICE_RIGHT, 0);
1572			sc->sc_bufcnt--; /* it finished a buffer */
1573			if (sc->sc_bufcnt > 0) {
1574			    /*
1575			     * probably a race to get here: the voice
1576			     * stopped while the DMA code was just trying to
1577			     * get the next buffer in place.
1578			     * Start the voice again.
1579			     */
1580			    printf("%s: stopped voice not drained? (%x)\n",
1581				   sc->sc_dev.dv_xname, sc->sc_bufcnt);
1582			    gus_falsestops++;
1583
1584			    sc->sc_playbuf = ++sc->sc_playbuf % sc->sc_nbufs;
1585			    gus_start_playing(sc, sc->sc_playbuf);
1586			} else if (sc->sc_bufcnt < 0) {
1587#ifdef DDB
1588			    printf("%s: negative bufcnt in stopped voice\n",
1589				   sc->sc_dev.dv_xname);
1590			    Debugger();
1591#else
1592			    panic("%s: negative bufcnt in stopped voice",
1593				  sc->sc_dev.dv_xname);
1594#endif
1595			} else {
1596			    sc->sc_playbuf = -1; /* none are active */
1597			    gus_stops++;
1598			}
1599			/* fall through to callback and admit another
1600			   buffer.... */
1601		    } else if (sc->sc_bufcnt != 0) {
1602			/*
1603			 * This should always be taken if the voice
1604			 * is not stopped.
1605			 */
1606			gus_continues++;
1607			if (gus_continue_playing(sc, voice)) {
1608				/*
1609				 * we shouldn't have continued--active DMA
1610				 * is in the way in the ring, for
1611				 * some as-yet undebugged reason.
1612				 */
1613				gus_stop_voice(sc, GUS_VOICE_LEFT, 1);
1614				/* also kill right voice */
1615				gus_stop_voice(sc, GUS_VOICE_RIGHT, 0);
1616				sc->sc_playbuf = -1;
1617				gus_stops++;
1618			}
1619		    }
1620		    /*
1621		     * call the upper level to send on down another
1622		     * block. We do admission rate control as follows:
1623		     *
1624		     * When starting up output (in the first N
1625		     * blocks), call the upper layer after the DMA is
1626		     * complete (see above in gus_dmaout_intr()).
1627		     *
1628		     * When output is already in progress and we have
1629		     * no more GUS buffers to use for DMA, the DMA
1630		     * output routines do not call the upper layer.
1631		     * Instead, we call the DMA completion routine
1632		     * here, after the voice interrupts indicating
1633		     * that it's finished with a buffer.
1634		     *
1635		     * However, don't call anything here if the DMA
1636		     * output flag is set, (which shouldn't happen)
1637		     * because we'll squish somebody else's DMA if
1638		     * that's the case.  When DMA is done, it will
1639		     * call back if there is a spare buffer.
1640		     */
1641		    if (sc->sc_dmaoutintr && !(sc->sc_flags & GUS_LOCKED)) {
1642			if (sc->sc_dmaoutintr == stereo_dmaintr)
1643			    printf("gusdmaout botch?\n");
1644			else {
1645			    /* clean out to avoid double calls */
1646			    void (*pfunc) __P((void *)) = sc->sc_dmaoutintr;
1647			    void *arg = sc->sc_outarg;
1648
1649			    sc->sc_outarg = 0;
1650			    sc->sc_dmaoutintr = 0;
1651			    (*pfunc)(arg);
1652			}
1653		    }
1654		}
1655
1656		/*
1657		 * Ignore other interrupts for now
1658		 */
1659	}
1660	return 0;
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 int
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("%s: continue into active dmabuf?\n", sc->sc_dev.dv_xname);
1770	return 1;
1771    }
1772
1773    /*
1774     * Select the end of the buffer based on the currently active
1775     * buffer, [plus extra contiguous buffers (if ready)].
1776     */
1777
1778    /*
1779     * set endpoint at end of buffer we just started playing.
1780     *
1781     * The total gets -1 because end addrs are one less than you might
1782     * think (the end_addr is the address of the last sample to play)
1783     */
1784    gus_set_endaddr(sc, voice, GUS_MEM_OFFSET +
1785		    sc->sc_chanblocksize * (sc->sc_playbuf + 1) - 1);
1786
1787    if (sc->sc_bufcnt < 2) {
1788	/*
1789	 * Clear out the loop and roll flags, and rotate the currently
1790	 * playing buffer.  That way, if we don't manage to get more
1791	 * data before this buffer finishes, we'll just stop.
1792	 */
1793	sc->sc_voc[voice].voccntl &= ~GUSMASK_LOOP_ENABLE;
1794	sc->sc_voc[voice].volcntl &= ~GUSMASK_VOICE_ROLL;
1795	playstats[playcntr].vaction = 0;
1796    } else {
1797	/*
1798	 * We have some buffers to play.  set LOOP if we're on the
1799	 * last buffer in the ring, otherwise set ROLL.
1800	 */
1801	if (sc->sc_playbuf == sc->sc_nbufs - 1) {
1802	    sc->sc_voc[voice].voccntl |= GUSMASK_LOOP_ENABLE;
1803	    sc->sc_voc[voice].volcntl &= ~GUSMASK_VOICE_ROLL;
1804	    playstats[playcntr].vaction = 1;
1805	} else {
1806	    sc->sc_voc[voice].voccntl &= ~GUSMASK_LOOP_ENABLE;
1807	    sc->sc_voc[voice].volcntl |= GUSMASK_VOICE_ROLL;
1808	    playstats[playcntr].vaction = 2;
1809	}
1810    }
1811#ifdef GUSPLAYDEBUG
1812    if (gusstats) {
1813      microtime(&playstats[playcntr].tv);
1814      playstats[playcntr].curaddr = gus_get_curaddr(sc, voice);
1815
1816      playstats[playcntr].voccntl = sc->sc_voc[voice].voccntl;
1817      playstats[playcntr].volcntl = sc->sc_voc[voice].volcntl;
1818      playstats[playcntr].endaddr = sc->sc_voc[voice].end_addr;
1819      playstats[playcntr].playbuf = sc->sc_playbuf;
1820      playstats[playcntr].dmabuf = sc->sc_dmabuf;
1821      playstats[playcntr].bufcnt = sc->sc_bufcnt;
1822      playcntr = ++playcntr % NDMARECS;
1823    }
1824#endif
1825
1826    /*
1827     * (re-)set voice parameters.  This will reenable interrupts from this
1828     * voice.
1829     */
1830
1831    SELECT_GUS_REG(port, GUSREG_VOICE_CNTL);
1832    outb(port+GUS_DATA_HIGH, sc->sc_voc[voice].voccntl);
1833    SELECT_GUS_REG(port, GUSREG_VOLUME_CONTROL);
1834    outb(port+GUS_DATA_HIGH, sc->sc_voc[voice].volcntl);
1835    return 0;
1836}
1837
1838/*
1839 * Send/receive data into GUS's DRAM using DMA.  Called at splgus()
1840 */
1841
1842STATIC void
1843gusdmaout(sc, flags, gusaddr, buffaddr, length)
1844	struct gus_softc *sc;
1845	int flags, length;
1846	u_long gusaddr;
1847	caddr_t buffaddr;
1848{
1849	register unsigned char c = (unsigned char) flags;
1850	register int port = sc->sc_iobase;
1851
1852	DMAPRINTF(("gusdmaout flags=%x scflags=%x\n", flags, sc->sc_flags));
1853
1854	sc->sc_gusaddr = gusaddr;
1855
1856	/*
1857	 * If we're using a 16 bit DMA channel, we have to jump through some
1858	 * extra hoops; this includes translating the DRAM address a bit
1859	 */
1860
1861	if (sc->sc_drq >= 4) {
1862		c |= GUSMASK_DMA_WIDTH;
1863		gusaddr = convert_to_16bit(gusaddr);
1864	}
1865
1866	/*
1867	 * Add flag bits that we always set - fast DMA, enable IRQ
1868	 */
1869
1870	c |= GUSMASK_DMA_ENABLE | GUSMASK_DMA_R0 | GUSMASK_DMA_IRQ;
1871
1872	/*
1873	 * Make sure the GUS _isn't_ setup for DMA
1874	 */
1875
1876 	SELECT_GUS_REG(port, GUSREG_DMA_CONTROL);
1877	outb(port+GUS_DATA_HIGH, 0);
1878
1879	/*
1880	 * Tell the PC DMA controller to start doing DMA
1881	 */
1882
1883	sc->sc_dmaoutaddr = (u_char *) buffaddr;
1884	sc->sc_dmaoutcnt = length;
1885	isa_dmastart(sc->sc_dev.dv_parent, sc->sc_drq, buffaddr, length,
1886	    NULL, DMAMODE_WRITE, BUS_DMA_NOWAIT);
1887
1888	/*
1889	 * Set up DMA address - use the upper 16 bits ONLY
1890	 */
1891
1892	sc->sc_flags |= GUS_DMAOUT_ACTIVE;
1893
1894 	SELECT_GUS_REG(port, GUSREG_DMA_START);
1895 	outw(port+GUS_DATA_LOW, (int) (gusaddr >> 4));
1896
1897 	/*
1898 	 * Tell the GUS to start doing DMA
1899 	 */
1900
1901 	SELECT_GUS_REG(port, GUSREG_DMA_CONTROL);
1902	outb(port+GUS_DATA_HIGH, c);
1903
1904	/*
1905	 * XXX If we don't finish in one second, give up...
1906	 */
1907	untimeout(gus_dmaout_timeout, sc); /* flush old one, if there is one */
1908	timeout(gus_dmaout_timeout, sc, hz);
1909}
1910
1911/*
1912 * Start a voice playing on the GUS.  Called from interrupt handler at
1913 * splgus().
1914 */
1915
1916STATIC void
1917gus_start_voice(sc, voice, intrs)
1918	struct gus_softc *sc;
1919	int voice;
1920	int intrs;
1921{
1922	register int port = sc->sc_iobase;
1923	u_long start;
1924	u_long current;
1925	u_long end;
1926
1927	/*
1928	 * Pick all the values for the voice out of the gus_voice struct
1929	 * and use those to program the voice
1930	 */
1931
1932 	start = sc->sc_voc[voice].start_addr;
1933 	current = sc->sc_voc[voice].current_addr;
1934 	end = sc->sc_voc[voice].end_addr;
1935
1936 	/*
1937	 * If we're using 16 bit data, mangle the addresses a bit
1938	 */
1939
1940	if (sc->sc_voc[voice].voccntl & GUSMASK_DATA_SIZE16) {
1941	        /* -1 on start so that we get onto sample boundary--other
1942		   code always sets it for 1-byte rollover protection */
1943		start = convert_to_16bit(start-1);
1944		current = convert_to_16bit(current);
1945		end = convert_to_16bit(end);
1946	}
1947
1948	/*
1949	 * Select the voice we want to use, and program the data addresses
1950	 */
1951
1952	outb(port+GUS_VOICE_SELECT, (unsigned char) voice);
1953
1954	SELECT_GUS_REG(port, GUSREG_START_ADDR_HIGH);
1955	outw(port+GUS_DATA_LOW, ADDR_HIGH(start));
1956	SELECT_GUS_REG(port, GUSREG_START_ADDR_LOW);
1957	outw(port+GUS_DATA_LOW, ADDR_LOW(start));
1958
1959	SELECT_GUS_REG(port, GUSREG_CUR_ADDR_HIGH);
1960	outw(port+GUS_DATA_LOW, ADDR_HIGH(current));
1961	SELECT_GUS_REG(port, GUSREG_CUR_ADDR_LOW);
1962	outw(port+GUS_DATA_LOW, ADDR_LOW(current));
1963
1964	SELECT_GUS_REG(port, GUSREG_END_ADDR_HIGH);
1965	outw(port+GUS_DATA_LOW, ADDR_HIGH(end));
1966	SELECT_GUS_REG(port, GUSREG_END_ADDR_LOW);
1967	outw(port+GUS_DATA_LOW, ADDR_LOW(end));
1968
1969	/*
1970	 * (maybe) enable interrupts, disable voice stopping
1971	 */
1972
1973	if (intrs) {
1974		sc->sc_flags |= GUS_PLAYING; /* playing is about to start */
1975		sc->sc_voc[voice].voccntl |= GUSMASK_VOICE_IRQ;
1976		DMAPRINTF(("gus voice playing=%x\n", sc->sc_flags));
1977	} else
1978		sc->sc_voc[voice].voccntl &= ~GUSMASK_VOICE_IRQ;
1979	sc->sc_voc[voice].voccntl &= ~(GUSMASK_VOICE_STOPPED |
1980		GUSMASK_STOP_VOICE);
1981
1982	/*
1983	 * Tell the GUS about it.  Note that we're doing volume ramping here
1984	 * from 0 up to the set volume to help reduce clicks.
1985	 */
1986
1987	SELECT_GUS_REG(port, GUSREG_START_VOLUME);
1988	outb(port+GUS_DATA_HIGH, 0x00);
1989	SELECT_GUS_REG(port, GUSREG_END_VOLUME);
1990	outb(port+GUS_DATA_HIGH, sc->sc_voc[voice].current_volume >> 4);
1991	SELECT_GUS_REG(port, GUSREG_CUR_VOLUME);
1992	outw(port+GUS_DATA_LOW, 0x00);
1993	SELECT_GUS_REG(port, GUSREG_VOLUME_RATE);
1994	outb(port+GUS_DATA_HIGH, 63);
1995
1996	SELECT_GUS_REG(port, GUSREG_VOICE_CNTL);
1997	outb(port+GUS_DATA_HIGH, sc->sc_voc[voice].voccntl);
1998	SELECT_GUS_REG(port, GUSREG_VOLUME_CONTROL);
1999	outb(port+GUS_DATA_HIGH, 0x00);
2000	delay(50);
2001	SELECT_GUS_REG(port, GUSREG_VOICE_CNTL);
2002	outb(port+GUS_DATA_HIGH, sc->sc_voc[voice].voccntl);
2003	SELECT_GUS_REG(port, GUSREG_VOLUME_CONTROL);
2004	outb(port+GUS_DATA_HIGH, 0x00);
2005
2006}
2007
2008/*
2009 * Stop a given voice.  called at splgus()
2010 */
2011
2012STATIC void
2013gus_stop_voice(sc, voice, intrs_too)
2014	struct gus_softc *sc;
2015	int voice;
2016	int intrs_too;
2017{
2018	register int port = sc->sc_iobase;
2019
2020	sc->sc_voc[voice].voccntl |= GUSMASK_VOICE_STOPPED |
2021		GUSMASK_STOP_VOICE;
2022	if (intrs_too) {
2023	  sc->sc_voc[voice].voccntl &= ~(GUSMASK_VOICE_IRQ);
2024	  /* no more DMA to do */
2025	  sc->sc_flags &= ~GUS_PLAYING;
2026	}
2027	DMAPRINTF(("gusintr voice notplaying=%x\n", sc->sc_flags));
2028
2029	guspoke(port, 0L, 0);
2030
2031	outb(port+GUS_VOICE_SELECT, (unsigned char) voice);
2032
2033	SELECT_GUS_REG(port, GUSREG_CUR_VOLUME);
2034	outw(port+GUS_DATA_LOW, 0x0000);
2035	SELECT_GUS_REG(port, GUSREG_VOICE_CNTL);
2036	outb(port+GUS_DATA_HIGH, sc->sc_voc[voice].voccntl);
2037	delay(100);
2038	SELECT_GUS_REG(port, GUSREG_CUR_VOLUME);
2039	outw(port+GUS_DATA_LOW, 0x0000);
2040	SELECT_GUS_REG(port, GUSREG_VOICE_CNTL);
2041	outb(port+GUS_DATA_HIGH, sc->sc_voc[voice].voccntl);
2042
2043	SELECT_GUS_REG(port, GUSREG_CUR_ADDR_HIGH);
2044	outw(port+GUS_DATA_LOW, 0x0000);
2045	SELECT_GUS_REG(port, GUSREG_CUR_ADDR_LOW);
2046	outw(port+GUS_DATA_LOW, 0x0000);
2047
2048}
2049
2050
2051/*
2052 * Set the volume of a given voice.  Called at splgus().
2053 */
2054STATIC void
2055gus_set_volume(sc, voice, volume)
2056	struct gus_softc *sc;
2057	int voice, volume;
2058{
2059	register int port = sc->sc_iobase;
2060	unsigned int gusvol;
2061
2062	gusvol = gus_log_volumes[volume < 512 ? volume : 511];
2063
2064	sc->sc_voc[voice].current_volume = gusvol;
2065
2066	outb(port+GUS_VOICE_SELECT, (unsigned char) voice);
2067
2068	SELECT_GUS_REG(port, GUSREG_START_VOLUME);
2069	outb(port+GUS_DATA_HIGH, (unsigned char) (gusvol >> 4));
2070
2071	SELECT_GUS_REG(port, GUSREG_END_VOLUME);
2072	outb(port+GUS_DATA_HIGH, (unsigned char) (gusvol >> 4));
2073
2074	SELECT_GUS_REG(port, GUSREG_CUR_VOLUME);
2075	outw(port+GUS_DATA_LOW, gusvol << 4);
2076	delay(500);
2077	outw(port+GUS_DATA_LOW, gusvol << 4);
2078
2079}
2080
2081/*
2082 * Interface to the audio layer.
2083 */
2084
2085int
2086gusmax_set_params(addr, mode, p, q)
2087	void *addr;
2088	int mode;
2089	struct audio_params *p, *q;
2090{
2091	register struct ad1848_softc *ac = addr;
2092	register struct gus_softc *sc = ac->parent;
2093	int error;
2094
2095	error = ad1848_set_params(ac, mode, p, q);
2096	if (error)
2097		return error;
2098	error = gus_set_params(sc, mode, p, q);
2099	return error;
2100}
2101
2102int
2103gus_set_params(addr, mode, p, q)
2104	void *addr;
2105	int mode;
2106	struct audio_params *p, *q;
2107{
2108	register struct gus_softc *sc = addr;
2109	int s;
2110
2111	switch (p->encoding) {
2112	case AUDIO_ENCODING_ULAW:
2113	case AUDIO_ENCODING_SLINEAR_LE:
2114	case AUDIO_ENCODING_ULINEAR_LE:
2115	case AUDIO_ENCODING_SLINEAR_BE:
2116	case AUDIO_ENCODING_ULINEAR_BE:
2117		break;
2118	default:
2119		return (EINVAL);
2120	}
2121
2122	s = splaudio();
2123
2124	if (p->precision == 8) {
2125		sc->sc_voc[GUS_VOICE_LEFT].voccntl &= ~GUSMASK_DATA_SIZE16;
2126		sc->sc_voc[GUS_VOICE_RIGHT].voccntl &= ~GUSMASK_DATA_SIZE16;
2127	} else {
2128		sc->sc_voc[GUS_VOICE_LEFT].voccntl |= GUSMASK_DATA_SIZE16;
2129		sc->sc_voc[GUS_VOICE_RIGHT].voccntl |= GUSMASK_DATA_SIZE16;
2130	}
2131
2132	sc->sc_encoding = p->encoding;
2133	sc->sc_precision = p->precision;
2134	sc->sc_channels = p->channels;
2135
2136	splx(s);
2137
2138	if (p->sample_rate > gus_max_frequency[sc->sc_voices - GUS_MIN_VOICES])
2139		p->sample_rate = gus_max_frequency[sc->sc_voices - GUS_MIN_VOICES];
2140	if (mode == AUMODE_RECORD)
2141		sc->sc_irate = p->sample_rate;
2142	else
2143		sc->sc_orate = p->sample_rate;
2144
2145	switch (p->encoding) {
2146	case AUDIO_ENCODING_ULAW:
2147		p->sw_code = mode == AUMODE_PLAY ?
2148			mulaw_to_ulinear8 : ulinear8_to_mulaw;
2149		break;
2150	case AUDIO_ENCODING_ULINEAR_BE:
2151	case AUDIO_ENCODING_SLINEAR_BE:
2152		p->sw_code = swap_bytes;
2153		break;
2154	default:
2155		p->sw_code = 0;
2156	}
2157
2158	/* Update setting for the other mode. */
2159	q->encoding = p->encoding;
2160	q->channels = p->channels;
2161	q->precision = p->precision;
2162	return 0;
2163}
2164
2165/*
2166 * Interface to the audio layer - set the blocksize to the correct number
2167 * of units
2168 */
2169
2170int
2171gusmax_round_blocksize(addr, blocksize)
2172	void * addr;
2173	int blocksize;
2174{
2175	register struct ad1848_softc *ac = addr;
2176	register struct gus_softc *sc = ac->parent;
2177
2178/*	blocksize = ad1848_round_blocksize(ac, blocksize);*/
2179	return gus_round_blocksize(sc, blocksize);
2180}
2181
2182int
2183gus_round_blocksize(addr, blocksize)
2184	void * addr;
2185	int blocksize;
2186{
2187	register struct gus_softc *sc = addr;
2188
2189	DPRINTF(("gus_round_blocksize called\n"));
2190
2191	if (sc->sc_encoding == AUDIO_ENCODING_ULAW && blocksize > 32768)
2192		blocksize = 32768;
2193	else if (blocksize > 65536)
2194		blocksize = 65536;
2195
2196	if ((blocksize % GUS_BUFFER_MULTIPLE) != 0)
2197		blocksize = (blocksize / GUS_BUFFER_MULTIPLE + 1) *
2198			GUS_BUFFER_MULTIPLE;
2199
2200	/* set up temporary buffer to hold the deinterleave, if necessary
2201	   for stereo output */
2202	if (sc->sc_deintr_buf) {
2203		FREE(sc->sc_deintr_buf, M_DEVBUF);
2204		sc->sc_deintr_buf = NULL;
2205	}
2206	MALLOC(sc->sc_deintr_buf, void *, blocksize>>1, M_DEVBUF, M_WAITOK);
2207
2208	sc->sc_blocksize = blocksize;
2209	/* multi-buffering not quite working yet. */
2210	sc->sc_nbufs = /*GUS_MEM_FOR_BUFFERS / blocksize*/ 2;
2211
2212	gus_set_chan_addrs(sc);
2213
2214	return blocksize;
2215}
2216
2217int
2218gus_get_out_gain(addr)
2219	caddr_t addr;
2220{
2221	register struct gus_softc *sc = (struct gus_softc *) addr;
2222
2223	DPRINTF(("gus_get_out_gain called\n"));
2224	return sc->sc_ogain / 2;
2225}
2226
2227STATIC inline void gus_set_voices(sc, voices)
2228struct gus_softc *sc;
2229int voices;
2230{
2231	register int port = sc->sc_iobase;
2232	/*
2233	 * Select the active number of voices
2234	 */
2235
2236	SELECT_GUS_REG(port, GUSREG_ACTIVE_VOICES);
2237	outb(port+GUS_DATA_HIGH, (voices-1) | 0xc0);
2238
2239	sc->sc_voices = voices;
2240}
2241
2242/*
2243 * Actually set the settings of various values on the card
2244 */
2245
2246int
2247gusmax_commit_settings(addr)
2248	void * addr;
2249{
2250	register struct ad1848_softc *ac = addr;
2251	register struct gus_softc *sc = ac->parent;
2252
2253	(void) ad1848_commit_settings(ac);
2254	return gus_commit_settings(sc);
2255}
2256
2257/*
2258 * Commit the settings.  Called at normal IPL.
2259 */
2260int
2261gus_commit_settings(addr)
2262	void * addr;
2263{
2264	register struct gus_softc *sc = addr;
2265	int s;
2266
2267	DPRINTF(("gus_commit_settings called (gain = %d)\n",sc->sc_ogain));
2268
2269
2270	s = splgus();
2271
2272	gus_set_recrate(sc, sc->sc_irate);
2273	gus_set_volume(sc, GUS_VOICE_LEFT, sc->sc_ogain);
2274	gus_set_volume(sc, GUS_VOICE_RIGHT, sc->sc_ogain);
2275	gus_set_samprate(sc, GUS_VOICE_LEFT, sc->sc_orate);
2276	gus_set_samprate(sc, GUS_VOICE_RIGHT, sc->sc_orate);
2277	splx(s);
2278	gus_set_chan_addrs(sc);
2279
2280	return 0;
2281}
2282
2283STATIC void
2284gus_set_chan_addrs(sc)
2285struct gus_softc *sc;
2286{
2287	/*
2288	 * We use sc_nbufs * blocksize bytes of storage in the on-board GUS
2289	 * ram.
2290	 * For mono, each of the sc_nbufs buffers is DMA'd to in one chunk,
2291	 * and both left & right channels play the same buffer.
2292	 *
2293	 * For stereo, each channel gets a contiguous half of the memory,
2294	 * and each has sc_nbufs buffers of size blocksize/2.
2295	 * Stereo data are deinterleaved in main memory before the DMA out
2296	 * routines are called to queue the output.
2297	 *
2298	 * The blocksize per channel is kept in sc_chanblocksize.
2299	 */
2300	if (sc->sc_channels == 2)
2301	    sc->sc_chanblocksize = sc->sc_blocksize/2;
2302	else
2303	    sc->sc_chanblocksize = sc->sc_blocksize;
2304
2305	sc->sc_voc[GUS_VOICE_LEFT].start_addr = GUS_MEM_OFFSET - 1;
2306	sc->sc_voc[GUS_VOICE_RIGHT].start_addr =
2307	    (gus_dostereo && sc->sc_channels == 2 ? GUS_LEFT_RIGHT_OFFSET : 0)
2308	      + GUS_MEM_OFFSET - 1;
2309	sc->sc_voc[GUS_VOICE_RIGHT].current_addr =
2310	    sc->sc_voc[GUS_VOICE_RIGHT].start_addr + 1;
2311	sc->sc_voc[GUS_VOICE_RIGHT].end_addr =
2312	    sc->sc_voc[GUS_VOICE_RIGHT].start_addr +
2313	    sc->sc_nbufs * sc->sc_chanblocksize;
2314
2315}
2316
2317/*
2318 * Set the sample rate of the given voice.  Called at splgus().
2319 */
2320
2321STATIC void
2322gus_set_samprate(sc, voice, freq)
2323	struct gus_softc *sc;
2324	int voice, freq;
2325{
2326	register int port = sc->sc_iobase;
2327	unsigned int fc;
2328	u_long temp, f = (u_long) freq;
2329
2330	/*
2331	 * calculate fc based on the number of active voices;
2332	 * we need to use longs to preserve enough bits
2333	 */
2334
2335	temp = (u_long) gus_max_frequency[sc->sc_voices-GUS_MIN_VOICES];
2336
2337 	fc = (unsigned int)(((f << 9L) + (temp >> 1L)) / temp);
2338
2339 	fc <<= 1;
2340
2341
2342	/*
2343	 * Program the voice frequency, and set it in the voice data record
2344	 */
2345
2346	outb(port+GUS_VOICE_SELECT, (unsigned char) voice);
2347	SELECT_GUS_REG(port, GUSREG_FREQ_CONTROL);
2348	outw(port+GUS_DATA_LOW, fc);
2349
2350	sc->sc_voc[voice].rate = freq;
2351
2352}
2353
2354/*
2355 * Set the sample rate of the recording frequency.  Formula is from the GUS
2356 * SDK.  Called at splgus().
2357 */
2358
2359STATIC void
2360gus_set_recrate(sc, rate)
2361	struct gus_softc *sc;
2362	u_long rate;
2363{
2364	register int port = sc->sc_iobase;
2365	u_char realrate;
2366	DPRINTF(("gus_set_recrate %lu\n", rate));
2367
2368#if 0
2369	realrate = 9878400/(16*(rate+2)); /* formula from GUS docs */
2370#endif
2371	realrate = (9878400 >> 4)/rate - 2; /* formula from code, sigh. */
2372
2373	SELECT_GUS_REG(port, GUSREG_SAMPLE_FREQ);
2374 	outb(port+GUS_DATA_HIGH, realrate);
2375}
2376
2377/*
2378 * Interface to the audio layer - turn the output on or off.  Note that some
2379 * of these bits are flipped in the register
2380 */
2381
2382int
2383gusmax_speaker_ctl(addr, newstate)
2384	void * addr;
2385	int newstate;
2386{
2387	register struct ad1848_softc *sc = addr;
2388	return gus_speaker_ctl(sc->parent, newstate);
2389}
2390
2391int
2392gus_speaker_ctl(addr, newstate)
2393	void * addr;
2394	int newstate;
2395{
2396	register struct gus_softc *sc = (struct gus_softc *) addr;
2397
2398	/* Line out bit is flipped: 0 enables, 1 disables */
2399	if ((newstate == SPKR_ON) &&
2400	    (sc->sc_mixcontrol & GUSMASK_LINE_OUT)) {
2401		sc->sc_mixcontrol &= ~GUSMASK_LINE_OUT;
2402		outb(sc->sc_iobase+GUS_MIX_CONTROL, sc->sc_mixcontrol);
2403	}
2404	if ((newstate == SPKR_OFF) &&
2405	    (sc->sc_mixcontrol & GUSMASK_LINE_OUT) == 0) {
2406		sc->sc_mixcontrol |= GUSMASK_LINE_OUT;
2407		outb(sc->sc_iobase+GUS_MIX_CONTROL, sc->sc_mixcontrol);
2408	}
2409
2410	return 0;
2411}
2412
2413STATIC int
2414gus_linein_ctl(addr, newstate)
2415	void * addr;
2416	int newstate;
2417{
2418	register struct gus_softc *sc = (struct gus_softc *) addr;
2419
2420	/* Line in bit is flipped: 0 enables, 1 disables */
2421	if ((newstate == SPKR_ON) &&
2422	    (sc->sc_mixcontrol & GUSMASK_LINE_IN)) {
2423		sc->sc_mixcontrol &= ~GUSMASK_LINE_IN;
2424		outb(sc->sc_iobase+GUS_MIX_CONTROL, sc->sc_mixcontrol);
2425	}
2426	if ((newstate == SPKR_OFF) &&
2427	    (sc->sc_mixcontrol & GUSMASK_LINE_IN) == 0) {
2428		sc->sc_mixcontrol |= GUSMASK_LINE_IN;
2429		outb(sc->sc_iobase+GUS_MIX_CONTROL, sc->sc_mixcontrol);
2430	}
2431
2432	return 0;
2433}
2434
2435STATIC int
2436gus_mic_ctl(addr, newstate)
2437	void * addr;
2438	int newstate;
2439{
2440	register struct gus_softc *sc = (struct gus_softc *) addr;
2441
2442	/* Mic bit is normal: 1 enables, 0 disables */
2443	if ((newstate == SPKR_ON) &&
2444	    (sc->sc_mixcontrol & GUSMASK_MIC_IN) == 0) {
2445		sc->sc_mixcontrol |= GUSMASK_MIC_IN;
2446		outb(sc->sc_iobase+GUS_MIX_CONTROL, sc->sc_mixcontrol);
2447	}
2448	if ((newstate == SPKR_OFF) &&
2449	    (sc->sc_mixcontrol & GUSMASK_MIC_IN)) {
2450		sc->sc_mixcontrol &= ~GUSMASK_MIC_IN;
2451		outb(sc->sc_iobase+GUS_MIX_CONTROL, sc->sc_mixcontrol);
2452	}
2453
2454	return 0;
2455}
2456
2457/*
2458 * Set the end address of a give voice.  Called at splgus()
2459 */
2460
2461STATIC void
2462gus_set_endaddr(sc, voice, addr)
2463	struct gus_softc *sc;
2464	int voice;
2465	u_long addr;
2466{
2467	register int port = sc->sc_iobase;
2468
2469	sc->sc_voc[voice].end_addr = addr;
2470
2471	if (sc->sc_voc[voice].voccntl & GUSMASK_DATA_SIZE16)
2472		addr = convert_to_16bit(addr);
2473
2474	SELECT_GUS_REG(port, GUSREG_END_ADDR_HIGH);
2475	outw(port+GUS_DATA_LOW, ADDR_HIGH(addr));
2476	SELECT_GUS_REG(port, GUSREG_END_ADDR_LOW);
2477	outw(port+GUS_DATA_LOW, ADDR_LOW(addr));
2478
2479}
2480
2481#ifdef GUSPLAYDEBUG
2482/*
2483 * Set current address.  called at splgus()
2484 */
2485STATIC void
2486gus_set_curaddr(sc, voice, addr)
2487	struct gus_softc *sc;
2488	int voice;
2489	u_long addr;
2490{
2491	register int port = sc->sc_iobase;
2492
2493	sc->sc_voc[voice].current_addr = addr;
2494
2495	if (sc->sc_voc[voice].voccntl & GUSMASK_DATA_SIZE16)
2496		addr = convert_to_16bit(addr);
2497
2498	outb(port+GUS_VOICE_SELECT, (unsigned char) voice);
2499
2500	SELECT_GUS_REG(port, GUSREG_CUR_ADDR_HIGH);
2501	outw(port+GUS_DATA_LOW, ADDR_HIGH(addr));
2502	SELECT_GUS_REG(port, GUSREG_CUR_ADDR_LOW);
2503	outw(port+GUS_DATA_LOW, ADDR_LOW(addr));
2504
2505}
2506
2507/*
2508 * Get current GUS playback address.  Called at splgus().
2509 */
2510STATIC u_long
2511gus_get_curaddr(sc, voice)
2512	struct gus_softc *sc;
2513	int voice;
2514{
2515	register int port = sc->sc_iobase;
2516	u_long addr;
2517
2518	outb(port+GUS_VOICE_SELECT, (unsigned char) voice);
2519	SELECT_GUS_REG(port, GUSREG_CUR_ADDR_HIGH|GUSREG_READ);
2520	addr = (inw(port+GUS_DATA_LOW) & 0x1fff) << 7;
2521	SELECT_GUS_REG(port, GUSREG_CUR_ADDR_LOW|GUSREG_READ);
2522	addr |= (inw(port+GUS_DATA_LOW) >> 9L) & 0x7f;
2523
2524	if (sc->sc_voc[voice].voccntl & GUSMASK_DATA_SIZE16)
2525	    addr = (addr & 0xc0000) | ((addr & 0x1ffff) << 1); /* undo 16-bit change */
2526	DPRINTF(("gus voice %d curaddr %ld end_addr %ld\n",
2527		 voice, addr, sc->sc_voc[voice].end_addr));
2528	/* XXX sanity check the address? */
2529
2530	return(addr);
2531}
2532#endif
2533
2534/*
2535 * Convert an address value to a "16 bit" value - why this is necessary I
2536 * have NO idea
2537 */
2538
2539STATIC u_long
2540convert_to_16bit(address)
2541	u_long address;
2542{
2543	u_long old_address;
2544
2545	old_address = address;
2546	address >>= 1;
2547	address &= 0x0001ffffL;
2548	address |= (old_address & 0x000c0000L);
2549
2550	return (address);
2551}
2552
2553/*
2554 * Write a value into the GUS's DRAM
2555 */
2556
2557STATIC void
2558guspoke(port, address, value)
2559	int port;
2560	long address;
2561	unsigned char value;
2562{
2563
2564	/*
2565	 * Select the DRAM address
2566	 */
2567
2568 	SELECT_GUS_REG(port, GUSREG_DRAM_ADDR_LOW);
2569 	outw(port+GUS_DATA_LOW, (unsigned int) (address & 0xffff));
2570 	SELECT_GUS_REG(port, GUSREG_DRAM_ADDR_HIGH);
2571 	outb(port+GUS_DATA_HIGH, (unsigned char) ((address >> 16) & 0xff));
2572
2573	/*
2574	 * Actually write the data
2575	 */
2576
2577	outb(port+GUS_DRAM_DATA, value);
2578}
2579
2580/*
2581 * Read a value from the GUS's DRAM
2582 */
2583
2584STATIC unsigned char
2585guspeek(port, address)
2586	int port;
2587	u_long address;
2588{
2589
2590	/*
2591	 * Select the DRAM address
2592	 */
2593
2594 	SELECT_GUS_REG(port, GUSREG_DRAM_ADDR_LOW);
2595 	outw(port+GUS_DATA_LOW, (unsigned int) (address & 0xffff));
2596 	SELECT_GUS_REG(port, GUSREG_DRAM_ADDR_HIGH);
2597 	outb(port+GUS_DATA_HIGH, (unsigned char) ((address >> 16) & 0xff));
2598
2599	/*
2600	 * Read in the data from the board
2601	 */
2602
2603	return (unsigned char) inb(port+GUS_DRAM_DATA);
2604}
2605
2606/*
2607 * Reset the Gravis UltraSound card, completely
2608 */
2609
2610STATIC void
2611gusreset(sc, voices)
2612	struct gus_softc *sc;
2613	int voices;
2614{
2615	register int port = sc->sc_iobase;
2616	int i,s;
2617
2618	s = splgus();
2619
2620	/*
2621	 * Reset the GF1 chip
2622	 */
2623
2624	SELECT_GUS_REG(port, GUSREG_RESET);
2625	outb(port+GUS_DATA_HIGH, 0x00);
2626
2627	delay(500);
2628
2629	/*
2630	 * Release reset
2631	 */
2632
2633	SELECT_GUS_REG(port, GUSREG_RESET);
2634	outb(port+GUS_DATA_HIGH, GUSMASK_MASTER_RESET);
2635
2636	delay(500);
2637
2638	/*
2639	 * Reset MIDI port as well
2640	 */
2641
2642	outb(GUS_MIDI_CONTROL,MIDI_RESET);
2643
2644	delay(500);
2645
2646	outb(GUS_MIDI_CONTROL,0x00);
2647
2648	/*
2649	 * Clear interrupts
2650	 */
2651
2652	SELECT_GUS_REG(port, GUSREG_DMA_CONTROL);
2653	outb(port+GUS_DATA_HIGH, 0x00);
2654	SELECT_GUS_REG(port, GUSREG_TIMER_CONTROL);
2655	outb(port+GUS_DATA_HIGH, 0x00);
2656	SELECT_GUS_REG(port, GUSREG_SAMPLE_CONTROL);
2657	outb(port+GUS_DATA_HIGH, 0x00);
2658
2659	gus_set_voices(sc, voices);
2660
2661	inb(port+GUS_IRQ_STATUS);
2662	SELECT_GUS_REG(port, GUSREG_DMA_CONTROL);
2663	inb(port+GUS_DATA_HIGH);
2664	SELECT_GUS_REG(port, GUSREG_SAMPLE_CONTROL);
2665	inb(port+GUS_DATA_HIGH);
2666	SELECT_GUS_REG(port, GUSREG_IRQ_STATUS);
2667	inb(port+GUS_DATA_HIGH);
2668
2669	/*
2670	 * Reset voice specific information
2671	 */
2672
2673	for(i = 0; i < voices; i++) {
2674		outb(port+GUS_VOICE_SELECT, (unsigned char) i);
2675
2676		SELECT_GUS_REG(port, GUSREG_VOICE_CNTL);
2677
2678		sc->sc_voc[i].voccntl = GUSMASK_VOICE_STOPPED |
2679			GUSMASK_STOP_VOICE;
2680
2681		outb(port+GUS_DATA_HIGH, sc->sc_voc[i].voccntl);
2682
2683		sc->sc_voc[i].volcntl = GUSMASK_VOLUME_STOPPED |
2684				GUSMASK_STOP_VOLUME;
2685
2686		SELECT_GUS_REG(port, GUSREG_VOLUME_CONTROL);
2687		outb(port+GUS_DATA_HIGH, sc->sc_voc[i].volcntl);
2688
2689		delay(100);
2690
2691		gus_set_samprate(sc, i, 8000);
2692		SELECT_GUS_REG(port, GUSREG_START_ADDR_HIGH);
2693		outw(port+GUS_DATA_LOW, 0x0000);
2694		SELECT_GUS_REG(port, GUSREG_START_ADDR_LOW);
2695		outw(port+GUS_DATA_LOW, 0x0000);
2696		SELECT_GUS_REG(port, GUSREG_END_ADDR_HIGH);
2697		outw(port+GUS_DATA_LOW, 0x0000);
2698		SELECT_GUS_REG(port, GUSREG_END_ADDR_LOW);
2699		outw(port+GUS_DATA_LOW, 0x0000);
2700		SELECT_GUS_REG(port, GUSREG_VOLUME_RATE);
2701		outb(port+GUS_DATA_HIGH, 0x01);
2702		SELECT_GUS_REG(port, GUSREG_START_VOLUME);
2703		outb(port+GUS_DATA_HIGH, 0x10);
2704		SELECT_GUS_REG(port, GUSREG_END_VOLUME);
2705		outb(port+GUS_DATA_HIGH, 0xe0);
2706		SELECT_GUS_REG(port, GUSREG_CUR_VOLUME);
2707		outw(port+GUS_DATA_LOW, 0x0000);
2708
2709		SELECT_GUS_REG(port, GUSREG_CUR_ADDR_HIGH);
2710		outw(port+GUS_DATA_LOW, 0x0000);
2711		SELECT_GUS_REG(port, GUSREG_CUR_ADDR_LOW);
2712		outw(port+GUS_DATA_LOW, 0x0000);
2713		SELECT_GUS_REG(port, GUSREG_PAN_POS);
2714		outb(port+GUS_DATA_HIGH, 0x07);
2715	}
2716
2717	/*
2718	 * Clear out any pending IRQs
2719	 */
2720
2721	inb(port+GUS_IRQ_STATUS);
2722	SELECT_GUS_REG(port, GUSREG_DMA_CONTROL);
2723	inb(port+GUS_DATA_HIGH);
2724	SELECT_GUS_REG(port, GUSREG_SAMPLE_CONTROL);
2725	inb(port+GUS_DATA_HIGH);
2726	SELECT_GUS_REG(port, GUSREG_IRQ_STATUS);
2727	inb(port+GUS_DATA_HIGH);
2728
2729	SELECT_GUS_REG(port, GUSREG_RESET);
2730	outb(port+GUS_DATA_HIGH, GUSMASK_MASTER_RESET | GUSMASK_DAC_ENABLE |
2731		GUSMASK_IRQ_ENABLE);
2732
2733	splx(s);
2734}
2735
2736
2737STATIC void
2738gus_init_cs4231(sc)
2739	struct gus_softc *sc;
2740{
2741	register int port = sc->sc_iobase;
2742	u_char ctrl;
2743
2744	ctrl = (port & 0xf0) >> 4;	/* set port address middle nibble */
2745	/*
2746	 * The codec is a bit weird--swapped dma channels.
2747	 */
2748	ctrl |= GUS_MAX_CODEC_ENABLE;
2749	if (sc->sc_drq >= 4)
2750		ctrl |= GUS_MAX_RECCHAN16;
2751	if (sc->sc_recdrq >= 4)
2752		ctrl |= GUS_MAX_PLAYCHAN16;
2753
2754	outb(port+GUS_MAX_CTRL, ctrl);
2755
2756	sc->sc_codec.sc_iot = sc->sc_iot;
2757	sc->sc_codec.sc_iobase = port+GUS_MAX_CODEC_BASE;
2758
2759	if (ad1848_probe(&sc->sc_codec) == 0) {
2760		sc->sc_flags &= ~GUS_CODEC_INSTALLED;
2761	} else {
2762		struct ad1848_volume vol = {AUDIO_MAX_GAIN, AUDIO_MAX_GAIN};
2763		struct audio_hw_if gusmax_hw_if = {
2764			gusopen,
2765			gusmax_close,
2766			NULL,				/* drain */
2767
2768			gus_query_encoding, /* query encoding */
2769
2770			gusmax_set_params,
2771
2772			gusmax_round_blocksize,
2773
2774			gusmax_set_out_port,
2775			gusmax_get_out_port,
2776			gusmax_set_in_port,
2777			gusmax_get_in_port,
2778
2779			gusmax_commit_settings,
2780
2781			NULL,
2782			NULL,
2783
2784			gusmax_dma_output,
2785			gusmax_dma_input,
2786			gusmax_halt_out_dma,
2787			gusmax_halt_in_dma,
2788			gusmax_cont_out_dma,
2789			gusmax_cont_in_dma,
2790
2791			gusmax_speaker_ctl,
2792
2793			gus_getdev,
2794			NULL,
2795			gusmax_mixer_set_port,
2796			gusmax_mixer_get_port,
2797			gusmax_mixer_query_devinfo,
2798			NULL,
2799			NULL,
2800			NULL,
2801			AUDIO_PROP_FULLDUPLEX,
2802			0,
2803		};
2804		sc->sc_flags |= GUS_CODEC_INSTALLED;
2805		sc->sc_codec.parent = sc;
2806		sc->sc_codec.sc_drq = sc->sc_recdrq;
2807		sc->sc_codec.sc_recdrq = sc->sc_drq;
2808		gus_hw_if = gusmax_hw_if;
2809		/* enable line in and mic in the GUS mixer; the codec chip
2810		   will do the real mixing for them. */
2811		sc->sc_mixcontrol &= ~GUSMASK_LINE_IN; /* 0 enables. */
2812		sc->sc_mixcontrol |= GUSMASK_MIC_IN; /* 1 enables. */
2813		outb(sc->sc_iobase+GUS_MIX_CONTROL, sc->sc_mixcontrol);
2814
2815		ad1848_attach(&sc->sc_codec);
2816		/* turn on pre-MUX microphone gain. */
2817		ad1848_set_mic_gain(&sc->sc_codec, &vol);
2818	}
2819}
2820
2821
2822/*
2823 * Return info about the audio device, for the AUDIO_GETINFO ioctl
2824 */
2825
2826int
2827gus_getdev(addr, dev)
2828	void * addr;
2829	struct audio_device *dev;
2830{
2831	*dev = gus_device;
2832	return 0;
2833}
2834
2835/*
2836 * stubs (XXX)
2837 */
2838
2839int
2840gus_set_in_gain(addr, gain, balance)
2841	caddr_t addr;
2842	u_int gain;
2843	u_char balance;
2844{
2845	DPRINTF(("gus_set_in_gain called\n"));
2846	return 0;
2847}
2848
2849int
2850gus_get_in_gain(addr)
2851	caddr_t addr;
2852{
2853	DPRINTF(("gus_get_in_gain called\n"));
2854	return 0;
2855}
2856
2857int
2858gusmax_set_out_port(addr, port)
2859	void * addr;
2860	int port;
2861{
2862	register struct ad1848_softc *sc = addr;
2863	return gus_set_out_port(sc->parent, port);
2864}
2865
2866int
2867gus_set_out_port(addr, port)
2868	void * addr;
2869	int port;
2870{
2871	register struct gus_softc *sc = addr;
2872	DPRINTF(("gus_set_out_port called\n"));
2873	sc->sc_out_port = port;
2874
2875	return 0;
2876}
2877
2878int
2879gusmax_get_out_port(addr)
2880	void * addr;
2881{
2882	register struct ad1848_softc *sc = addr;
2883	return gus_get_out_port(sc->parent);
2884}
2885
2886int
2887gus_get_out_port(addr)
2888	void * addr;
2889{
2890	register struct gus_softc *sc = addr;
2891	DPRINTF(("gus_get_out_port() called\n"));
2892	return sc->sc_out_port;
2893}
2894
2895int
2896gusmax_set_in_port(addr, port)
2897	void * addr;
2898	int port;
2899{
2900	register struct ad1848_softc *sc = addr;
2901	DPRINTF(("gusmax_set_in_port: %d\n", port));
2902
2903	switch(port) {
2904	case MIC_IN_PORT:
2905	case LINE_IN_PORT:
2906	case AUX1_IN_PORT:
2907	case DAC_IN_PORT:
2908		break;
2909	default:
2910		return(EINVAL);
2911		/*NOTREACHED*/
2912	}
2913	return(ad1848_set_rec_port(sc, port));
2914}
2915
2916int
2917gusmax_get_in_port(addr)
2918	void * addr;
2919{
2920	register struct ad1848_softc *sc = addr;
2921	int port;
2922
2923	port = ad1848_get_rec_port(sc);
2924	DPRINTF(("gusmax_get_in_port: %d\n", port));
2925
2926	return(port);
2927}
2928
2929int
2930gus_set_in_port(addr, port)
2931	void * addr;
2932	int port;
2933{
2934	register struct gus_softc *sc = addr;
2935	DPRINTF(("gus_set_in_port called\n"));
2936	/*
2937	 * On the GUS with ICS mixer, the ADC input is after the mixer stage,
2938	 * so we can't set the input port.
2939	 *
2940	 * On the GUS with CS4231 codec/mixer, see gusmax_set_in_port().
2941	 */
2942	sc->sc_in_port = port;
2943
2944	return 0;
2945}
2946
2947
2948int
2949gus_get_in_port(addr)
2950	void * addr;
2951{
2952	register struct gus_softc *sc = addr;
2953	DPRINTF(("gus_get_in_port called\n"));
2954	return sc->sc_in_port;
2955}
2956
2957
2958int
2959gusmax_dma_input(addr, buf, size, callback, arg)
2960	void * addr;
2961	void *buf;
2962	int size;
2963	void (*callback) __P((void *));
2964	void *arg;
2965{
2966	register struct ad1848_softc *sc = addr;
2967	return gus_dma_input(sc->parent, buf, size, callback, arg);
2968}
2969
2970/*
2971 * Start sampling the input source into the requested DMA buffer.
2972 * Called at splgus(), either from top-half or from interrupt handler.
2973 */
2974int
2975gus_dma_input(addr, buf, size, callback, arg)
2976	void * addr;
2977	void *buf;
2978	int size;
2979	void (*callback) __P((void *));
2980	void *arg;
2981{
2982	register struct gus_softc *sc = addr;
2983	register int port = sc->sc_iobase;
2984	register u_char dmac;
2985	DMAPRINTF(("gus_dma_input called\n"));
2986
2987	/*
2988	 * Sample SIZE bytes of data from the card, into buffer at BUF.
2989	 */
2990
2991	if (sc->sc_precision == 16)
2992	    return EINVAL;		/* XXX */
2993
2994	/* set DMA modes */
2995	dmac = GUSMASK_SAMPLE_IRQ|GUSMASK_SAMPLE_START;
2996	if (sc->sc_recdrq >= 4)
2997		dmac |= GUSMASK_SAMPLE_DATA16;
2998	if (sc->sc_encoding == AUDIO_ENCODING_ULAW ||
2999	    sc->sc_encoding == AUDIO_ENCODING_ULINEAR_LE ||
3000	    sc->sc_encoding == AUDIO_ENCODING_ULINEAR_BE)
3001	    dmac |= GUSMASK_SAMPLE_INVBIT;
3002	if (sc->sc_channels == 2)
3003	    dmac |= GUSMASK_SAMPLE_STEREO;
3004	isa_dmastart(sc->sc_dev.dv_parent, sc->sc_recdrq, buf, size,
3005	    NULL, DMAMODE_READ, BUS_DMA_NOWAIT);
3006
3007	DMAPRINTF(("gus_dma_input isa_dmastarted\n"));
3008	sc->sc_flags |= GUS_DMAIN_ACTIVE;
3009	sc->sc_dmainintr = callback;
3010	sc->sc_inarg = arg;
3011	sc->sc_dmaincnt = size;
3012	sc->sc_dmainaddr = buf;
3013
3014	SELECT_GUS_REG(port, GUSREG_SAMPLE_CONTROL);
3015	outb(port+GUS_DATA_HIGH, dmac);	/* Go! */
3016
3017
3018	DMAPRINTF(("gus_dma_input returning\n"));
3019
3020	return 0;
3021}
3022
3023STATIC int
3024gus_dmain_intr(sc)
3025	struct gus_softc *sc;
3026{
3027        void (*callback) __P((void *));
3028	void *arg;
3029
3030	DMAPRINTF(("gus_dmain_intr called\n"));
3031	if (sc->sc_dmainintr) {
3032	    isa_dmadone(sc->sc_dev.dv_parent, sc->sc_recdrq);
3033	    callback = sc->sc_dmainintr;
3034	    arg = sc->sc_inarg;
3035
3036	    sc->sc_dmainaddr = 0;
3037	    sc->sc_dmaincnt = 0;
3038	    sc->sc_dmainintr = 0;
3039	    sc->sc_inarg = 0;
3040
3041	    sc->sc_flags &= ~GUS_DMAIN_ACTIVE;
3042	    DMAPRINTF(("calling dmain_intr callback %p(%p)\n", callback, arg));
3043	    (*callback)(arg);
3044	    return 1;
3045	} else {
3046	    DMAPRINTF(("gus_dmain_intr false?\n"));
3047	    return 0;			/* XXX ??? */
3048	}
3049}
3050
3051int
3052gusmax_halt_out_dma(addr)
3053	void * addr;
3054{
3055	register struct ad1848_softc *sc = addr;
3056	return gus_halt_out_dma(sc->parent);
3057}
3058
3059
3060int
3061gusmax_halt_in_dma(addr)
3062	void * addr;
3063{
3064	register struct ad1848_softc *sc = addr;
3065	return gus_halt_in_dma(sc->parent);
3066}
3067
3068int
3069gusmax_cont_out_dma(addr)
3070	void * addr;
3071{
3072	register struct ad1848_softc *sc = addr;
3073	return gus_cont_out_dma(sc->parent);
3074}
3075
3076int
3077gusmax_cont_in_dma(addr)
3078	void * addr;
3079{
3080	register struct ad1848_softc *sc = addr;
3081	return gus_cont_in_dma(sc->parent);
3082}
3083
3084/*
3085 * Stop any DMA output.  Called at splgus().
3086 */
3087int
3088gus_halt_out_dma(addr)
3089	void * addr;
3090{
3091	register struct gus_softc *sc = addr;
3092	register int port = sc->sc_iobase;
3093
3094	DMAPRINTF(("gus_halt_out_dma called\n"));
3095	/*
3096	 * Make sure the GUS _isn't_ setup for DMA
3097	 */
3098
3099 	SELECT_GUS_REG(port, GUSREG_DMA_CONTROL);
3100	outb(sc->sc_iobase+GUS_DATA_HIGH, 0);
3101
3102	untimeout(gus_dmaout_timeout, sc);
3103	isa_dmaabort(sc->sc_dev.dv_parent, sc->sc_drq);
3104	sc->sc_flags &= ~(GUS_DMAOUT_ACTIVE|GUS_LOCKED);
3105	sc->sc_dmaoutintr = 0;
3106	sc->sc_outarg = 0;
3107	sc->sc_dmaoutaddr = 0;
3108	sc->sc_dmaoutcnt = 0;
3109	sc->sc_dmabuf = 0;
3110	sc->sc_bufcnt = 0;
3111	sc->sc_playbuf = -1;
3112	/* also stop playing */
3113	gus_stop_voice(sc, GUS_VOICE_LEFT, 1);
3114	gus_stop_voice(sc, GUS_VOICE_RIGHT, 0);
3115
3116	return 0;
3117}
3118
3119/*
3120 * Stop any DMA output.  Called at splgus().
3121 */
3122int
3123gus_halt_in_dma(addr)
3124	void * addr;
3125{
3126	register struct gus_softc *sc = addr;
3127	register int port = sc->sc_iobase;
3128	DMAPRINTF(("gus_halt_in_dma called\n"));
3129
3130	/*
3131	 * Make sure the GUS _isn't_ setup for DMA
3132	 */
3133
3134 	SELECT_GUS_REG(port, GUSREG_SAMPLE_CONTROL);
3135	outb(port+GUS_DATA_HIGH,
3136	     inb(port+GUS_DATA_HIGH) & ~(GUSMASK_SAMPLE_START|GUSMASK_SAMPLE_IRQ));
3137
3138	isa_dmaabort(sc->sc_dev.dv_parent, sc->sc_recdrq);
3139	sc->sc_flags &= ~GUS_DMAIN_ACTIVE;
3140	sc->sc_dmainintr = 0;
3141	sc->sc_inarg = 0;
3142	sc->sc_dmainaddr = 0;
3143	sc->sc_dmaincnt = 0;
3144
3145	return 0;
3146}
3147
3148int
3149gus_cont_out_dma(addr)
3150	void * addr;
3151{
3152	DPRINTF(("gus_cont_out_dma called\n"));
3153	return EOPNOTSUPP;
3154}
3155
3156int
3157gus_cont_in_dma(addr)
3158	void * addr;
3159{
3160	DPRINTF(("gus_cont_in_dma called\n"));
3161	return EOPNOTSUPP;
3162}
3163
3164
3165STATIC __inline int
3166gus_to_vol(cp, vol)
3167	mixer_ctrl_t *cp;
3168	struct ad1848_volume *vol;
3169{
3170	if (cp->un.value.num_channels == 1) {
3171		vol->left = vol->right = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
3172		return(1);
3173	}
3174	else if (cp->un.value.num_channels == 2) {
3175		vol->left  = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
3176		vol->right = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
3177		return(1);
3178	}
3179	return(0);
3180}
3181
3182STATIC __inline int
3183gus_from_vol(cp, vol)
3184	mixer_ctrl_t *cp;
3185	struct ad1848_volume *vol;
3186{
3187	if (cp->un.value.num_channels == 1) {
3188		cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = vol->left;
3189		return(1);
3190	}
3191	else if (cp->un.value.num_channels == 2) {
3192		cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = vol->left;
3193		cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = vol->right;
3194		return(1);
3195	}
3196	return(0);
3197}
3198
3199STATIC int
3200gusmax_mixer_get_port(addr, cp)
3201	void *addr;
3202	mixer_ctrl_t *cp;
3203{
3204	register struct ad1848_softc *ac = addr;
3205	register struct gus_softc *sc = ac->parent;
3206	struct ad1848_volume vol;
3207	int error = EINVAL;
3208
3209	DPRINTF(("gusmax_mixer_get_port: port=%d\n", cp->dev));
3210
3211	switch (cp->dev) {
3212#if 0 /* use mono level instead */
3213	case GUSMAX_MIC_IN_LVL:	/* Microphone */
3214		if (cp->type == AUDIO_MIXER_VALUE) {
3215			error = ad1848_get_mic_gain(ac, &vol);
3216			if (!error)
3217				gus_from_vol(cp, &vol);
3218		}
3219		break;
3220#endif
3221
3222	case GUSMAX_DAC_LVL:		/* dac out */
3223		if (cp->type == AUDIO_MIXER_VALUE) {
3224			error = ad1848_get_aux1_gain(ac, &vol);
3225			if (!error)
3226				gus_from_vol(cp, &vol);
3227		}
3228		break;
3229
3230	case GUSMAX_LINE_IN_LVL:	/* line in */
3231		if (cp->type == AUDIO_MIXER_VALUE) {
3232			error = cs4231_get_linein_gain(ac, &vol);
3233			if (!error)
3234				gus_from_vol(cp, &vol);
3235		}
3236		break;
3237
3238	case GUSMAX_MONO_LVL:	/* mono */
3239		if (cp->type == AUDIO_MIXER_VALUE &&
3240		    cp->un.value.num_channels == 1) {
3241			error = cs4231_get_mono_gain(ac, &vol);
3242			if (!error)
3243				gus_from_vol(cp, &vol);
3244		}
3245		break;
3246
3247	case GUSMAX_CD_LVL:	/* CD */
3248		if (cp->type == AUDIO_MIXER_VALUE) {
3249			error = ad1848_get_aux2_gain(ac, &vol);
3250			if (!error)
3251				gus_from_vol(cp, &vol);
3252		}
3253		break;
3254
3255	case GUSMAX_MONITOR_LVL:	/* monitor level */
3256		if (cp->type == AUDIO_MIXER_VALUE &&
3257		    cp->un.value.num_channels == 1) {
3258			error = ad1848_get_mon_gain(ac, &vol);
3259			if (!error)
3260				cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
3261					vol.left;
3262		}
3263		break;
3264
3265	case GUSMAX_OUT_LVL:	/* output level */
3266		if (cp->type == AUDIO_MIXER_VALUE) {
3267			error = ad1848_get_out_gain(ac, &vol);
3268			if (!error)
3269				gus_from_vol(cp, &vol);
3270		}
3271		break;
3272
3273	case GUSMAX_SPEAKER_LVL:	/* fake speaker for mute naming */
3274		if (cp->type == AUDIO_MIXER_VALUE) {
3275			if (sc->sc_mixcontrol & GUSMASK_LINE_OUT)
3276				vol.left = vol.right = AUDIO_MAX_GAIN;
3277			else
3278				vol.left = vol.right = AUDIO_MIN_GAIN;
3279			error = 0;
3280			gus_from_vol(cp, &vol);
3281		}
3282		break;
3283
3284	case GUSMAX_LINE_IN_MUTE:
3285		if (cp->type == AUDIO_MIXER_ENUM) {
3286			cp->un.ord = ac->line_mute;
3287			error = 0;
3288		}
3289		break;
3290
3291
3292	case GUSMAX_DAC_MUTE:
3293		if (cp->type == AUDIO_MIXER_ENUM) {
3294			cp->un.ord = ac->aux1_mute;
3295			error = 0;
3296		}
3297		break;
3298
3299	case GUSMAX_CD_MUTE:
3300		if (cp->type == AUDIO_MIXER_ENUM) {
3301			cp->un.ord = ac->aux2_mute;
3302			error = 0;
3303		}
3304		break;
3305
3306	case GUSMAX_MONO_MUTE:
3307		if (cp->type == AUDIO_MIXER_ENUM) {
3308			cp->un.ord = ac->mono_mute;
3309			error = 0;
3310		}
3311		break;
3312
3313	case GUSMAX_MONITOR_MUTE:
3314		if (cp->type == AUDIO_MIXER_ENUM) {
3315			cp->un.ord = ac->mon_mute;
3316			error = 0;
3317		}
3318		break;
3319
3320	case GUSMAX_SPEAKER_MUTE:
3321		if (cp->type == AUDIO_MIXER_ENUM) {
3322			cp->un.ord = sc->sc_mixcontrol & GUSMASK_LINE_OUT ? 1 : 0;
3323			error = 0;
3324		}
3325		break;
3326
3327	case GUSMAX_REC_LVL:		/* record level */
3328		if (cp->type == AUDIO_MIXER_VALUE) {
3329			error = ad1848_get_rec_gain(ac, &vol);
3330			if (!error)
3331				gus_from_vol(cp, &vol);
3332		}
3333		break;
3334
3335	case GUSMAX_RECORD_SOURCE:
3336		if (cp->type == AUDIO_MIXER_ENUM) {
3337			cp->un.ord = ad1848_get_rec_port(ac);
3338			error = 0;
3339		}
3340		break;
3341
3342	default:
3343		error = ENXIO;
3344		break;
3345	}
3346
3347	return(error);
3348}
3349
3350STATIC int
3351gus_mixer_get_port(addr, cp)
3352	void *addr;
3353	mixer_ctrl_t *cp;
3354{
3355	register struct gus_softc *sc = addr;
3356	register struct ics2101_softc *ic = &sc->sc_mixer;
3357	struct ad1848_volume vol;
3358	int error = EINVAL;
3359
3360	DPRINTF(("gus_mixer_get_port: dev=%d type=%d\n", cp->dev, cp->type));
3361
3362	if (!HAS_MIXER(sc) && cp->dev > GUSICS_MASTER_MUTE)
3363		return ENXIO;
3364
3365	switch (cp->dev) {
3366
3367	case GUSICS_MIC_IN_MUTE:	/* Microphone */
3368		if (cp->type == AUDIO_MIXER_ENUM) {
3369			if (HAS_MIXER(sc))
3370				cp->un.ord = ic->sc_mute[GUSMIX_CHAN_MIC][ICSMIX_LEFT];
3371			else
3372				cp->un.ord =
3373				    sc->sc_mixcontrol & GUSMASK_MIC_IN ? 0 : 1;
3374			error = 0;
3375		}
3376		break;
3377
3378	case GUSICS_LINE_IN_MUTE:
3379		if (cp->type == AUDIO_MIXER_ENUM) {
3380			if (HAS_MIXER(sc))
3381				cp->un.ord = ic->sc_mute[GUSMIX_CHAN_LINE][ICSMIX_LEFT];
3382			else
3383				cp->un.ord =
3384				    sc->sc_mixcontrol & GUSMASK_LINE_IN ? 1 : 0;
3385			error = 0;
3386		}
3387		break;
3388
3389	case GUSICS_MASTER_MUTE:
3390		if (cp->type == AUDIO_MIXER_ENUM) {
3391			if (HAS_MIXER(sc))
3392				cp->un.ord = ic->sc_mute[GUSMIX_CHAN_MASTER][ICSMIX_LEFT];
3393			else
3394				cp->un.ord =
3395				    sc->sc_mixcontrol & GUSMASK_LINE_OUT ? 1 : 0;
3396			error = 0;
3397		}
3398		break;
3399
3400	case GUSICS_DAC_MUTE:
3401		if (cp->type == AUDIO_MIXER_ENUM) {
3402			cp->un.ord = ic->sc_mute[GUSMIX_CHAN_DAC][ICSMIX_LEFT];
3403			error = 0;
3404		}
3405		break;
3406
3407	case GUSICS_CD_MUTE:
3408		if (cp->type == AUDIO_MIXER_ENUM) {
3409			cp->un.ord = ic->sc_mute[GUSMIX_CHAN_CD][ICSMIX_LEFT];
3410			error = 0;
3411		}
3412		break;
3413
3414	case GUSICS_MASTER_LVL:
3415		if (cp->type == AUDIO_MIXER_VALUE) {
3416			vol.left = ic->sc_setting[GUSMIX_CHAN_MASTER][ICSMIX_LEFT];
3417			vol.right = ic->sc_setting[GUSMIX_CHAN_MASTER][ICSMIX_RIGHT];
3418			if (gus_from_vol(cp, &vol))
3419				error = 0;
3420		}
3421		break;
3422
3423	case GUSICS_MIC_IN_LVL:	/* Microphone */
3424		if (cp->type == AUDIO_MIXER_VALUE) {
3425			vol.left = ic->sc_setting[GUSMIX_CHAN_MIC][ICSMIX_LEFT];
3426			vol.right = ic->sc_setting[GUSMIX_CHAN_MIC][ICSMIX_RIGHT];
3427			if (gus_from_vol(cp, &vol))
3428				error = 0;
3429		}
3430		break;
3431
3432	case GUSICS_LINE_IN_LVL:	/* line in */
3433		if (cp->type == AUDIO_MIXER_VALUE) {
3434			vol.left = ic->sc_setting[GUSMIX_CHAN_LINE][ICSMIX_LEFT];
3435			vol.right = ic->sc_setting[GUSMIX_CHAN_LINE][ICSMIX_RIGHT];
3436			if (gus_from_vol(cp, &vol))
3437				error = 0;
3438		}
3439		break;
3440
3441
3442	case GUSICS_CD_LVL:
3443		if (cp->type == AUDIO_MIXER_VALUE) {
3444			vol.left = ic->sc_setting[GUSMIX_CHAN_CD][ICSMIX_LEFT];
3445			vol.right = ic->sc_setting[GUSMIX_CHAN_CD][ICSMIX_RIGHT];
3446			if (gus_from_vol(cp, &vol))
3447				error = 0;
3448		}
3449		break;
3450
3451	case GUSICS_DAC_LVL:		/* dac out */
3452		if (cp->type == AUDIO_MIXER_VALUE) {
3453			vol.left = ic->sc_setting[GUSMIX_CHAN_DAC][ICSMIX_LEFT];
3454			vol.right = ic->sc_setting[GUSMIX_CHAN_DAC][ICSMIX_RIGHT];
3455			if (gus_from_vol(cp, &vol))
3456				error = 0;
3457		}
3458		break;
3459
3460
3461	case GUSICS_RECORD_SOURCE:
3462		if (cp->type == AUDIO_MIXER_ENUM) {
3463			/* Can't set anything else useful, sigh. */
3464			 cp->un.ord = 0;
3465		}
3466		break;
3467
3468	default:
3469		return ENXIO;
3470	    /*NOTREACHED*/
3471	}
3472	return error;
3473}
3474
3475STATIC void
3476gusics_master_mute(ic, mute)
3477	struct ics2101_softc *ic;
3478	int mute;
3479{
3480	ics2101_mix_mute(ic, GUSMIX_CHAN_MASTER, ICSMIX_LEFT, mute);
3481	ics2101_mix_mute(ic, GUSMIX_CHAN_MASTER, ICSMIX_RIGHT, mute);
3482}
3483
3484STATIC void
3485gusics_mic_mute(ic, mute)
3486	struct ics2101_softc *ic;
3487	int mute;
3488{
3489	ics2101_mix_mute(ic, GUSMIX_CHAN_MIC, ICSMIX_LEFT, mute);
3490	ics2101_mix_mute(ic, GUSMIX_CHAN_MIC, ICSMIX_RIGHT, mute);
3491}
3492
3493STATIC void
3494gusics_linein_mute(ic, mute)
3495	struct ics2101_softc *ic;
3496	int mute;
3497{
3498	ics2101_mix_mute(ic, GUSMIX_CHAN_LINE, ICSMIX_LEFT, mute);
3499	ics2101_mix_mute(ic, GUSMIX_CHAN_LINE, ICSMIX_RIGHT, mute);
3500}
3501
3502STATIC void
3503gusics_cd_mute(ic, mute)
3504	struct ics2101_softc *ic;
3505	int mute;
3506{
3507	ics2101_mix_mute(ic, GUSMIX_CHAN_CD, ICSMIX_LEFT, mute);
3508	ics2101_mix_mute(ic, GUSMIX_CHAN_CD, ICSMIX_RIGHT, mute);
3509}
3510
3511STATIC void
3512gusics_dac_mute(ic, mute)
3513	struct ics2101_softc *ic;
3514	int mute;
3515{
3516	ics2101_mix_mute(ic, GUSMIX_CHAN_DAC, ICSMIX_LEFT, mute);
3517	ics2101_mix_mute(ic, GUSMIX_CHAN_DAC, ICSMIX_RIGHT, mute);
3518}
3519
3520STATIC int
3521gusmax_mixer_set_port(addr, cp)
3522	void *addr;
3523	mixer_ctrl_t *cp;
3524{
3525	register struct ad1848_softc *ac = addr;
3526	register struct gus_softc *sc = ac->parent;
3527	struct ad1848_volume vol;
3528	int error = EINVAL;
3529
3530	DPRINTF(("gusmax_mixer_set_port: dev=%d type=%d\n", cp->dev, cp->type));
3531
3532	switch (cp->dev) {
3533#if 0
3534	case GUSMAX_MIC_IN_LVL:	/* Microphone */
3535		if (cp->type == AUDIO_MIXER_VALUE &&
3536		    cp->un.value.num_channels == 1) {
3537			/* XXX enable/disable pre-MUX fixed gain */
3538			if (gus_to_vol(cp, &vol))
3539				error = ad1848_set_mic_gain(ac, &vol);
3540		}
3541		break;
3542#endif
3543
3544	case GUSMAX_DAC_LVL:		/* dac out */
3545		if (cp->type == AUDIO_MIXER_VALUE) {
3546			if (gus_to_vol(cp, &vol))
3547				error = ad1848_set_aux1_gain(ac, &vol);
3548		}
3549		break;
3550
3551	case GUSMAX_LINE_IN_LVL:	/* line in */
3552		if (cp->type == AUDIO_MIXER_VALUE) {
3553			if (gus_to_vol(cp, &vol))
3554				error = cs4231_set_linein_gain(ac, &vol);
3555		}
3556		break;
3557
3558	case GUSMAX_MONO_LVL:	/* mic/mono in */
3559		if (cp->type == AUDIO_MIXER_VALUE &&
3560		    cp->un.value.num_channels == 1) {
3561			if (gus_to_vol(cp, &vol))
3562				error = cs4231_set_mono_gain(ac, &vol);
3563		}
3564		break;
3565
3566	case GUSMAX_CD_LVL:	/* CD: AUX2 */
3567		if (cp->type == AUDIO_MIXER_VALUE) {
3568			if (gus_to_vol(cp, &vol))
3569				error = ad1848_set_aux2_gain(ac, &vol);
3570		}
3571		break;
3572
3573	case GUSMAX_MONITOR_LVL:
3574		if (cp->type == AUDIO_MIXER_VALUE &&
3575		    cp->un.value.num_channels == 1) {
3576			vol.left  = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
3577			error = ad1848_set_mon_gain(ac, &vol);
3578		}
3579		break;
3580
3581	case GUSMAX_OUT_LVL:	/* output volume */
3582		if (cp->type == AUDIO_MIXER_VALUE) {
3583			if (gus_to_vol(cp, &vol))
3584				error = ad1848_set_out_gain(ac, &vol);
3585		}
3586		break;
3587
3588	case GUSMAX_SPEAKER_LVL:
3589		if (cp->type == AUDIO_MIXER_VALUE &&
3590		    cp->un.value.num_channels == 1) {
3591			if (gus_to_vol(cp, &vol)) {
3592				gus_speaker_ctl(sc, vol.left > AUDIO_MIN_GAIN ?
3593						SPKR_ON : SPKR_OFF);
3594				error = 0;
3595			}
3596		}
3597		break;
3598
3599	case GUSMAX_LINE_IN_MUTE:
3600		if (cp->type == AUDIO_MIXER_ENUM) {
3601			ac->line_mute = cp->un.ord ? 1 : 0;
3602			DPRINTF(("line mute %d\n", cp->un.ord));
3603			cs4231_mute_line(ac, ac->line_mute);
3604			gus_linein_ctl(sc, ac->line_mute ? SPKR_OFF : SPKR_ON);
3605			error = 0;
3606		}
3607		break;
3608
3609	case GUSMAX_DAC_MUTE:
3610		if (cp->type == AUDIO_MIXER_ENUM) {
3611			ac->aux1_mute = cp->un.ord ? 1 : 0;
3612			DPRINTF(("dac mute %d\n", cp->un.ord));
3613			ad1848_mute_aux1(ac, ac->aux1_mute);
3614			error = 0;
3615		}
3616		break;
3617
3618	case GUSMAX_CD_MUTE:
3619		if (cp->type == AUDIO_MIXER_ENUM) {
3620			ac->aux2_mute = cp->un.ord ? 1 : 0;
3621			DPRINTF(("cd mute %d\n", cp->un.ord));
3622			ad1848_mute_aux2(ac, ac->aux2_mute);
3623			error = 0;
3624		}
3625		break;
3626
3627	case GUSMAX_MONO_MUTE:	/* Microphone */
3628		if (cp->type == AUDIO_MIXER_ENUM) {
3629			ac->mono_mute = cp->un.ord ? 1 : 0;
3630			DPRINTF(("mono mute %d\n", cp->un.ord));
3631			cs4231_mute_mono(ac, ac->mono_mute);
3632			gus_mic_ctl(sc, ac->mono_mute ? SPKR_OFF : SPKR_ON);
3633			error = 0;
3634		}
3635		break;
3636
3637	case GUSMAX_MONITOR_MUTE:
3638		if (cp->type == AUDIO_MIXER_ENUM) {
3639			ac->mon_mute = cp->un.ord ? 1 : 0;
3640			DPRINTF(("mono mute %d\n", cp->un.ord));
3641			cs4231_mute_monitor(ac, ac->mon_mute);
3642			error = 0;
3643		}
3644		break;
3645
3646	case GUSMAX_SPEAKER_MUTE:
3647		if (cp->type == AUDIO_MIXER_ENUM) {
3648			gus_speaker_ctl(sc, cp->un.ord ? SPKR_OFF : SPKR_ON);
3649			error = 0;
3650		}
3651		break;
3652
3653	case GUSMAX_REC_LVL:		/* record level */
3654		if (cp->type == AUDIO_MIXER_VALUE) {
3655			if (gus_to_vol(cp, &vol))
3656				error = ad1848_set_rec_gain(ac, &vol);
3657		}
3658		break;
3659
3660	case GUSMAX_RECORD_SOURCE:
3661		if (cp->type == AUDIO_MIXER_ENUM) {
3662			error = ad1848_set_rec_port(ac, cp->un.ord);
3663		}
3664		break;
3665
3666	default:
3667		return ENXIO;
3668	    /*NOTREACHED*/
3669    }
3670    return error;
3671}
3672
3673STATIC int
3674gus_mixer_set_port(addr, cp)
3675	void *addr;
3676	mixer_ctrl_t *cp;
3677{
3678	register struct gus_softc *sc = addr;
3679	register struct ics2101_softc *ic = &sc->sc_mixer;
3680	struct ad1848_volume vol;
3681	int error = EINVAL;
3682
3683	DPRINTF(("gus_mixer_set_port: dev=%d type=%d\n", cp->dev, cp->type));
3684
3685	if (!HAS_MIXER(sc) && cp->dev > GUSICS_MASTER_MUTE)
3686		return ENXIO;
3687
3688	switch (cp->dev) {
3689
3690	case GUSICS_MIC_IN_MUTE:	/* Microphone */
3691		if (cp->type == AUDIO_MIXER_ENUM) {
3692			DPRINTF(("mic mute %d\n", cp->un.ord));
3693			if (HAS_MIXER(sc)) {
3694				gusics_mic_mute(ic, cp->un.ord);
3695			}
3696			gus_mic_ctl(sc, cp->un.ord ? SPKR_OFF : SPKR_ON);
3697			error = 0;
3698		}
3699		break;
3700
3701	case GUSICS_LINE_IN_MUTE:
3702		if (cp->type == AUDIO_MIXER_ENUM) {
3703			DPRINTF(("linein mute %d\n", cp->un.ord));
3704			if (HAS_MIXER(sc)) {
3705				gusics_linein_mute(ic, cp->un.ord);
3706			}
3707			gus_linein_ctl(sc, cp->un.ord ? SPKR_OFF : SPKR_ON);
3708			error = 0;
3709		}
3710		break;
3711
3712	case GUSICS_MASTER_MUTE:
3713		if (cp->type == AUDIO_MIXER_ENUM) {
3714			DPRINTF(("master mute %d\n", cp->un.ord));
3715			if (HAS_MIXER(sc)) {
3716				gusics_master_mute(ic, cp->un.ord);
3717			}
3718			gus_speaker_ctl(sc, cp->un.ord ? SPKR_OFF : SPKR_ON);
3719			error = 0;
3720		}
3721		break;
3722
3723	case GUSICS_DAC_MUTE:
3724		if (cp->type == AUDIO_MIXER_ENUM) {
3725			gusics_dac_mute(ic, cp->un.ord);
3726			error = 0;
3727		}
3728		break;
3729
3730	case GUSICS_CD_MUTE:
3731		if (cp->type == AUDIO_MIXER_ENUM) {
3732			gusics_cd_mute(ic, cp->un.ord);
3733			error = 0;
3734		}
3735		break;
3736
3737	case GUSICS_MASTER_LVL:
3738		if (cp->type == AUDIO_MIXER_VALUE) {
3739			if (gus_to_vol(cp, &vol)) {
3740				ics2101_mix_attenuate(ic,
3741						      GUSMIX_CHAN_MASTER,
3742						      ICSMIX_LEFT,
3743						      vol.left);
3744				ics2101_mix_attenuate(ic,
3745						      GUSMIX_CHAN_MASTER,
3746						      ICSMIX_RIGHT,
3747						      vol.right);
3748				error = 0;
3749			}
3750		}
3751		break;
3752
3753	case GUSICS_MIC_IN_LVL:	/* Microphone */
3754		if (cp->type == AUDIO_MIXER_VALUE) {
3755			if (gus_to_vol(cp, &vol)) {
3756				ics2101_mix_attenuate(ic,
3757						      GUSMIX_CHAN_MIC,
3758						      ICSMIX_LEFT,
3759						      vol.left);
3760				ics2101_mix_attenuate(ic,
3761						      GUSMIX_CHAN_MIC,
3762						      ICSMIX_RIGHT,
3763						      vol.right);
3764				error = 0;
3765			}
3766		}
3767		break;
3768
3769	case GUSICS_LINE_IN_LVL:	/* line in */
3770		if (cp->type == AUDIO_MIXER_VALUE) {
3771			if (gus_to_vol(cp, &vol)) {
3772				ics2101_mix_attenuate(ic,
3773						      GUSMIX_CHAN_LINE,
3774						      ICSMIX_LEFT,
3775						      vol.left);
3776				ics2101_mix_attenuate(ic,
3777						      GUSMIX_CHAN_LINE,
3778						      ICSMIX_RIGHT,
3779						      vol.right);
3780				error = 0;
3781			}
3782		}
3783		break;
3784
3785
3786	case GUSICS_CD_LVL:
3787		if (cp->type == AUDIO_MIXER_VALUE) {
3788			if (gus_to_vol(cp, &vol)) {
3789				ics2101_mix_attenuate(ic,
3790						      GUSMIX_CHAN_CD,
3791						      ICSMIX_LEFT,
3792						      vol.left);
3793				ics2101_mix_attenuate(ic,
3794						      GUSMIX_CHAN_CD,
3795						      ICSMIX_RIGHT,
3796						      vol.right);
3797				error = 0;
3798			}
3799		}
3800		break;
3801
3802	case GUSICS_DAC_LVL:		/* dac out */
3803		if (cp->type == AUDIO_MIXER_VALUE) {
3804			if (gus_to_vol(cp, &vol)) {
3805				ics2101_mix_attenuate(ic,
3806						      GUSMIX_CHAN_DAC,
3807						      ICSMIX_LEFT,
3808						      vol.left);
3809				ics2101_mix_attenuate(ic,
3810						      GUSMIX_CHAN_DAC,
3811						      ICSMIX_RIGHT,
3812						      vol.right);
3813				error = 0;
3814			}
3815		}
3816		break;
3817
3818
3819	case GUSICS_RECORD_SOURCE:
3820		if (cp->type == AUDIO_MIXER_ENUM && cp->un.ord == 0) {
3821			/* Can't set anything else useful, sigh. */
3822			error = 0;
3823		}
3824		break;
3825
3826	default:
3827		return ENXIO;
3828	    /*NOTREACHED*/
3829	}
3830	return error;
3831}
3832
3833STATIC int
3834gusmax_mixer_query_devinfo(addr, dip)
3835	void *addr;
3836	register mixer_devinfo_t *dip;
3837{
3838	DPRINTF(("gusmax_query_devinfo: index=%d\n", dip->index));
3839
3840	switch(dip->index) {
3841#if 0
3842    case GUSMAX_MIC_IN_LVL:	/* Microphone */
3843	dip->type = AUDIO_MIXER_VALUE;
3844	dip->mixer_class = GUSMAX_INPUT_CLASS;
3845	dip->prev = AUDIO_MIXER_LAST;
3846	dip->next = GUSMAX_MIC_IN_MUTE;
3847	strcpy(dip->label.name, AudioNmicrophone);
3848	dip->un.v.num_channels = 2;
3849	strcpy(dip->un.v.units.name, AudioNvolume);
3850	break;
3851#endif
3852
3853    case GUSMAX_MONO_LVL:	/* mono/microphone mixer */
3854	dip->type = AUDIO_MIXER_VALUE;
3855	dip->mixer_class = GUSMAX_INPUT_CLASS;
3856	dip->prev = AUDIO_MIXER_LAST;
3857	dip->next = GUSMAX_MONO_MUTE;
3858	strcpy(dip->label.name, AudioNmicrophone);
3859	dip->un.v.num_channels = 1;
3860	strcpy(dip->un.v.units.name, AudioNvolume);
3861	break;
3862
3863    case GUSMAX_DAC_LVL:		/*  dacout */
3864	dip->type = AUDIO_MIXER_VALUE;
3865	dip->mixer_class = GUSMAX_INPUT_CLASS;
3866	dip->prev = AUDIO_MIXER_LAST;
3867	dip->next = GUSMAX_DAC_MUTE;
3868	strcpy(dip->label.name, AudioNdac);
3869	dip->un.v.num_channels = 2;
3870	strcpy(dip->un.v.units.name, AudioNvolume);
3871	break;
3872
3873    case GUSMAX_LINE_IN_LVL:	/* line */
3874	dip->type = AUDIO_MIXER_VALUE;
3875	dip->mixer_class = GUSMAX_INPUT_CLASS;
3876	dip->prev = AUDIO_MIXER_LAST;
3877	dip->next = GUSMAX_LINE_IN_MUTE;
3878	strcpy(dip->label.name, AudioNline);
3879	dip->un.v.num_channels = 2;
3880	strcpy(dip->un.v.units.name, AudioNvolume);
3881	break;
3882
3883    case GUSMAX_CD_LVL:		/* cd */
3884	dip->type = AUDIO_MIXER_VALUE;
3885	dip->mixer_class = GUSMAX_INPUT_CLASS;
3886	dip->prev = AUDIO_MIXER_LAST;
3887	dip->next = GUSMAX_CD_MUTE;
3888	strcpy(dip->label.name, AudioNcd);
3889	dip->un.v.num_channels = 2;
3890	strcpy(dip->un.v.units.name, AudioNvolume);
3891	break;
3892
3893
3894    case GUSMAX_MONITOR_LVL:	/* monitor level */
3895	dip->type = AUDIO_MIXER_VALUE;
3896	dip->mixer_class = GUSMAX_MONITOR_CLASS;
3897	dip->next = GUSMAX_MONITOR_MUTE;
3898	dip->prev = AUDIO_MIXER_LAST;
3899	strcpy(dip->label.name, AudioNmonitor);
3900	dip->un.v.num_channels = 1;
3901	strcpy(dip->un.v.units.name, AudioNvolume);
3902	break;
3903
3904    case GUSMAX_OUT_LVL:		/* cs4231 output volume: not useful? */
3905	dip->type = AUDIO_MIXER_VALUE;
3906	dip->mixer_class = GUSMAX_MONITOR_CLASS;
3907	dip->prev = dip->next = AUDIO_MIXER_LAST;
3908	strcpy(dip->label.name, AudioNoutput);
3909	dip->un.v.num_channels = 2;
3910	strcpy(dip->un.v.units.name, AudioNvolume);
3911	break;
3912
3913    case GUSMAX_SPEAKER_LVL:		/* fake speaker volume */
3914	dip->type = AUDIO_MIXER_VALUE;
3915	dip->mixer_class = GUSMAX_MONITOR_CLASS;
3916	dip->prev = AUDIO_MIXER_LAST;
3917	dip->next = GUSMAX_SPEAKER_MUTE;
3918	strcpy(dip->label.name, AudioNspeaker);
3919	dip->un.v.num_channels = 2;
3920	strcpy(dip->un.v.units.name, AudioNvolume);
3921	break;
3922
3923    case GUSMAX_LINE_IN_MUTE:
3924	dip->mixer_class = GUSMAX_INPUT_CLASS;
3925	dip->type = AUDIO_MIXER_ENUM;
3926	dip->prev = GUSMAX_LINE_IN_LVL;
3927	dip->next = AUDIO_MIXER_LAST;
3928	goto mute;
3929
3930    case GUSMAX_DAC_MUTE:
3931	dip->mixer_class = GUSMAX_INPUT_CLASS;
3932	dip->type = AUDIO_MIXER_ENUM;
3933	dip->prev = GUSMAX_DAC_LVL;
3934	dip->next = AUDIO_MIXER_LAST;
3935	goto mute;
3936
3937    case GUSMAX_CD_MUTE:
3938	dip->mixer_class = GUSMAX_INPUT_CLASS;
3939	dip->type = AUDIO_MIXER_ENUM;
3940	dip->prev = GUSMAX_CD_LVL;
3941	dip->next = AUDIO_MIXER_LAST;
3942	goto mute;
3943
3944    case GUSMAX_MONO_MUTE:
3945	dip->mixer_class = GUSMAX_INPUT_CLASS;
3946	dip->type = AUDIO_MIXER_ENUM;
3947	dip->prev = GUSMAX_MONO_LVL;
3948	dip->next = AUDIO_MIXER_LAST;
3949	goto mute;
3950
3951    case GUSMAX_MONITOR_MUTE:
3952	dip->mixer_class = GUSMAX_OUTPUT_CLASS;
3953	dip->type = AUDIO_MIXER_ENUM;
3954	dip->prev = GUSMAX_MONITOR_LVL;
3955	dip->next = AUDIO_MIXER_LAST;
3956	goto mute;
3957
3958    case GUSMAX_SPEAKER_MUTE:
3959	dip->mixer_class = GUSMAX_OUTPUT_CLASS;
3960	dip->type = AUDIO_MIXER_ENUM;
3961	dip->prev = GUSMAX_SPEAKER_LVL;
3962	dip->next = AUDIO_MIXER_LAST;
3963    mute:
3964	strcpy(dip->label.name, AudioNmute);
3965	dip->un.e.num_mem = 2;
3966	strcpy(dip->un.e.member[0].label.name, AudioNoff);
3967	dip->un.e.member[0].ord = 0;
3968	strcpy(dip->un.e.member[1].label.name, AudioNon);
3969	dip->un.e.member[1].ord = 1;
3970	break;
3971
3972    case GUSMAX_REC_LVL:	/* record level */
3973	dip->type = AUDIO_MIXER_VALUE;
3974	dip->mixer_class = GUSMAX_RECORD_CLASS;
3975	dip->prev = AUDIO_MIXER_LAST;
3976	dip->next = GUSMAX_RECORD_SOURCE;
3977	strcpy(dip->label.name, AudioNrecord);
3978	dip->un.v.num_channels = 2;
3979	strcpy(dip->un.v.units.name, AudioNvolume);
3980	break;
3981
3982    case GUSMAX_RECORD_SOURCE:
3983	dip->mixer_class = GUSMAX_RECORD_CLASS;
3984	dip->type = AUDIO_MIXER_ENUM;
3985	dip->prev = GUSMAX_REC_LVL;
3986	dip->next = AUDIO_MIXER_LAST;
3987	strcpy(dip->label.name, AudioNsource);
3988	dip->un.e.num_mem = 4;
3989	strcpy(dip->un.e.member[0].label.name, AudioNoutput);
3990	dip->un.e.member[0].ord = DAC_IN_PORT;
3991	strcpy(dip->un.e.member[1].label.name, AudioNmicrophone);
3992	dip->un.e.member[1].ord = MIC_IN_PORT;
3993	strcpy(dip->un.e.member[2].label.name, AudioNdac);
3994	dip->un.e.member[2].ord = AUX1_IN_PORT;
3995	strcpy(dip->un.e.member[3].label.name, AudioNline);
3996	dip->un.e.member[3].ord = LINE_IN_PORT;
3997	break;
3998
3999    case GUSMAX_INPUT_CLASS:			/* input class descriptor */
4000	dip->type = AUDIO_MIXER_CLASS;
4001	dip->mixer_class = GUSMAX_INPUT_CLASS;
4002	dip->next = dip->prev = AUDIO_MIXER_LAST;
4003	strcpy(dip->label.name, AudioCInputs);
4004	break;
4005
4006    case GUSMAX_OUTPUT_CLASS:			/* output class descriptor */
4007	dip->type = AUDIO_MIXER_CLASS;
4008	dip->mixer_class = GUSMAX_OUTPUT_CLASS;
4009	dip->next = dip->prev = AUDIO_MIXER_LAST;
4010	strcpy(dip->label.name, AudioCOutputs);
4011	break;
4012
4013    case GUSMAX_MONITOR_CLASS:			/* monitor class descriptor */
4014	dip->type = AUDIO_MIXER_CLASS;
4015	dip->mixer_class = GUSMAX_MONITOR_CLASS;
4016	dip->next = dip->prev = AUDIO_MIXER_LAST;
4017	strcpy(dip->label.name, AudioCMonitor);
4018	break;
4019
4020    case GUSMAX_RECORD_CLASS:			/* record source class */
4021	dip->type = AUDIO_MIXER_CLASS;
4022	dip->mixer_class = GUSMAX_RECORD_CLASS;
4023	dip->next = dip->prev = AUDIO_MIXER_LAST;
4024	strcpy(dip->label.name, AudioCRecord);
4025	break;
4026
4027    default:
4028	return ENXIO;
4029	/*NOTREACHED*/
4030    }
4031    DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name));
4032	return 0;
4033}
4034
4035STATIC int
4036gus_mixer_query_devinfo(addr, dip)
4037	void *addr;
4038	register mixer_devinfo_t *dip;
4039{
4040	register struct gus_softc *sc = addr;
4041
4042	DPRINTF(("gusmax_query_devinfo: index=%d\n", dip->index));
4043
4044	if (!HAS_MIXER(sc) && dip->index > GUSICS_MASTER_MUTE)
4045		return ENXIO;
4046
4047	switch(dip->index) {
4048
4049	case GUSICS_MIC_IN_LVL:	/* Microphone */
4050		dip->type = AUDIO_MIXER_VALUE;
4051		dip->mixer_class = GUSICS_INPUT_CLASS;
4052		dip->prev = AUDIO_MIXER_LAST;
4053		dip->next = GUSICS_MIC_IN_MUTE;
4054		strcpy(dip->label.name, AudioNmicrophone);
4055		dip->un.v.num_channels = 2;
4056		strcpy(dip->un.v.units.name, AudioNvolume);
4057		break;
4058
4059	case GUSICS_LINE_IN_LVL:	/* line */
4060		dip->type = AUDIO_MIXER_VALUE;
4061		dip->mixer_class = GUSICS_INPUT_CLASS;
4062		dip->prev = AUDIO_MIXER_LAST;
4063		dip->next = GUSICS_LINE_IN_MUTE;
4064		strcpy(dip->label.name, AudioNline);
4065		dip->un.v.num_channels = 2;
4066		strcpy(dip->un.v.units.name, AudioNvolume);
4067		break;
4068
4069	case GUSICS_CD_LVL:		/* cd */
4070		dip->type = AUDIO_MIXER_VALUE;
4071		dip->mixer_class = GUSICS_INPUT_CLASS;
4072		dip->prev = AUDIO_MIXER_LAST;
4073		dip->next = GUSICS_CD_MUTE;
4074		strcpy(dip->label.name, AudioNcd);
4075		dip->un.v.num_channels = 2;
4076		strcpy(dip->un.v.units.name, AudioNvolume);
4077		break;
4078
4079	case GUSICS_DAC_LVL:		/*  dacout */
4080		dip->type = AUDIO_MIXER_VALUE;
4081		dip->mixer_class = GUSICS_INPUT_CLASS;
4082		dip->prev = AUDIO_MIXER_LAST;
4083		dip->next = GUSICS_DAC_MUTE;
4084		strcpy(dip->label.name, AudioNdac);
4085		dip->un.v.num_channels = 2;
4086		strcpy(dip->un.v.units.name, AudioNvolume);
4087		break;
4088
4089	case GUSICS_MASTER_LVL:		/*  master output */
4090		dip->type = AUDIO_MIXER_VALUE;
4091		dip->mixer_class = GUSICS_OUTPUT_CLASS;
4092		dip->prev = AUDIO_MIXER_LAST;
4093		dip->next = GUSICS_MASTER_MUTE;
4094		strcpy(dip->label.name, AudioNvolume);
4095		dip->un.v.num_channels = 2;
4096		strcpy(dip->un.v.units.name, AudioNvolume);
4097		break;
4098
4099
4100	case GUSICS_LINE_IN_MUTE:
4101		dip->mixer_class = GUSICS_INPUT_CLASS;
4102		dip->type = AUDIO_MIXER_ENUM;
4103		dip->prev = GUSICS_LINE_IN_LVL;
4104		dip->next = AUDIO_MIXER_LAST;
4105		goto mute;
4106
4107	case GUSICS_DAC_MUTE:
4108		dip->mixer_class = GUSICS_INPUT_CLASS;
4109		dip->type = AUDIO_MIXER_ENUM;
4110		dip->prev = GUSICS_DAC_LVL;
4111		dip->next = AUDIO_MIXER_LAST;
4112		goto mute;
4113
4114	case GUSICS_CD_MUTE:
4115		dip->mixer_class = GUSICS_INPUT_CLASS;
4116		dip->type = AUDIO_MIXER_ENUM;
4117		dip->prev = GUSICS_CD_LVL;
4118		dip->next = AUDIO_MIXER_LAST;
4119		goto mute;
4120
4121	case GUSICS_MIC_IN_MUTE:
4122		dip->mixer_class = GUSICS_INPUT_CLASS;
4123		dip->type = AUDIO_MIXER_ENUM;
4124		dip->prev = GUSICS_MIC_IN_LVL;
4125		dip->next = AUDIO_MIXER_LAST;
4126		goto mute;
4127
4128	case GUSICS_MASTER_MUTE:
4129		dip->mixer_class = GUSICS_OUTPUT_CLASS;
4130		dip->type = AUDIO_MIXER_ENUM;
4131		dip->prev = GUSICS_MASTER_LVL;
4132		dip->next = AUDIO_MIXER_LAST;
4133mute:
4134		strcpy(dip->label.name, AudioNmute);
4135		dip->un.e.num_mem = 2;
4136		strcpy(dip->un.e.member[0].label.name, AudioNoff);
4137		dip->un.e.member[0].ord = 0;
4138		strcpy(dip->un.e.member[1].label.name, AudioNon);
4139		dip->un.e.member[1].ord = 1;
4140		break;
4141
4142	case GUSICS_RECORD_SOURCE:
4143		dip->mixer_class = GUSICS_RECORD_CLASS;
4144		dip->type = AUDIO_MIXER_ENUM;
4145		dip->prev = dip->next = AUDIO_MIXER_LAST;
4146		strcpy(dip->label.name, AudioNsource);
4147		dip->un.e.num_mem = 1;
4148		strcpy(dip->un.e.member[0].label.name, AudioNoutput);
4149		dip->un.e.member[0].ord = GUSICS_MASTER_LVL;
4150		break;
4151
4152	case GUSICS_INPUT_CLASS:
4153		dip->type = AUDIO_MIXER_CLASS;
4154		dip->mixer_class = GUSICS_INPUT_CLASS;
4155		dip->next = dip->prev = AUDIO_MIXER_LAST;
4156		strcpy(dip->label.name, AudioCInputs);
4157		break;
4158
4159	case GUSICS_OUTPUT_CLASS:
4160		dip->type = AUDIO_MIXER_CLASS;
4161		dip->mixer_class = GUSICS_OUTPUT_CLASS;
4162		dip->next = dip->prev = AUDIO_MIXER_LAST;
4163		strcpy(dip->label.name, AudioCOutputs);
4164		break;
4165
4166	case GUSICS_RECORD_CLASS:
4167		dip->type = AUDIO_MIXER_CLASS;
4168		dip->mixer_class = GUSICS_RECORD_CLASS;
4169		dip->next = dip->prev = AUDIO_MIXER_LAST;
4170		strcpy(dip->label.name, AudioCRecord);
4171		break;
4172
4173	default:
4174		return ENXIO;
4175	/*NOTREACHED*/
4176	}
4177	DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name));
4178	return 0;
4179}
4180
4181STATIC int
4182gus_query_encoding(addr, fp)
4183	void *addr;
4184	struct audio_encoding *fp;
4185{
4186	switch (fp->index) {
4187	case 0:
4188		strcpy(fp->name, AudioEmulaw);
4189		fp->encoding = AUDIO_ENCODING_ULAW;
4190		fp->precision = 8;
4191		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
4192		break;
4193	case 1:
4194		strcpy(fp->name, AudioElinear);
4195		fp->encoding = AUDIO_ENCODING_SLINEAR;
4196		fp->precision = 8;
4197		fp->flags = 0;
4198		break;
4199	case 2:
4200		strcpy(fp->name, AudioElinear_le);
4201		fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
4202		fp->precision = 16;
4203		fp->flags = 0;
4204		break;
4205	case 3:
4206		strcpy(fp->name, AudioEulinear);
4207		fp->encoding = AUDIO_ENCODING_ULINEAR;
4208		fp->precision = 8;
4209		fp->flags = 0;
4210		break;
4211	case 4:
4212		strcpy(fp->name, AudioEulinear_le);
4213		fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
4214		fp->precision = 16;
4215		fp->flags = 0;
4216		break;
4217	case 5:
4218		strcpy(fp->name, AudioElinear_be);
4219		fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
4220		fp->precision = 16;
4221		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
4222		break;
4223	case 6:
4224		strcpy(fp->name, AudioEulinear_be);
4225		fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
4226		fp->precision = 16;
4227		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
4228		break;
4229	default:
4230		return(EINVAL);
4231		/*NOTREACHED*/
4232	}
4233	return (0);
4234}
4235
4236/*
4237 * Setup the ICS mixer in "transparent" mode: reset everything to a sensible
4238 * level.  Levels as suggested by GUS SDK code.
4239 */
4240
4241STATIC void
4242gus_init_ics2101(sc)
4243	struct gus_softc *sc;
4244{
4245	register int port = sc->sc_iobase;
4246	register struct ics2101_softc *ic = &sc->sc_mixer;
4247	sc->sc_mixer.sc_selio = port+GUS_MIXER_SELECT;
4248	sc->sc_mixer.sc_dataio = port+GUS_MIXER_DATA;
4249	sc->sc_mixer.sc_flags = (sc->sc_revision == 5) ? ICS_FLIP : 0;
4250
4251	ics2101_mix_attenuate(ic,
4252			      GUSMIX_CHAN_MIC,
4253			      ICSMIX_LEFT,
4254			      ICSMIX_MIN_ATTN);
4255	ics2101_mix_attenuate(ic,
4256			      GUSMIX_CHAN_MIC,
4257			      ICSMIX_RIGHT,
4258			      ICSMIX_MIN_ATTN);
4259	/*
4260	 * Start with microphone muted by the mixer...
4261	 */
4262	gusics_mic_mute(ic, 1);
4263
4264	/* ... and enabled by the GUS master mix control */
4265	gus_mic_ctl(sc, SPKR_ON);
4266
4267	ics2101_mix_attenuate(ic,
4268			      GUSMIX_CHAN_LINE,
4269			      ICSMIX_LEFT,
4270			      ICSMIX_MIN_ATTN);
4271	ics2101_mix_attenuate(ic,
4272			      GUSMIX_CHAN_LINE,
4273			      ICSMIX_RIGHT,
4274			      ICSMIX_MIN_ATTN);
4275
4276	ics2101_mix_attenuate(ic,
4277			      GUSMIX_CHAN_CD,
4278			      ICSMIX_LEFT,
4279			      ICSMIX_MIN_ATTN);
4280	ics2101_mix_attenuate(ic,
4281			      GUSMIX_CHAN_CD,
4282			      ICSMIX_RIGHT,
4283			      ICSMIX_MIN_ATTN);
4284
4285	ics2101_mix_attenuate(ic,
4286			      GUSMIX_CHAN_DAC,
4287			      ICSMIX_LEFT,
4288			      ICSMIX_MIN_ATTN);
4289	ics2101_mix_attenuate(ic,
4290			      GUSMIX_CHAN_DAC,
4291			      ICSMIX_RIGHT,
4292			      ICSMIX_MIN_ATTN);
4293
4294	ics2101_mix_attenuate(ic,
4295			      ICSMIX_CHAN_4,
4296			      ICSMIX_LEFT,
4297			      ICSMIX_MAX_ATTN);
4298	ics2101_mix_attenuate(ic,
4299			      ICSMIX_CHAN_4,
4300			      ICSMIX_RIGHT,
4301			      ICSMIX_MAX_ATTN);
4302
4303	ics2101_mix_attenuate(ic,
4304			      GUSMIX_CHAN_MASTER,
4305			      ICSMIX_LEFT,
4306			      ICSMIX_MIN_ATTN);
4307	ics2101_mix_attenuate(ic,
4308			      GUSMIX_CHAN_MASTER,
4309			      ICSMIX_RIGHT,
4310			      ICSMIX_MIN_ATTN);
4311	/* unmute other stuff: */
4312	gusics_cd_mute(ic, 0);
4313	gusics_dac_mute(ic, 0);
4314	gusics_linein_mute(ic, 0);
4315	return;
4316}
4317
4318
4319#endif /* NGUS */
4320