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