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