Annotation of sys/dev/isa/gusvar.h, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: gusvar.h,v 1.5 2002/03/14 03:16:05 millert Exp $ */
! 2: /* $NetBSD: gus.c,v 1.51 1998/01/25 23:48:06 mycroft Exp $ */
! 3:
! 4: /*-
! 5: * Copyright (c) 1996 The NetBSD Foundation, Inc.
! 6: * All rights reserved.
! 7: *
! 8: * This code is derived from software contributed to The NetBSD Foundation
! 9: * by Ken Hornstein and John Kohl.
! 10: *
! 11: * Redistribution and use in source and binary forms, with or without
! 12: * modification, are permitted provided that the following conditions
! 13: * are met:
! 14: * 1. Redistributions of source code must retain the above copyright
! 15: * notice, this list of conditions and the following disclaimer.
! 16: * 2. Redistributions in binary form must reproduce the above copyright
! 17: * notice, this list of conditions and the following disclaimer in the
! 18: * documentation and/or other materials provided with the distribution.
! 19: * 3. All advertising materials mentioning features or use of this software
! 20: * must display the following acknowledgement:
! 21: * This product includes software developed by the NetBSD
! 22: * Foundation, Inc. and its contributors.
! 23: * 4. Neither the name of The NetBSD Foundation nor the names of its
! 24: * contributors may be used to endorse or promote products derived
! 25: * from this software without specific prior written permission.
! 26: *
! 27: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
! 28: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
! 29: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
! 30: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
! 31: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
! 32: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
! 33: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
! 34: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
! 35: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
! 36: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
! 37: * POSSIBILITY OF SUCH DAMAGE.
! 38: */
! 39:
! 40: /*
! 41: *
! 42: * TODO:
! 43: * . figure out why mixer activity while sound is playing causes problems
! 44: * (phantom interrupts?)
! 45: * . figure out a better deinterleave strategy that avoids sucking up
! 46: * CPU, memory and cache bandwidth. (Maybe a special encoding?
! 47: * Maybe use the double-speed sampling/hardware deinterleave trick
! 48: * from the GUS SDK?) A 486/33 isn't quite fast enough to keep
! 49: * up with 44.1kHz 16-bit stereo output without some drop-outs.
! 50: * . use CS4231 for 16-bit sampling, for a-law and mu-law playback.
! 51: * . actually test full-duplex sampling(recording) and playback.
! 52: */
! 53:
! 54: /*
! 55: * Gravis UltraSound driver
! 56: *
! 57: * For more detailed information, see the GUS developers' kit
! 58: * available on the net at:
! 59: *
! 60: * ftp://freedom.nmsu.edu/pub/ultrasound/gravis/util/
! 61: * gusdkXXX.zip (developers' kit--get rev 2.22 or later)
! 62: * See ultrawrd.doc inside--it's MS Word (ick), but it's the bible
! 63: *
! 64: */
! 65:
! 66: /*
! 67: * The GUS Max has a slightly strange set of connections between the CS4231
! 68: * and the GF1 and the DMA interconnects. It's set up so that the CS4231 can
! 69: * be playing while the GF1 is loading patches from the system.
! 70: *
! 71: * Here's a recreation of the DMA interconnect diagram:
! 72: *
! 73: * GF1
! 74: * +---------+ digital
! 75: * | | record ASIC
! 76: * | |--------------+
! 77: * | | | +--------+
! 78: * | | play (dram) | +----+ | |
! 79: * | |--------------(------|-\ | | +-+ |
! 80: * +---------+ | | >-|----|---|C|--|------ dma chan 1
! 81: * | +---|-/ | | +-+ |
! 82: * | | +----+ | | |
! 83: * | | +----+ | | |
! 84: * +---------+ +-+ +--(---|-\ | | | |
! 85: * | | play |8| | | >-|----|----+---|------ dma chan 2
! 86: * | ---C----|--------|/|------(---|-/ | | |
! 87: * | ^ |record |1| | +----+ | |
! 88: * | | | /----|6|------+ +--------+
! 89: * | ---+----|--/ +-+
! 90: * +---------+
! 91: * CS4231 8-to-16 bit bus conversion, if needed
! 92: *
! 93: *
! 94: * "C" is an optional combiner.
! 95: *
! 96: */
! 97:
! 98: /*
! 99: * Software state of a single "voice" on the GUS
! 100: */
! 101: struct gus_voice {
! 102:
! 103: /*
! 104: * Various control bits
! 105: */
! 106:
! 107: unsigned char voccntl; /* State of voice control register */
! 108: unsigned char volcntl; /* State of volume control register */
! 109: unsigned char pan_pos; /* Position of volume panning (4 bits) */
! 110: int rate; /* Sample rate of voice being played back */
! 111:
! 112: /*
! 113: * Address of the voice data into the GUS's DRAM. 20 bits each
! 114: */
! 115:
! 116: u_long start_addr; /* Starting address of voice data loop area */
! 117: u_long end_addr; /* Ending address of voice data loop */
! 118: u_long current_addr; /* Beginning address of voice data
! 119: (start playing here) */
! 120:
! 121: /*
! 122: * linear volume values for the GUS's volume ramp. 0-511 (9 bits).
! 123: * These values must be translated into the logarithmic values using
! 124: * gus_log_volumes[]
! 125: */
! 126:
! 127: int start_volume; /* Starting position of volume ramp */
! 128: int current_volume; /* Current position of volume on volume ramp */
! 129: int end_volume; /* Ending position of volume on volume ramp */
! 130: };
! 131:
! 132: /*
! 133: * Software state of GUS
! 134: */
! 135: struct gus_softc {
! 136: struct device sc_dev; /* base device */
! 137: struct device *sc_isa; /* pointer to ISA parent */
! 138: void *sc_ih; /* interrupt vector */
! 139: struct timeout sc_dma_tmo;
! 140: bus_space_tag_t sc_iot; /* tag */
! 141: bus_space_handle_t sc_ioh1; /* handle */
! 142: bus_space_handle_t sc_ioh2; /* handle */
! 143: bus_space_handle_t sc_ioh3; /* ICS2101 handle */
! 144: bus_space_handle_t sc_ioh4; /* MIDI handle */
! 145:
! 146: int sc_iobase; /* I/O base address */
! 147: int sc_irq; /* IRQ used */
! 148: int sc_drq; /* DMA channel for play */
! 149: int sc_recdrq; /* DMA channel for recording */
! 150:
! 151: int sc_flags; /* Various flags about the GUS */
! 152: #define GUS_MIXER_INSTALLED 0x01 /* An ICS mixer is installed */
! 153: #define GUS_LOCKED 0x02 /* GUS is busy doing multi-phase DMA */
! 154: #define GUS_CODEC_INSTALLED 0x04 /* CS4231 installed/MAX */
! 155: #define GUS_PLAYING 0x08 /* GUS is playing a voice */
! 156: #define GUS_DMAOUT_ACTIVE 0x10 /* GUS is busy doing audio DMA */
! 157: #define GUS_DMAIN_ACTIVE 0x20 /* GUS is busy sampling */
! 158: #define GUS_OPEN 0x100 /* GUS is open */
! 159: int sc_dsize; /* Size of GUS DRAM */
! 160: int sc_voices; /* Number of active voices */
! 161: u_char sc_revision; /* Board revision of GUS */
! 162: u_char sc_mixcontrol; /* Value of GUS_MIX_CONTROL register */
! 163:
! 164: u_long sc_orate; /* Output sampling rate */
! 165: u_long sc_irate; /* Input sampling rate */
! 166:
! 167: int sc_encoding; /* Current data encoding type */
! 168: int sc_precision; /* # of bits of precision */
! 169: int sc_channels; /* Number of active channels */
! 170: int sc_blocksize; /* Current blocksize */
! 171: int sc_chanblocksize; /* Current blocksize for each in-use
! 172: channel */
! 173: short sc_nbufs; /* how many on-GUS bufs per-channel */
! 174: short sc_bufcnt; /* how many need to be played */
! 175: void *sc_deintr_buf; /* deinterleave buffer for stereo */
! 176:
! 177: int sc_ogain; /* Output gain control */
! 178: u_char sc_out_port; /* Current out port (generic only) */
! 179: u_char sc_in_port; /* keep track of it when no codec */
! 180:
! 181: void (*sc_dmaoutintr)(void *); /* DMA completion intr handler */
! 182: void *sc_outarg; /* argument for sc_dmaoutintr() */
! 183: u_char *sc_dmaoutaddr; /* for isadma_done */
! 184: u_long sc_gusaddr; /* where did we just put it? */
! 185: int sc_dmaoutcnt; /* for isadma_done */
! 186:
! 187: void (*sc_dmainintr)(void *); /* DMA completion intr handler */
! 188: void *sc_inarg; /* argument for sc_dmaoutintr() */
! 189: u_char *sc_dmainaddr; /* for isadma_done */
! 190: int sc_dmaincnt; /* for isadma_done */
! 191:
! 192: struct stereo_dma_intr {
! 193: void (*intr)(void *);
! 194: void *arg;
! 195: u_char *buffer;
! 196: u_long dmabuf;
! 197: int size;
! 198: int flags;
! 199: } sc_stereo;
! 200:
! 201: /*
! 202: * State information for linear audio layer
! 203: */
! 204:
! 205: int sc_dmabuf; /* Which ring buffer we're DMA'ing to */
! 206: int sc_playbuf; /* Which ring buffer we're playing */
! 207:
! 208: /*
! 209: * Voice information array. All voice-specific information is stored
! 210: * here
! 211: */
! 212:
! 213: struct gus_voice sc_voc[32]; /* Voice data for each voice */
! 214: union {
! 215: struct ics2101_softc sc_mixer_u;
! 216: struct ad1848_softc sc_codec_u;
! 217: } u;
! 218: #define sc_mixer u.sc_mixer_u
! 219: #define sc_codec u.sc_codec_u
! 220: };
! 221:
! 222: struct ics2101_volume {
! 223: u_char left;
! 224: u_char right;
! 225: };
! 226:
! 227: #define HAS_CODEC(sc) ((sc)->sc_flags & GUS_CODEC_INSTALLED)
! 228: #define HAS_MIXER(sc) ((sc)->sc_flags & GUS_MIXER_INSTALLED)
! 229:
! 230: /*
! 231: * Mixer devices for ICS2101
! 232: */
! 233: /* MIC IN mute, line in mute, line out mute are first since they can be done
! 234: even if no ICS mixer. */
! 235: #define GUSICS_MIC_IN_MUTE 0
! 236: #define GUSICS_LINE_IN_MUTE 1
! 237: #define GUSICS_MASTER_MUTE 2
! 238: #define GUSICS_CD_MUTE 3
! 239: #define GUSICS_DAC_MUTE 4
! 240: #define GUSICS_MIC_IN_LVL 5
! 241: #define GUSICS_LINE_IN_LVL 6
! 242: #define GUSICS_CD_LVL 7
! 243: #define GUSICS_DAC_LVL 8
! 244: #define GUSICS_MASTER_LVL 9
! 245:
! 246: #define GUSICS_RECORD_SOURCE 10
! 247:
! 248: /* Classes */
! 249: #define GUSICS_INPUT_CLASS 11
! 250: #define GUSICS_OUTPUT_CLASS 12
! 251: #define GUSICS_RECORD_CLASS 13
! 252:
! 253: /*
! 254: * Mixer & MUX devices for CS4231
! 255: */
! 256: #define GUSMAX_MONO_LVL 0 /* mic input to MUX;
! 257: also mono mixer input */
! 258: #define GUSMAX_DAC_LVL 1 /* input to MUX; also mixer input */
! 259: #define GUSMAX_LINE_IN_LVL 2 /* input to MUX; also mixer input */
! 260: #define GUSMAX_CD_LVL 3 /* mixer input only */
! 261: #define GUSMAX_MONITOR_LVL 4 /* digital mix (?) */
! 262: #define GUSMAX_OUT_LVL 5 /* output level. (?) */
! 263: #define GUSMAX_SPEAKER_LVL 6 /* pseudo-device for mute */
! 264: #define GUSMAX_LINE_IN_MUTE 7 /* pre-mixer */
! 265: #define GUSMAX_DAC_MUTE 8 /* pre-mixer */
! 266: #define GUSMAX_CD_MUTE 9 /* pre-mixer */
! 267: #define GUSMAX_MONO_MUTE 10 /* pre-mixer--microphone/mono */
! 268: #define GUSMAX_MONITOR_MUTE 11 /* post-mixer level/mute */
! 269: #define GUSMAX_SPEAKER_MUTE 12 /* speaker mute */
! 270:
! 271: #define GUSMAX_REC_LVL 13 /* post-MUX gain */
! 272:
! 273: #define GUSMAX_RECORD_SOURCE 14
! 274:
! 275: /* Classes */
! 276: #define GUSMAX_INPUT_CLASS 15
! 277: #define GUSMAX_RECORD_CLASS 16
! 278: #define GUSMAX_MONITOR_CLASS 17
! 279: #define GUSMAX_OUTPUT_CLASS 18
! 280:
! 281: #ifdef AUDIO_DEBUG
! 282: #define GUSPLAYDEBUG /*XXX*/
! 283: #define DPRINTF(x) if (gusdebug) printf x
! 284: #define DMAPRINTF(x) if (gusdmadebug) printf x
! 285: extern int gusdebug;
! 286: extern int gusdmadebug;
! 287: #else
! 288: #define DPRINTF(x)
! 289: #define DMAPRINTF(x)
! 290: #endif
! 291: extern int gus_dostereo;
! 292:
! 293: #define NDMARECS 2048
! 294: #ifdef GUSPLAYDEBUG
! 295: extern int gusstats;
! 296: struct dma_record {
! 297: struct timeval tv;
! 298: u_long gusaddr;
! 299: caddr_t bsdaddr;
! 300: u_short count;
! 301: u_char channel;
! 302: u_char direction;
! 303: };
! 304:
! 305: extern struct dma_record dmarecords[NDMARECS];
! 306:
! 307: extern int dmarecord_index;
! 308: #endif
! 309:
! 310: /*
! 311: * local routines
! 312: */
! 313:
! 314: int gusopen(void *, int);
! 315: void gusclose(void *);
! 316: void gusmax_close(void *);
! 317: int gusintr(void *);
! 318: int gus_set_in_gain(caddr_t, u_int, u_char);
! 319: int gus_get_in_gain(caddr_t);
! 320: int gus_set_out_gain(caddr_t, u_int, u_char);
! 321: int gus_get_out_gain(caddr_t);
! 322: int gus_set_params(void *, int, int, struct audio_params *, struct audio_params *);
! 323: int gusmax_set_params(void *, int, int, struct audio_params *, struct audio_params *);
! 324: int gus_round_blocksize(void *, int);
! 325: int gus_commit_settings(void *);
! 326: int gus_dma_output(void *, void *, int, void (*)(void *), void *);
! 327: int gus_dma_input(void *, void *, int, void (*)(void *), void *);
! 328: int gus_halt_out_dma(void *);
! 329: int gus_halt_in_dma(void *);
! 330: int gus_speaker_ctl(void *, int);
! 331: int gusmaxopen(void *, int);
! 332: int gusmax_round_blocksize(void *, int);
! 333: int gusmax_commit_settings(void *);
! 334: int gusmax_dma_output(void *, void *, int, void (*)(void *), void *);
! 335: int gusmax_dma_input(void *, void *, int, void (*)(void *), void *);
! 336: int gusmax_halt_out_dma(void *);
! 337: int gusmax_halt_in_dma(void *);
! 338: int gusmax_speaker_ctl(void *, int);
! 339: int gus_getdev(void *, struct audio_device *);
! 340:
! 341: void gus_deinterleave(struct gus_softc *, void *, int);
! 342:
! 343: int gus_mic_ctl(void *, int);
! 344: int gus_linein_ctl(void *, int);
! 345: int gus_test_iobase(bus_space_tag_t, int);
! 346: void guspoke(bus_space_tag_t, bus_space_handle_t, long, u_char);
! 347: void gusdmaout(struct gus_softc *, int, u_long, caddr_t, int);
! 348: int gus_init_cs4231(struct gus_softc *);
! 349: void gus_init_ics2101(struct gus_softc *);
! 350:
! 351: void gus_set_chan_addrs(struct gus_softc *);
! 352: void gusreset(struct gus_softc *, int);
! 353: void gus_set_voices(struct gus_softc *, int);
! 354: void gus_set_volume(struct gus_softc *, int, int);
! 355: void gus_set_samprate(struct gus_softc *, int, int);
! 356: void gus_set_recrate(struct gus_softc *, u_long);
! 357: void gus_start_voice(struct gus_softc *, int, int);
! 358: void gus_stop_voice(struct gus_softc *, int, int);
! 359: void gus_set_endaddr(struct gus_softc *, int, u_long);
! 360: #ifdef GUSPLAYDEBUG
! 361: void gus_set_curaddr(struct gus_softc *, int, u_long);
! 362: u_long gus_get_curaddr(struct gus_softc *, int);
! 363: #endif
! 364: int gus_dmaout_intr(struct gus_softc *);
! 365: void gus_dmaout_dointr(struct gus_softc *);
! 366: void gus_dmaout_timeout(void *);
! 367: int gus_dmain_intr(struct gus_softc *);
! 368: int gus_voice_intr(struct gus_softc *);
! 369: void gus_start_playing(struct gus_softc *, int);
! 370: int gus_continue_playing(struct gus_softc *, int);
! 371: u_char guspeek(bus_space_tag_t, bus_space_handle_t, u_long);
! 372: u_long convert_to_16bit(u_long);
! 373: int gus_mixer_set_port(void *, mixer_ctrl_t *);
! 374: int gus_mixer_get_port(void *, mixer_ctrl_t *);
! 375: int gusmax_mixer_set_port(void *, mixer_ctrl_t *);
! 376: int gusmax_mixer_get_port(void *, mixer_ctrl_t *);
! 377: int gus_mixer_query_devinfo(void *, mixer_devinfo_t *);
! 378: int gusmax_mixer_query_devinfo(void *, mixer_devinfo_t *);
! 379: int gus_query_encoding(void *, struct audio_encoding *);
! 380: int gus_get_props(void *);
! 381: int gusmax_get_props(void *);
! 382:
! 383: void gusics_master_mute(struct ics2101_softc *, int);
! 384: void gusics_dac_mute(struct ics2101_softc *, int);
! 385: void gusics_mic_mute(struct ics2101_softc *, int);
! 386: void gusics_linein_mute(struct ics2101_softc *, int);
! 387: void gusics_cd_mute(struct ics2101_softc *, int);
! 388:
! 389: void stereo_dmaintr(void *);
! 390:
! 391: extern const int gus_irq_map[];
! 392: extern const int gus_drq_map[];
! 393: extern const int gus_base_addrs[];
! 394: extern const int gus_addrs;
! 395: extern const int gus_max_frequency[];
! 396:
! 397: extern const ushort gus_log_volumes[];
! 398:
! 399: #define SELECT_GUS_REG(iot,ioh1,x) bus_space_write_1(iot,ioh1,GUS_REG_SELECT,x)
! 400: #define ADDR_HIGH(x) (unsigned int) ((x >> 7L) & 0x1fffL)
! 401: #define ADDR_LOW(x) (unsigned int) ((x & 0x7fL) << 9L)
! 402:
! 403: #define GUS_MIN_VOICES 14 /* Minimum possible number of voices */
! 404: #define GUS_MAX_VOICES 32 /* Maximum possible number of voices */
! 405: #define GUS_VOICE_LEFT 0 /* Voice used for left (and mono) playback */
! 406: #define GUS_VOICE_RIGHT 1 /* Voice used for right playback */
! 407: #define GUS_MEM_OFFSET 32 /* Offset into GUS memory to begin of buffer */
! 408: #define GUS_BUFFER_MULTIPLE 1024 /* Audio buffers are multiples of this */
! 409: #define GUS_MEM_FOR_BUFFERS 131072 /* use this many bytes on-GUS */
! 410: #define GUS_LEFT_RIGHT_OFFSET (sc->sc_nbufs * sc->sc_chanblocksize + GUS_MEM_OFFSET)
! 411:
! 412: #define GUS_PREC_BYTES (sc->sc_precision >> 3) /* precision to bytes */
! 413:
! 414: /* splgus() must be splaudio() */
! 415:
! 416: #define splgus splaudio
! 417:
! 418: extern struct audio_hw_if gus_hw_if;
! 419: extern struct audio_hw_if gusmax_hw_if;
! 420: extern struct audio_device gus_device;
! 421:
! 422: #define FLIP_REV 5 /* This rev has flipped mixer chans */
! 423:
! 424: void gus_subattach(struct gus_softc *, struct isa_attach_args *);
CVSweb