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