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