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