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