gus.c revision 1.20
1218885Sdim/*	$NetBSD: gus.c,v 1.20 1997/03/19 19:54:44 mycroft Exp $	*/
2218885Sdim
3218885Sdim/*-
4218885Sdim * Copyright (c) 1996 The NetBSD Foundation, Inc.
5218885Sdim * All rights reserved.
6218885Sdim *
7218885Sdim * This code is derived from software contributed to The NetBSD Foundation
8218885Sdim * by Ken Hornstein and John Kohl.
9218885Sdim *
10218885Sdim * Redistribution and use in source and binary forms, with or without
11218885Sdim * modification, are permitted provided that the following conditions
12218885Sdim * are met:
13218885Sdim * 1. Redistributions of source code must retain the above copyright
14218885Sdim *    notice, this list of conditions and the following disclaimer.
15218885Sdim * 2. Redistributions in binary form must reproduce the above copyright
16218885Sdim *    notice, this list of conditions and the following disclaimer in the
17218885Sdim *    documentation and/or other materials provided with the distribution.
18218885Sdim * 3. All advertising materials mentioning features or use of this software
19218885Sdim *    must display the following acknowledgement:
20218885Sdim *        This product includes software developed by the NetBSD
21218885Sdim *	  Foundation, Inc. and its contributors.
22218885Sdim * 4. Neither the name of The NetBSD Foundation nor the names of its
23218885Sdim *    contributors may be used to endorse or promote products derived
24218885Sdim *    from this software without specific prior written permission.
25218885Sdim *
26218885Sdim * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27218885Sdim * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28218885Sdim * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29218885Sdim * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
30218885Sdim * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31218885Sdim * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32218885Sdim * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33218885Sdim * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34219077Sdim * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35219077Sdim * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36219077Sdim * POSSIBILITY OF SUCH DAMAGE.
37219077Sdim */
38219077Sdim
39218885Sdim/*
40218885Sdim *
41218885Sdim * TODO:
42218885Sdim *	. figure out why mixer activity while sound is playing causes problems
43218885Sdim *	  (phantom interrupts?)
44218885Sdim *  	. figure out a better deinterleave strategy that avoids sucking up
45218885Sdim *	  CPU, memory and cache bandwidth.  (Maybe a special encoding?
46239462Sdim *	  Maybe use the double-speed sampling/hardware deinterleave trick
47218885Sdim *	  from the GUS SDK?)  A 486/33 isn't quite fast enough to keep
48218885Sdim *	  up with 44.1kHz 16-bit stereo output without some drop-outs.
49239462Sdim *	. use CS4231 for 16-bit sampling, for a-law and mu-law playback.
50218885Sdim *	. actually test full-duplex sampling(recording) and playback.
51249423Sdim */
52218885Sdim
53249423Sdim/*
54249423Sdim * Gravis UltraSound driver
55249423Sdim *
56249423Sdim * For more detailed information, see the GUS developers' kit
57239462Sdim * available on the net at:
58239462Sdim *
59218885Sdim * ftp://freedom.nmsu.edu/pub/ultrasound/gravis/util/
60218885Sdim * 	gusdkXXX.zip (developers' kit--get rev 2.22 or later)
61218885Sdim *		See ultrawrd.doc inside--it's MS Word (ick), but it's the bible
62218885Sdim *
63218885Sdim */
64218885Sdim
65218885Sdim/*
66218885Sdim * The GUS Max has a slightly strange set of connections between the CS4231
67249423Sdim * and the GF1 and the DMA interconnects.  It's set up so that the CS4231 can
68249423Sdim * be playing while the GF1 is loading patches from the system.
69249423Sdim *
70249423Sdim * Here's a recreation of the DMA interconnect diagram:
71249423Sdim *
72249423Sdim *       GF1
73249423Sdim *   +---------+				 digital
74249423Sdim *   |         |  record			 ASIC
75249423Sdim *   |         |--------------+
76249423Sdim *   |         |              |		       +--------+
77249423Sdim *   |         | play (dram)  |      +----+    |	|
78249423Sdim *   |         |--------------(------|-\  |    |   +-+  |
79249423Sdim *   +---------+              |      |  >-|----|---|C|--|------  dma chan 1
80249423Sdim *                            |  +---|-/  |    |   +-+ 	|
81249423Sdim *                            |  |   +----+    |    |   |
82249423Sdim *                            |	 |   +----+    |    |   |
83249423Sdim *   +---------+        +-+   +--(---|-\  |    |    |   |
84263508Sdim *   |         | play   |8|      |   |  >-|----|----+---|------  dma chan 2
85249423Sdim *   | ---C----|--------|/|------(---|-/  |    |        |
86249423Sdim *   |    ^    |record  |1|      |   +----+    |	|
87249423Sdim *   |    |    |   /----|6|------+   	       +--------+
88249423Sdim *   | ---+----|--/     +-+
89249423Sdim *   +---------+
90249423Sdim *     CS4231   	8-to-16 bit bus conversion, if needed
91249423Sdim *
92249423Sdim *
93249423Sdim * "C" is an optional combiner.
94249423Sdim *
95249423Sdim */
96249423Sdim
97249423Sdim#include "gus.h"
98249423Sdim#if NGUS > 0
99249423Sdim
100249423Sdim#include <sys/param.h>
101249423Sdim#include <sys/systm.h>
102249423Sdim#include <sys/errno.h>
103249423Sdim#include <sys/ioctl.h>
104249423Sdim#include <sys/syslog.h>
105249423Sdim#include <sys/device.h>
106249423Sdim#include <sys/proc.h>
107249423Sdim#include <sys/buf.h>
108249423Sdim#include <sys/fcntl.h>
109249423Sdim#include <sys/malloc.h>
110249423Sdim#include <sys/kernel.h>
111249423Sdim
112249423Sdim#include <machine/cpu.h>
113249423Sdim#include <machine/intr.h>
114263508Sdim#include <machine/pio.h>
115249423Sdim#include <machine/cpufunc.h>
116249423Sdim#include <sys/audioio.h>
117249423Sdim#include <dev/audio_if.h>
118249423Sdim#include <dev/mulaw.h>
119249423Sdim
120249423Sdim#include <dev/isa/isavar.h>
121249423Sdim#include <dev/isa/isadmavar.h>
122249423Sdim#include <i386/isa/icu.h>
123249423Sdim
124249423Sdim#include <dev/ic/ics2101reg.h>
125249423Sdim#include <dev/ic/cs4231reg.h>
126249423Sdim#include <dev/ic/ad1848reg.h>
127249423Sdim#include <dev/isa/ics2101var.h>
128249423Sdim#include <dev/isa/ad1848var.h>
129249423Sdim#include <dev/isa/cs4231var.h>
130249423Sdim#include "gusreg.h"
131249423Sdim
132218885Sdim#ifdef AUDIO_DEBUG
133218885Sdim#define STATIC /* empty; for debugging symbols */
134243830Sdim#else
135218885Sdim#define STATIC static
136218885Sdim#endif
137218885Sdim
138249423Sdim/*
139218885Sdim * Software state of a single "voice" on the GUS
140218885Sdim */
141218885Sdim
142218885Sdimstruct gus_voice {
143249423Sdim
144218885Sdim	/*
145218885Sdim	 * Various control bits
146218885Sdim	 */
147218885Sdim
148218885Sdim	unsigned char voccntl;	/* State of voice control register */
149218885Sdim	unsigned char volcntl;	/* State of volume control register */
150218885Sdim	unsigned char pan_pos;	/* Position of volume panning (4 bits) */
151218885Sdim	int rate;		/* Sample rate of voice being played back */
152221345Sdim
153218885Sdim	/*
154218885Sdim	 * Address of the voice data into the GUS's DRAM.  20 bits each
155218885Sdim	 */
156218885Sdim
157218885Sdim	u_long start_addr;	/* Starting address of voice data loop area */
158218885Sdim	u_long end_addr;	/* Ending address of voice data loop */
159218885Sdim	u_long current_addr;	/* Beginning address of voice data
160218885Sdim				   (start playing here) */
161218885Sdim
162221345Sdim	/*
163218885Sdim	 * linear volume values for the GUS's volume ramp.  0-511 (9 bits).
164218885Sdim	 * These values must be translated into the logarithmic values using
165218885Sdim	 * gus_log_volumes[]
166218885Sdim	 */
167218885Sdim
168218885Sdim	int start_volume;	/* Starting position of volume ramp */
169218885Sdim	int current_volume;	/* Current position of volume on volume ramp */
170218885Sdim	int end_volume;		/* Ending position of volume on volume ramp */
171218885Sdim};
172218885Sdim
173218885Sdim/*
174218885Sdim * Software state of GUS
175218885Sdim */
176218885Sdim
177218885Sdimstruct gus_softc {
178218885Sdim	struct device sc_dev;		/* base device */
179218885Sdim	struct isadev sc_id;		/* ISA device */
180249423Sdim	void *sc_ih;			/* interrupt vector */
181218885Sdim
182249423Sdim	int sc_iobase;			/* I/O base address */
183249423Sdim	int sc_irq;			/* IRQ used */
184249423Sdim	int sc_drq;			/* DMA channel for play */
185249423Sdim	int sc_recdrq;			/* DMA channel for recording */
186249423Sdim
187249423Sdim	int sc_flags;			/* Various flags about the GUS */
188249423Sdim#define GUS_MIXER_INSTALLED	0x01	/* An ICS mixer is installed */
189249423Sdim#define GUS_LOCKED		0x02	/* GUS is busy doing multi-phase DMA */
190249423Sdim#define GUS_CODEC_INSTALLED	0x04	/* CS4231 installed/MAX */
191249423Sdim#define GUS_PLAYING		0x08	/* GUS is playing a voice */
192249423Sdim#define GUS_DMAOUT_ACTIVE	0x10	/* GUS is busy doing audio DMA */
193249423Sdim#define GUS_DMAIN_ACTIVE	0x20	/* GUS is busy sampling  */
194249423Sdim#define GUS_OPEN		0x100	/* GUS is open */
195249423Sdim	int sc_dsize;			/* Size of GUS DRAM */
196249423Sdim	int sc_voices;			/* Number of active voices */
197249423Sdim	u_char sc_revision;		/* Board revision of GUS */
198249423Sdim	u_char sc_mixcontrol;		/* Value of GUS_MIX_CONTROL register */
199249423Sdim
200249423Sdim	u_long sc_orate;		/* Output sampling rate */
201249423Sdim	u_long sc_irate;		/* Input sampling rate */
202249423Sdim
203249423Sdim	int sc_encoding;		/* Current data encoding type */
204249423Sdim	int sc_precision;		/* # of bits of precision */
205249423Sdim	int sc_channels;		/* Number of active channels */
206249423Sdim	int sc_blocksize;		/* Current blocksize */
207249423Sdim	int sc_chanblocksize;		/* Current blocksize for each in-use
208218885Sdim					   channel */
209218885Sdim	short sc_nbufs;			/* how many on-GUS bufs per-channel */
210218885Sdim	short sc_bufcnt;		/* how many need to be played */
211218885Sdim	void *sc_deintr_buf;		/* deinterleave buffer for stereo */
212218885Sdim
213218885Sdim	int sc_ogain;			/* Output gain control */
214218885Sdim	u_char sc_out_port;		/* Current out port (generic only) */
215218885Sdim	u_char sc_in_port;		/* keep track of it when no codec */
216218885Sdim
217218885Sdim	void (*sc_dmaoutintr) __P((void*)); /* DMA completion intr handler */
218218885Sdim	void *sc_outarg;		/* argument for sc_dmaoutintr() */
219218885Sdim	u_char *sc_dmaoutaddr;		/* for isa_dmadone */
220218885Sdim	u_long sc_gusaddr;		/* where did we just put it? */
221249423Sdim	int sc_dmaoutcnt;		/* for isa_dmadone */
222218885Sdim
223218885Sdim	void (*sc_dmainintr) __P((void*)); /* DMA completion intr handler */
224218885Sdim	void *sc_inarg;			/* argument for sc_dmaoutintr() */
225218885Sdim	u_char *sc_dmainaddr;		/* for isa_dmadone */
226218885Sdim	int sc_dmaincnt;		/* for isa_dmadone */
227223017Sdim
228218885Sdim	struct stereo_dma_intr {
229218885Sdim		void (*intr)__P((void *));
230218885Sdim		void *arg;
231243830Sdim		u_char *buffer;
232243830Sdim		u_long dmabuf;
233218885Sdim		int size;
234221345Sdim		int flags;
235218885Sdim	} sc_stereo;
236221345Sdim
237218885Sdim	/*
238218885Sdim	 * State information for linear audio layer
239218885Sdim	 */
240221345Sdim
241218885Sdim	int sc_dmabuf;			/* Which ring buffer we're DMA'ing to */
242218885Sdim	int sc_playbuf;			/* Which ring buffer we're playing */
243218885Sdim
244221345Sdim	/*
245218885Sdim	 * Voice information array.  All voice-specific information is stored
246218885Sdim	 * here
247218885Sdim	 */
248221345Sdim
249218885Sdim	struct gus_voice sc_voc[32];	/* Voice data for each voice */
250218885Sdim	union {
251221345Sdim		struct ics2101_softc sc_mixer_u;
252218885Sdim		struct ad1848_softc sc_codec_u;
253243830Sdim	} u;
254218885Sdim#define sc_mixer u.sc_mixer_u
255218885Sdim#define sc_codec u.sc_codec_u
256221345Sdim};
257218885Sdim
258221345Sdimstruct ics2101_volume {
259218885Sdim	u_char left;
260218885Sdim	u_char right;
261218885Sdim};
262223017Sdim
263223017Sdim#define HAS_CODEC(sc) ((sc)->sc_flags & GUS_CODEC_INSTALLED)
264243830Sdim#define HAS_MIXER(sc) ((sc)->sc_flags & GUS_MIXER_INSTALLED)
265243830Sdim
266223017Sdim/*
267243830Sdim * Mixer devices for ICS2101
268243830Sdim */
269223017Sdim/* MIC IN mute, line in mute, line out mute are first since they can be done
270223017Sdim   even if no ICS mixer. */
271249423Sdim#define GUSICS_MIC_IN_MUTE		0
272249423Sdim#define GUSICS_LINE_IN_MUTE		1
273249423Sdim#define GUSICS_MASTER_MUTE		2
274249423Sdim#define GUSICS_CD_MUTE			3
275249423Sdim#define GUSICS_DAC_MUTE			4
276221345Sdim#define GUSICS_MIC_IN_LVL		5
277263508Sdim#define GUSICS_LINE_IN_LVL		6
278263508Sdim#define GUSICS_CD_LVL			7
279263508Sdim#define GUSICS_DAC_LVL			8
280263508Sdim#define GUSICS_MASTER_LVL		9
281263508Sdim
282249423Sdim#define GUSICS_RECORD_SOURCE		10
283249423Sdim
284249423Sdim/* Classes */
285249423Sdim#define GUSICS_INPUT_CLASS		11
286249423Sdim#define GUSICS_OUTPUT_CLASS		12
287249423Sdim#define GUSICS_RECORD_CLASS		13
288249423Sdim
289249423Sdim/*
290249423Sdim * Mixer & MUX devices for CS4231
291249423Sdim */
292249423Sdim#define GUSMAX_MIX_IN			0 /* input to MUX from mixer output */
293249423Sdim#define GUSMAX_MONO_LVL			1 /* mic input to MUX;
294249423Sdim					     also mono mixer input */
295249423Sdim#define GUSMAX_DAC_LVL			2 /* input to MUX; also mixer input */
296249423Sdim#define GUSMAX_LINE_IN_LVL		3 /* input to MUX; also mixer input */
297249423Sdim#define GUSMAX_CD_LVL			4 /* mixer input only */
298249423Sdim#define GUSMAX_MONITOR_LVL		5 /* digital mix (?) */
299249423Sdim#define GUSMAX_OUT_LVL			6 /* output level. (?) */
300249423Sdim#define GUSMAX_SPEAKER_LVL		7 /* pseudo-device for mute */
301249423Sdim#define GUSMAX_LINE_IN_MUTE		8 /* pre-mixer */
302249423Sdim#define GUSMAX_DAC_MUTE			9 /* pre-mixer */
303249423Sdim#define GUSMAX_CD_MUTE			10 /* pre-mixer */
304249423Sdim#define GUSMAX_MONO_MUTE		11 /* pre-mixer--microphone/mono */
305249423Sdim#define GUSMAX_MONITOR_MUTE		12 /* post-mixer level/mute */
306249423Sdim#define GUSMAX_SPEAKER_MUTE		13 /* speaker mute */
307249423Sdim
308249423Sdim#define GUSMAX_REC_LVL			14 /* post-MUX gain */
309249423Sdim
310249423Sdim#define GUSMAX_RECORD_SOURCE		15
311249423Sdim
312249423Sdim/* Classes */
313249423Sdim#define GUSMAX_INPUT_CLASS		16
314249423Sdim#define GUSMAX_RECORD_CLASS		17
315243830Sdim#define GUSMAX_MONITOR_CLASS		18
316243830Sdim#define GUSMAX_OUTPUT_CLASS		19
317263508Sdim
318249423Sdim#ifdef AUDIO_DEBUG
319249423Sdim#define GUSPLAYDEBUG	/*XXX*/
320249423Sdimextern void Dprintf __P((const char *, ...));
321249423Sdim#define DPRINTF(x)	if (gusdebug) Dprintf x
322249423Sdim#define DMAPRINTF(x)	if (gusdmadebug) Dprintf x
323249423Sdimint	gusdebug = 0;
324224145Sdimint	gusdmadebug = 0;
325224145Sdim#else
326249423Sdim#define DPRINTF(x)
327249423Sdim#define DMAPRINTF(x)
328249423Sdim#endif
329218885Sdimint	gus_dostereo = 1;
330249423Sdim
331249423Sdim#define NDMARECS 2048
332249423Sdim#ifdef GUSPLAYDEBUG
333249423Sdimint	gusstats = 0;
334249423Sdimstruct dma_record {
335249423Sdim    struct timeval tv;
336249423Sdim    u_long gusaddr;
337249423Sdim    caddr_t bsdaddr;
338249423Sdim    u_short count;
339249423Sdim    u_char channel;
340249423Sdim    u_char direction;
341249423Sdim} dmarecords[NDMARECS];
342263508Sdim
343249423Sdimint dmarecord_index = 0;
344249423Sdim#endif
345249423Sdim
346249423Sdim/*
347249423Sdim * local routines
348249423Sdim */
349249423Sdim
350249423Sdimint	gusopen __P((dev_t, int));
351249423Sdimvoid	gusclose __P((void *));
352249423Sdimvoid	gusmax_close __P((void *));
353249423Sdimint	gusintr __P((void *));
354249423Sdimint	gus_set_in_gain __P((caddr_t, u_int, u_char));
355249423Sdimint	gus_get_in_gain __P((caddr_t));
356249423Sdimint	gus_set_out_gain __P((caddr_t, u_int, u_char));
357249423Sdimint	gus_get_out_gain __P((caddr_t));
358249423Sdimint 	gus_set_in_sr __P((void *, u_long));
359249423Sdimu_long 	gus_get_in_sr __P((void *));
360249423Sdimint 	gusmax_set_in_sr __P((void *, u_long));
361249423Sdimu_long 	gusmax_get_in_sr __P((void *));
362249423Sdimint 	gus_set_out_sr __P((void *, u_long));
363249423Sdimu_long 	gus_get_out_sr __P((void *));
364249423Sdimint 	gusmax_set_out_sr __P((void *, u_long));
365249423Sdimu_long 	gusmax_get_out_sr __P((void *));
366249423Sdimint	gus_set_encoding __P((void *, u_int));
367249423Sdimint	gus_get_encoding __P((void *));
368249423Sdimint	gusmax_set_encoding __P((void *, u_int));
369249423Sdimint	gusmax_get_encoding __P((void *));
370249423Sdimint	gus_set_precision __P((void *, u_int));
371249423Sdimint	gus_get_precision __P((void *));
372249423Sdimint	gusmax_set_precision __P((void *, u_int));
373249423Sdimint	gusmax_get_precision __P((void *));
374249423Sdimint	gus_set_channels __P((void *, int));
375249423Sdimint	gus_get_channels __P((void *));
376249423Sdimint	gusmax_set_channels __P((void *, int));
377249423Sdimint	gusmax_get_channels __P((void *));
378249423Sdimint	gus_round_blocksize __P((void *, int));
379249423Sdimint	gus_set_out_port __P((void *, int));
380249423Sdimint	gus_get_out_port __P((void *));
381249423Sdimint	gus_set_in_port __P((void *, int));
382249423Sdimint	gus_get_in_port __P((void *));
383249423Sdimint	gus_commit_settings __P((void *));
384249423Sdimint	gus_dma_output __P((void *, void *, int, void (*)(void *), void *));
385249423Sdimint	gus_dma_input __P((void *, void *, int, void (*)(void *), void *));
386249423Sdimint	gus_halt_out_dma __P((void *));
387249423Sdimint	gus_halt_in_dma __P((void *));
388249423Sdimint	gus_cont_out_dma __P((void *));
389249423Sdimint	gus_cont_in_dma __P((void *));
390249423Sdimint	gus_speaker_ctl __P((void *, int));
391249423Sdimint	gusmax_set_precision __P((void *, u_int));
392249423Sdimint	gusmax_get_precision __P((void *));
393249423Sdimint	gusmax_round_blocksize __P((void *, int));
394249423Sdimint	gusmax_commit_settings __P((void *));
395249423Sdimint	gusmax_dma_output __P((void *, void *, int, void (*)(void *), void *));
396249423Sdimint	gusmax_dma_input __P((void *, void *, int, void (*)(void *), void *));
397249423Sdimint	gusmax_halt_out_dma __P((void *));
398249423Sdimint	gusmax_halt_in_dma __P((void *));
399249423Sdimint	gusmax_cont_out_dma __P((void *));
400249423Sdimint	gusmax_cont_in_dma __P((void *));
401249423Sdimint	gusmax_speaker_ctl __P((void *, int));
402249423Sdimint	gusmax_set_out_port __P((void *, int));
403249423Sdimint	gusmax_get_out_port __P((void *));
404249423Sdimint	gusmax_set_in_port __P((void *, int));
405249423Sdimint	gusmax_get_in_port __P((void *));
406249423Sdimint	gus_getdev __P((void *, struct audio_device *));
407249423Sdim
408249423SdimSTATIC void	gus_deinterleave __P((struct gus_softc *, void *, int));
409249423SdimSTATIC void	gus_expand __P((void *, int, u_char *, int));
410249423SdimSTATIC void	gusmax_expand __P((void *, int, u_char *, int));
411249423Sdim
412249423SdimSTATIC int	gus_mic_ctl __P((void *, int));
413249423SdimSTATIC int	gus_linein_ctl __P((void *, int));
414249423SdimSTATIC int	gus_test_iobase __P((int));
415249423SdimSTATIC void	guspoke __P((int, long, u_char));
416249423SdimSTATIC void	gusdmaout __P((struct gus_softc *, int, u_long, caddr_t, int));
417249423SdimSTATIC void	gus_init_cs4231 __P((struct gus_softc *));
418249423SdimSTATIC void	gus_init_ics2101 __P((struct gus_softc *));
419249423Sdim
420249423SdimSTATIC void	gus_set_chan_addrs __P((struct gus_softc *));
421249423SdimSTATIC void	gusreset __P((struct gus_softc *, int));
422249423SdimSTATIC void	gus_set_voices __P((struct gus_softc *, int));
423249423SdimSTATIC void	gus_set_volume __P((struct gus_softc *, int, int));
424249423SdimSTATIC void	gus_set_samprate __P((struct gus_softc *, int, int));
425249423SdimSTATIC void	gus_set_recrate __P((struct gus_softc *, u_long));
426249423SdimSTATIC void	gus_start_voice __P((struct gus_softc *, int, int));
427249423SdimSTATIC void	gus_stop_voice __P((struct gus_softc *, int, int));
428249423SdimSTATIC void	gus_set_endaddr __P((struct gus_softc *, int, u_long));
429249423Sdim#ifdef GUSPLAYDEBUG
430249423SdimSTATIC void	gus_set_curaddr __P((struct gus_softc *, int, u_long));
431249423SdimSTATIC u_long	gus_get_curaddr __P((struct gus_softc *, int));
432249423Sdim#endif
433249423SdimSTATIC int	gus_dmaout_intr __P((struct gus_softc *));
434249423SdimSTATIC void	gus_dmaout_dointr __P((struct gus_softc *));
435249423SdimSTATIC void	gus_dmaout_timeout __P((void *));
436249423SdimSTATIC int	gus_dmain_intr __P((struct gus_softc *));
437249423SdimSTATIC int	gus_voice_intr __P((struct gus_softc *));
438249423SdimSTATIC void	gus_start_playing __P((struct gus_softc *, int));
439249423SdimSTATIC int	gus_continue_playing __P((struct gus_softc *, int));
440249423SdimSTATIC u_char guspeek __P((int, u_long));
441249423SdimSTATIC u_long convert_to_16bit __P((u_long));
442249423SdimSTATIC int	gus_setfd __P((void *, int));
443249423SdimSTATIC int	gus_mixer_set_port __P((void *, mixer_ctrl_t *));
444249423SdimSTATIC int	gus_mixer_get_port __P((void *, mixer_ctrl_t *));
445249423SdimSTATIC int	gusmax_mixer_set_port __P((void *, mixer_ctrl_t *));
446249423SdimSTATIC int	gusmax_mixer_get_port __P((void *, mixer_ctrl_t *));
447249423SdimSTATIC int	gus_mixer_query_devinfo __P((void *, mixer_devinfo_t *));
448249423SdimSTATIC int	gusmax_mixer_query_devinfo __P((void *, mixer_devinfo_t *));
449249423SdimSTATIC int	gus_query_encoding __P((void *, struct audio_encoding *));
450249423Sdim
451249423SdimSTATIC void	gusics_master_mute __P((struct ics2101_softc *, int));
452249423SdimSTATIC void	gusics_dac_mute __P((struct ics2101_softc *, int));
453249423SdimSTATIC void	gusics_mic_mute __P((struct ics2101_softc *, int));
454249423SdimSTATIC void	gusics_linein_mute __P((struct ics2101_softc *, int));
455249423SdimSTATIC void	gusics_cd_mute __P((struct ics2101_softc *, int));
456249423Sdim
457249423SdimSTATIC __inline int gus_to_vol __P((mixer_ctrl_t *, struct ad1848_volume *));
458249423SdimSTATIC __inline int gus_from_vol __P((mixer_ctrl_t *, struct ad1848_volume *));
459249423Sdim
460249423Sdimvoid	stereo_dmaintr __P((void *));
461249423Sdim
462249423Sdim/*
463249423Sdim * ISA bus driver routines
464249423Sdim */
465249423Sdim
466249423Sdimint	gusprobe __P((struct device *, void *, void *));
467249423Sdimvoid	gusattach __P((struct device *, struct device *, void *));
468249423Sdim
469249423Sdimstruct cfattach gus_ca = {
470249423Sdim	sizeof(struct gus_softc), gusprobe, gusattach,
471249423Sdim};
472249423Sdim
473249423Sdimstruct cfdriver gus_cd = {
474249423Sdim	NULL, "gus", DV_DULL
475249423Sdim};
476249423Sdim
477249423Sdim
478249423Sdim/*
479249423Sdim * A mapping from IRQ/DRQ values to the values used in the GUS's internal
480249423Sdim * registers.  A zero means that the referenced IRQ/DRQ is invalid
481249423Sdim */
482249423Sdim
483249423Sdimstatic int gus_irq_map[] = {
484249423Sdim	IRQUNK, IRQUNK, 1, 3, IRQUNK, 2, IRQUNK, 4, IRQUNK, 1, IRQUNK, 5, 6,
485249423Sdim	IRQUNK, IRQUNK, 7
486249423Sdim};
487249423Sdimstatic int gus_drq_map[] = {
488249423Sdim	DRQUNK, 1, DRQUNK, 2, DRQUNK, 3, 4, 5
489249423Sdim};
490249423Sdim
491249423Sdim/*
492249423Sdim * A list of valid base addresses for the GUS
493249423Sdim */
494249423Sdim
495249423Sdimstatic int gus_base_addrs[] = {
496249423Sdim	0x210, 0x220, 0x230, 0x240, 0x250, 0x260
497249423Sdim};
498249423Sdimstatic int gus_addrs = sizeof(gus_base_addrs) / sizeof(gus_base_addrs[0]);
499249423Sdim
500249423Sdim/*
501249423Sdim * Maximum frequency values of the GUS based on the number of currently active
502249423Sdim * voices.  Since the GUS samples a voice every 1.6 us, the maximum frequency
503249423Sdim * is dependent on the number of active voices.  Yes, it is pretty weird.
504249423Sdim */
505249423Sdim
506249423Sdimstatic int gus_max_frequency[] = {
507263508Sdim		44100,		/* 14 voices */
508249423Sdim		41160,		/* 15 voices */
509249423Sdim		38587,		/* 16 voices */
510249423Sdim		36317,		/* 17 voices */
511249423Sdim		34300,		/* 18 voices */
512249423Sdim		32494,		/* 19 voices */
513249423Sdim		30870,		/* 20 voices */
514249423Sdim		29400,		/* 21 voices */
515249423Sdim		28063,		/* 22 voices */
516249423Sdim		26843,		/* 23 voices */
517249423Sdim		25725,		/* 24 voices */
518249423Sdim		24696,		/* 25 voices */
519249423Sdim		23746,		/* 26 voices */
520249423Sdim		22866,		/* 27 voices */
521249423Sdim		22050,		/* 28 voices */
522249423Sdim		21289,		/* 29 voices */
523249423Sdim		20580,		/* 30 voices */
524249423Sdim		19916,		/* 31 voices */
525249423Sdim		19293		/* 32 voices */
526249423Sdim};
527249423Sdim/*
528249423Sdim * A mapping of linear volume levels to the logarithmic volume values used
529249423Sdim * by the GF1 chip on the GUS.  From GUS SDK vol1.c.
530249423Sdim */
531249423Sdim
532249423Sdimstatic unsigned short gus_log_volumes[512] = {
533249423Sdim 0x0000,
534249423Sdim 0x0700, 0x07ff, 0x0880, 0x08ff, 0x0940, 0x0980, 0x09c0, 0x09ff, 0x0a20,
535249423Sdim 0x0a40, 0x0a60, 0x0a80, 0x0aa0, 0x0ac0, 0x0ae0, 0x0aff, 0x0b10, 0x0b20,
536249423Sdim 0x0b30, 0x0b40, 0x0b50, 0x0b60, 0x0b70, 0x0b80, 0x0b90, 0x0ba0, 0x0bb0,
537249423Sdim 0x0bc0, 0x0bd0, 0x0be0, 0x0bf0, 0x0bff, 0x0c08, 0x0c10, 0x0c18, 0x0c20,
538249423Sdim 0x0c28, 0x0c30, 0x0c38, 0x0c40, 0x0c48, 0x0c50, 0x0c58, 0x0c60, 0x0c68,
539249423Sdim 0x0c70, 0x0c78, 0x0c80, 0x0c88, 0x0c90, 0x0c98, 0x0ca0, 0x0ca8, 0x0cb0,
540249423Sdim 0x0cb8, 0x0cc0, 0x0cc8, 0x0cd0, 0x0cd8, 0x0ce0, 0x0ce8, 0x0cf0, 0x0cf8,
541249423Sdim 0x0cff, 0x0d04, 0x0d08, 0x0d0c, 0x0d10, 0x0d14, 0x0d18, 0x0d1c, 0x0d20,
542249423Sdim 0x0d24, 0x0d28, 0x0d2c, 0x0d30, 0x0d34, 0x0d38, 0x0d3c, 0x0d40, 0x0d44,
543249423Sdim 0x0d48, 0x0d4c, 0x0d50, 0x0d54, 0x0d58, 0x0d5c, 0x0d60, 0x0d64, 0x0d68,
544249423Sdim 0x0d6c, 0x0d70, 0x0d74, 0x0d78, 0x0d7c, 0x0d80, 0x0d84, 0x0d88, 0x0d8c,
545249423Sdim 0x0d90, 0x0d94, 0x0d98, 0x0d9c, 0x0da0, 0x0da4, 0x0da8, 0x0dac, 0x0db0,
546249423Sdim 0x0db4, 0x0db8, 0x0dbc, 0x0dc0, 0x0dc4, 0x0dc8, 0x0dcc, 0x0dd0, 0x0dd4,
547249423Sdim 0x0dd8, 0x0ddc, 0x0de0, 0x0de4, 0x0de8, 0x0dec, 0x0df0, 0x0df4, 0x0df8,
548249423Sdim 0x0dfc, 0x0dff, 0x0e02, 0x0e04, 0x0e06, 0x0e08, 0x0e0a, 0x0e0c, 0x0e0e,
549249423Sdim 0x0e10, 0x0e12, 0x0e14, 0x0e16, 0x0e18, 0x0e1a, 0x0e1c, 0x0e1e, 0x0e20,
550249423Sdim 0x0e22, 0x0e24, 0x0e26, 0x0e28, 0x0e2a, 0x0e2c, 0x0e2e, 0x0e30, 0x0e32,
551249423Sdim 0x0e34, 0x0e36, 0x0e38, 0x0e3a, 0x0e3c, 0x0e3e, 0x0e40, 0x0e42, 0x0e44,
552249423Sdim 0x0e46, 0x0e48, 0x0e4a, 0x0e4c, 0x0e4e, 0x0e50, 0x0e52, 0x0e54, 0x0e56,
553249423Sdim 0x0e58, 0x0e5a, 0x0e5c, 0x0e5e, 0x0e60, 0x0e62, 0x0e64, 0x0e66, 0x0e68,
554249423Sdim 0x0e6a, 0x0e6c, 0x0e6e, 0x0e70, 0x0e72, 0x0e74, 0x0e76, 0x0e78, 0x0e7a,
555249423Sdim 0x0e7c, 0x0e7e, 0x0e80, 0x0e82, 0x0e84, 0x0e86, 0x0e88, 0x0e8a, 0x0e8c,
556249423Sdim 0x0e8e, 0x0e90, 0x0e92, 0x0e94, 0x0e96, 0x0e98, 0x0e9a, 0x0e9c, 0x0e9e,
557249423Sdim 0x0ea0, 0x0ea2, 0x0ea4, 0x0ea6, 0x0ea8, 0x0eaa, 0x0eac, 0x0eae, 0x0eb0,
558249423Sdim 0x0eb2, 0x0eb4, 0x0eb6, 0x0eb8, 0x0eba, 0x0ebc, 0x0ebe, 0x0ec0, 0x0ec2,
559249423Sdim 0x0ec4, 0x0ec6, 0x0ec8, 0x0eca, 0x0ecc, 0x0ece, 0x0ed0, 0x0ed2, 0x0ed4,
560249423Sdim 0x0ed6, 0x0ed8, 0x0eda, 0x0edc, 0x0ede, 0x0ee0, 0x0ee2, 0x0ee4, 0x0ee6,
561249423Sdim 0x0ee8, 0x0eea, 0x0eec, 0x0eee, 0x0ef0, 0x0ef2, 0x0ef4, 0x0ef6, 0x0ef8,
562249423Sdim 0x0efa, 0x0efc, 0x0efe, 0x0eff, 0x0f01, 0x0f02, 0x0f03, 0x0f04, 0x0f05,
563249423Sdim 0x0f06, 0x0f07, 0x0f08, 0x0f09, 0x0f0a, 0x0f0b, 0x0f0c, 0x0f0d, 0x0f0e,
564249423Sdim 0x0f0f, 0x0f10, 0x0f11, 0x0f12, 0x0f13, 0x0f14, 0x0f15, 0x0f16, 0x0f17,
565249423Sdim 0x0f18, 0x0f19, 0x0f1a, 0x0f1b, 0x0f1c, 0x0f1d, 0x0f1e, 0x0f1f, 0x0f20,
566249423Sdim 0x0f21, 0x0f22, 0x0f23, 0x0f24, 0x0f25, 0x0f26, 0x0f27, 0x0f28, 0x0f29,
567249423Sdim 0x0f2a, 0x0f2b, 0x0f2c, 0x0f2d, 0x0f2e, 0x0f2f, 0x0f30, 0x0f31, 0x0f32,
568249423Sdim 0x0f33, 0x0f34, 0x0f35, 0x0f36, 0x0f37, 0x0f38, 0x0f39, 0x0f3a, 0x0f3b,
569249423Sdim 0x0f3c, 0x0f3d, 0x0f3e, 0x0f3f, 0x0f40, 0x0f41, 0x0f42, 0x0f43, 0x0f44,
570249423Sdim 0x0f45, 0x0f46, 0x0f47, 0x0f48, 0x0f49, 0x0f4a, 0x0f4b, 0x0f4c, 0x0f4d,
571249423Sdim 0x0f4e, 0x0f4f, 0x0f50, 0x0f51, 0x0f52, 0x0f53, 0x0f54, 0x0f55, 0x0f56,
572249423Sdim 0x0f57, 0x0f58, 0x0f59, 0x0f5a, 0x0f5b, 0x0f5c, 0x0f5d, 0x0f5e, 0x0f5f,
573249423Sdim 0x0f60, 0x0f61, 0x0f62, 0x0f63, 0x0f64, 0x0f65, 0x0f66, 0x0f67, 0x0f68,
574249423Sdim 0x0f69, 0x0f6a, 0x0f6b, 0x0f6c, 0x0f6d, 0x0f6e, 0x0f6f, 0x0f70, 0x0f71,
575249423Sdim 0x0f72, 0x0f73, 0x0f74, 0x0f75, 0x0f76, 0x0f77, 0x0f78, 0x0f79, 0x0f7a,
576249423Sdim 0x0f7b, 0x0f7c, 0x0f7d, 0x0f7e, 0x0f7f, 0x0f80, 0x0f81, 0x0f82, 0x0f83,
577249423Sdim 0x0f84, 0x0f85, 0x0f86, 0x0f87, 0x0f88, 0x0f89, 0x0f8a, 0x0f8b, 0x0f8c,
578249423Sdim 0x0f8d, 0x0f8e, 0x0f8f, 0x0f90, 0x0f91, 0x0f92, 0x0f93, 0x0f94, 0x0f95,
579249423Sdim 0x0f96, 0x0f97, 0x0f98, 0x0f99, 0x0f9a, 0x0f9b, 0x0f9c, 0x0f9d, 0x0f9e,
580249423Sdim 0x0f9f, 0x0fa0, 0x0fa1, 0x0fa2, 0x0fa3, 0x0fa4, 0x0fa5, 0x0fa6, 0x0fa7,
581249423Sdim 0x0fa8, 0x0fa9, 0x0faa, 0x0fab, 0x0fac, 0x0fad, 0x0fae, 0x0faf, 0x0fb0,
582249423Sdim 0x0fb1, 0x0fb2, 0x0fb3, 0x0fb4, 0x0fb5, 0x0fb6, 0x0fb7, 0x0fb8, 0x0fb9,
583249423Sdim 0x0fba, 0x0fbb, 0x0fbc, 0x0fbd, 0x0fbe, 0x0fbf, 0x0fc0, 0x0fc1, 0x0fc2,
584249423Sdim 0x0fc3, 0x0fc4, 0x0fc5, 0x0fc6, 0x0fc7, 0x0fc8, 0x0fc9, 0x0fca, 0x0fcb,
585249423Sdim 0x0fcc, 0x0fcd, 0x0fce, 0x0fcf, 0x0fd0, 0x0fd1, 0x0fd2, 0x0fd3, 0x0fd4,
586249423Sdim 0x0fd5, 0x0fd6, 0x0fd7, 0x0fd8, 0x0fd9, 0x0fda, 0x0fdb, 0x0fdc, 0x0fdd,
587249423Sdim 0x0fde, 0x0fdf, 0x0fe0, 0x0fe1, 0x0fe2, 0x0fe3, 0x0fe4, 0x0fe5, 0x0fe6,
588249423Sdim 0x0fe7, 0x0fe8, 0x0fe9, 0x0fea, 0x0feb, 0x0fec, 0x0fed, 0x0fee, 0x0fef,
589249423Sdim 0x0ff0, 0x0ff1, 0x0ff2, 0x0ff3, 0x0ff4, 0x0ff5, 0x0ff6, 0x0ff7, 0x0ff8,
590249423Sdim 0x0ff9, 0x0ffa, 0x0ffb, 0x0ffc, 0x0ffd, 0x0ffe, 0x0fff};
591249423Sdim
592249423Sdim#define SELECT_GUS_REG(port,x) outb(port+GUS_REG_SELECT,x)
593249423Sdim#define WHICH_GUS_REG(port) inb(port+GUS_REG_SELECT)
594249423Sdim#define ADDR_HIGH(x) (unsigned int) ((x >> 7L) & 0x1fffL)
595249423Sdim#define ADDR_LOW(x) (unsigned int) ((x & 0x7fL) << 9L)
596249423Sdim
597249423Sdim#define GUS_MIN_VOICES 14	/* Minimum possible number of voices */
598249423Sdim#define GUS_MAX_VOICES 32	/* Maximum possible number of voices */
599249423Sdim#define GUS_VOICE_LEFT 0	/* Voice used for left (and mono) playback */
600249423Sdim#define GUS_VOICE_RIGHT 1	/* Voice used for right playback */
601249423Sdim#define GUS_MEM_OFFSET 32	/* Offset into GUS memory to begin of buffer */
602249423Sdim#define GUS_BUFFER_MULTIPLE 1024	/* Audio buffers are multiples of this */
603249423Sdim#define	GUS_MEM_FOR_BUFFERS	131072	/* use this many bytes on-GUS */
604249423Sdim#define	GUS_LEFT_RIGHT_OFFSET	(sc->sc_nbufs * sc->sc_chanblocksize + GUS_MEM_OFFSET)
605249423Sdim
606249423Sdim#define GUS_PREC_BYTES (sc->sc_precision >> 3) /* precision to bytes */
607249423Sdim
608249423Sdim/* splgus() must be splaudio() */
609249423Sdim
610249423Sdim#define splgus splaudio
611249423Sdim
612249423Sdim/*
613249423Sdim * Interface to higher level audio driver
614263508Sdim */
615249423Sdim
616249423Sdimstruct audio_hw_if gus_hw_if = {
617249423Sdim	gusopen,
618249423Sdim	gusclose,
619249423Sdim	NULL,				/* drain */
620249423Sdim	gus_set_in_sr,
621249423Sdim	gus_get_in_sr,
622249423Sdim	gus_set_out_sr,
623249423Sdim	gus_get_out_sr,
624249423Sdim
625249423Sdim	gus_query_encoding,
626249423Sdim	gus_set_encoding,
627249423Sdim	gus_get_encoding,
628249423Sdim
629249423Sdim	gus_set_precision,
630249423Sdim	gus_get_precision,
631249423Sdim
632249423Sdim	gus_set_channels,
633249423Sdim	gus_get_channels,
634249423Sdim
635249423Sdim	gus_round_blocksize,
636249423Sdim
637249423Sdim	gus_set_out_port,
638249423Sdim	gus_get_out_port,
639249423Sdim	gus_set_in_port,
640249423Sdim	gus_get_in_port,
641249423Sdim
642249423Sdim	gus_commit_settings,
643249423Sdim
644249423Sdim	gus_expand,
645249423Sdim	mulaw_compress,
646249423Sdim
647249423Sdim	gus_dma_output,
648249423Sdim	gus_dma_input,
649249423Sdim	gus_halt_out_dma,
650249423Sdim	gus_halt_in_dma,
651249423Sdim	gus_cont_out_dma,
652249423Sdim	gus_cont_in_dma,
653249423Sdim
654249423Sdim	gus_speaker_ctl,
655249423Sdim
656249423Sdim	gus_getdev,
657249423Sdim	gus_setfd,
658218885Sdim	gus_mixer_set_port,
659221345Sdim	gus_mixer_get_port,
660218885Sdim	gus_mixer_query_devinfo,
661218885Sdim	1,				/* full-duplex */
662218885Sdim	0,
663218885Sdim};
664218885Sdim
665221345Sdim
666218885Sdim/*
667249423Sdim * Some info about the current audio device
668249423Sdim */
669218885Sdim
670263508Sdimstruct audio_device gus_device = {
671249423Sdim	"UltraSound",
672249423Sdim	"",
673218885Sdim	"gus",
674218885Sdim};
675221345Sdim
676263508Sdim#define FLIP_REV	5		/* This rev has flipped mixer chans */
677249423Sdim
678249423Sdim
679218885Sdimint
680218885Sdimgusprobe(parent, match, aux)
681218885Sdim	struct device *parent;
682218885Sdim	void *match, *aux;
683249423Sdim{
684249423Sdim	register struct gus_softc *sc = match;
685221345Sdim	register struct isa_attach_args *ia = aux;
686218885Sdim	struct cfdata *cf = sc->sc_dev.dv_cfdata;
687218885Sdim	register int iobase = ia->ia_iobase;
688249423Sdim	int recdrq = cf->cf_flags;
689249423Sdim
690218885Sdim	/*
691218885Sdim	 * Before we do anything else, make sure requested IRQ and DRQ are
692218885Sdim	 * valid for this card.
693221345Sdim	 */
694218885Sdim
695218885Sdim	if (gus_irq_map[ia->ia_irq] == IRQUNK) {
696218885Sdim		printf("gus: invalid irq %d, card not probed\n", ia->ia_irq);
697218885Sdim		return(0);
698218885Sdim	}
699249423Sdim
700249423Sdim	if (gus_drq_map[ia->ia_drq] == DRQUNK) {
701249423Sdim		printf("gus: invalid drq %d, card not probed\n", ia->ia_drq);
702249423Sdim		return(0);
703249423Sdim	}
704249423Sdim
705249423Sdim	if (recdrq != 0x00) {
706249423Sdim		if (recdrq > 7 || gus_drq_map[recdrq] == DRQUNK) {
707249423Sdim		   printf("gus: invalid flag given for second DMA channel (0x%x), card not probed\n", recdrq);
708249423Sdim		   return(0);
709249423Sdim	        }
710249423Sdim	} else
711249423Sdim		recdrq = ia->ia_drq;
712249423Sdim
713249423Sdim	if (iobase == IOBASEUNK) {
714249423Sdim		int i;
715249423Sdim		for(i = 0; i < gus_addrs; i++)
716249423Sdim			if (gus_test_iobase(gus_base_addrs[i])) {
717249423Sdim				iobase = gus_base_addrs[i];
718249423Sdim				goto done;
719249423Sdim			}
720249423Sdim		return 0;
721249423Sdim	} else if (! gus_test_iobase(iobase))
722249423Sdim			return 0;
723249423Sdim
724249423Sdimdone:
725249423Sdim	sc->sc_iobase = iobase;
726218885Sdim	sc->sc_irq = ia->ia_irq;
727218885Sdim	sc->sc_drq = ia->ia_drq;
728218885Sdim	sc->sc_recdrq = recdrq;
729218885Sdim
730218885Sdim	ia->ia_iobase = sc->sc_iobase;
731218885Sdim	ia->ia_iosize = 16;		/* XXX */
732218885Sdim	return(1);
733218885Sdim}
734218885Sdim
735218885Sdim/*
736218885Sdim * Test to see if a particular I/O base is valid for the GUS.  Return true
737221345Sdim * if it is.
738218885Sdim */
739218885Sdim
740218885SdimSTATIC int
741218885Sdimgus_test_iobase (int iobase)
742218885Sdim{
743218885Sdim	int i = splgus();
744218885Sdim	u_char s1, s2;
745218885Sdim
746221345Sdim	/*
747218885Sdim	 * Reset GUS to an initial state before we do anything.
748218885Sdim	 */
749218885Sdim
750218885Sdim	delay(500);
751218885Sdim
752218885Sdim 	SELECT_GUS_REG(iobase, GUSREG_RESET);
753221345Sdim 	outb(iobase+GUS_DATA_HIGH, 0x00);
754218885Sdim
755218885Sdim 	delay(500);
756218885Sdim
757218885Sdim	SELECT_GUS_REG(iobase, GUSREG_RESET);
758218885Sdim 	outb(iobase+GUS_DATA_HIGH, GUSMASK_MASTER_RESET);
759221345Sdim
760218885Sdim 	delay(500);
761218885Sdim
762218885Sdim	splx(i);
763218885Sdim
764218885Sdim	/*
765218885Sdim	 * See if we can write to the board's memory
766218885Sdim	 */
767221345Sdim
768218885Sdim 	s1 = guspeek(iobase, 0L);
769218885Sdim 	s2 = guspeek(iobase, 1L);
770218885Sdim
771218885Sdim 	guspoke(iobase, 0L, 0xaa);
772218885Sdim 	guspoke(iobase, 1L, 0x55);
773218885Sdim
774226633Sdim 	if ((i=(int)guspeek(iobase, 0L)) != 0xaa) {
775218885Sdim		return(0);
776218885Sdim	}
777218885Sdim
778221345Sdim	guspoke(iobase, 0L, s1);
779218885Sdim	guspoke(iobase, 1L, s2);
780218885Sdim
781218885Sdim	return 1;
782218885Sdim}
783221345Sdim
784218885Sdim/*
785218885Sdim * Setup the GUS for use; called shortly after probe
786218885Sdim */
787218885Sdim
788218885Sdimvoid
789218885Sdimgusattach(parent, self, aux)
790218885Sdim	struct device *parent, *self;
791218885Sdim	void *aux;
792218885Sdim{
793218885Sdim	register struct gus_softc *sc = (void *) self;
794221345Sdim	register struct isa_attach_args *ia = aux;
795218885Sdim	register int port = ia->ia_iobase;
796221345Sdim	int		i;
797219077Sdim	register unsigned char	c,d,m;
798219077Sdim
799219077Sdim	/*
800219077Sdim	 * Figure out our board rev, and see if we need to initialize the
801219077Sdim	 * mixer
802219077Sdim	 */
803219077Sdim
804219077Sdim 	delay(500);
805221345Sdim
806218885Sdim 	c = inb(port+GUS_BOARD_REV);
807219077Sdim	if (c != 0xff)
808218885Sdim		sc->sc_revision = c;
809218885Sdim	else
810218885Sdim		sc->sc_revision = 0;
811218885Sdim
812218885Sdim
813218885Sdim 	SELECT_GUS_REG(port, GUSREG_RESET);
814218885Sdim 	outb(port+GUS_DATA_HIGH, 0x00);
815218885Sdim
816218885Sdim	gusreset(sc, GUS_MAX_VOICES); /* initialize all voices */
817218885Sdim	gusreset(sc, GUS_MIN_VOICES); /* then set to just the ones we use */
818218885Sdim
819218885Sdim	/*
820218885Sdim	 * Setup the IRQ and DRQ lines in software, using values from
821226633Sdim	 * config file
822218885Sdim	 */
823218885Sdim
824218885Sdim	m = GUSMASK_LINE_IN|GUSMASK_LINE_OUT;		/* disable all */
825218885Sdim
826218885Sdim	c = ((unsigned char) gus_irq_map[ia->ia_irq]) | GUSMASK_BOTH_RQ;
827218885Sdim
828218885Sdim	if (sc->sc_recdrq == sc->sc_drq)
829218885Sdim		d = (unsigned char) (gus_drq_map[sc->sc_drq] |
830218885Sdim				GUSMASK_BOTH_RQ);
831218885Sdim	else
832218885Sdim		d = (unsigned char) (gus_drq_map[sc->sc_drq] |
833218885Sdim				gus_drq_map[sc->sc_recdrq] << 3);
834218885Sdim
835218885Sdim	/*
836218885Sdim	 * Program the IRQ and DMA channels on the GUS.  Note that we hardwire
837218885Sdim	 * the GUS to only use one IRQ channel, but we give the user the
838218885Sdim	 * option of using two DMA channels (the other one given by the flags
839221345Sdim	 * option in the config file).  Two DMA channels are needed for full-
840218885Sdim	 * duplex operation.
841221345Sdim	 *
842218885Sdim	 * The order of these operations is very magical.
843218885Sdim	 */
844218885Sdim
845218885Sdim	disable_intr();
846218885Sdim
847218885Sdim	outb(port+GUS_REG_CONTROL, GUS_REG_IRQCTL);
848218885Sdim	outb(port+GUS_MIX_CONTROL, m);
849218885Sdim	outb(port+GUS_IRQCTL_CONTROL, 0x00);
850218885Sdim	outb(port+0x0f, 0x00);
851218885Sdim
852218885Sdim	outb(port+GUS_MIX_CONTROL, m);
853221345Sdim	outb(port+GUS_DMA_CONTROL, d | 0x80); /* magic reset? */
854218885Sdim
855218885Sdim	outb(port+GUS_MIX_CONTROL, m | GUSMASK_CONTROL_SEL);
856218885Sdim	outb(port+GUS_IRQ_CONTROL, c);
857221345Sdim
858218885Sdim	outb(port+GUS_MIX_CONTROL, m);
859218885Sdim	outb(port+GUS_DMA_CONTROL, d);
860218885Sdim
861218885Sdim	outb(port+GUS_MIX_CONTROL, m | GUSMASK_CONTROL_SEL);
862221345Sdim	outb(port+GUS_IRQ_CONTROL, c);
863218885Sdim
864218885Sdim	outb(port+GUS_VOICE_SELECT, 0x00);
865218885Sdim
866218885Sdim	/* enable line in, line out.  leave mic disabled. */
867218885Sdim	outb(port+GUS_MIX_CONTROL,
868218885Sdim	     (m | GUSMASK_LATCHES) & ~(GUSMASK_LINE_OUT|GUSMASK_LINE_IN));
869218885Sdim	outb(port+GUS_VOICE_SELECT, 0x00);
870218885Sdim
871218885Sdim	enable_intr();
872218885Sdim
873218885Sdim	sc->sc_mixcontrol =
874218885Sdim		(m | GUSMASK_LATCHES) & ~(GUSMASK_LINE_OUT|GUSMASK_LINE_IN);
875218885Sdim
876218885Sdim
877218885Sdim 	if (sc->sc_revision >= 5 && sc->sc_revision <= 9) {
878218885Sdim 		sc->sc_flags |= GUS_MIXER_INSTALLED;
879218885Sdim 		gus_init_ics2101(sc);
880218885Sdim	}
881218885Sdim	if (sc->sc_revision >= 0xa) {
882218885Sdim		gus_init_cs4231(sc);
883218885Sdim	}
884218885Sdim
885221345Sdim 	SELECT_GUS_REG(port, GUSREG_RESET);
886218885Sdim 	/*
887218885Sdim 	 * Check to see how much memory we have on this card; see if any
888218885Sdim 	 * "mirroring" occurs.  We're assuming at least 256K already exists
889218885Sdim 	 * on the card; otherwise the initial probe would have failed
890218885Sdim 	 */
891218885Sdim
892218885Sdim	guspoke(port, 0L, 0x00);
893218885Sdim	for(i = 1; i < 1024; i++) {
894218885Sdim		u_long loc;
895218885Sdim
896218885Sdim		/*
897218885Sdim		 * See if we've run into mirroring yet
898218885Sdim		 */
899218885Sdim
900218885Sdim		if (guspeek(port, 0L) != 0)
901218885Sdim			break;
902218885Sdim
903218885Sdim		loc = i << 10;
904218885Sdim
905218885Sdim		guspoke(port, loc, 0xaa);
906218885Sdim		if (guspeek(port, loc) != 0xaa)
907218885Sdim			break;
908243830Sdim	}
909218885Sdim
910218885Sdim	sc->sc_dsize = i;
911218885Sdim	sprintf(gus_device.version, "3.%d", sc->sc_revision);
912218885Sdim
913218885Sdim	printf("\n <Gravis UltraSound version 3.%d, %dKB DRAM, ",
914221345Sdim	       sc->sc_revision, sc->sc_dsize);
915218885Sdim	if (HAS_MIXER(sc))
916218885Sdim		printf("ICS2101 mixer, ");
917218885Sdim	if (HAS_CODEC(sc))
918218885Sdim		printf("%s codec/mixer, ", sc->sc_codec.chip_name);
919221345Sdim	if (sc->sc_recdrq == sc->sc_drq) {
920218885Sdim		printf("half-duplex");
921218885Sdim		gus_hw_if.full_duplex = 0;
922218885Sdim	} else {
923218885Sdim		printf("full-duplex, record drq %d", sc->sc_recdrq);
924218885Sdim		gus_hw_if.full_duplex = 1;
925218885Sdim	}
926218885Sdim
927218885Sdim	printf(">\n");
928218885Sdim
929218885Sdim	/*
930221345Sdim	 * Setup a default interrupt handler
931218885Sdim	 */
932218885Sdim
933218885Sdim	/* XXX we shouldn't have to use splgus == splclock, nor should
934218885Sdim	 * we use IPL_CLOCK.
935218885Sdim	 */
936218885Sdim	sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
937218885Sdim	    IPL_AUDIO, gusintr, sc /* sc->sc_gusdsp */);
938218885Sdim
939218885Sdim	/*
940218885Sdim	 * Set some default values
941218885Sdim	 */
942218885Sdim
943218885Sdim	sc->sc_irate = sc->sc_orate = 44100;
944218885Sdim	sc->sc_encoding = AUDIO_ENCODING_LINEAR;
945218885Sdim	sc->sc_precision = 16;
946218885Sdim	sc->sc_voc[GUS_VOICE_LEFT].voccntl |= GUSMASK_DATA_SIZE16;
947218885Sdim	sc->sc_voc[GUS_VOICE_RIGHT].voccntl |= GUSMASK_DATA_SIZE16;
948221345Sdim	sc->sc_channels = 1;
949218885Sdim	sc->sc_ogain = 340;
950218885Sdim	gus_commit_settings(sc);
951218885Sdim
952218885Sdim	/*
953218885Sdim	 * We always put the left channel full left & right channel
954218885Sdim	 * full right.
955221345Sdim	 * For mono playback, we set up both voices playing the same buffer.
956263508Sdim	 */
957263508Sdim	outb(sc->sc_iobase+GUS_VOICE_SELECT, (unsigned char) GUS_VOICE_LEFT);
958218885Sdim	SELECT_GUS_REG(sc->sc_iobase, GUSREG_PAN_POS);
959218885Sdim	outb(sc->sc_iobase+GUS_DATA_HIGH, GUS_PAN_FULL_LEFT);
960218885Sdim
961218885Sdim	outb(sc->sc_iobase+GUS_VOICE_SELECT, (unsigned char) GUS_VOICE_RIGHT);
962218885Sdim	SELECT_GUS_REG(sc->sc_iobase, GUSREG_PAN_POS);
963218885Sdim	outb(sc->sc_iobase+GUS_DATA_HIGH, GUS_PAN_FULL_RIGHT);
964218885Sdim
965218885Sdim	/*
966263508Sdim	 * Attach to the generic audio layer
967263508Sdim	 */
968218885Sdim
969263508Sdim	if (audio_hardware_attach(&gus_hw_if, HAS_CODEC(sc) ? (void *)&sc->sc_codec : (void *)sc) != 0)
970218885Sdim		printf("gus: could not attach to audio pseudo-device driver\n");
971218885Sdim}
972218885Sdim
973218885Sdimint
974226633Sdimgusopen(dev, flags)
975218885Sdim	dev_t dev;
976218885Sdim	int flags;
977221345Sdim{
978223017Sdim	int unit = AUDIOUNIT(dev);
979223017Sdim	struct gus_softc *sc;
980223017Sdim
981223017Sdim	DPRINTF(("gusopen() called\n"));
982223017Sdim
983224145Sdim	if (unit >= gus_cd.cd_ndevs)
984224145Sdim		return ENXIO;
985263508Sdim	sc = gus_cd.cd_devs[unit];
986263508Sdim	if (!sc)
987218885Sdim		return ENXIO;
988218885Sdim
989218885Sdim	if (sc->sc_flags & GUS_OPEN)
990223017Sdim		return EBUSY;
991223017Sdim
992221345Sdim	/*
993263508Sdim	 * Some initialization
994218885Sdim	 */
995221345Sdim
996223017Sdim	sc->sc_flags |= GUS_OPEN;
997223017Sdim	sc->sc_dmabuf = 0;
998263508Sdim	sc->sc_playbuf = -1;
999223017Sdim	sc->sc_bufcnt = 0;
1000223017Sdim	sc->sc_voc[GUS_VOICE_LEFT].start_addr = GUS_MEM_OFFSET - 1;
1001243830Sdim	sc->sc_voc[GUS_VOICE_LEFT].current_addr = GUS_MEM_OFFSET;
1002223017Sdim
1003223017Sdim	if (HAS_CODEC(sc)) {
1004224145Sdim		ad1848_open(&sc->sc_codec, dev, flags);
1005223017Sdim		sc->sc_codec.aux1_mute = 0;
1006223017Sdim		ad1848_mute_aux1(&sc->sc_codec, 0); /* turn on DAC output */
1007218885Sdim		if (flags & FREAD) {
1008218885Sdim			sc->sc_codec.mono_mute = 0;
1009263508Sdim			cs4231_mute_mono(&sc->sc_codec, 0);
1010218885Sdim		}
1011221345Sdim	} else if (flags & FREAD) {
1012218885Sdim		/* enable/unmute the microphone */
1013221345Sdim		if (HAS_MIXER(sc)) {
1014263508Sdim			gusics_mic_mute(&sc->sc_mixer, 0);
1015218885Sdim		} else
1016221345Sdim			gus_mic_ctl(sc, SPKR_ON);
1017263508Sdim	}
1018221345Sdim	if (sc->sc_nbufs == 0)
1019221345Sdim	    gus_round_blocksize(sc, GUS_BUFFER_MULTIPLE); /* default blksiz */
1020218885Sdim	return 0;
1021221345Sdim}
1022221345Sdim
1023263508SdimSTATIC void
1024263508Sdimgusmax_expand(hdl, encoding, buf, count)
1025263508Sdim	void *hdl;
1026263508Sdim	int encoding;
1027263508Sdim	u_char *buf;
1028263508Sdim	int count;
1029263508Sdim{
1030263508Sdim	register struct ad1848_softc *ac = hdl;
1031263508Sdim
1032218885Sdim	gus_expand(ac->parent, encoding, buf, count);
1033218885Sdim}
1034218885Sdim
1035263508SdimSTATIC void
1036263508Sdimgus_expand(hdl, encoding, buf, count)
1037263508Sdim	void *hdl;
1038218885Sdim	int encoding;
1039221345Sdim	u_char *buf;
1040218885Sdim	int count;
1041218885Sdim{
1042218885Sdim	struct gus_softc *sc = hdl;
1043218885Sdim
1044218885Sdim	mulaw_expand(NULL, encoding, buf, count);
1045218885Sdim	/*
1046218885Sdim	 * If we need stereo deinterleaving, do it now.
1047263508Sdim	 */
1048218885Sdim	if (sc->sc_channels == 2)
1049218885Sdim		gus_deinterleave(sc, (void *)buf, count);
1050221345Sdim}
1051218885Sdim
1052218885SdimSTATIC void
1053221345Sdimgus_deinterleave(sc, buf, size)
1054221345Sdim	register struct gus_softc *sc;
1055218885Sdim	void *buf;
1056218885Sdim	int size;
1057243830Sdim{
1058218885Sdim	/* deinterleave the stereo data.  We can use sc->sc_deintr_buf
1059218885Sdim	   for scratch space. */
1060218885Sdim	register int i;
1061218885Sdim
1062218885Sdim	/*
1063218885Sdim	 * size is in bytes.
1064218885Sdim	 */
1065218885Sdim	if (sc->sc_precision == 16) {
1066218885Sdim		register u_short *dei = sc->sc_deintr_buf;
1067218885Sdim		register u_short *sbuf = buf;
1068218885Sdim		size >>= 1;		/* bytecnt to shortcnt */
1069218885Sdim		/* copy 2nd of each pair of samples to the staging area, while
1070218885Sdim		   compacting the 1st of each pair into the original area. */
1071218885Sdim		for (i = 0; i < size/2-1; i++)  {
1072221345Sdim			dei[i] = sbuf[i*2+1];
1073218885Sdim			sbuf[i+1] = sbuf[i*2+2];
1074221345Sdim		}
1075223017Sdim		/*
1076223017Sdim		 * this has copied one less sample than half of the
1077223017Sdim		 * buffer.  The first sample of the 1st stream was
1078223017Sdim		 * already in place and didn't need copying.
1079223017Sdim		 * Therefore, we've moved all of the 1st stream's
1080224145Sdim		 * samples into place.  We have one sample from 2nd
1081224145Sdim		 * stream in the last slot of original area, not
1082218885Sdim		 * copied to the staging area (But we don't need to!).
1083218885Sdim		 * Copy the remainder of the original stream into place.
1084218885Sdim		 */
1085223017Sdim		bcopy(dei, &sbuf[size/2], i * sizeof(short));
1086223017Sdim	} else {
1087223017Sdim		register u_char *dei = sc->sc_deintr_buf;
1088223017Sdim		register u_char *sbuf = buf;
1089223017Sdim		for (i = 0; i < size/2-1; i++)  {
1090223017Sdim			dei[i] = sbuf[i*2+1];
1091223017Sdim			sbuf[i+1] = sbuf[i*2+2];
1092224145Sdim		}
1093223017Sdim		bcopy(dei, &sbuf[size/2], i);
1094218885Sdim	}
1095223017Sdim}
1096223017Sdim
1097223017Sdim/*
1098243830Sdim * Actually output a buffer to the DSP chip
1099218885Sdim */
1100223017Sdim
1101218885Sdimint
1102218885Sdimgusmax_dma_output(addr, buf, size, intr, arg)
1103218885Sdim	void * addr;
1104221345Sdim	void *buf;
1105218885Sdim	int size;
1106218885Sdim	void (*intr) __P((void *));
1107218885Sdim	void *arg;
1108221345Sdim{
1109223017Sdim	register struct ad1848_softc *ac = addr;
1110223017Sdim	return gus_dma_output(ac->parent, buf, size, intr, arg);
1111223017Sdim}
1112223017Sdim
1113243830Sdim/*
1114243830Sdim * called at splgus() from interrupt handler.
1115223017Sdim */
1116223017Sdimvoid
1117224145Sdimstereo_dmaintr(arg)
1118223017Sdim	void *arg;
1119223017Sdim{
1120224145Sdim    struct gus_softc *sc = arg;
1121218885Sdim    struct stereo_dma_intr *sa = &sc->sc_stereo;
1122218885Sdim
1123263508Sdim    DMAPRINTF(("stereo_dmaintr"));
1124263508Sdim
1125221345Sdim    /*
1126263508Sdim     * Put other half in its place, then call the real interrupt routine :)
1127221345Sdim     */
1128218885Sdim
1129263508Sdim    sc->sc_dmaoutintr = sa->intr;
1130221345Sdim    sc->sc_outarg = sa->arg;
1131221345Sdim
1132218885Sdim#ifdef GUSPLAYDEBUG
1133263508Sdim    if (gusstats) {
1134221345Sdim      microtime(&dmarecords[dmarecord_index].tv);
1135223017Sdim      dmarecords[dmarecord_index].gusaddr = sa->dmabuf;
1136218885Sdim      dmarecords[dmarecord_index].bsdaddr = sa->buffer;
1137218885Sdim      dmarecords[dmarecord_index].count = sa->size;
1138223017Sdim      dmarecords[dmarecord_index].channel = 1;
1139221345Sdim      dmarecords[dmarecord_index].direction = 1;
1140218885Sdim      dmarecord_index = ++dmarecord_index % NDMARECS;
1141218885Sdim    }
1142218885Sdim#endif
1143221345Sdim
1144224145Sdim    gusdmaout(sc, sa->flags, sa->dmabuf, (caddr_t) sa->buffer, sa->size);
1145218885Sdim
1146218885Sdim    sa->flags = 0;
1147243830Sdim    sa->dmabuf = 0;
1148218885Sdim    sa->buffer = 0;
1149218885Sdim    sa->size = 0;
1150218885Sdim    sa->intr = 0;
1151    sa->arg = 0;
1152}
1153
1154/*
1155 * Start up DMA output to the card.
1156 * Called at splgus/splaudio already, either from intr handler or from
1157 * generic audio code.
1158 */
1159int
1160gus_dma_output(addr, buf, size, intr, arg)
1161	void * addr;
1162	void *buf;
1163	int size;
1164	void (*intr) __P((void *));
1165	void *arg;
1166{
1167	struct gus_softc *sc = addr;
1168	u_char *buffer = buf;
1169	u_long boarddma;
1170	int flags;
1171
1172	DMAPRINTF(("gus_dma_output %d @ %x\n", size, buf));
1173
1174	if (size != sc->sc_blocksize) {
1175	    DPRINTF(("gus_dma_output reqsize %d not sc_blocksize %d\n",
1176		     size, sc->sc_blocksize));
1177	    return EINVAL;
1178	}
1179
1180	flags = GUSMASK_DMA_WRITE;
1181	if (sc->sc_precision == 16)
1182	    flags |= GUSMASK_DMA_DATA_SIZE;
1183	/* pcm16 is signed, mulaw & pcm8 are unsigned */
1184	if (sc->sc_encoding == AUDIO_ENCODING_ULAW ||
1185	    sc->sc_encoding == AUDIO_ENCODING_PCM8)
1186	    flags |= GUSMASK_DMA_INVBIT;
1187
1188	if (sc->sc_channels == 2) {
1189		if (sc->sc_precision == 16) {
1190			if (size & 3) {
1191				DPRINTF(("gus_dma_output: unpaired 16bit samples"));
1192				size &= 3;
1193			}
1194		} else if (size & 1) {
1195			DPRINTF(("gus_dma_output: unpaired samples"));
1196			size &= 1;
1197		}
1198		if (size == 0)
1199			return 0;
1200		size >>= 1;
1201
1202		boarddma = size * sc->sc_dmabuf + GUS_MEM_OFFSET;
1203
1204		sc->sc_stereo.intr = intr;
1205		sc->sc_stereo.arg = arg;
1206		sc->sc_stereo.size = size;
1207		sc->sc_stereo.dmabuf = boarddma + GUS_LEFT_RIGHT_OFFSET;
1208		sc->sc_stereo.buffer = buffer + size;
1209		sc->sc_stereo.flags = flags;
1210		if (gus_dostereo) {
1211		  intr = stereo_dmaintr;
1212		  arg = sc;
1213		}
1214	} else
1215		boarddma = size * sc->sc_dmabuf + GUS_MEM_OFFSET;
1216
1217
1218	sc->sc_flags |= GUS_LOCKED;
1219	sc->sc_dmaoutintr = intr;
1220	sc->sc_outarg = arg;
1221
1222#ifdef GUSPLAYDEBUG
1223	if (gusstats) {
1224	  microtime(&dmarecords[dmarecord_index].tv);
1225	  dmarecords[dmarecord_index].gusaddr = boarddma;
1226	  dmarecords[dmarecord_index].bsdaddr = buffer;
1227	  dmarecords[dmarecord_index].count = size;
1228	  dmarecords[dmarecord_index].channel = 0;
1229	  dmarecords[dmarecord_index].direction = 1;
1230	  dmarecord_index = ++dmarecord_index % NDMARECS;
1231	}
1232#endif
1233
1234	gusdmaout(sc, flags, boarddma, (caddr_t) buffer, size);
1235
1236	return 0;
1237}
1238
1239void
1240gusmax_close(addr)
1241	void *addr;
1242{
1243	register struct ad1848_softc *ac = addr;
1244	register struct gus_softc *sc = ac->parent;
1245#if 0
1246	ac->aux1_mute = 1;
1247	ad1848_mute_aux1(ac, 1);	/* turn off DAC output */
1248#endif
1249	ad1848_close(ac);
1250	gusclose(sc);
1251}
1252
1253/*
1254 * Close out device stuff.  Called at splgus() from generic audio layer.
1255 */
1256void
1257gusclose(addr)
1258	void *addr;
1259{
1260	struct gus_softc *sc = addr;
1261
1262        DPRINTF(("gus_close: sc=0x%x\n", sc));
1263
1264
1265/*	if (sc->sc_flags & GUS_DMAOUT_ACTIVE) */ {
1266		gus_halt_out_dma(sc);
1267	}
1268/*	if (sc->sc_flags & GUS_DMAIN_ACTIVE) */ {
1269		gus_halt_in_dma(sc);
1270	}
1271	sc->sc_flags &= ~(GUS_OPEN|GUS_LOCKED|GUS_DMAOUT_ACTIVE|GUS_DMAIN_ACTIVE);
1272
1273	if (sc->sc_deintr_buf) {
1274		FREE(sc->sc_deintr_buf, M_DEVBUF);
1275		sc->sc_deintr_buf = NULL;
1276	}
1277	/* turn off speaker, etc. */
1278
1279	/* make sure the voices shut up: */
1280	gus_stop_voice(sc, GUS_VOICE_LEFT, 1);
1281	gus_stop_voice(sc, GUS_VOICE_RIGHT, 0);
1282}
1283
1284/*
1285 * Service interrupts.  Farm them off to helper routines if we are using the
1286 * GUS for simple playback/record
1287 */
1288
1289#ifdef DIAGNOSTIC
1290int gusintrcnt;
1291int gusdmaintrcnt;
1292int gusvocintrcnt;
1293#endif
1294
1295int
1296gusintr(arg)
1297	void *arg;
1298{
1299	register struct gus_softc *sc = arg;
1300	unsigned char intr;
1301	register int port = sc->sc_iobase;
1302	int retval = 0;
1303
1304	DPRINTF(("gusintr\n"));
1305#ifdef DIAGNOSTIC
1306	gusintrcnt++;
1307#endif
1308	if (HAS_CODEC(sc))
1309		retval = ad1848_intr(&sc->sc_codec);
1310	if ((intr = inb(port+GUS_IRQ_STATUS)) & GUSMASK_IRQ_DMATC) {
1311		DMAPRINTF(("gusintr dma flags=%x\n", sc->sc_flags));
1312#ifdef DIAGNOSTIC
1313		gusdmaintrcnt++;
1314#endif
1315		retval += gus_dmaout_intr(sc);
1316		if (sc->sc_flags & GUS_DMAIN_ACTIVE) {
1317		    SELECT_GUS_REG(port, GUSREG_SAMPLE_CONTROL);
1318		    intr = inb(port+GUS_DATA_HIGH);
1319		    if (intr & GUSMASK_SAMPLE_DMATC) {
1320			retval += gus_dmain_intr(sc);
1321		    }
1322		}
1323	}
1324	if (intr & (GUSMASK_IRQ_VOICE | GUSMASK_IRQ_VOLUME)) {
1325		DMAPRINTF(("gusintr voice flags=%x\n", sc->sc_flags));
1326#ifdef DIAGNOSTIC
1327		gusvocintrcnt++;
1328#endif
1329		retval += gus_voice_intr(sc);
1330	}
1331	if (retval)
1332		return 1;
1333	return retval;
1334}
1335
1336int gus_bufcnt[GUS_MEM_FOR_BUFFERS / GUS_BUFFER_MULTIPLE];
1337int gus_restart;				/* how many restarts? */
1338int gus_stops;				/* how many times did voice stop? */
1339int gus_falsestops;			/* stopped but not done? */
1340int gus_continues;
1341
1342struct playcont {
1343	struct timeval tv;
1344	u_int playbuf;
1345	u_int dmabuf;
1346	u_char bufcnt;
1347	u_char vaction;
1348	u_char voccntl;
1349	u_char volcntl;
1350	u_long curaddr;
1351	u_long endaddr;
1352} playstats[NDMARECS];
1353
1354int playcntr;
1355
1356STATIC void
1357gus_dmaout_timeout(arg)
1358     void *arg;
1359{
1360    register struct gus_softc *sc = arg;
1361    register int port = sc->sc_iobase;
1362    int s;
1363
1364    printf("%s: dmaout timeout\n", sc->sc_dev.dv_xname);
1365    /*
1366     * Stop any DMA.
1367     */
1368
1369    s = splgus();
1370    SELECT_GUS_REG(port, GUSREG_DMA_CONTROL);
1371    outb(sc->sc_iobase+GUS_DATA_HIGH, 0);
1372
1373#if 0
1374    isa_dmaabort(sc->sc_drq);		/* XXX we will dmadone below? */
1375#endif
1376
1377    gus_dmaout_dointr(sc);
1378    splx(s);
1379}
1380
1381
1382/*
1383 * Service DMA interrupts.  This routine will only get called if we're doing
1384 * a DMA transfer for playback/record requests from the audio layer.
1385 */
1386
1387STATIC int
1388gus_dmaout_intr(sc)
1389	struct gus_softc *sc;
1390{
1391	register int port = sc->sc_iobase;
1392
1393	/*
1394	 * If we got a DMA transfer complete from the GUS DRAM, then deal
1395	 * with it.
1396	 */
1397
1398	SELECT_GUS_REG(port, GUSREG_DMA_CONTROL);
1399 	if (inb(port+GUS_DATA_HIGH) & GUSMASK_DMA_IRQPEND) {
1400	    untimeout(gus_dmaout_timeout, sc);
1401	    gus_dmaout_dointr(sc);
1402	    return 1;
1403	}
1404	return 0;
1405}
1406
1407STATIC void
1408gus_dmaout_dointr(sc)
1409	struct gus_softc *sc;
1410{
1411	register int port = sc->sc_iobase;
1412
1413	/* sc->sc_dmaoutcnt - 1 because DMA controller counts from zero?. */
1414	isa_dmadone(DMAMODE_WRITE,
1415		    sc->sc_dmaoutaddr,
1416		    sc->sc_dmaoutcnt - 1,
1417		    sc->sc_drq);
1418	sc->sc_flags &= ~GUS_DMAOUT_ACTIVE;  /* pending DMA is done */
1419	DMAPRINTF(("gus_dmaout_dointr %d @ %x\n", sc->sc_dmaoutcnt,
1420		   sc->sc_dmaoutaddr));
1421
1422	/*
1423	 * to prevent clicking, we need to copy last sample
1424	 * from last buffer to scratch area just before beginning of
1425	 * buffer.  However, if we're doing formats that are converted by
1426	 * the card during the DMA process, we need to pick up the converted
1427	 * byte rather than the one we have in memory.
1428	 */
1429	if (sc->sc_dmabuf == sc->sc_nbufs - 1) {
1430	  register int i;
1431	  switch (sc->sc_encoding) {
1432	  case AUDIO_ENCODING_PCM16:
1433	    /* we have the native format */
1434	    for (i = 1; i <= 2; i++)
1435	      guspoke(port, sc->sc_gusaddr -
1436		      (sc->sc_nbufs - 1) * sc->sc_chanblocksize - i,
1437		      sc->sc_dmaoutaddr[sc->sc_dmaoutcnt-i]);
1438	    break;
1439	  case AUDIO_ENCODING_PCM8:
1440	  case AUDIO_ENCODING_ULAW:
1441	    /* we need to fetch the translated byte, then stuff it. */
1442	    guspoke(port, sc->sc_gusaddr -
1443		    (sc->sc_nbufs - 1) * sc->sc_chanblocksize - 1,
1444		    guspeek(port,
1445			    sc->sc_gusaddr + sc->sc_chanblocksize - 1));
1446	    break;
1447	  }
1448	}
1449	/*
1450	 * If this is the first half of stereo, "ignore" this one
1451	 * and copy out the second half.
1452	 */
1453	if (sc->sc_dmaoutintr == stereo_dmaintr) {
1454	    (*sc->sc_dmaoutintr)(sc->sc_outarg);
1455	    return;
1456	}
1457	/*
1458	 * If the voice is stopped, then start it.  Reset the loop
1459	 * and roll bits.  Call the audio layer routine, since if
1460	 * we're starting a stopped voice, that means that the next
1461	 * buffer can be filled
1462	 */
1463
1464	sc->sc_flags &= ~GUS_LOCKED;
1465	if (sc->sc_voc[GUS_VOICE_LEFT].voccntl &
1466	    GUSMASK_VOICE_STOPPED) {
1467	    if (sc->sc_flags & GUS_PLAYING) {
1468		printf("%s: playing yet stopped?\n", sc->sc_dev.dv_xname);
1469	    }
1470	    sc->sc_bufcnt++; /* another yet to be played */
1471	    gus_start_playing(sc, sc->sc_dmabuf);
1472	    gus_restart++;
1473	} else {
1474	    /*
1475	     * set the sound action based on which buffer we
1476	     * just transferred.  If we just transferred buffer 0
1477	     * we want the sound to loop when it gets to the nth
1478	     * buffer; if we just transferred
1479	     * any other buffer, we want the sound to roll over
1480	     * at least one more time.  The voice interrupt
1481	     * handlers will take care of accounting &
1482	     * setting control bits if it's not caught up to us
1483	     * yet.
1484	     */
1485	    if (++sc->sc_bufcnt == 2) {
1486		/*
1487		 * XXX
1488		 * If we're too slow in reaction here,
1489		 * the voice could be just approaching the
1490		 * end of its run.  It should be set to stop,
1491		 * so these adjustments might not DTRT.
1492		 */
1493		if (sc->sc_dmabuf == 0 &&
1494		    sc->sc_playbuf == sc->sc_nbufs - 1) {
1495		    /* player is just at the last buf, we're at the
1496		       first.  Turn on looping, turn off rolling. */
1497		    sc->sc_voc[GUS_VOICE_LEFT].voccntl |= GUSMASK_LOOP_ENABLE;
1498		    sc->sc_voc[GUS_VOICE_LEFT].volcntl &= ~GUSMASK_VOICE_ROLL;
1499		    playstats[playcntr].vaction = 3;
1500		} else {
1501		    /* player is at previous buf:
1502		       turn on rolling, turn off looping */
1503		    sc->sc_voc[GUS_VOICE_LEFT].voccntl &= ~GUSMASK_LOOP_ENABLE;
1504		    sc->sc_voc[GUS_VOICE_LEFT].volcntl |= GUSMASK_VOICE_ROLL;
1505		    playstats[playcntr].vaction = 4;
1506		}
1507#ifdef GUSPLAYDEBUG
1508		if (gusstats) {
1509		  microtime(&playstats[playcntr].tv);
1510		  playstats[playcntr].endaddr = sc->sc_voc[GUS_VOICE_LEFT].end_addr;
1511		  playstats[playcntr].voccntl = sc->sc_voc[GUS_VOICE_LEFT].voccntl;
1512		  playstats[playcntr].volcntl = sc->sc_voc[GUS_VOICE_LEFT].volcntl;
1513		  playstats[playcntr].playbuf = sc->sc_playbuf;
1514		  playstats[playcntr].dmabuf = sc->sc_dmabuf;
1515		  playstats[playcntr].bufcnt = sc->sc_bufcnt;
1516		  playstats[playcntr].curaddr = gus_get_curaddr(sc, GUS_VOICE_LEFT);
1517		  playcntr = ++playcntr % NDMARECS;
1518		}
1519#endif
1520		outb(port+GUS_VOICE_SELECT, GUS_VOICE_LEFT);
1521		SELECT_GUS_REG(port, GUSREG_VOICE_CNTL);
1522		outb(port+GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_LEFT].voccntl);
1523		SELECT_GUS_REG(port, GUSREG_VOLUME_CONTROL);
1524		outb(port+GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_LEFT].volcntl);
1525	    }
1526	}
1527	gus_bufcnt[sc->sc_bufcnt-1]++;
1528	/*
1529	 * flip to the next DMA buffer
1530	 */
1531
1532	sc->sc_dmabuf = ++sc->sc_dmabuf % sc->sc_nbufs;
1533	/*
1534	 * See comments below about DMA admission control strategy.
1535	 * We can call the upper level here if we have an
1536	 * idle buffer (not currently playing) to DMA into.
1537	 */
1538	if (sc->sc_dmaoutintr && sc->sc_bufcnt < sc->sc_nbufs) {
1539	    /* clean out to prevent double calls */
1540	    void (*pfunc) __P((void *)) = sc->sc_dmaoutintr;
1541	    void *arg = sc->sc_outarg;
1542
1543	    sc->sc_outarg = 0;
1544	    sc->sc_dmaoutintr = 0;
1545	    (*pfunc)(arg);
1546	}
1547}
1548
1549/*
1550 * Service voice interrupts
1551 */
1552
1553STATIC int
1554gus_voice_intr(sc)
1555	struct gus_softc *sc;
1556{
1557	register int port = sc->sc_iobase;
1558	int ignore = 0, voice, rval = 0;
1559	unsigned char intr, status;
1560
1561	/*
1562	 * The point of this may not be obvious at first.  A voice can
1563	 * interrupt more than once; according to the GUS SDK we are supposed
1564	 * to ignore multiple interrupts for the same voice.
1565	 */
1566
1567	while(1) {
1568		SELECT_GUS_REG(port, GUSREG_IRQ_STATUS);
1569		intr = inb(port+GUS_DATA_HIGH);
1570
1571		if ((intr & (GUSMASK_WIRQ_VOLUME | GUSMASK_WIRQ_VOICE))
1572			== (GUSMASK_WIRQ_VOLUME | GUSMASK_WIRQ_VOICE))
1573			/*
1574			 * No more interrupts, time to return
1575			 */
1576		 	return rval;
1577
1578		if ((intr & GUSMASK_WIRQ_VOICE) == 0) {
1579
1580		    /*
1581		     * We've got a voice interrupt.  Ignore previous
1582		     * interrupts by the same voice.
1583		     */
1584
1585		    rval = 1;
1586		    voice = intr & GUSMASK_WIRQ_VOICEMASK;
1587
1588		    if ((1 << voice) & ignore)
1589			break;
1590
1591		    ignore |= 1 << voice;
1592
1593		    /*
1594		     * If the voice is stopped, then force it to stop
1595		     * (this stops it from continuously generating IRQs)
1596		     */
1597
1598		    SELECT_GUS_REG(port, GUSREG_VOICE_CNTL+0x80);
1599		    status = inb(port+GUS_DATA_HIGH);
1600		    if (status & GUSMASK_VOICE_STOPPED) {
1601			if (voice != GUS_VOICE_LEFT) {
1602			    DMAPRINTF(("%s: spurious voice %d stop?\n",
1603				       sc->sc_dev.dv_xname, voice));
1604			    gus_stop_voice(sc, voice, 0);
1605			    continue;
1606			}
1607			gus_stop_voice(sc, voice, 1);
1608			/* also kill right voice */
1609			gus_stop_voice(sc, GUS_VOICE_RIGHT, 0);
1610			sc->sc_bufcnt--; /* it finished a buffer */
1611			if (sc->sc_bufcnt > 0) {
1612			    /*
1613			     * probably a race to get here: the voice
1614			     * stopped while the DMA code was just trying to
1615			     * get the next buffer in place.
1616			     * Start the voice again.
1617			     */
1618			    printf("%s: stopped voice not drained? (%x)\n",
1619				   sc->sc_dev.dv_xname, sc->sc_bufcnt);
1620			    gus_falsestops++;
1621
1622			    sc->sc_playbuf = ++sc->sc_playbuf % sc->sc_nbufs;
1623			    gus_start_playing(sc, sc->sc_playbuf);
1624			} else if (sc->sc_bufcnt < 0) {
1625#ifdef DDB
1626			    printf("%s: negative bufcnt in stopped voice\n",
1627				   sc->sc_dev.dv_xname);
1628			    Debugger();
1629#else
1630			    panic("%s: negative bufcnt in stopped voice",
1631				  sc->sc_dev.dv_xname);
1632#endif
1633			} else {
1634			    sc->sc_playbuf = -1; /* none are active */
1635			    gus_stops++;
1636			}
1637			/* fall through to callback and admit another
1638			   buffer.... */
1639		    } else if (sc->sc_bufcnt != 0) {
1640			/*
1641			 * This should always be taken if the voice
1642			 * is not stopped.
1643			 */
1644			gus_continues++;
1645			if (gus_continue_playing(sc, voice)) {
1646				/*
1647				 * we shouldn't have continued--active DMA
1648				 * is in the way in the ring, for
1649				 * some as-yet undebugged reason.
1650				 */
1651				gus_stop_voice(sc, GUS_VOICE_LEFT, 1);
1652				/* also kill right voice */
1653				gus_stop_voice(sc, GUS_VOICE_RIGHT, 0);
1654				sc->sc_playbuf = -1;
1655				gus_stops++;
1656			}
1657		    }
1658		    /*
1659		     * call the upper level to send on down another
1660		     * block. We do admission rate control as follows:
1661		     *
1662		     * When starting up output (in the first N
1663		     * blocks), call the upper layer after the DMA is
1664		     * complete (see above in gus_dmaout_intr()).
1665		     *
1666		     * When output is already in progress and we have
1667		     * no more GUS buffers to use for DMA, the DMA
1668		     * output routines do not call the upper layer.
1669		     * Instead, we call the DMA completion routine
1670		     * here, after the voice interrupts indicating
1671		     * that it's finished with a buffer.
1672		     *
1673		     * However, don't call anything here if the DMA
1674		     * output flag is set, (which shouldn't happen)
1675		     * because we'll squish somebody else's DMA if
1676		     * that's the case.  When DMA is done, it will
1677		     * call back if there is a spare buffer.
1678		     */
1679		    if (sc->sc_dmaoutintr && !(sc->sc_flags & GUS_LOCKED)) {
1680			if (sc->sc_dmaoutintr == stereo_dmaintr)
1681			    printf("gusdmaout botch?\n");
1682			else {
1683			    /* clean out to avoid double calls */
1684			    void (*pfunc) __P((void *)) = sc->sc_dmaoutintr;
1685			    void *arg = sc->sc_outarg;
1686
1687			    sc->sc_outarg = 0;
1688			    sc->sc_dmaoutintr = 0;
1689			    (*pfunc)(arg);
1690			}
1691		    }
1692		}
1693
1694		/*
1695		 * Ignore other interrupts for now
1696		 */
1697	}
1698	return 0;
1699}
1700
1701STATIC void
1702gus_start_playing(sc, bufno)
1703struct gus_softc *sc;
1704int bufno;
1705{
1706    register int port = sc->sc_iobase;
1707    /*
1708     * Start the voices playing, with buffer BUFNO.
1709     */
1710
1711    /*
1712     * Loop or roll if we have buffers ready.
1713     */
1714
1715    if (sc->sc_bufcnt == 1) {
1716	sc->sc_voc[GUS_VOICE_LEFT].voccntl &= ~(GUSMASK_LOOP_ENABLE);
1717	sc->sc_voc[GUS_VOICE_LEFT].volcntl &= ~(GUSMASK_VOICE_ROLL);
1718    } else {
1719	if (bufno == sc->sc_nbufs - 1) {
1720	    sc->sc_voc[GUS_VOICE_LEFT].voccntl |= GUSMASK_LOOP_ENABLE;
1721	    sc->sc_voc[GUS_VOICE_LEFT].volcntl &= ~(GUSMASK_VOICE_ROLL);
1722	} else {
1723	    sc->sc_voc[GUS_VOICE_LEFT].voccntl &= ~GUSMASK_LOOP_ENABLE;
1724	    sc->sc_voc[GUS_VOICE_LEFT].volcntl |= GUSMASK_VOICE_ROLL;
1725	}
1726    }
1727
1728    outb(port+GUS_VOICE_SELECT, GUS_VOICE_LEFT);
1729
1730    SELECT_GUS_REG(port, GUSREG_VOICE_CNTL);
1731    outb(port+GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_LEFT].voccntl);
1732
1733    SELECT_GUS_REG(port, GUSREG_VOLUME_CONTROL);
1734    outb(port+GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_LEFT].volcntl);
1735
1736    sc->sc_voc[GUS_VOICE_LEFT].current_addr =
1737	GUS_MEM_OFFSET + sc->sc_chanblocksize * bufno;
1738    sc->sc_voc[GUS_VOICE_LEFT].end_addr =
1739	sc->sc_voc[GUS_VOICE_LEFT].current_addr + sc->sc_chanblocksize - 1;
1740    sc->sc_voc[GUS_VOICE_RIGHT].current_addr =
1741	sc->sc_voc[GUS_VOICE_LEFT].current_addr +
1742	(gus_dostereo && sc->sc_channels == 2 ? GUS_LEFT_RIGHT_OFFSET : 0);
1743    /*
1744     * set up right channel to just loop forever, no interrupts,
1745     * starting at the buffer we just filled.  We'll feed it data
1746     * at the same time as left channel.
1747     */
1748    sc->sc_voc[GUS_VOICE_RIGHT].voccntl |= GUSMASK_LOOP_ENABLE;
1749    sc->sc_voc[GUS_VOICE_RIGHT].volcntl &= ~(GUSMASK_VOICE_ROLL);
1750
1751#ifdef GUSPLAYDEBUG
1752    if (gusstats) {
1753      microtime(&playstats[playcntr].tv);
1754      playstats[playcntr].curaddr = sc->sc_voc[GUS_VOICE_LEFT].current_addr;
1755
1756      playstats[playcntr].voccntl = sc->sc_voc[GUS_VOICE_LEFT].voccntl;
1757      playstats[playcntr].volcntl = sc->sc_voc[GUS_VOICE_LEFT].volcntl;
1758      playstats[playcntr].endaddr = sc->sc_voc[GUS_VOICE_LEFT].end_addr;
1759      playstats[playcntr].playbuf = bufno;
1760      playstats[playcntr].dmabuf = sc->sc_dmabuf;
1761      playstats[playcntr].bufcnt = sc->sc_bufcnt;
1762      playstats[playcntr].vaction = 5;
1763      playcntr = ++playcntr % NDMARECS;
1764    }
1765#endif
1766
1767    outb(port+GUS_VOICE_SELECT, GUS_VOICE_RIGHT);
1768    SELECT_GUS_REG(port, GUSREG_VOICE_CNTL);
1769    outb(port+GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_RIGHT].voccntl);
1770    SELECT_GUS_REG(port, GUSREG_VOLUME_CONTROL);
1771    outb(port+GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_RIGHT].volcntl);
1772
1773    gus_start_voice(sc, GUS_VOICE_RIGHT, 0);
1774    gus_start_voice(sc, GUS_VOICE_LEFT, 1);
1775    if (sc->sc_playbuf == -1)
1776	/* mark start of playing */
1777	sc->sc_playbuf = bufno;
1778}
1779
1780STATIC int
1781gus_continue_playing(sc, voice)
1782register struct gus_softc *sc;
1783int voice;
1784{
1785    register int port = sc->sc_iobase;
1786
1787    /*
1788     * stop this voice from interrupting while we work.
1789     */
1790
1791    SELECT_GUS_REG(port, GUSREG_VOICE_CNTL);
1792    outb(port+GUS_DATA_HIGH, sc->sc_voc[voice].voccntl & ~(GUSMASK_VOICE_IRQ));
1793
1794    /*
1795     * update playbuf to point to the buffer the hardware just started
1796     * playing
1797     */
1798    sc->sc_playbuf = ++sc->sc_playbuf % sc->sc_nbufs;
1799
1800    /*
1801     * account for buffer just finished
1802     */
1803    if (--sc->sc_bufcnt == 0) {
1804	DPRINTF(("gus: bufcnt 0 on continuing voice?\n"));
1805    }
1806    if (sc->sc_playbuf == sc->sc_dmabuf && (sc->sc_flags & GUS_LOCKED)) {
1807	printf("%s: continue into active dmabuf?\n", sc->sc_dev.dv_xname);
1808	return 1;
1809    }
1810
1811    /*
1812     * Select the end of the buffer based on the currently active
1813     * buffer, [plus extra contiguous buffers (if ready)].
1814     */
1815
1816    /*
1817     * set endpoint at end of buffer we just started playing.
1818     *
1819     * The total gets -1 because end addrs are one less than you might
1820     * think (the end_addr is the address of the last sample to play)
1821     */
1822    gus_set_endaddr(sc, voice, GUS_MEM_OFFSET +
1823		    sc->sc_chanblocksize * (sc->sc_playbuf + 1) - 1);
1824
1825    if (sc->sc_bufcnt < 2) {
1826	/*
1827	 * Clear out the loop and roll flags, and rotate the currently
1828	 * playing buffer.  That way, if we don't manage to get more
1829	 * data before this buffer finishes, we'll just stop.
1830	 */
1831	sc->sc_voc[voice].voccntl &= ~GUSMASK_LOOP_ENABLE;
1832	sc->sc_voc[voice].volcntl &= ~GUSMASK_VOICE_ROLL;
1833	playstats[playcntr].vaction = 0;
1834    } else {
1835	/*
1836	 * We have some buffers to play.  set LOOP if we're on the
1837	 * last buffer in the ring, otherwise set ROLL.
1838	 */
1839	if (sc->sc_playbuf == sc->sc_nbufs - 1) {
1840	    sc->sc_voc[voice].voccntl |= GUSMASK_LOOP_ENABLE;
1841	    sc->sc_voc[voice].volcntl &= ~GUSMASK_VOICE_ROLL;
1842	    playstats[playcntr].vaction = 1;
1843	} else {
1844	    sc->sc_voc[voice].voccntl &= ~GUSMASK_LOOP_ENABLE;
1845	    sc->sc_voc[voice].volcntl |= GUSMASK_VOICE_ROLL;
1846	    playstats[playcntr].vaction = 2;
1847	}
1848    }
1849#ifdef GUSPLAYDEBUG
1850    if (gusstats) {
1851      microtime(&playstats[playcntr].tv);
1852      playstats[playcntr].curaddr = gus_get_curaddr(sc, voice);
1853
1854      playstats[playcntr].voccntl = sc->sc_voc[voice].voccntl;
1855      playstats[playcntr].volcntl = sc->sc_voc[voice].volcntl;
1856      playstats[playcntr].endaddr = sc->sc_voc[voice].end_addr;
1857      playstats[playcntr].playbuf = sc->sc_playbuf;
1858      playstats[playcntr].dmabuf = sc->sc_dmabuf;
1859      playstats[playcntr].bufcnt = sc->sc_bufcnt;
1860      playcntr = ++playcntr % NDMARECS;
1861    }
1862#endif
1863
1864    /*
1865     * (re-)set voice parameters.  This will reenable interrupts from this
1866     * voice.
1867     */
1868
1869    SELECT_GUS_REG(port, GUSREG_VOICE_CNTL);
1870    outb(port+GUS_DATA_HIGH, sc->sc_voc[voice].voccntl);
1871    SELECT_GUS_REG(port, GUSREG_VOLUME_CONTROL);
1872    outb(port+GUS_DATA_HIGH, sc->sc_voc[voice].volcntl);
1873    return 0;
1874}
1875
1876/*
1877 * Send/receive data into GUS's DRAM using DMA.  Called at splgus()
1878 */
1879
1880STATIC void
1881gusdmaout(sc, flags, gusaddr, buffaddr, length)
1882	struct gus_softc *sc;
1883	int flags, length;
1884	u_long gusaddr;
1885	caddr_t buffaddr;
1886{
1887	register unsigned char c = (unsigned char) flags;
1888	register int port = sc->sc_iobase;
1889
1890	DMAPRINTF(("gusdmaout flags=%x scflags=%x\n", flags, sc->sc_flags));
1891
1892	sc->sc_gusaddr = gusaddr;
1893
1894	/*
1895	 * If we're using a 16 bit DMA channel, we have to jump through some
1896	 * extra hoops; this includes translating the DRAM address a bit
1897	 */
1898
1899	if (sc->sc_drq >= 4) {
1900		c |= GUSMASK_DMA_WIDTH;
1901		gusaddr = convert_to_16bit(gusaddr);
1902	}
1903
1904	/*
1905	 * Add flag bits that we always set - fast DMA, enable IRQ
1906	 */
1907
1908	c |= GUSMASK_DMA_ENABLE | GUSMASK_DMA_R0 | GUSMASK_DMA_IRQ;
1909
1910	/*
1911	 * Make sure the GUS _isn't_ setup for DMA
1912	 */
1913
1914 	SELECT_GUS_REG(port, GUSREG_DMA_CONTROL);
1915	outb(port+GUS_DATA_HIGH, 0);
1916
1917	/*
1918	 * Tell the PC DMA controller to start doing DMA
1919	 */
1920
1921	sc->sc_dmaoutaddr = (u_char *) buffaddr;
1922	sc->sc_dmaoutcnt = length;
1923	isa_dmastart(DMAMODE_WRITE, buffaddr, length, sc->sc_drq);
1924
1925	/*
1926	 * Set up DMA address - use the upper 16 bits ONLY
1927	 */
1928
1929	sc->sc_flags |= GUS_DMAOUT_ACTIVE;
1930
1931 	SELECT_GUS_REG(port, GUSREG_DMA_START);
1932 	outw(port+GUS_DATA_LOW, (int) (gusaddr >> 4));
1933
1934 	/*
1935 	 * Tell the GUS to start doing DMA
1936 	 */
1937
1938 	SELECT_GUS_REG(port, GUSREG_DMA_CONTROL);
1939	outb(port+GUS_DATA_HIGH, c);
1940
1941	/*
1942	 * XXX If we don't finish in one second, give up...
1943	 */
1944	untimeout(gus_dmaout_timeout, sc); /* flush old one, if there is one */
1945	timeout(gus_dmaout_timeout, sc, hz);
1946}
1947
1948/*
1949 * Start a voice playing on the GUS.  Called from interrupt handler at
1950 * splgus().
1951 */
1952
1953STATIC void
1954gus_start_voice(sc, voice, intrs)
1955	struct gus_softc *sc;
1956	int voice;
1957	int intrs;
1958{
1959	register int port = sc->sc_iobase;
1960	u_long start;
1961	u_long current;
1962	u_long end;
1963
1964	/*
1965	 * Pick all the values for the voice out of the gus_voice struct
1966	 * and use those to program the voice
1967	 */
1968
1969 	start = sc->sc_voc[voice].start_addr;
1970 	current = sc->sc_voc[voice].current_addr;
1971 	end = sc->sc_voc[voice].end_addr;
1972
1973 	/*
1974	 * If we're using 16 bit data, mangle the addresses a bit
1975	 */
1976
1977	if (sc->sc_voc[voice].voccntl & GUSMASK_DATA_SIZE16) {
1978	        /* -1 on start so that we get onto sample boundary--other
1979		   code always sets it for 1-byte rollover protection */
1980		start = convert_to_16bit(start-1);
1981		current = convert_to_16bit(current);
1982		end = convert_to_16bit(end);
1983	}
1984
1985	/*
1986	 * Select the voice we want to use, and program the data addresses
1987	 */
1988
1989	outb(port+GUS_VOICE_SELECT, (unsigned char) voice);
1990
1991	SELECT_GUS_REG(port, GUSREG_START_ADDR_HIGH);
1992	outw(port+GUS_DATA_LOW, ADDR_HIGH(start));
1993	SELECT_GUS_REG(port, GUSREG_START_ADDR_LOW);
1994	outw(port+GUS_DATA_LOW, ADDR_LOW(start));
1995
1996	SELECT_GUS_REG(port, GUSREG_CUR_ADDR_HIGH);
1997	outw(port+GUS_DATA_LOW, ADDR_HIGH(current));
1998	SELECT_GUS_REG(port, GUSREG_CUR_ADDR_LOW);
1999	outw(port+GUS_DATA_LOW, ADDR_LOW(current));
2000
2001	SELECT_GUS_REG(port, GUSREG_END_ADDR_HIGH);
2002	outw(port+GUS_DATA_LOW, ADDR_HIGH(end));
2003	SELECT_GUS_REG(port, GUSREG_END_ADDR_LOW);
2004	outw(port+GUS_DATA_LOW, ADDR_LOW(end));
2005
2006	/*
2007	 * (maybe) enable interrupts, disable voice stopping
2008	 */
2009
2010	if (intrs) {
2011		sc->sc_flags |= GUS_PLAYING; /* playing is about to start */
2012		sc->sc_voc[voice].voccntl |= GUSMASK_VOICE_IRQ;
2013		DMAPRINTF(("gus voice playing=%x\n", sc->sc_flags));
2014	} else
2015		sc->sc_voc[voice].voccntl &= ~GUSMASK_VOICE_IRQ;
2016	sc->sc_voc[voice].voccntl &= ~(GUSMASK_VOICE_STOPPED |
2017		GUSMASK_STOP_VOICE);
2018
2019	/*
2020	 * Tell the GUS about it.  Note that we're doing volume ramping here
2021	 * from 0 up to the set volume to help reduce clicks.
2022	 */
2023
2024	SELECT_GUS_REG(port, GUSREG_START_VOLUME);
2025	outb(port+GUS_DATA_HIGH, 0x00);
2026	SELECT_GUS_REG(port, GUSREG_END_VOLUME);
2027	outb(port+GUS_DATA_HIGH, sc->sc_voc[voice].current_volume >> 4);
2028	SELECT_GUS_REG(port, GUSREG_CUR_VOLUME);
2029	outw(port+GUS_DATA_LOW, 0x00);
2030	SELECT_GUS_REG(port, GUSREG_VOLUME_RATE);
2031	outb(port+GUS_DATA_HIGH, 63);
2032
2033	SELECT_GUS_REG(port, GUSREG_VOICE_CNTL);
2034	outb(port+GUS_DATA_HIGH, sc->sc_voc[voice].voccntl);
2035	SELECT_GUS_REG(port, GUSREG_VOLUME_CONTROL);
2036	outb(port+GUS_DATA_HIGH, 0x00);
2037	delay(50);
2038	SELECT_GUS_REG(port, GUSREG_VOICE_CNTL);
2039	outb(port+GUS_DATA_HIGH, sc->sc_voc[voice].voccntl);
2040	SELECT_GUS_REG(port, GUSREG_VOLUME_CONTROL);
2041	outb(port+GUS_DATA_HIGH, 0x00);
2042
2043}
2044
2045/*
2046 * Stop a given voice.  called at splgus()
2047 */
2048
2049STATIC void
2050gus_stop_voice(sc, voice, intrs_too)
2051	struct gus_softc *sc;
2052	int voice;
2053	int intrs_too;
2054{
2055	register int port = sc->sc_iobase;
2056
2057	sc->sc_voc[voice].voccntl |= GUSMASK_VOICE_STOPPED |
2058		GUSMASK_STOP_VOICE;
2059	if (intrs_too) {
2060	  sc->sc_voc[voice].voccntl &= ~(GUSMASK_VOICE_IRQ);
2061	  /* no more DMA to do */
2062	  sc->sc_flags &= ~GUS_PLAYING;
2063	}
2064	DMAPRINTF(("gusintr voice notplaying=%x\n", sc->sc_flags));
2065
2066	guspoke(port, 0L, 0);
2067
2068	outb(port+GUS_VOICE_SELECT, (unsigned char) voice);
2069
2070	SELECT_GUS_REG(port, GUSREG_CUR_VOLUME);
2071	outw(port+GUS_DATA_LOW, 0x0000);
2072	SELECT_GUS_REG(port, GUSREG_VOICE_CNTL);
2073	outb(port+GUS_DATA_HIGH, sc->sc_voc[voice].voccntl);
2074	delay(100);
2075	SELECT_GUS_REG(port, GUSREG_CUR_VOLUME);
2076	outw(port+GUS_DATA_LOW, 0x0000);
2077	SELECT_GUS_REG(port, GUSREG_VOICE_CNTL);
2078	outb(port+GUS_DATA_HIGH, sc->sc_voc[voice].voccntl);
2079
2080	SELECT_GUS_REG(port, GUSREG_CUR_ADDR_HIGH);
2081	outw(port+GUS_DATA_LOW, 0x0000);
2082	SELECT_GUS_REG(port, GUSREG_CUR_ADDR_LOW);
2083	outw(port+GUS_DATA_LOW, 0x0000);
2084
2085}
2086
2087
2088/*
2089 * Set the volume of a given voice.  Called at splgus().
2090 */
2091STATIC void
2092gus_set_volume(sc, voice, volume)
2093	struct gus_softc *sc;
2094	int voice, volume;
2095{
2096	register int port = sc->sc_iobase;
2097	unsigned int gusvol;
2098
2099	gusvol = gus_log_volumes[volume < 512 ? volume : 511];
2100
2101	sc->sc_voc[voice].current_volume = gusvol;
2102
2103	outb(port+GUS_VOICE_SELECT, (unsigned char) voice);
2104
2105	SELECT_GUS_REG(port, GUSREG_START_VOLUME);
2106	outb(port+GUS_DATA_HIGH, (unsigned char) (gusvol >> 4));
2107
2108	SELECT_GUS_REG(port, GUSREG_END_VOLUME);
2109	outb(port+GUS_DATA_HIGH, (unsigned char) (gusvol >> 4));
2110
2111	SELECT_GUS_REG(port, GUSREG_CUR_VOLUME);
2112	outw(port+GUS_DATA_LOW, gusvol << 4);
2113	delay(500);
2114	outw(port+GUS_DATA_LOW, gusvol << 4);
2115
2116}
2117
2118/*
2119 * Interface to the audio layer - set the data encoding type
2120 */
2121
2122int
2123gusmax_set_encoding(addr, encoding)
2124	void * addr;
2125	u_int encoding;
2126{
2127	register struct ad1848_softc *ac = addr;
2128	register struct gus_softc *sc = ac->parent;
2129	int error;
2130
2131	error = ad1848_set_encoding(ac, encoding);
2132	return (error ? error : gus_set_encoding(sc, encoding));
2133}
2134
2135int
2136gus_set_encoding(addr, encoding)
2137	void * addr;
2138	u_int encoding;
2139{
2140	register struct gus_softc *sc = addr;
2141
2142	DPRINTF(("gus_set_encoding called\n"));
2143
2144	/* XXX todo: add alaw for codec */
2145	if (encoding != AUDIO_ENCODING_ULAW &&
2146	    encoding != AUDIO_ENCODING_PCM16 &&
2147	    encoding != AUDIO_ENCODING_PCM8)
2148		return EINVAL;
2149
2150	if (encoding != AUDIO_ENCODING_PCM16)
2151		sc->sc_precision = 8;       /* XXX force it. */
2152
2153	sc->sc_encoding = encoding;
2154
2155	if (sc->sc_precision == 8) {
2156		sc->sc_voc[GUS_VOICE_LEFT].voccntl &= ~GUSMASK_DATA_SIZE16;
2157		sc->sc_voc[GUS_VOICE_RIGHT].voccntl &= ~GUSMASK_DATA_SIZE16;
2158	} else {
2159		sc->sc_voc[GUS_VOICE_LEFT].voccntl |= GUSMASK_DATA_SIZE16;
2160		sc->sc_voc[GUS_VOICE_RIGHT].voccntl |= GUSMASK_DATA_SIZE16;
2161	}
2162	return 0;
2163}
2164
2165int
2166gusmax_set_channels(addr, channels)
2167	void * addr;
2168	int channels;
2169{
2170	register struct ad1848_softc *ac = addr;
2171	register struct gus_softc *sc = ac->parent;
2172	int error;
2173
2174	error = ad1848_set_channels(ac, channels);
2175	return (error ? error : gus_set_channels(sc, channels));
2176}
2177
2178int
2179gus_set_channels(addr, channels)
2180	void * addr;
2181	int channels;
2182{
2183	register struct gus_softc *sc = addr;
2184
2185	DPRINTF(("gus_set_channels called\n"));
2186
2187	if (channels != 1 && channels != 2)
2188		return EINVAL;
2189
2190	sc->sc_channels = channels;
2191
2192	return 0;
2193}
2194
2195/*
2196 * Interface to the audio layer - set the data precision
2197 */
2198
2199int
2200gusmax_set_precision(addr, bits)
2201	void * addr;
2202	u_int bits;
2203{
2204	register struct ad1848_softc *ac = addr;
2205	register struct gus_softc *sc = ac->parent;
2206	int error;
2207
2208	error = ad1848_set_precision(ac, bits);
2209	return (error ? error : gus_set_precision(sc, bits));
2210}
2211
2212
2213int
2214gus_set_precision(addr, bits)
2215	void * addr;
2216	u_int bits;
2217{
2218	register struct gus_softc *sc = addr;
2219
2220	DPRINTF(("gus_set_precision called\n"));
2221
2222	if (bits != 8 && bits != 16)
2223		return EINVAL;
2224
2225	if (sc->sc_encoding != AUDIO_ENCODING_PCM16 && bits != 8)
2226		/* If we're doing PCM8 or MULAW, it must be 8 bits. */
2227		return EINVAL;
2228
2229	sc->sc_precision = bits;
2230
2231	if (bits == 16) {
2232		sc->sc_voc[GUS_VOICE_LEFT].voccntl |= GUSMASK_DATA_SIZE16;
2233		sc->sc_voc[GUS_VOICE_RIGHT].voccntl |= GUSMASK_DATA_SIZE16;
2234	} else {
2235		sc->sc_voc[GUS_VOICE_LEFT].voccntl &= ~GUSMASK_DATA_SIZE16;
2236		sc->sc_voc[GUS_VOICE_RIGHT].voccntl &= ~GUSMASK_DATA_SIZE16;
2237	}
2238	return 0;
2239}
2240
2241/*
2242 * Interface to the audio layer - set the blocksize to the correct number
2243 * of units
2244 */
2245
2246int
2247gusmax_round_blocksize(addr, blocksize)
2248	void * addr;
2249	int blocksize;
2250{
2251	register struct ad1848_softc *ac = addr;
2252	register struct gus_softc *sc = ac->parent;
2253
2254/*	blocksize = ad1848_round_blocksize(ac, blocksize);*/
2255	return gus_round_blocksize(sc, blocksize);
2256}
2257
2258int
2259gus_round_blocksize(addr, blocksize)
2260	void * addr;
2261	int blocksize;
2262{
2263	register struct gus_softc *sc = addr;
2264
2265	DPRINTF(("gus_round_blocksize called\n"));
2266
2267	if (sc->sc_encoding == AUDIO_ENCODING_ULAW && blocksize > 32768)
2268		blocksize = 32768;
2269	else if (blocksize > 65536)
2270		blocksize = 65536;
2271
2272	if ((blocksize % GUS_BUFFER_MULTIPLE) != 0)
2273		blocksize = (blocksize / GUS_BUFFER_MULTIPLE + 1) *
2274			GUS_BUFFER_MULTIPLE;
2275
2276	/* set up temporary buffer to hold the deinterleave, if necessary
2277	   for stereo output */
2278	if (sc->sc_deintr_buf) {
2279		FREE(sc->sc_deintr_buf, M_DEVBUF);
2280		sc->sc_deintr_buf = NULL;
2281	}
2282	MALLOC(sc->sc_deintr_buf, void *, blocksize>>1, M_DEVBUF, M_WAITOK);
2283
2284	sc->sc_blocksize = blocksize;
2285	/* multi-buffering not quite working yet. */
2286	sc->sc_nbufs = /*GUS_MEM_FOR_BUFFERS / blocksize*/ 2;
2287
2288	gus_set_chan_addrs(sc);
2289
2290	return blocksize;
2291}
2292
2293/*
2294 * Interfaces to the audio layer - return values from the software config
2295 * struct
2296 */
2297
2298int
2299gusmax_get_encoding(addr)
2300	void * addr;
2301{
2302	register struct ad1848_softc *ac = addr;
2303	register struct gus_softc *sc = ac->parent;
2304	return gus_get_encoding(sc);
2305}
2306
2307int
2308gus_get_encoding(addr)
2309	void * addr;
2310{
2311	register struct gus_softc *sc = addr;
2312
2313	DPRINTF(("gus_get_encoding called\n"));
2314
2315	/* XXX TODO: codec stuff */
2316	return sc->sc_encoding;
2317}
2318
2319int
2320gusmax_get_channels(addr)
2321	void * addr;
2322{
2323	register struct ad1848_softc *ac = addr;
2324	register struct gus_softc *sc = ac->parent;
2325	return gus_get_channels(sc);
2326}
2327
2328int
2329gus_get_channels(addr)
2330	void * addr;
2331{
2332	register struct gus_softc *sc = addr;
2333
2334	DPRINTF(("gus_get_channels called\n"));
2335
2336	return sc->sc_channels;
2337}
2338
2339u_long
2340gus_get_in_sr(addr)
2341	void * addr;
2342{
2343	register struct gus_softc *sc = addr;
2344
2345	DPRINTF(("gus_get_in_sr called\n"));
2346	return sc->sc_irate;
2347}
2348
2349u_long
2350gusmax_get_in_sr(addr)
2351	void * addr;
2352{
2353	register struct ad1848_softc *ac = addr;
2354	register struct gus_softc *sc = ac->parent;
2355	return gus_get_in_sr(sc);
2356}
2357
2358u_long
2359gusmax_get_out_sr(addr)
2360	void * addr;
2361{
2362	register struct ad1848_softc *ac = addr;
2363	register struct gus_softc *sc = ac->parent;
2364	return gus_get_out_sr(sc);
2365}
2366
2367u_long
2368gus_get_out_sr(addr)
2369	void * addr;
2370{
2371	register struct gus_softc *sc = addr;
2372
2373	DPRINTF(("gus_get_out_sr called\n"));
2374	return sc->sc_orate;
2375}
2376
2377int
2378gusmax_get_precision(addr)
2379	void * addr;
2380{
2381	register struct ad1848_softc *sc = addr;
2382	return gus_get_precision(sc->parent);
2383}
2384
2385int
2386gus_get_precision(addr)
2387	void * addr;
2388{
2389	register struct gus_softc *sc = addr;
2390
2391	DPRINTF(("gus_get_precision called\n"));
2392
2393	return sc->sc_precision;
2394}
2395
2396int
2397gus_get_out_gain(addr)
2398	caddr_t addr;
2399{
2400	register struct gus_softc *sc = (struct gus_softc *) addr;
2401
2402	DPRINTF(("gus_get_out_gain called\n"));
2403	return sc->sc_ogain / 2;
2404}
2405
2406/*
2407 * Interface to the audio layer - set the sample rate of the output voices
2408 */
2409
2410int
2411gusmax_set_out_sr(addr, rate)
2412	void * addr;
2413	u_long rate;
2414{
2415	register struct ad1848_softc *ac = addr;
2416	register struct gus_softc *sc = ac->parent;
2417	int error;
2418
2419	error = ad1848_set_out_sr(ac, rate);
2420	return (error ? error : gus_set_out_sr(sc, rate));
2421}
2422
2423int
2424gus_set_out_sr(addr, rate)
2425	void * addr;
2426	u_long rate;
2427{
2428	register struct gus_softc *sc = addr;
2429
2430	DPRINTF(("gus_set_out_sr called\n"));
2431
2432	if (rate > gus_max_frequency[sc->sc_voices - GUS_MIN_VOICES])
2433		rate = gus_max_frequency[sc->sc_voices - GUS_MIN_VOICES];
2434
2435	sc->sc_orate = rate;
2436
2437	return 0;
2438}
2439
2440STATIC inline void gus_set_voices(sc, voices)
2441struct gus_softc *sc;
2442int voices;
2443{
2444	register int port = sc->sc_iobase;
2445	/*
2446	 * Select the active number of voices
2447	 */
2448
2449	SELECT_GUS_REG(port, GUSREG_ACTIVE_VOICES);
2450	outb(port+GUS_DATA_HIGH, (voices-1) | 0xc0);
2451
2452	sc->sc_voices = voices;
2453}
2454
2455/*
2456 * Actually set the settings of various values on the card
2457 */
2458
2459int
2460gusmax_commit_settings(addr)
2461	void * addr;
2462{
2463	register struct ad1848_softc *ac = addr;
2464	register struct gus_softc *sc = ac->parent;
2465
2466	(void) ad1848_commit_settings(ac);
2467	return gus_commit_settings(sc);
2468}
2469
2470/*
2471 * Commit the settings.  Called at normal IPL.
2472 */
2473int
2474gus_commit_settings(addr)
2475	void * addr;
2476{
2477	register struct gus_softc *sc = addr;
2478	int s;
2479
2480	DPRINTF(("gus_commit_settings called (gain = %d)\n",sc->sc_ogain));
2481
2482
2483	s = splgus();
2484
2485	gus_set_recrate(sc, sc->sc_irate);
2486	gus_set_volume(sc, GUS_VOICE_LEFT, sc->sc_ogain);
2487	gus_set_volume(sc, GUS_VOICE_RIGHT, sc->sc_ogain);
2488	gus_set_samprate(sc, GUS_VOICE_LEFT, sc->sc_orate);
2489	gus_set_samprate(sc, GUS_VOICE_RIGHT, sc->sc_orate);
2490	splx(s);
2491	gus_set_chan_addrs(sc);
2492
2493	return 0;
2494}
2495
2496STATIC void
2497gus_set_chan_addrs(sc)
2498struct gus_softc *sc;
2499{
2500	/*
2501	 * We use sc_nbufs * blocksize bytes of storage in the on-board GUS
2502	 * ram.
2503	 * For mono, each of the sc_nbufs buffers is DMA'd to in one chunk,
2504	 * and both left & right channels play the same buffer.
2505	 *
2506	 * For stereo, each channel gets a contiguous half of the memory,
2507	 * and each has sc_nbufs buffers of size blocksize/2.
2508	 * Stereo data are deinterleaved in main memory before the DMA out
2509	 * routines are called to queue the output.
2510	 *
2511	 * The blocksize per channel is kept in sc_chanblocksize.
2512	 */
2513	if (sc->sc_channels == 2)
2514	    sc->sc_chanblocksize = sc->sc_blocksize/2;
2515	else
2516	    sc->sc_chanblocksize = sc->sc_blocksize;
2517
2518	sc->sc_voc[GUS_VOICE_LEFT].start_addr = GUS_MEM_OFFSET - 1;
2519	sc->sc_voc[GUS_VOICE_RIGHT].start_addr =
2520	    (gus_dostereo && sc->sc_channels == 2 ? GUS_LEFT_RIGHT_OFFSET : 0)
2521	      + GUS_MEM_OFFSET - 1;
2522	sc->sc_voc[GUS_VOICE_RIGHT].current_addr =
2523	    sc->sc_voc[GUS_VOICE_RIGHT].start_addr + 1;
2524	sc->sc_voc[GUS_VOICE_RIGHT].end_addr =
2525	    sc->sc_voc[GUS_VOICE_RIGHT].start_addr +
2526	    sc->sc_nbufs * sc->sc_chanblocksize;
2527
2528}
2529
2530/*
2531 * Set the sample rate of the given voice.  Called at splgus().
2532 */
2533
2534STATIC void
2535gus_set_samprate(sc, voice, freq)
2536	struct gus_softc *sc;
2537	int voice, freq;
2538{
2539	register int port = sc->sc_iobase;
2540	unsigned int fc;
2541	u_long temp, f = (u_long) freq;
2542
2543	/*
2544	 * calculate fc based on the number of active voices;
2545	 * we need to use longs to preserve enough bits
2546	 */
2547
2548	temp = (u_long) gus_max_frequency[sc->sc_voices-GUS_MIN_VOICES];
2549
2550 	fc = (unsigned int)(((f << 9L) + (temp >> 1L)) / temp);
2551
2552 	fc <<= 1;
2553
2554
2555	/*
2556	 * Program the voice frequency, and set it in the voice data record
2557	 */
2558
2559	outb(port+GUS_VOICE_SELECT, (unsigned char) voice);
2560	SELECT_GUS_REG(port, GUSREG_FREQ_CONTROL);
2561	outw(port+GUS_DATA_LOW, fc);
2562
2563	sc->sc_voc[voice].rate = freq;
2564
2565}
2566
2567/*
2568 * Interface to the audio layer - set the recording sampling rate
2569 */
2570
2571int
2572gusmax_set_in_sr(addr, rate)
2573	void * addr;
2574	u_long rate;
2575{
2576	register struct ad1848_softc *ac = addr;
2577	register struct gus_softc *sc = ac->parent;
2578	int error;
2579
2580	error = ad1848_set_in_sr(ac, rate);
2581	return (error ? error : gus_set_in_sr(sc, rate));
2582}
2583
2584
2585int
2586gus_set_in_sr(addr, rate)
2587	void *addr;
2588	u_long rate;
2589{
2590	register struct gus_softc *sc = addr;
2591
2592	DPRINTF(("gus_set_in_sr called\n"));
2593
2594	sc->sc_irate = rate;
2595
2596	return 0;
2597}
2598/*
2599 * Set the sample rate of the recording frequency.  Formula is from the GUS
2600 * SDK.  Called at splgus().
2601 */
2602
2603STATIC void
2604gus_set_recrate(sc, rate)
2605	struct gus_softc *sc;
2606	u_long rate;
2607{
2608	register int port = sc->sc_iobase;
2609	u_char realrate;
2610	DPRINTF(("gus_set_recrate %lu\n", rate));
2611
2612#if 0
2613	realrate = 9878400/(16*(rate+2)); /* formula from GUS docs */
2614#endif
2615	realrate = (9878400 >> 4)/rate - 2; /* formula from code, sigh. */
2616
2617	SELECT_GUS_REG(port, GUSREG_SAMPLE_FREQ);
2618 	outb(port+GUS_DATA_HIGH, realrate);
2619}
2620
2621/*
2622 * Interface to the audio layer - turn the output on or off.  Note that some
2623 * of these bits are flipped in the register
2624 */
2625
2626int
2627gusmax_speaker_ctl(addr, newstate)
2628	void * addr;
2629	int newstate;
2630{
2631	register struct ad1848_softc *sc = addr;
2632	return gus_speaker_ctl(sc->parent, newstate);
2633}
2634
2635int
2636gus_speaker_ctl(addr, newstate)
2637	void * addr;
2638	int newstate;
2639{
2640	register struct gus_softc *sc = (struct gus_softc *) addr;
2641
2642	/* Line out bit is flipped: 0 enables, 1 disables */
2643	if ((newstate == SPKR_ON) &&
2644	    (sc->sc_mixcontrol & GUSMASK_LINE_OUT)) {
2645		sc->sc_mixcontrol &= ~GUSMASK_LINE_OUT;
2646		outb(sc->sc_iobase+GUS_MIX_CONTROL, sc->sc_mixcontrol);
2647	}
2648	if ((newstate == SPKR_OFF) &&
2649	    (sc->sc_mixcontrol & GUSMASK_LINE_OUT) == 0) {
2650		sc->sc_mixcontrol |= GUSMASK_LINE_OUT;
2651		outb(sc->sc_iobase+GUS_MIX_CONTROL, sc->sc_mixcontrol);
2652	}
2653
2654	return 0;
2655}
2656
2657STATIC int
2658gus_linein_ctl(addr, newstate)
2659	void * addr;
2660	int newstate;
2661{
2662	register struct gus_softc *sc = (struct gus_softc *) addr;
2663
2664	/* Line in bit is flipped: 0 enables, 1 disables */
2665	if ((newstate == SPKR_ON) &&
2666	    (sc->sc_mixcontrol & GUSMASK_LINE_IN)) {
2667		sc->sc_mixcontrol &= ~GUSMASK_LINE_IN;
2668		outb(sc->sc_iobase+GUS_MIX_CONTROL, sc->sc_mixcontrol);
2669	}
2670	if ((newstate == SPKR_OFF) &&
2671	    (sc->sc_mixcontrol & GUSMASK_LINE_IN) == 0) {
2672		sc->sc_mixcontrol |= GUSMASK_LINE_IN;
2673		outb(sc->sc_iobase+GUS_MIX_CONTROL, sc->sc_mixcontrol);
2674	}
2675
2676	return 0;
2677}
2678
2679STATIC int
2680gus_mic_ctl(addr, newstate)
2681	void * addr;
2682	int newstate;
2683{
2684	register struct gus_softc *sc = (struct gus_softc *) addr;
2685
2686	/* Mic bit is normal: 1 enables, 0 disables */
2687	if ((newstate == SPKR_ON) &&
2688	    (sc->sc_mixcontrol & GUSMASK_MIC_IN) == 0) {
2689		sc->sc_mixcontrol |= GUSMASK_MIC_IN;
2690		outb(sc->sc_iobase+GUS_MIX_CONTROL, sc->sc_mixcontrol);
2691	}
2692	if ((newstate == SPKR_OFF) &&
2693	    (sc->sc_mixcontrol & GUSMASK_MIC_IN)) {
2694		sc->sc_mixcontrol &= ~GUSMASK_MIC_IN;
2695		outb(sc->sc_iobase+GUS_MIX_CONTROL, sc->sc_mixcontrol);
2696	}
2697
2698	return 0;
2699}
2700
2701/*
2702 * Set the end address of a give voice.  Called at splgus()
2703 */
2704
2705STATIC void
2706gus_set_endaddr(sc, voice, addr)
2707	struct gus_softc *sc;
2708	int voice;
2709	u_long addr;
2710{
2711	register int port = sc->sc_iobase;
2712
2713	sc->sc_voc[voice].end_addr = addr;
2714
2715	if (sc->sc_voc[voice].voccntl & GUSMASK_DATA_SIZE16)
2716		addr = convert_to_16bit(addr);
2717
2718	SELECT_GUS_REG(port, GUSREG_END_ADDR_HIGH);
2719	outw(port+GUS_DATA_LOW, ADDR_HIGH(addr));
2720	SELECT_GUS_REG(port, GUSREG_END_ADDR_LOW);
2721	outw(port+GUS_DATA_LOW, ADDR_LOW(addr));
2722
2723}
2724
2725#ifdef GUSPLAYDEBUG
2726/*
2727 * Set current address.  called at splgus()
2728 */
2729STATIC void
2730gus_set_curaddr(sc, voice, addr)
2731	struct gus_softc *sc;
2732	int voice;
2733	u_long addr;
2734{
2735	register int port = sc->sc_iobase;
2736
2737	sc->sc_voc[voice].current_addr = addr;
2738
2739	if (sc->sc_voc[voice].voccntl & GUSMASK_DATA_SIZE16)
2740		addr = convert_to_16bit(addr);
2741
2742	outb(port+GUS_VOICE_SELECT, (unsigned char) voice);
2743
2744	SELECT_GUS_REG(port, GUSREG_CUR_ADDR_HIGH);
2745	outw(port+GUS_DATA_LOW, ADDR_HIGH(addr));
2746	SELECT_GUS_REG(port, GUSREG_CUR_ADDR_LOW);
2747	outw(port+GUS_DATA_LOW, ADDR_LOW(addr));
2748
2749}
2750
2751/*
2752 * Get current GUS playback address.  Called at splgus().
2753 */
2754STATIC u_long
2755gus_get_curaddr(sc, voice)
2756	struct gus_softc *sc;
2757	int voice;
2758{
2759	register int port = sc->sc_iobase;
2760	u_long addr;
2761
2762	outb(port+GUS_VOICE_SELECT, (unsigned char) voice);
2763	SELECT_GUS_REG(port, GUSREG_CUR_ADDR_HIGH|GUSREG_READ);
2764	addr = (inw(port+GUS_DATA_LOW) & 0x1fff) << 7;
2765	SELECT_GUS_REG(port, GUSREG_CUR_ADDR_LOW|GUSREG_READ);
2766	addr |= (inw(port+GUS_DATA_LOW) >> 9L) & 0x7f;
2767
2768	if (sc->sc_voc[voice].voccntl & GUSMASK_DATA_SIZE16)
2769	    addr = (addr & 0xc0000) | ((addr & 0x1ffff) << 1); /* undo 16-bit change */
2770	DPRINTF(("gus voice %d curaddr %d end_addr %d\n",
2771		 voice, addr, sc->sc_voc[voice].end_addr));
2772	/* XXX sanity check the address? */
2773
2774	return(addr);
2775}
2776#endif
2777
2778/*
2779 * Convert an address value to a "16 bit" value - why this is necessary I
2780 * have NO idea
2781 */
2782
2783STATIC u_long
2784convert_to_16bit(address)
2785	u_long address;
2786{
2787	u_long old_address;
2788
2789	old_address = address;
2790	address >>= 1;
2791	address &= 0x0001ffffL;
2792	address |= (old_address & 0x000c0000L);
2793
2794	return (address);
2795}
2796
2797/*
2798 * Write a value into the GUS's DRAM
2799 */
2800
2801STATIC void
2802guspoke(port, address, value)
2803	int port;
2804	long address;
2805	unsigned char value;
2806{
2807
2808	/*
2809	 * Select the DRAM address
2810	 */
2811
2812 	SELECT_GUS_REG(port, GUSREG_DRAM_ADDR_LOW);
2813 	outw(port+GUS_DATA_LOW, (unsigned int) (address & 0xffff));
2814 	SELECT_GUS_REG(port, GUSREG_DRAM_ADDR_HIGH);
2815 	outb(port+GUS_DATA_HIGH, (unsigned char) ((address >> 16) & 0xff));
2816
2817	/*
2818	 * Actually write the data
2819	 */
2820
2821	outb(port+GUS_DRAM_DATA, value);
2822}
2823
2824/*
2825 * Read a value from the GUS's DRAM
2826 */
2827
2828STATIC unsigned char
2829guspeek(port, address)
2830	int port;
2831	u_long address;
2832{
2833
2834	/*
2835	 * Select the DRAM address
2836	 */
2837
2838 	SELECT_GUS_REG(port, GUSREG_DRAM_ADDR_LOW);
2839 	outw(port+GUS_DATA_LOW, (unsigned int) (address & 0xffff));
2840 	SELECT_GUS_REG(port, GUSREG_DRAM_ADDR_HIGH);
2841 	outb(port+GUS_DATA_HIGH, (unsigned char) ((address >> 16) & 0xff));
2842
2843	/*
2844	 * Read in the data from the board
2845	 */
2846
2847	return (unsigned char) inb(port+GUS_DRAM_DATA);
2848}
2849
2850/*
2851 * Reset the Gravis UltraSound card, completely
2852 */
2853
2854STATIC void
2855gusreset(sc, voices)
2856	struct gus_softc *sc;
2857	int voices;
2858{
2859	register int port = sc->sc_iobase;
2860	int i,s;
2861
2862	s = splgus();
2863
2864	/*
2865	 * Reset the GF1 chip
2866	 */
2867
2868	SELECT_GUS_REG(port, GUSREG_RESET);
2869	outb(port+GUS_DATA_HIGH, 0x00);
2870
2871	delay(500);
2872
2873	/*
2874	 * Release reset
2875	 */
2876
2877	SELECT_GUS_REG(port, GUSREG_RESET);
2878	outb(port+GUS_DATA_HIGH, GUSMASK_MASTER_RESET);
2879
2880	delay(500);
2881
2882	/*
2883	 * Reset MIDI port as well
2884	 */
2885
2886	outb(GUS_MIDI_CONTROL,MIDI_RESET);
2887
2888	delay(500);
2889
2890	outb(GUS_MIDI_CONTROL,0x00);
2891
2892	/*
2893	 * Clear interrupts
2894	 */
2895
2896	SELECT_GUS_REG(port, GUSREG_DMA_CONTROL);
2897	outb(port+GUS_DATA_HIGH, 0x00);
2898	SELECT_GUS_REG(port, GUSREG_TIMER_CONTROL);
2899	outb(port+GUS_DATA_HIGH, 0x00);
2900	SELECT_GUS_REG(port, GUSREG_SAMPLE_CONTROL);
2901	outb(port+GUS_DATA_HIGH, 0x00);
2902
2903	gus_set_voices(sc, voices);
2904
2905	inb(port+GUS_IRQ_STATUS);
2906	SELECT_GUS_REG(port, GUSREG_DMA_CONTROL);
2907	inb(port+GUS_DATA_HIGH);
2908	SELECT_GUS_REG(port, GUSREG_SAMPLE_CONTROL);
2909	inb(port+GUS_DATA_HIGH);
2910	SELECT_GUS_REG(port, GUSREG_IRQ_STATUS);
2911	inb(port+GUS_DATA_HIGH);
2912
2913	/*
2914	 * Reset voice specific information
2915	 */
2916
2917	for(i = 0; i < voices; i++) {
2918		outb(port+GUS_VOICE_SELECT, (unsigned char) i);
2919
2920		SELECT_GUS_REG(port, GUSREG_VOICE_CNTL);
2921
2922		sc->sc_voc[i].voccntl = GUSMASK_VOICE_STOPPED |
2923			GUSMASK_STOP_VOICE;
2924
2925		outb(port+GUS_DATA_HIGH, sc->sc_voc[i].voccntl);
2926
2927		sc->sc_voc[i].volcntl = GUSMASK_VOLUME_STOPPED |
2928				GUSMASK_STOP_VOLUME;
2929
2930		SELECT_GUS_REG(port, GUSREG_VOLUME_CONTROL);
2931		outb(port+GUS_DATA_HIGH, sc->sc_voc[i].volcntl);
2932
2933		delay(100);
2934
2935		gus_set_samprate(sc, i, 8000);
2936		SELECT_GUS_REG(port, GUSREG_START_ADDR_HIGH);
2937		outw(port+GUS_DATA_LOW, 0x0000);
2938		SELECT_GUS_REG(port, GUSREG_START_ADDR_LOW);
2939		outw(port+GUS_DATA_LOW, 0x0000);
2940		SELECT_GUS_REG(port, GUSREG_END_ADDR_HIGH);
2941		outw(port+GUS_DATA_LOW, 0x0000);
2942		SELECT_GUS_REG(port, GUSREG_END_ADDR_LOW);
2943		outw(port+GUS_DATA_LOW, 0x0000);
2944		SELECT_GUS_REG(port, GUSREG_VOLUME_RATE);
2945		outb(port+GUS_DATA_HIGH, 0x01);
2946		SELECT_GUS_REG(port, GUSREG_START_VOLUME);
2947		outb(port+GUS_DATA_HIGH, 0x10);
2948		SELECT_GUS_REG(port, GUSREG_END_VOLUME);
2949		outb(port+GUS_DATA_HIGH, 0xe0);
2950		SELECT_GUS_REG(port, GUSREG_CUR_VOLUME);
2951		outw(port+GUS_DATA_LOW, 0x0000);
2952
2953		SELECT_GUS_REG(port, GUSREG_CUR_ADDR_HIGH);
2954		outw(port+GUS_DATA_LOW, 0x0000);
2955		SELECT_GUS_REG(port, GUSREG_CUR_ADDR_LOW);
2956		outw(port+GUS_DATA_LOW, 0x0000);
2957		SELECT_GUS_REG(port, GUSREG_PAN_POS);
2958		outb(port+GUS_DATA_HIGH, 0x07);
2959	}
2960
2961	/*
2962	 * Clear out any pending IRQs
2963	 */
2964
2965	inb(port+GUS_IRQ_STATUS);
2966	SELECT_GUS_REG(port, GUSREG_DMA_CONTROL);
2967	inb(port+GUS_DATA_HIGH);
2968	SELECT_GUS_REG(port, GUSREG_SAMPLE_CONTROL);
2969	inb(port+GUS_DATA_HIGH);
2970	SELECT_GUS_REG(port, GUSREG_IRQ_STATUS);
2971	inb(port+GUS_DATA_HIGH);
2972
2973	SELECT_GUS_REG(port, GUSREG_RESET);
2974	outb(port+GUS_DATA_HIGH, GUSMASK_MASTER_RESET | GUSMASK_DAC_ENABLE |
2975		GUSMASK_IRQ_ENABLE);
2976
2977	splx(s);
2978}
2979
2980
2981STATIC void
2982gus_init_cs4231(sc)
2983	struct gus_softc *sc;
2984{
2985	register int port = sc->sc_iobase;
2986	u_char ctrl;
2987
2988	ctrl = (port & 0xf0) >> 4;	/* set port address middle nibble */
2989	/*
2990	 * The codec is a bit weird--swapped dma channels.
2991	 */
2992	ctrl |= GUS_MAX_CODEC_ENABLE;
2993	if (sc->sc_drq >= 4)
2994		ctrl |= GUS_MAX_RECCHAN16;
2995	if (sc->sc_recdrq >= 4)
2996		ctrl |= GUS_MAX_PLAYCHAN16;
2997
2998	outb(port+GUS_MAX_CTRL, ctrl);
2999
3000	sc->sc_codec.sc_iobase = port+GUS_MAX_CODEC_BASE;
3001
3002	if (ad1848_probe(&sc->sc_codec) == 0) {
3003		sc->sc_flags &= ~GUS_CODEC_INSTALLED;
3004	} else {
3005		struct ad1848_volume vol = {AUDIO_MAX_GAIN, AUDIO_MAX_GAIN};
3006		struct audio_hw_if gusmax_hw_if = {
3007			gusopen,
3008			gusmax_close,
3009			NULL,				/* drain */
3010			gusmax_set_in_sr,
3011			gusmax_get_in_sr,
3012			gusmax_set_out_sr,
3013			gusmax_get_out_sr,
3014
3015			ad1848_query_encoding, /* query encoding */
3016			gusmax_set_encoding,
3017			gusmax_get_encoding,
3018
3019			gusmax_set_precision,
3020			gusmax_get_precision,
3021
3022			gusmax_set_channels,
3023			gusmax_get_channels,
3024
3025			gusmax_round_blocksize,
3026
3027			gusmax_set_out_port,
3028			gusmax_get_out_port,
3029			gusmax_set_in_port,
3030			gusmax_get_in_port,
3031
3032			gusmax_commit_settings,
3033
3034			gusmax_expand,	/* XXX use codec */
3035			mulaw_compress,
3036
3037			gusmax_dma_output,
3038			gusmax_dma_input,
3039			gusmax_halt_out_dma,
3040			gusmax_halt_in_dma,
3041			gusmax_cont_out_dma,
3042			gusmax_cont_in_dma,
3043
3044			gusmax_speaker_ctl,
3045
3046			gus_getdev,
3047			gus_setfd,
3048			gusmax_mixer_set_port,
3049			gusmax_mixer_get_port,
3050			gusmax_mixer_query_devinfo,
3051			1,				/* full-duplex */
3052			0,
3053		};
3054		sc->sc_flags |= GUS_CODEC_INSTALLED;
3055		sc->sc_codec.parent = sc;
3056		sc->sc_codec.sc_drq = sc->sc_recdrq;
3057		sc->sc_codec.sc_recdrq = sc->sc_drq;
3058		gus_hw_if = gusmax_hw_if;
3059		/* enable line in and mic in the GUS mixer; the codec chip
3060		   will do the real mixing for them. */
3061		sc->sc_mixcontrol &= ~GUSMASK_LINE_IN; /* 0 enables. */
3062		sc->sc_mixcontrol |= GUSMASK_MIC_IN; /* 1 enables. */
3063		outb(sc->sc_iobase+GUS_MIX_CONTROL, sc->sc_mixcontrol);
3064
3065		ad1848_attach(&sc->sc_codec);
3066		/* turn on pre-MUX microphone gain. */
3067		ad1848_set_mic_gain(&sc->sc_codec, &vol);
3068	}
3069}
3070
3071
3072/*
3073 * Return info about the audio device, for the AUDIO_GETINFO ioctl
3074 */
3075
3076int
3077gus_getdev(addr, dev)
3078	void * addr;
3079	struct audio_device *dev;
3080{
3081	*dev = gus_device;
3082	return 0;
3083}
3084
3085/*
3086 * stubs (XXX)
3087 */
3088
3089int
3090gus_set_in_gain(addr, gain, balance)
3091	caddr_t addr;
3092	u_int gain;
3093	u_char balance;
3094{
3095	DPRINTF(("gus_set_in_gain called\n"));
3096	return 0;
3097}
3098
3099int
3100gus_get_in_gain(addr)
3101	caddr_t addr;
3102{
3103	DPRINTF(("gus_get_in_gain called\n"));
3104	return 0;
3105}
3106
3107int
3108gusmax_set_out_port(addr, port)
3109	void * addr;
3110	int port;
3111{
3112	register struct ad1848_softc *sc = addr;
3113	return gus_set_out_port(sc->parent, port);
3114}
3115
3116int
3117gus_set_out_port(addr, port)
3118	void * addr;
3119	int port;
3120{
3121	register struct gus_softc *sc = addr;
3122	DPRINTF(("gus_set_out_port called\n"));
3123	sc->sc_out_port = port;
3124
3125	return 0;
3126}
3127
3128int
3129gusmax_get_out_port(addr)
3130	void * addr;
3131{
3132	register struct ad1848_softc *sc = addr;
3133	return gus_get_out_port(sc->parent);
3134}
3135
3136int
3137gus_get_out_port(addr)
3138	void * addr;
3139{
3140	register struct gus_softc *sc = addr;
3141	DPRINTF(("gus_get_out_port() called\n"));
3142	return sc->sc_out_port;
3143}
3144
3145int
3146gusmax_set_in_port(addr, port)
3147	void * addr;
3148	int port;
3149{
3150	register struct ad1848_softc *sc = addr;
3151	DPRINTF(("gusmax_set_in_port: %d\n", port));
3152
3153	switch(port) {
3154	case GUSMAX_MONO_LVL:
3155		port = MIC_IN_PORT;
3156		break;
3157	case GUSMAX_LINE_IN_LVL:
3158		port = LINE_IN_PORT;
3159		break;
3160	case GUSMAX_DAC_LVL:
3161		port = AUX1_IN_PORT;
3162		break;
3163	case GUSMAX_MIX_IN:
3164		port = DAC_IN_PORT;
3165		break;
3166	default:
3167		return(EINVAL);
3168		/*NOTREACHED*/
3169	}
3170	return(ad1848_set_rec_port(sc, port));
3171}
3172
3173int
3174gusmax_get_in_port(addr)
3175	void * addr;
3176{
3177	register struct ad1848_softc *sc = addr;
3178	int port = GUSMAX_MONO_LVL;
3179
3180	switch(ad1848_get_rec_port(sc)) {
3181	case MIC_IN_PORT:
3182		port = GUSMAX_MONO_LVL;
3183		break;
3184	case LINE_IN_PORT:
3185		port = GUSMAX_LINE_IN_LVL;
3186		break;
3187	case DAC_IN_PORT:
3188		port = GUSMAX_MIX_IN;
3189		break;
3190	case AUX1_IN_PORT:
3191		port = GUSMAX_DAC_LVL;
3192		break;
3193	}
3194
3195	DPRINTF(("gusmax_get_in_port: %d\n", port));
3196
3197	return(port);
3198}
3199
3200int
3201gus_set_in_port(addr, port)
3202	void * addr;
3203	int port;
3204{
3205	register struct gus_softc *sc = addr;
3206	DPRINTF(("gus_set_in_port called\n"));
3207	/*
3208	 * On the GUS with ICS mixer, the ADC input is after the mixer stage,
3209	 * so we can't set the input port.
3210	 *
3211	 * On the GUS with CS4231 codec/mixer, see gusmax_set_in_port().
3212	 */
3213	sc->sc_in_port = port;
3214
3215	return 0;
3216}
3217
3218
3219int
3220gus_get_in_port(addr)
3221	void * addr;
3222{
3223	register struct gus_softc *sc = addr;
3224	DPRINTF(("gus_get_in_port called\n"));
3225	return sc->sc_in_port;
3226}
3227
3228
3229int
3230gusmax_dma_input(addr, buf, size, callback, arg)
3231	void * addr;
3232	void *buf;
3233	int size;
3234	void (*callback) __P((void *));
3235	void *arg;
3236{
3237	register struct ad1848_softc *sc = addr;
3238	return gus_dma_input(sc->parent, buf, size, callback, arg);
3239}
3240
3241/*
3242 * Start sampling the input source into the requested DMA buffer.
3243 * Called at splgus(), either from top-half or from interrupt handler.
3244 */
3245int
3246gus_dma_input(addr, buf, size, callback, arg)
3247	void * addr;
3248	void *buf;
3249	int size;
3250	void (*callback) __P((void *));
3251	void *arg;
3252{
3253	register struct gus_softc *sc = addr;
3254	register int port = sc->sc_iobase;
3255	register u_char dmac;
3256	DMAPRINTF(("gus_dma_input called\n"));
3257
3258	/*
3259	 * Sample SIZE bytes of data from the card, into buffer at BUF.
3260	 */
3261
3262	if (sc->sc_precision == 16)
3263	    return EINVAL;		/* XXX */
3264
3265	/* set DMA modes */
3266	dmac = GUSMASK_SAMPLE_IRQ|GUSMASK_SAMPLE_START;
3267	if (sc->sc_recdrq >= 4)
3268		dmac |= GUSMASK_SAMPLE_DATA16;
3269	if (sc->sc_encoding == AUDIO_ENCODING_ULAW ||
3270	    sc->sc_encoding == AUDIO_ENCODING_PCM8)
3271	    dmac |= GUSMASK_SAMPLE_INVBIT;
3272	if (sc->sc_channels == 2)
3273	    dmac |= GUSMASK_SAMPLE_STEREO;
3274	isa_dmastart(DMAMODE_READ, (caddr_t) buf, size, sc->sc_recdrq);
3275
3276	DMAPRINTF(("gus_dma_input isa_dmastarted\n"));
3277	sc->sc_flags |= GUS_DMAIN_ACTIVE;
3278	sc->sc_dmainintr = callback;
3279	sc->sc_inarg = arg;
3280	sc->sc_dmaincnt = size;
3281	sc->sc_dmainaddr = buf;
3282
3283	SELECT_GUS_REG(port, GUSREG_SAMPLE_CONTROL);
3284	outb(port+GUS_DATA_HIGH, dmac);	/* Go! */
3285
3286
3287	DMAPRINTF(("gus_dma_input returning\n"));
3288
3289	return 0;
3290}
3291
3292STATIC int
3293gus_dmain_intr(sc)
3294	struct gus_softc *sc;
3295{
3296        void (*callback) __P((void *));
3297	void *arg;
3298
3299	DMAPRINTF(("gus_dmain_intr called\n"));
3300	if (sc->sc_dmainintr) {
3301	    isa_dmadone(DMAMODE_READ, sc->sc_dmainaddr, sc->sc_dmaincnt - 1,
3302			sc->sc_recdrq);
3303	    callback = sc->sc_dmainintr;
3304	    arg = sc->sc_inarg;
3305
3306	    sc->sc_dmainaddr = 0;
3307	    sc->sc_dmaincnt = 0;
3308	    sc->sc_dmainintr = 0;
3309	    sc->sc_inarg = 0;
3310
3311	    sc->sc_flags &= ~GUS_DMAIN_ACTIVE;
3312	    DMAPRINTF(("calling dmain_intr callback %x(%x)\n", callback, arg));
3313	    (*callback)(arg);
3314	    return 1;
3315	} else {
3316	    DMAPRINTF(("gus_dmain_intr false?\n"));
3317	    return 0;			/* XXX ??? */
3318	}
3319}
3320
3321int
3322gusmax_halt_out_dma(addr)
3323	void * addr;
3324{
3325	register struct ad1848_softc *sc = addr;
3326	return gus_halt_out_dma(sc->parent);
3327}
3328
3329
3330int
3331gusmax_halt_in_dma(addr)
3332	void * addr;
3333{
3334	register struct ad1848_softc *sc = addr;
3335	return gus_halt_in_dma(sc->parent);
3336}
3337
3338int
3339gusmax_cont_out_dma(addr)
3340	void * addr;
3341{
3342	register struct ad1848_softc *sc = addr;
3343	return gus_cont_out_dma(sc->parent);
3344}
3345
3346int
3347gusmax_cont_in_dma(addr)
3348	void * addr;
3349{
3350	register struct ad1848_softc *sc = addr;
3351	return gus_cont_in_dma(sc->parent);
3352}
3353
3354/*
3355 * Stop any DMA output.  Called at splgus().
3356 */
3357int
3358gus_halt_out_dma(addr)
3359	void * addr;
3360{
3361	register struct gus_softc *sc = addr;
3362	register int port = sc->sc_iobase;
3363
3364	DMAPRINTF(("gus_halt_out_dma called\n"));
3365	/*
3366	 * Make sure the GUS _isn't_ setup for DMA
3367	 */
3368
3369 	SELECT_GUS_REG(port, GUSREG_DMA_CONTROL);
3370	outb(sc->sc_iobase+GUS_DATA_HIGH, 0);
3371
3372	untimeout(gus_dmaout_timeout, sc);
3373	isa_dmaabort(sc->sc_drq);
3374	sc->sc_flags &= ~(GUS_DMAOUT_ACTIVE|GUS_LOCKED);
3375	sc->sc_dmaoutintr = 0;
3376	sc->sc_outarg = 0;
3377	sc->sc_dmaoutaddr = 0;
3378	sc->sc_dmaoutcnt = 0;
3379	sc->sc_dmabuf = 0;
3380	sc->sc_bufcnt = 0;
3381	sc->sc_playbuf = -1;
3382	/* also stop playing */
3383	gus_stop_voice(sc, GUS_VOICE_LEFT, 1);
3384	gus_stop_voice(sc, GUS_VOICE_RIGHT, 0);
3385
3386	return 0;
3387}
3388
3389/*
3390 * Stop any DMA output.  Called at splgus().
3391 */
3392int
3393gus_halt_in_dma(addr)
3394	void * addr;
3395{
3396	register struct gus_softc *sc = addr;
3397	register int port = sc->sc_iobase;
3398	DMAPRINTF(("gus_halt_in_dma called\n"));
3399
3400	/*
3401	 * Make sure the GUS _isn't_ setup for DMA
3402	 */
3403
3404 	SELECT_GUS_REG(port, GUSREG_SAMPLE_CONTROL);
3405	outb(port+GUS_DATA_HIGH,
3406	     inb(port+GUS_DATA_HIGH) & ~(GUSMASK_SAMPLE_START|GUSMASK_SAMPLE_IRQ));
3407
3408	isa_dmaabort(sc->sc_recdrq);
3409	sc->sc_flags &= ~GUS_DMAIN_ACTIVE;
3410	sc->sc_dmainintr = 0;
3411	sc->sc_inarg = 0;
3412	sc->sc_dmainaddr = 0;
3413	sc->sc_dmaincnt = 0;
3414
3415	return 0;
3416}
3417
3418int
3419gus_cont_out_dma(addr)
3420	void * addr;
3421{
3422	DPRINTF(("gus_cont_out_dma called\n"));
3423	return EOPNOTSUPP;
3424}
3425
3426int
3427gus_cont_in_dma(addr)
3428	void * addr;
3429{
3430	DPRINTF(("gus_cont_in_dma called\n"));
3431	return EOPNOTSUPP;
3432}
3433
3434
3435STATIC int
3436gus_setfd(addr, flag)
3437	void *addr;
3438	int flag;
3439{
3440    if (gus_hw_if.full_duplex == 0)
3441	 return ENOTTY;
3442
3443    return(0);				/* nothing fancy to do. */
3444}
3445
3446STATIC __inline int
3447gus_to_vol(cp, vol)
3448	mixer_ctrl_t *cp;
3449	struct ad1848_volume *vol;
3450{
3451	if (cp->un.value.num_channels == 1) {
3452		vol->left = vol->right = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
3453		return(1);
3454	}
3455	else if (cp->un.value.num_channels == 2) {
3456		vol->left  = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
3457		vol->right = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
3458		return(1);
3459	}
3460	return(0);
3461}
3462
3463STATIC __inline int
3464gus_from_vol(cp, vol)
3465	mixer_ctrl_t *cp;
3466	struct ad1848_volume *vol;
3467{
3468	if (cp->un.value.num_channels == 1) {
3469		cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = vol->left;
3470		return(1);
3471	}
3472	else if (cp->un.value.num_channels == 2) {
3473		cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = vol->left;
3474		cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = vol->right;
3475		return(1);
3476	}
3477	return(0);
3478}
3479
3480STATIC int
3481gusmax_mixer_get_port(addr, cp)
3482	void *addr;
3483	mixer_ctrl_t *cp;
3484{
3485	register struct ad1848_softc *ac = addr;
3486	register struct gus_softc *sc = ac->parent;
3487	struct ad1848_volume vol;
3488	int error = EINVAL;
3489
3490	DPRINTF(("gusmax_mixer_get_port: port=%d\n", cp->dev));
3491
3492	switch (cp->dev) {
3493#if 0 /* use mono level instead */
3494	case GUSMAX_MIC_IN_LVL:	/* Microphone */
3495		if (cp->type == AUDIO_MIXER_VALUE) {
3496			error = ad1848_get_mic_gain(ac, &vol);
3497			if (!error)
3498				gus_from_vol(cp, &vol);
3499		}
3500		break;
3501#endif
3502
3503	case GUSMAX_DAC_LVL:		/* dac out */
3504		if (cp->type == AUDIO_MIXER_VALUE) {
3505			error = ad1848_get_aux1_gain(ac, &vol);
3506			if (!error)
3507				gus_from_vol(cp, &vol);
3508		}
3509		break;
3510
3511	case GUSMAX_LINE_IN_LVL:	/* line in */
3512		if (cp->type == AUDIO_MIXER_VALUE) {
3513			error = cs4231_get_linein_gain(ac, &vol);
3514			if (!error)
3515				gus_from_vol(cp, &vol);
3516		}
3517		break;
3518
3519	case GUSMAX_MONO_LVL:	/* mono */
3520		if (cp->type == AUDIO_MIXER_VALUE &&
3521		    cp->un.value.num_channels == 1) {
3522			error = cs4231_get_mono_gain(ac, &vol);
3523			if (!error)
3524				gus_from_vol(cp, &vol);
3525		}
3526		break;
3527
3528	case GUSMAX_CD_LVL:	/* CD */
3529		if (cp->type == AUDIO_MIXER_VALUE) {
3530			error = ad1848_get_aux2_gain(ac, &vol);
3531			if (!error)
3532				gus_from_vol(cp, &vol);
3533		}
3534		break;
3535
3536	case GUSMAX_MONITOR_LVL:	/* monitor level */
3537		if (cp->type == AUDIO_MIXER_VALUE &&
3538		    cp->un.value.num_channels == 1) {
3539			error = ad1848_get_mon_gain(ac, &vol);
3540			if (!error)
3541				cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
3542					vol.left;
3543		}
3544		break;
3545
3546	case GUSMAX_OUT_LVL:	/* output level */
3547		if (cp->type == AUDIO_MIXER_VALUE) {
3548			error = ad1848_get_out_gain(ac, &vol);
3549			if (!error)
3550				gus_from_vol(cp, &vol);
3551		}
3552		break;
3553
3554	case GUSMAX_SPEAKER_LVL:	/* fake speaker for mute naming */
3555		if (cp->type == AUDIO_MIXER_VALUE) {
3556			if (sc->sc_mixcontrol & GUSMASK_LINE_OUT)
3557				vol.left = vol.right = AUDIO_MAX_GAIN;
3558			else
3559				vol.left = vol.right = AUDIO_MIN_GAIN;
3560			error = 0;
3561			gus_from_vol(cp, &vol);
3562		}
3563		break;
3564
3565	case GUSMAX_LINE_IN_MUTE:
3566		if (cp->type == AUDIO_MIXER_ENUM) {
3567			cp->un.ord = ac->line_mute;
3568			error = 0;
3569		}
3570		break;
3571
3572
3573	case GUSMAX_DAC_MUTE:
3574		if (cp->type == AUDIO_MIXER_ENUM) {
3575			cp->un.ord = ac->aux1_mute;
3576			error = 0;
3577		}
3578		break;
3579
3580	case GUSMAX_CD_MUTE:
3581		if (cp->type == AUDIO_MIXER_ENUM) {
3582			cp->un.ord = ac->aux2_mute;
3583			error = 0;
3584		}
3585		break;
3586
3587	case GUSMAX_MONO_MUTE:
3588		if (cp->type == AUDIO_MIXER_ENUM) {
3589			cp->un.ord = ac->mono_mute;
3590			error = 0;
3591		}
3592		break;
3593
3594	case GUSMAX_MONITOR_MUTE:
3595		if (cp->type == AUDIO_MIXER_ENUM) {
3596			cp->un.ord = ac->mon_mute;
3597			error = 0;
3598		}
3599		break;
3600
3601	case GUSMAX_SPEAKER_MUTE:
3602		if (cp->type == AUDIO_MIXER_ENUM) {
3603			cp->un.ord = sc->sc_mixcontrol & GUSMASK_LINE_OUT ? 1 : 0;
3604			error = 0;
3605		}
3606		break;
3607
3608	case GUSMAX_REC_LVL:		/* record level */
3609		if (cp->type == AUDIO_MIXER_VALUE) {
3610			error = ad1848_get_rec_gain(ac, &vol);
3611			if (!error)
3612				gus_from_vol(cp, &vol);
3613		}
3614		break;
3615
3616	case GUSMAX_RECORD_SOURCE:
3617		if (cp->type == AUDIO_MIXER_ENUM) {
3618			cp->un.ord = ad1848_get_rec_port(ac);
3619			error = 0;
3620		}
3621		break;
3622
3623	default:
3624		error = ENXIO;
3625		break;
3626	}
3627
3628	return(error);
3629}
3630
3631STATIC int
3632gus_mixer_get_port(addr, cp)
3633	void *addr;
3634	mixer_ctrl_t *cp;
3635{
3636	register struct gus_softc *sc = addr;
3637	register struct ics2101_softc *ic = &sc->sc_mixer;
3638	struct ad1848_volume vol;
3639	int error = EINVAL;
3640
3641	DPRINTF(("gus_mixer_get_port: dev=%d type=%d\n", cp->dev, cp->type));
3642
3643	if (!HAS_MIXER(sc) && cp->dev > GUSICS_MASTER_MUTE)
3644		return ENXIO;
3645
3646	switch (cp->dev) {
3647
3648	case GUSICS_MIC_IN_MUTE:	/* Microphone */
3649		if (cp->type == AUDIO_MIXER_ENUM) {
3650			if (HAS_MIXER(sc))
3651				cp->un.ord = ic->sc_mute[GUSMIX_CHAN_MIC][ICSMIX_LEFT];
3652			else
3653				cp->un.ord =
3654				    sc->sc_mixcontrol & GUSMASK_MIC_IN ? 0 : 1;
3655			error = 0;
3656		}
3657		break;
3658
3659	case GUSICS_LINE_IN_MUTE:
3660		if (cp->type == AUDIO_MIXER_ENUM) {
3661			if (HAS_MIXER(sc))
3662				cp->un.ord = ic->sc_mute[GUSMIX_CHAN_LINE][ICSMIX_LEFT];
3663			else
3664				cp->un.ord =
3665				    sc->sc_mixcontrol & GUSMASK_LINE_IN ? 1 : 0;
3666			error = 0;
3667		}
3668		break;
3669
3670	case GUSICS_MASTER_MUTE:
3671		if (cp->type == AUDIO_MIXER_ENUM) {
3672			if (HAS_MIXER(sc))
3673				cp->un.ord = ic->sc_mute[GUSMIX_CHAN_MASTER][ICSMIX_LEFT];
3674			else
3675				cp->un.ord =
3676				    sc->sc_mixcontrol & GUSMASK_LINE_OUT ? 1 : 0;
3677			error = 0;
3678		}
3679		break;
3680
3681	case GUSICS_DAC_MUTE:
3682		if (cp->type == AUDIO_MIXER_ENUM) {
3683			cp->un.ord = ic->sc_mute[GUSMIX_CHAN_DAC][ICSMIX_LEFT];
3684			error = 0;
3685		}
3686		break;
3687
3688	case GUSICS_CD_MUTE:
3689		if (cp->type == AUDIO_MIXER_ENUM) {
3690			cp->un.ord = ic->sc_mute[GUSMIX_CHAN_CD][ICSMIX_LEFT];
3691			error = 0;
3692		}
3693		break;
3694
3695	case GUSICS_MASTER_LVL:
3696		if (cp->type == AUDIO_MIXER_VALUE) {
3697			vol.left = ic->sc_setting[GUSMIX_CHAN_MASTER][ICSMIX_LEFT];
3698			vol.right = ic->sc_setting[GUSMIX_CHAN_MASTER][ICSMIX_RIGHT];
3699			if (gus_from_vol(cp, &vol))
3700				error = 0;
3701		}
3702		break;
3703
3704	case GUSICS_MIC_IN_LVL:	/* Microphone */
3705		if (cp->type == AUDIO_MIXER_VALUE) {
3706			vol.left = ic->sc_setting[GUSMIX_CHAN_MIC][ICSMIX_LEFT];
3707			vol.right = ic->sc_setting[GUSMIX_CHAN_MIC][ICSMIX_RIGHT];
3708			if (gus_from_vol(cp, &vol))
3709				error = 0;
3710		}
3711		break;
3712
3713	case GUSICS_LINE_IN_LVL:	/* line in */
3714		if (cp->type == AUDIO_MIXER_VALUE) {
3715			vol.left = ic->sc_setting[GUSMIX_CHAN_LINE][ICSMIX_LEFT];
3716			vol.right = ic->sc_setting[GUSMIX_CHAN_LINE][ICSMIX_RIGHT];
3717			if (gus_from_vol(cp, &vol))
3718				error = 0;
3719		}
3720		break;
3721
3722
3723	case GUSICS_CD_LVL:
3724		if (cp->type == AUDIO_MIXER_VALUE) {
3725			vol.left = ic->sc_setting[GUSMIX_CHAN_CD][ICSMIX_LEFT];
3726			vol.right = ic->sc_setting[GUSMIX_CHAN_CD][ICSMIX_RIGHT];
3727			if (gus_from_vol(cp, &vol))
3728				error = 0;
3729		}
3730		break;
3731
3732	case GUSICS_DAC_LVL:		/* dac out */
3733		if (cp->type == AUDIO_MIXER_VALUE) {
3734			vol.left = ic->sc_setting[GUSMIX_CHAN_DAC][ICSMIX_LEFT];
3735			vol.right = ic->sc_setting[GUSMIX_CHAN_DAC][ICSMIX_RIGHT];
3736			if (gus_from_vol(cp, &vol))
3737				error = 0;
3738		}
3739		break;
3740
3741
3742	case GUSICS_RECORD_SOURCE:
3743		if (cp->type == AUDIO_MIXER_ENUM) {
3744			/* Can't set anything else useful, sigh. */
3745			 cp->un.ord = 0;
3746		}
3747		break;
3748
3749	default:
3750		return ENXIO;
3751	    /*NOTREACHED*/
3752	}
3753	return error;
3754}
3755
3756STATIC void
3757gusics_master_mute(ic, mute)
3758	struct ics2101_softc *ic;
3759	int mute;
3760{
3761	ics2101_mix_mute(ic, GUSMIX_CHAN_MASTER, ICSMIX_LEFT, mute);
3762	ics2101_mix_mute(ic, GUSMIX_CHAN_MASTER, ICSMIX_RIGHT, mute);
3763}
3764
3765STATIC void
3766gusics_mic_mute(ic, mute)
3767	struct ics2101_softc *ic;
3768	int mute;
3769{
3770	ics2101_mix_mute(ic, GUSMIX_CHAN_MIC, ICSMIX_LEFT, mute);
3771	ics2101_mix_mute(ic, GUSMIX_CHAN_MIC, ICSMIX_RIGHT, mute);
3772}
3773
3774STATIC void
3775gusics_linein_mute(ic, mute)
3776	struct ics2101_softc *ic;
3777	int mute;
3778{
3779	ics2101_mix_mute(ic, GUSMIX_CHAN_LINE, ICSMIX_LEFT, mute);
3780	ics2101_mix_mute(ic, GUSMIX_CHAN_LINE, ICSMIX_RIGHT, mute);
3781}
3782
3783STATIC void
3784gusics_cd_mute(ic, mute)
3785	struct ics2101_softc *ic;
3786	int mute;
3787{
3788	ics2101_mix_mute(ic, GUSMIX_CHAN_CD, ICSMIX_LEFT, mute);
3789	ics2101_mix_mute(ic, GUSMIX_CHAN_CD, ICSMIX_RIGHT, mute);
3790}
3791
3792STATIC void
3793gusics_dac_mute(ic, mute)
3794	struct ics2101_softc *ic;
3795	int mute;
3796{
3797	ics2101_mix_mute(ic, GUSMIX_CHAN_DAC, ICSMIX_LEFT, mute);
3798	ics2101_mix_mute(ic, GUSMIX_CHAN_DAC, ICSMIX_RIGHT, mute);
3799}
3800
3801STATIC int
3802gusmax_mixer_set_port(addr, cp)
3803	void *addr;
3804	mixer_ctrl_t *cp;
3805{
3806	register struct ad1848_softc *ac = addr;
3807	register struct gus_softc *sc = ac->parent;
3808	struct ad1848_volume vol;
3809	int error = EINVAL;
3810
3811	DPRINTF(("gusmax_mixer_set_port: dev=%d type=%d\n", cp->dev, cp->type));
3812
3813	switch (cp->dev) {
3814#if 0
3815	case GUSMAX_MIC_IN_LVL:	/* Microphone */
3816		if (cp->type == AUDIO_MIXER_VALUE &&
3817		    cp->un.value.num_channels == 1) {
3818			/* XXX enable/disable pre-MUX fixed gain */
3819			if (gus_to_vol(cp, &vol))
3820				error = ad1848_set_mic_gain(ac, &vol);
3821		}
3822		break;
3823#endif
3824
3825	case GUSMAX_DAC_LVL:		/* dac out */
3826		if (cp->type == AUDIO_MIXER_VALUE) {
3827			if (gus_to_vol(cp, &vol))
3828				error = ad1848_set_aux1_gain(ac, &vol);
3829		}
3830		break;
3831
3832	case GUSMAX_LINE_IN_LVL:	/* line in */
3833		if (cp->type == AUDIO_MIXER_VALUE) {
3834			if (gus_to_vol(cp, &vol))
3835				error = cs4231_set_linein_gain(ac, &vol);
3836		}
3837		break;
3838
3839	case GUSMAX_MONO_LVL:	/* mic/mono in */
3840		if (cp->type == AUDIO_MIXER_VALUE &&
3841		    cp->un.value.num_channels == 1) {
3842			if (gus_to_vol(cp, &vol))
3843				error = cs4231_set_mono_gain(ac, &vol);
3844		}
3845		break;
3846
3847	case GUSMAX_CD_LVL:	/* CD: AUX2 */
3848		if (cp->type == AUDIO_MIXER_VALUE) {
3849			if (gus_to_vol(cp, &vol))
3850				error = ad1848_set_aux2_gain(ac, &vol);
3851		}
3852		break;
3853
3854	case GUSMAX_MONITOR_LVL:
3855		if (cp->type == AUDIO_MIXER_VALUE &&
3856		    cp->un.value.num_channels == 1) {
3857			vol.left  = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
3858			error = ad1848_set_mon_gain(ac, &vol);
3859		}
3860		break;
3861
3862	case GUSMAX_OUT_LVL:	/* output volume */
3863		if (cp->type == AUDIO_MIXER_VALUE) {
3864			if (gus_to_vol(cp, &vol))
3865				error = ad1848_set_out_gain(ac, &vol);
3866		}
3867		break;
3868
3869	case GUSMAX_SPEAKER_LVL:
3870		if (cp->type == AUDIO_MIXER_VALUE &&
3871		    cp->un.value.num_channels == 1) {
3872			if (gus_to_vol(cp, &vol)) {
3873				gus_speaker_ctl(sc, vol.left > AUDIO_MIN_GAIN ?
3874						SPKR_ON : SPKR_OFF);
3875				error = 0;
3876			}
3877		}
3878		break;
3879
3880	case GUSMAX_LINE_IN_MUTE:
3881		if (cp->type == AUDIO_MIXER_ENUM) {
3882			ac->line_mute = cp->un.ord ? 1 : 0;
3883			DPRINTF(("line mute %d\n", cp->un.ord));
3884			cs4231_mute_line(ac, ac->line_mute);
3885			gus_linein_ctl(sc, ac->line_mute ? SPKR_OFF : SPKR_ON);
3886			error = 0;
3887		}
3888		break;
3889
3890	case GUSMAX_DAC_MUTE:
3891		if (cp->type == AUDIO_MIXER_ENUM) {
3892			ac->aux1_mute = cp->un.ord ? 1 : 0;
3893			DPRINTF(("dac mute %d\n", cp->un.ord));
3894			ad1848_mute_aux1(ac, ac->aux1_mute);
3895			error = 0;
3896		}
3897		break;
3898
3899	case GUSMAX_CD_MUTE:
3900		if (cp->type == AUDIO_MIXER_ENUM) {
3901			ac->aux2_mute = cp->un.ord ? 1 : 0;
3902			DPRINTF(("cd mute %d\n", cp->un.ord));
3903			ad1848_mute_aux2(ac, ac->aux2_mute);
3904			error = 0;
3905		}
3906		break;
3907
3908	case GUSMAX_MONO_MUTE:	/* Microphone */
3909		if (cp->type == AUDIO_MIXER_ENUM) {
3910			ac->mono_mute = cp->un.ord ? 1 : 0;
3911			DPRINTF(("mono mute %d\n", cp->un.ord));
3912			cs4231_mute_mono(ac, ac->mono_mute);
3913			gus_mic_ctl(sc, ac->mono_mute ? SPKR_OFF : SPKR_ON);
3914			error = 0;
3915		}
3916		break;
3917
3918	case GUSMAX_MONITOR_MUTE:
3919		if (cp->type == AUDIO_MIXER_ENUM) {
3920			ac->mon_mute = cp->un.ord ? 1 : 0;
3921			DPRINTF(("mono mute %d\n", cp->un.ord));
3922			cs4231_mute_monitor(ac, ac->mon_mute);
3923			error = 0;
3924		}
3925		break;
3926
3927	case GUSMAX_SPEAKER_MUTE:
3928		if (cp->type == AUDIO_MIXER_ENUM) {
3929			gus_speaker_ctl(sc, cp->un.ord ? SPKR_OFF : SPKR_ON);
3930			error = 0;
3931		}
3932		break;
3933
3934	case GUSMAX_REC_LVL:		/* record level */
3935		if (cp->type == AUDIO_MIXER_VALUE) {
3936			if (gus_to_vol(cp, &vol))
3937				error = ad1848_set_rec_gain(ac, &vol);
3938		}
3939		break;
3940
3941	case GUSMAX_RECORD_SOURCE:
3942		if (cp->type == AUDIO_MIXER_ENUM) {
3943			error = ad1848_set_rec_port(ac, cp->un.ord);
3944		}
3945		break;
3946
3947	default:
3948		return ENXIO;
3949	    /*NOTREACHED*/
3950    }
3951    return error;
3952}
3953
3954STATIC int
3955gus_mixer_set_port(addr, cp)
3956	void *addr;
3957	mixer_ctrl_t *cp;
3958{
3959	register struct gus_softc *sc = addr;
3960	register struct ics2101_softc *ic = &sc->sc_mixer;
3961	struct ad1848_volume vol;
3962	int error = EINVAL;
3963
3964	DPRINTF(("gus_mixer_set_port: dev=%d type=%d\n", cp->dev, cp->type));
3965
3966	if (!HAS_MIXER(sc) && cp->dev > GUSICS_MASTER_MUTE)
3967		return ENXIO;
3968
3969	switch (cp->dev) {
3970
3971	case GUSICS_MIC_IN_MUTE:	/* Microphone */
3972		if (cp->type == AUDIO_MIXER_ENUM) {
3973			DPRINTF(("mic mute %d\n", cp->un.ord));
3974			if (HAS_MIXER(sc)) {
3975				gusics_mic_mute(ic, cp->un.ord);
3976			}
3977			gus_mic_ctl(sc, cp->un.ord ? SPKR_OFF : SPKR_ON);
3978			error = 0;
3979		}
3980		break;
3981
3982	case GUSICS_LINE_IN_MUTE:
3983		if (cp->type == AUDIO_MIXER_ENUM) {
3984			DPRINTF(("linein mute %d\n", cp->un.ord));
3985			if (HAS_MIXER(sc)) {
3986				gusics_linein_mute(ic, cp->un.ord);
3987			}
3988			gus_linein_ctl(sc, cp->un.ord ? SPKR_OFF : SPKR_ON);
3989			error = 0;
3990		}
3991		break;
3992
3993	case GUSICS_MASTER_MUTE:
3994		if (cp->type == AUDIO_MIXER_ENUM) {
3995			DPRINTF(("master mute %d\n", cp->un.ord));
3996			if (HAS_MIXER(sc)) {
3997				gusics_master_mute(ic, cp->un.ord);
3998			}
3999			gus_speaker_ctl(sc, cp->un.ord ? SPKR_OFF : SPKR_ON);
4000			error = 0;
4001		}
4002		break;
4003
4004	case GUSICS_DAC_MUTE:
4005		if (cp->type == AUDIO_MIXER_ENUM) {
4006			gusics_dac_mute(ic, cp->un.ord);
4007			error = 0;
4008		}
4009		break;
4010
4011	case GUSICS_CD_MUTE:
4012		if (cp->type == AUDIO_MIXER_ENUM) {
4013			gusics_cd_mute(ic, cp->un.ord);
4014			error = 0;
4015		}
4016		break;
4017
4018	case GUSICS_MASTER_LVL:
4019		if (cp->type == AUDIO_MIXER_VALUE) {
4020			if (gus_to_vol(cp, &vol)) {
4021				ics2101_mix_attenuate(ic,
4022						      GUSMIX_CHAN_MASTER,
4023						      ICSMIX_LEFT,
4024						      vol.left);
4025				ics2101_mix_attenuate(ic,
4026						      GUSMIX_CHAN_MASTER,
4027						      ICSMIX_RIGHT,
4028						      vol.right);
4029				error = 0;
4030			}
4031		}
4032		break;
4033
4034	case GUSICS_MIC_IN_LVL:	/* Microphone */
4035		if (cp->type == AUDIO_MIXER_VALUE) {
4036			if (gus_to_vol(cp, &vol)) {
4037				ics2101_mix_attenuate(ic,
4038						      GUSMIX_CHAN_MIC,
4039						      ICSMIX_LEFT,
4040						      vol.left);
4041				ics2101_mix_attenuate(ic,
4042						      GUSMIX_CHAN_MIC,
4043						      ICSMIX_RIGHT,
4044						      vol.right);
4045				error = 0;
4046			}
4047		}
4048		break;
4049
4050	case GUSICS_LINE_IN_LVL:	/* line in */
4051		if (cp->type == AUDIO_MIXER_VALUE) {
4052			if (gus_to_vol(cp, &vol)) {
4053				ics2101_mix_attenuate(ic,
4054						      GUSMIX_CHAN_LINE,
4055						      ICSMIX_LEFT,
4056						      vol.left);
4057				ics2101_mix_attenuate(ic,
4058						      GUSMIX_CHAN_LINE,
4059						      ICSMIX_RIGHT,
4060						      vol.right);
4061				error = 0;
4062			}
4063		}
4064		break;
4065
4066
4067	case GUSICS_CD_LVL:
4068		if (cp->type == AUDIO_MIXER_VALUE) {
4069			if (gus_to_vol(cp, &vol)) {
4070				ics2101_mix_attenuate(ic,
4071						      GUSMIX_CHAN_CD,
4072						      ICSMIX_LEFT,
4073						      vol.left);
4074				ics2101_mix_attenuate(ic,
4075						      GUSMIX_CHAN_CD,
4076						      ICSMIX_RIGHT,
4077						      vol.right);
4078				error = 0;
4079			}
4080		}
4081		break;
4082
4083	case GUSICS_DAC_LVL:		/* dac out */
4084		if (cp->type == AUDIO_MIXER_VALUE) {
4085			if (gus_to_vol(cp, &vol)) {
4086				ics2101_mix_attenuate(ic,
4087						      GUSMIX_CHAN_DAC,
4088						      ICSMIX_LEFT,
4089						      vol.left);
4090				ics2101_mix_attenuate(ic,
4091						      GUSMIX_CHAN_DAC,
4092						      ICSMIX_RIGHT,
4093						      vol.right);
4094				error = 0;
4095			}
4096		}
4097		break;
4098
4099
4100	case GUSICS_RECORD_SOURCE:
4101		if (cp->type == AUDIO_MIXER_ENUM && cp->un.ord == 0) {
4102			/* Can't set anything else useful, sigh. */
4103			error = 0;
4104		}
4105		break;
4106
4107	default:
4108		return ENXIO;
4109	    /*NOTREACHED*/
4110	}
4111	return error;
4112}
4113
4114STATIC int
4115gusmax_mixer_query_devinfo(addr, dip)
4116	void *addr;
4117	register mixer_devinfo_t *dip;
4118{
4119	DPRINTF(("gusmax_query_devinfo: index=%d\n", dip->index));
4120
4121	switch(dip->index) {
4122	case GUSMAX_MIX_IN:	/* mixed MUX input */
4123		dip->type = AUDIO_MIXER_ENUM;
4124		dip->mixer_class = GUSMAX_INPUT_CLASS;
4125		dip->prev = dip->next = AUDIO_MIXER_LAST;
4126		strcpy(dip->label.name, AudioNmixerout);
4127		dip->un.e.num_mem = 0;		/* XXX */
4128		break;
4129
4130#if 0
4131    case GUSMAX_MIC_IN_LVL:	/* Microphone */
4132	dip->type = AUDIO_MIXER_VALUE;
4133	dip->mixer_class = GUSMAX_INPUT_CLASS;
4134	dip->prev = AUDIO_MIXER_LAST;
4135	dip->next = GUSMAX_MIC_IN_MUTE;
4136	strcpy(dip->label.name, AudioNmicrophone);
4137	dip->un.v.num_channels = 2;
4138	strcpy(dip->un.v.units.name, AudioNvolume);
4139	break;
4140#endif
4141
4142    case GUSMAX_MONO_LVL:	/* mono/microphone mixer */
4143	dip->type = AUDIO_MIXER_VALUE;
4144	dip->mixer_class = GUSMAX_INPUT_CLASS;
4145	dip->prev = AUDIO_MIXER_LAST;
4146	dip->next = GUSMAX_MONO_MUTE;
4147	strcpy(dip->label.name, AudioNmicrophone);
4148	dip->un.v.num_channels = 1;
4149	strcpy(dip->un.v.units.name, AudioNvolume);
4150	break;
4151
4152    case GUSMAX_DAC_LVL:		/*  dacout */
4153	dip->type = AUDIO_MIXER_VALUE;
4154	dip->mixer_class = GUSMAX_INPUT_CLASS;
4155	dip->prev = AUDIO_MIXER_LAST;
4156	dip->next = GUSMAX_DAC_MUTE;
4157	strcpy(dip->label.name, AudioNdac);
4158	dip->un.v.num_channels = 2;
4159	strcpy(dip->un.v.units.name, AudioNvolume);
4160	break;
4161
4162    case GUSMAX_LINE_IN_LVL:	/* line */
4163	dip->type = AUDIO_MIXER_VALUE;
4164	dip->mixer_class = GUSMAX_INPUT_CLASS;
4165	dip->prev = AUDIO_MIXER_LAST;
4166	dip->next = GUSMAX_LINE_IN_MUTE;
4167	strcpy(dip->label.name, AudioNline);
4168	dip->un.v.num_channels = 2;
4169	strcpy(dip->un.v.units.name, AudioNvolume);
4170	break;
4171
4172    case GUSMAX_CD_LVL:		/* cd */
4173	dip->type = AUDIO_MIXER_VALUE;
4174	dip->mixer_class = GUSMAX_INPUT_CLASS;
4175	dip->prev = AUDIO_MIXER_LAST;
4176	dip->next = GUSMAX_CD_MUTE;
4177	strcpy(dip->label.name, AudioNcd);
4178	dip->un.v.num_channels = 2;
4179	strcpy(dip->un.v.units.name, AudioNvolume);
4180	break;
4181
4182
4183    case GUSMAX_MONITOR_LVL:	/* monitor level */
4184	dip->type = AUDIO_MIXER_VALUE;
4185	dip->mixer_class = GUSMAX_MONITOR_CLASS;
4186	dip->next = GUSMAX_MONITOR_MUTE;
4187	dip->prev = AUDIO_MIXER_LAST;
4188	strcpy(dip->label.name, AudioNmonitor);
4189	dip->un.v.num_channels = 1;
4190	strcpy(dip->un.v.units.name, AudioNvolume);
4191	break;
4192
4193    case GUSMAX_OUT_LVL:		/* cs4231 output volume: not useful? */
4194	dip->type = AUDIO_MIXER_VALUE;
4195	dip->mixer_class = GUSMAX_MONITOR_CLASS;
4196	dip->prev = dip->next = AUDIO_MIXER_LAST;
4197	strcpy(dip->label.name, AudioNoutput);
4198	dip->un.v.num_channels = 2;
4199	strcpy(dip->un.v.units.name, AudioNvolume);
4200	break;
4201
4202    case GUSMAX_SPEAKER_LVL:		/* fake speaker volume */
4203	dip->type = AUDIO_MIXER_VALUE;
4204	dip->mixer_class = GUSMAX_MONITOR_CLASS;
4205	dip->prev = AUDIO_MIXER_LAST;
4206	dip->next = GUSMAX_SPEAKER_MUTE;
4207	strcpy(dip->label.name, AudioNspeaker);
4208	dip->un.v.num_channels = 2;
4209	strcpy(dip->un.v.units.name, AudioNvolume);
4210	break;
4211
4212    case GUSMAX_LINE_IN_MUTE:
4213	dip->mixer_class = GUSMAX_INPUT_CLASS;
4214	dip->type = AUDIO_MIXER_ENUM;
4215	dip->prev = GUSMAX_LINE_IN_LVL;
4216	dip->next = AUDIO_MIXER_LAST;
4217	goto mute;
4218
4219    case GUSMAX_DAC_MUTE:
4220	dip->mixer_class = GUSMAX_INPUT_CLASS;
4221	dip->type = AUDIO_MIXER_ENUM;
4222	dip->prev = GUSMAX_DAC_LVL;
4223	dip->next = AUDIO_MIXER_LAST;
4224	goto mute;
4225
4226    case GUSMAX_CD_MUTE:
4227	dip->mixer_class = GUSMAX_INPUT_CLASS;
4228	dip->type = AUDIO_MIXER_ENUM;
4229	dip->prev = GUSMAX_CD_LVL;
4230	dip->next = AUDIO_MIXER_LAST;
4231	goto mute;
4232
4233    case GUSMAX_MONO_MUTE:
4234	dip->mixer_class = GUSMAX_INPUT_CLASS;
4235	dip->type = AUDIO_MIXER_ENUM;
4236	dip->prev = GUSMAX_MONO_LVL;
4237	dip->next = AUDIO_MIXER_LAST;
4238	goto mute;
4239
4240    case GUSMAX_MONITOR_MUTE:
4241	dip->mixer_class = GUSMAX_OUTPUT_CLASS;
4242	dip->type = AUDIO_MIXER_ENUM;
4243	dip->prev = GUSMAX_MONITOR_LVL;
4244	dip->next = AUDIO_MIXER_LAST;
4245	goto mute;
4246
4247    case GUSMAX_SPEAKER_MUTE:
4248	dip->mixer_class = GUSMAX_OUTPUT_CLASS;
4249	dip->type = AUDIO_MIXER_ENUM;
4250	dip->prev = GUSMAX_SPEAKER_LVL;
4251	dip->next = AUDIO_MIXER_LAST;
4252    mute:
4253	strcpy(dip->label.name, AudioNmute);
4254	dip->un.e.num_mem = 2;
4255	strcpy(dip->un.e.member[0].label.name, AudioNoff);
4256	dip->un.e.member[0].ord = 0;
4257	strcpy(dip->un.e.member[1].label.name, AudioNon);
4258	dip->un.e.member[1].ord = 1;
4259	break;
4260
4261    case GUSMAX_REC_LVL:	/* record level */
4262	dip->type = AUDIO_MIXER_VALUE;
4263	dip->mixer_class = GUSMAX_RECORD_CLASS;
4264	dip->prev = AUDIO_MIXER_LAST;
4265	dip->next = GUSMAX_RECORD_SOURCE;
4266	strcpy(dip->label.name, AudioNrecord);
4267	dip->un.v.num_channels = 2;
4268	strcpy(dip->un.v.units.name, AudioNvolume);
4269	break;
4270
4271    case GUSMAX_RECORD_SOURCE:
4272	dip->mixer_class = GUSMAX_RECORD_CLASS;
4273	dip->type = AUDIO_MIXER_ENUM;
4274	dip->prev = GUSMAX_REC_LVL;
4275	dip->next = AUDIO_MIXER_LAST;
4276	strcpy(dip->label.name, AudioNsource);
4277	dip->un.e.num_mem = 4;
4278	strcpy(dip->un.e.member[0].label.name, AudioNoutput);
4279	dip->un.e.member[0].ord = GUSMAX_MIX_IN;
4280	strcpy(dip->un.e.member[1].label.name, AudioNmicrophone);
4281	dip->un.e.member[1].ord = GUSMAX_MONO_LVL;
4282	strcpy(dip->un.e.member[2].label.name, AudioNdac);
4283	dip->un.e.member[2].ord = GUSMAX_DAC_LVL;
4284	strcpy(dip->un.e.member[3].label.name, AudioNline);
4285	dip->un.e.member[3].ord = GUSMAX_LINE_IN_LVL;
4286	break;
4287
4288    case GUSMAX_INPUT_CLASS:			/* input class descriptor */
4289	dip->type = AUDIO_MIXER_CLASS;
4290	dip->mixer_class = GUSMAX_INPUT_CLASS;
4291	dip->next = dip->prev = AUDIO_MIXER_LAST;
4292	strcpy(dip->label.name, AudioCInputs);
4293	break;
4294
4295    case GUSMAX_OUTPUT_CLASS:			/* output class descriptor */
4296	dip->type = AUDIO_MIXER_CLASS;
4297	dip->mixer_class = GUSMAX_OUTPUT_CLASS;
4298	dip->next = dip->prev = AUDIO_MIXER_LAST;
4299	strcpy(dip->label.name, AudioCOutputs);
4300	break;
4301
4302    case GUSMAX_MONITOR_CLASS:			/* monitor class descriptor */
4303	dip->type = AUDIO_MIXER_CLASS;
4304	dip->mixer_class = GUSMAX_MONITOR_CLASS;
4305	dip->next = dip->prev = AUDIO_MIXER_LAST;
4306	strcpy(dip->label.name, AudioCMonitor);
4307	break;
4308
4309    case GUSMAX_RECORD_CLASS:			/* record source class */
4310	dip->type = AUDIO_MIXER_CLASS;
4311	dip->mixer_class = GUSMAX_RECORD_CLASS;
4312	dip->next = dip->prev = AUDIO_MIXER_LAST;
4313	strcpy(dip->label.name, AudioCRecord);
4314	break;
4315
4316    default:
4317	return ENXIO;
4318	/*NOTREACHED*/
4319    }
4320    DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name));
4321	return 0;
4322}
4323
4324STATIC int
4325gus_mixer_query_devinfo(addr, dip)
4326	void *addr;
4327	register mixer_devinfo_t *dip;
4328{
4329	register struct gus_softc *sc = addr;
4330
4331	DPRINTF(("gusmax_query_devinfo: index=%d\n", dip->index));
4332
4333	if (!HAS_MIXER(sc) && dip->index > GUSICS_MASTER_MUTE)
4334		return ENXIO;
4335
4336	switch(dip->index) {
4337
4338	case GUSICS_MIC_IN_LVL:	/* Microphone */
4339		dip->type = AUDIO_MIXER_VALUE;
4340		dip->mixer_class = GUSICS_INPUT_CLASS;
4341		dip->prev = AUDIO_MIXER_LAST;
4342		dip->next = GUSICS_MIC_IN_MUTE;
4343		strcpy(dip->label.name, AudioNmicrophone);
4344		dip->un.v.num_channels = 2;
4345		strcpy(dip->un.v.units.name, AudioNvolume);
4346		break;
4347
4348	case GUSICS_LINE_IN_LVL:	/* line */
4349		dip->type = AUDIO_MIXER_VALUE;
4350		dip->mixer_class = GUSICS_INPUT_CLASS;
4351		dip->prev = AUDIO_MIXER_LAST;
4352		dip->next = GUSICS_LINE_IN_MUTE;
4353		strcpy(dip->label.name, AudioNline);
4354		dip->un.v.num_channels = 2;
4355		strcpy(dip->un.v.units.name, AudioNvolume);
4356		break;
4357
4358	case GUSICS_CD_LVL:		/* cd */
4359		dip->type = AUDIO_MIXER_VALUE;
4360		dip->mixer_class = GUSICS_INPUT_CLASS;
4361		dip->prev = AUDIO_MIXER_LAST;
4362		dip->next = GUSICS_CD_MUTE;
4363		strcpy(dip->label.name, AudioNcd);
4364		dip->un.v.num_channels = 2;
4365		strcpy(dip->un.v.units.name, AudioNvolume);
4366		break;
4367
4368	case GUSICS_DAC_LVL:		/*  dacout */
4369		dip->type = AUDIO_MIXER_VALUE;
4370		dip->mixer_class = GUSICS_INPUT_CLASS;
4371		dip->prev = AUDIO_MIXER_LAST;
4372		dip->next = GUSICS_DAC_MUTE;
4373		strcpy(dip->label.name, AudioNdac);
4374		dip->un.v.num_channels = 2;
4375		strcpy(dip->un.v.units.name, AudioNvolume);
4376		break;
4377
4378	case GUSICS_MASTER_LVL:		/*  master output */
4379		dip->type = AUDIO_MIXER_VALUE;
4380		dip->mixer_class = GUSICS_OUTPUT_CLASS;
4381		dip->prev = AUDIO_MIXER_LAST;
4382		dip->next = GUSICS_MASTER_MUTE;
4383		strcpy(dip->label.name, AudioNvolume);
4384		dip->un.v.num_channels = 2;
4385		strcpy(dip->un.v.units.name, AudioNvolume);
4386		break;
4387
4388
4389	case GUSICS_LINE_IN_MUTE:
4390		dip->mixer_class = GUSICS_INPUT_CLASS;
4391		dip->type = AUDIO_MIXER_ENUM;
4392		dip->prev = GUSICS_LINE_IN_LVL;
4393		dip->next = AUDIO_MIXER_LAST;
4394		goto mute;
4395
4396	case GUSICS_DAC_MUTE:
4397		dip->mixer_class = GUSICS_INPUT_CLASS;
4398		dip->type = AUDIO_MIXER_ENUM;
4399		dip->prev = GUSICS_DAC_LVL;
4400		dip->next = AUDIO_MIXER_LAST;
4401		goto mute;
4402
4403	case GUSICS_CD_MUTE:
4404		dip->mixer_class = GUSICS_INPUT_CLASS;
4405		dip->type = AUDIO_MIXER_ENUM;
4406		dip->prev = GUSICS_CD_LVL;
4407		dip->next = AUDIO_MIXER_LAST;
4408		goto mute;
4409
4410	case GUSICS_MIC_IN_MUTE:
4411		dip->mixer_class = GUSICS_INPUT_CLASS;
4412		dip->type = AUDIO_MIXER_ENUM;
4413		dip->prev = GUSICS_MIC_IN_LVL;
4414		dip->next = AUDIO_MIXER_LAST;
4415		goto mute;
4416
4417	case GUSICS_MASTER_MUTE:
4418		dip->mixer_class = GUSICS_OUTPUT_CLASS;
4419		dip->type = AUDIO_MIXER_ENUM;
4420		dip->prev = GUSICS_MASTER_LVL;
4421		dip->next = AUDIO_MIXER_LAST;
4422mute:
4423		strcpy(dip->label.name, AudioNmute);
4424		dip->un.e.num_mem = 2;
4425		strcpy(dip->un.e.member[0].label.name, AudioNoff);
4426		dip->un.e.member[0].ord = 0;
4427		strcpy(dip->un.e.member[1].label.name, AudioNon);
4428		dip->un.e.member[1].ord = 1;
4429		break;
4430
4431	case GUSICS_RECORD_SOURCE:
4432		dip->mixer_class = GUSICS_RECORD_CLASS;
4433		dip->type = AUDIO_MIXER_ENUM;
4434		dip->prev = dip->next = AUDIO_MIXER_LAST;
4435		strcpy(dip->label.name, AudioNsource);
4436		dip->un.e.num_mem = 1;
4437		strcpy(dip->un.e.member[0].label.name, AudioNoutput);
4438		dip->un.e.member[0].ord = GUSICS_MASTER_LVL;
4439		break;
4440
4441	case GUSICS_INPUT_CLASS:
4442		dip->type = AUDIO_MIXER_CLASS;
4443		dip->mixer_class = GUSICS_INPUT_CLASS;
4444		dip->next = dip->prev = AUDIO_MIXER_LAST;
4445		strcpy(dip->label.name, AudioCInputs);
4446		break;
4447
4448	case GUSICS_OUTPUT_CLASS:
4449		dip->type = AUDIO_MIXER_CLASS;
4450		dip->mixer_class = GUSICS_OUTPUT_CLASS;
4451		dip->next = dip->prev = AUDIO_MIXER_LAST;
4452		strcpy(dip->label.name, AudioCOutputs);
4453		break;
4454
4455	case GUSICS_RECORD_CLASS:
4456		dip->type = AUDIO_MIXER_CLASS;
4457		dip->mixer_class = GUSICS_RECORD_CLASS;
4458		dip->next = dip->prev = AUDIO_MIXER_LAST;
4459		strcpy(dip->label.name, AudioCRecord);
4460		break;
4461
4462	default:
4463		return ENXIO;
4464	/*NOTREACHED*/
4465	}
4466	DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name));
4467	return 0;
4468}
4469
4470STATIC int
4471gus_query_encoding(addr, fp)
4472	void *addr;
4473	struct audio_encoding *fp;
4474{
4475	switch (fp->index) {
4476	case 0:
4477		strcpy(fp->name, AudioEmulaw);
4478		fp->format_id = AUDIO_ENCODING_ULAW;
4479		break;
4480	case 1:
4481		strcpy(fp->name, AudioEpcm16);
4482		fp->format_id = AUDIO_ENCODING_PCM16;
4483		break;
4484	case 2:
4485		strcpy(fp->name, AudioEpcm8);
4486		fp->format_id = AUDIO_ENCODING_PCM8;
4487		break;
4488	default:
4489		return(EINVAL);
4490		/*NOTREACHED*/
4491	}
4492	return (0);
4493}
4494
4495/*
4496 * Setup the ICS mixer in "transparent" mode: reset everything to a sensible
4497 * level.  Levels as suggested by GUS SDK code.
4498 */
4499
4500STATIC void
4501gus_init_ics2101(sc)
4502	struct gus_softc *sc;
4503{
4504	register int port = sc->sc_iobase;
4505	register struct ics2101_softc *ic = &sc->sc_mixer;
4506	sc->sc_mixer.sc_selio = port+GUS_MIXER_SELECT;
4507	sc->sc_mixer.sc_dataio = port+GUS_MIXER_DATA;
4508	sc->sc_mixer.sc_flags = (sc->sc_revision == 5) ? ICS_FLIP : 0;
4509
4510	ics2101_mix_attenuate(ic,
4511			      GUSMIX_CHAN_MIC,
4512			      ICSMIX_LEFT,
4513			      ICSMIX_MIN_ATTN);
4514	ics2101_mix_attenuate(ic,
4515			      GUSMIX_CHAN_MIC,
4516			      ICSMIX_RIGHT,
4517			      ICSMIX_MIN_ATTN);
4518	/*
4519	 * Start with microphone muted by the mixer...
4520	 */
4521	gusics_mic_mute(ic, 1);
4522
4523	/* ... and enabled by the GUS master mix control */
4524	gus_mic_ctl(sc, SPKR_ON);
4525
4526	ics2101_mix_attenuate(ic,
4527			      GUSMIX_CHAN_LINE,
4528			      ICSMIX_LEFT,
4529			      ICSMIX_MIN_ATTN);
4530	ics2101_mix_attenuate(ic,
4531			      GUSMIX_CHAN_LINE,
4532			      ICSMIX_RIGHT,
4533			      ICSMIX_MIN_ATTN);
4534
4535	ics2101_mix_attenuate(ic,
4536			      GUSMIX_CHAN_CD,
4537			      ICSMIX_LEFT,
4538			      ICSMIX_MIN_ATTN);
4539	ics2101_mix_attenuate(ic,
4540			      GUSMIX_CHAN_CD,
4541			      ICSMIX_RIGHT,
4542			      ICSMIX_MIN_ATTN);
4543
4544	ics2101_mix_attenuate(ic,
4545			      GUSMIX_CHAN_DAC,
4546			      ICSMIX_LEFT,
4547			      ICSMIX_MIN_ATTN);
4548	ics2101_mix_attenuate(ic,
4549			      GUSMIX_CHAN_DAC,
4550			      ICSMIX_RIGHT,
4551			      ICSMIX_MIN_ATTN);
4552
4553	ics2101_mix_attenuate(ic,
4554			      ICSMIX_CHAN_4,
4555			      ICSMIX_LEFT,
4556			      ICSMIX_MAX_ATTN);
4557	ics2101_mix_attenuate(ic,
4558			      ICSMIX_CHAN_4,
4559			      ICSMIX_RIGHT,
4560			      ICSMIX_MAX_ATTN);
4561
4562	ics2101_mix_attenuate(ic,
4563			      GUSMIX_CHAN_MASTER,
4564			      ICSMIX_LEFT,
4565			      ICSMIX_MIN_ATTN);
4566	ics2101_mix_attenuate(ic,
4567			      GUSMIX_CHAN_MASTER,
4568			      ICSMIX_RIGHT,
4569			      ICSMIX_MIN_ATTN);
4570	/* unmute other stuff: */
4571	gusics_cd_mute(ic, 0);
4572	gusics_dac_mute(ic, 0);
4573	gusics_linein_mute(ic, 0);
4574	return;
4575}
4576
4577
4578#endif /* NGUS */
4579