File: [local] / sys / dev / isa / gusvar.h (download)
Revision 1.1, Tue Mar 4 16:11:20 2008 UTC (16 years, 5 months ago) by nbrk
Branch point for: MAIN
Initial revision
|
/* $OpenBSD: gusvar.h,v 1.5 2002/03/14 03:16:05 millert Exp $ */
/* $NetBSD: gus.c,v 1.51 1998/01/25 23:48:06 mycroft Exp $ */
/*-
* Copyright (c) 1996 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Ken Hornstein and John Kohl.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
*
* TODO:
* . figure out why mixer activity while sound is playing causes problems
* (phantom interrupts?)
* . figure out a better deinterleave strategy that avoids sucking up
* CPU, memory and cache bandwidth. (Maybe a special encoding?
* Maybe use the double-speed sampling/hardware deinterleave trick
* from the GUS SDK?) A 486/33 isn't quite fast enough to keep
* up with 44.1kHz 16-bit stereo output without some drop-outs.
* . use CS4231 for 16-bit sampling, for a-law and mu-law playback.
* . actually test full-duplex sampling(recording) and playback.
*/
/*
* Gravis UltraSound driver
*
* For more detailed information, see the GUS developers' kit
* available on the net at:
*
* ftp://freedom.nmsu.edu/pub/ultrasound/gravis/util/
* gusdkXXX.zip (developers' kit--get rev 2.22 or later)
* See ultrawrd.doc inside--it's MS Word (ick), but it's the bible
*
*/
/*
* The GUS Max has a slightly strange set of connections between the CS4231
* and the GF1 and the DMA interconnects. It's set up so that the CS4231 can
* be playing while the GF1 is loading patches from the system.
*
* Here's a recreation of the DMA interconnect diagram:
*
* GF1
* +---------+ digital
* | | record ASIC
* | |--------------+
* | | | +--------+
* | | play (dram) | +----+ | |
* | |--------------(------|-\ | | +-+ |
* +---------+ | | >-|----|---|C|--|------ dma chan 1
* | +---|-/ | | +-+ |
* | | +----+ | | |
* | | +----+ | | |
* +---------+ +-+ +--(---|-\ | | | |
* | | play |8| | | >-|----|----+---|------ dma chan 2
* | ---C----|--------|/|------(---|-/ | | |
* | ^ |record |1| | +----+ | |
* | | | /----|6|------+ +--------+
* | ---+----|--/ +-+
* +---------+
* CS4231 8-to-16 bit bus conversion, if needed
*
*
* "C" is an optional combiner.
*
*/
/*
* Software state of a single "voice" on the GUS
*/
struct gus_voice {
/*
* Various control bits
*/
unsigned char voccntl; /* State of voice control register */
unsigned char volcntl; /* State of volume control register */
unsigned char pan_pos; /* Position of volume panning (4 bits) */
int rate; /* Sample rate of voice being played back */
/*
* Address of the voice data into the GUS's DRAM. 20 bits each
*/
u_long start_addr; /* Starting address of voice data loop area */
u_long end_addr; /* Ending address of voice data loop */
u_long current_addr; /* Beginning address of voice data
(start playing here) */
/*
* linear volume values for the GUS's volume ramp. 0-511 (9 bits).
* These values must be translated into the logarithmic values using
* gus_log_volumes[]
*/
int start_volume; /* Starting position of volume ramp */
int current_volume; /* Current position of volume on volume ramp */
int end_volume; /* Ending position of volume on volume ramp */
};
/*
* Software state of GUS
*/
struct gus_softc {
struct device sc_dev; /* base device */
struct device *sc_isa; /* pointer to ISA parent */
void *sc_ih; /* interrupt vector */
struct timeout sc_dma_tmo;
bus_space_tag_t sc_iot; /* tag */
bus_space_handle_t sc_ioh1; /* handle */
bus_space_handle_t sc_ioh2; /* handle */
bus_space_handle_t sc_ioh3; /* ICS2101 handle */
bus_space_handle_t sc_ioh4; /* MIDI handle */
int sc_iobase; /* I/O base address */
int sc_irq; /* IRQ used */
int sc_drq; /* DMA channel for play */
int sc_recdrq; /* DMA channel for recording */
int sc_flags; /* Various flags about the GUS */
#define GUS_MIXER_INSTALLED 0x01 /* An ICS mixer is installed */
#define GUS_LOCKED 0x02 /* GUS is busy doing multi-phase DMA */
#define GUS_CODEC_INSTALLED 0x04 /* CS4231 installed/MAX */
#define GUS_PLAYING 0x08 /* GUS is playing a voice */
#define GUS_DMAOUT_ACTIVE 0x10 /* GUS is busy doing audio DMA */
#define GUS_DMAIN_ACTIVE 0x20 /* GUS is busy sampling */
#define GUS_OPEN 0x100 /* GUS is open */
int sc_dsize; /* Size of GUS DRAM */
int sc_voices; /* Number of active voices */
u_char sc_revision; /* Board revision of GUS */
u_char sc_mixcontrol; /* Value of GUS_MIX_CONTROL register */
u_long sc_orate; /* Output sampling rate */
u_long sc_irate; /* Input sampling rate */
int sc_encoding; /* Current data encoding type */
int sc_precision; /* # of bits of precision */
int sc_channels; /* Number of active channels */
int sc_blocksize; /* Current blocksize */
int sc_chanblocksize; /* Current blocksize for each in-use
channel */
short sc_nbufs; /* how many on-GUS bufs per-channel */
short sc_bufcnt; /* how many need to be played */
void *sc_deintr_buf; /* deinterleave buffer for stereo */
int sc_ogain; /* Output gain control */
u_char sc_out_port; /* Current out port (generic only) */
u_char sc_in_port; /* keep track of it when no codec */
void (*sc_dmaoutintr)(void *); /* DMA completion intr handler */
void *sc_outarg; /* argument for sc_dmaoutintr() */
u_char *sc_dmaoutaddr; /* for isadma_done */
u_long sc_gusaddr; /* where did we just put it? */
int sc_dmaoutcnt; /* for isadma_done */
void (*sc_dmainintr)(void *); /* DMA completion intr handler */
void *sc_inarg; /* argument for sc_dmaoutintr() */
u_char *sc_dmainaddr; /* for isadma_done */
int sc_dmaincnt; /* for isadma_done */
struct stereo_dma_intr {
void (*intr)(void *);
void *arg;
u_char *buffer;
u_long dmabuf;
int size;
int flags;
} sc_stereo;
/*
* State information for linear audio layer
*/
int sc_dmabuf; /* Which ring buffer we're DMA'ing to */
int sc_playbuf; /* Which ring buffer we're playing */
/*
* Voice information array. All voice-specific information is stored
* here
*/
struct gus_voice sc_voc[32]; /* Voice data for each voice */
union {
struct ics2101_softc sc_mixer_u;
struct ad1848_softc sc_codec_u;
} u;
#define sc_mixer u.sc_mixer_u
#define sc_codec u.sc_codec_u
};
struct ics2101_volume {
u_char left;
u_char right;
};
#define HAS_CODEC(sc) ((sc)->sc_flags & GUS_CODEC_INSTALLED)
#define HAS_MIXER(sc) ((sc)->sc_flags & GUS_MIXER_INSTALLED)
/*
* Mixer devices for ICS2101
*/
/* MIC IN mute, line in mute, line out mute are first since they can be done
even if no ICS mixer. */
#define GUSICS_MIC_IN_MUTE 0
#define GUSICS_LINE_IN_MUTE 1
#define GUSICS_MASTER_MUTE 2
#define GUSICS_CD_MUTE 3
#define GUSICS_DAC_MUTE 4
#define GUSICS_MIC_IN_LVL 5
#define GUSICS_LINE_IN_LVL 6
#define GUSICS_CD_LVL 7
#define GUSICS_DAC_LVL 8
#define GUSICS_MASTER_LVL 9
#define GUSICS_RECORD_SOURCE 10
/* Classes */
#define GUSICS_INPUT_CLASS 11
#define GUSICS_OUTPUT_CLASS 12
#define GUSICS_RECORD_CLASS 13
/*
* Mixer & MUX devices for CS4231
*/
#define GUSMAX_MONO_LVL 0 /* mic input to MUX;
also mono mixer input */
#define GUSMAX_DAC_LVL 1 /* input to MUX; also mixer input */
#define GUSMAX_LINE_IN_LVL 2 /* input to MUX; also mixer input */
#define GUSMAX_CD_LVL 3 /* mixer input only */
#define GUSMAX_MONITOR_LVL 4 /* digital mix (?) */
#define GUSMAX_OUT_LVL 5 /* output level. (?) */
#define GUSMAX_SPEAKER_LVL 6 /* pseudo-device for mute */
#define GUSMAX_LINE_IN_MUTE 7 /* pre-mixer */
#define GUSMAX_DAC_MUTE 8 /* pre-mixer */
#define GUSMAX_CD_MUTE 9 /* pre-mixer */
#define GUSMAX_MONO_MUTE 10 /* pre-mixer--microphone/mono */
#define GUSMAX_MONITOR_MUTE 11 /* post-mixer level/mute */
#define GUSMAX_SPEAKER_MUTE 12 /* speaker mute */
#define GUSMAX_REC_LVL 13 /* post-MUX gain */
#define GUSMAX_RECORD_SOURCE 14
/* Classes */
#define GUSMAX_INPUT_CLASS 15
#define GUSMAX_RECORD_CLASS 16
#define GUSMAX_MONITOR_CLASS 17
#define GUSMAX_OUTPUT_CLASS 18
#ifdef AUDIO_DEBUG
#define GUSPLAYDEBUG /*XXX*/
#define DPRINTF(x) if (gusdebug) printf x
#define DMAPRINTF(x) if (gusdmadebug) printf x
extern int gusdebug;
extern int gusdmadebug;
#else
#define DPRINTF(x)
#define DMAPRINTF(x)
#endif
extern int gus_dostereo;
#define NDMARECS 2048
#ifdef GUSPLAYDEBUG
extern int gusstats;
struct dma_record {
struct timeval tv;
u_long gusaddr;
caddr_t bsdaddr;
u_short count;
u_char channel;
u_char direction;
};
extern struct dma_record dmarecords[NDMARECS];
extern int dmarecord_index;
#endif
/*
* local routines
*/
int gusopen(void *, int);
void gusclose(void *);
void gusmax_close(void *);
int gusintr(void *);
int gus_set_in_gain(caddr_t, u_int, u_char);
int gus_get_in_gain(caddr_t);
int gus_set_out_gain(caddr_t, u_int, u_char);
int gus_get_out_gain(caddr_t);
int gus_set_params(void *, int, int, struct audio_params *, struct audio_params *);
int gusmax_set_params(void *, int, int, struct audio_params *, struct audio_params *);
int gus_round_blocksize(void *, int);
int gus_commit_settings(void *);
int gus_dma_output(void *, void *, int, void (*)(void *), void *);
int gus_dma_input(void *, void *, int, void (*)(void *), void *);
int gus_halt_out_dma(void *);
int gus_halt_in_dma(void *);
int gus_speaker_ctl(void *, int);
int gusmaxopen(void *, int);
int gusmax_round_blocksize(void *, int);
int gusmax_commit_settings(void *);
int gusmax_dma_output(void *, void *, int, void (*)(void *), void *);
int gusmax_dma_input(void *, void *, int, void (*)(void *), void *);
int gusmax_halt_out_dma(void *);
int gusmax_halt_in_dma(void *);
int gusmax_speaker_ctl(void *, int);
int gus_getdev(void *, struct audio_device *);
void gus_deinterleave(struct gus_softc *, void *, int);
int gus_mic_ctl(void *, int);
int gus_linein_ctl(void *, int);
int gus_test_iobase(bus_space_tag_t, int);
void guspoke(bus_space_tag_t, bus_space_handle_t, long, u_char);
void gusdmaout(struct gus_softc *, int, u_long, caddr_t, int);
int gus_init_cs4231(struct gus_softc *);
void gus_init_ics2101(struct gus_softc *);
void gus_set_chan_addrs(struct gus_softc *);
void gusreset(struct gus_softc *, int);
void gus_set_voices(struct gus_softc *, int);
void gus_set_volume(struct gus_softc *, int, int);
void gus_set_samprate(struct gus_softc *, int, int);
void gus_set_recrate(struct gus_softc *, u_long);
void gus_start_voice(struct gus_softc *, int, int);
void gus_stop_voice(struct gus_softc *, int, int);
void gus_set_endaddr(struct gus_softc *, int, u_long);
#ifdef GUSPLAYDEBUG
void gus_set_curaddr(struct gus_softc *, int, u_long);
u_long gus_get_curaddr(struct gus_softc *, int);
#endif
int gus_dmaout_intr(struct gus_softc *);
void gus_dmaout_dointr(struct gus_softc *);
void gus_dmaout_timeout(void *);
int gus_dmain_intr(struct gus_softc *);
int gus_voice_intr(struct gus_softc *);
void gus_start_playing(struct gus_softc *, int);
int gus_continue_playing(struct gus_softc *, int);
u_char guspeek(bus_space_tag_t, bus_space_handle_t, u_long);
u_long convert_to_16bit(u_long);
int gus_mixer_set_port(void *, mixer_ctrl_t *);
int gus_mixer_get_port(void *, mixer_ctrl_t *);
int gusmax_mixer_set_port(void *, mixer_ctrl_t *);
int gusmax_mixer_get_port(void *, mixer_ctrl_t *);
int gus_mixer_query_devinfo(void *, mixer_devinfo_t *);
int gusmax_mixer_query_devinfo(void *, mixer_devinfo_t *);
int gus_query_encoding(void *, struct audio_encoding *);
int gus_get_props(void *);
int gusmax_get_props(void *);
void gusics_master_mute(struct ics2101_softc *, int);
void gusics_dac_mute(struct ics2101_softc *, int);
void gusics_mic_mute(struct ics2101_softc *, int);
void gusics_linein_mute(struct ics2101_softc *, int);
void gusics_cd_mute(struct ics2101_softc *, int);
void stereo_dmaintr(void *);
extern const int gus_irq_map[];
extern const int gus_drq_map[];
extern const int gus_base_addrs[];
extern const int gus_addrs;
extern const int gus_max_frequency[];
extern const ushort gus_log_volumes[];
#define SELECT_GUS_REG(iot,ioh1,x) bus_space_write_1(iot,ioh1,GUS_REG_SELECT,x)
#define ADDR_HIGH(x) (unsigned int) ((x >> 7L) & 0x1fffL)
#define ADDR_LOW(x) (unsigned int) ((x & 0x7fL) << 9L)
#define GUS_MIN_VOICES 14 /* Minimum possible number of voices */
#define GUS_MAX_VOICES 32 /* Maximum possible number of voices */
#define GUS_VOICE_LEFT 0 /* Voice used for left (and mono) playback */
#define GUS_VOICE_RIGHT 1 /* Voice used for right playback */
#define GUS_MEM_OFFSET 32 /* Offset into GUS memory to begin of buffer */
#define GUS_BUFFER_MULTIPLE 1024 /* Audio buffers are multiples of this */
#define GUS_MEM_FOR_BUFFERS 131072 /* use this many bytes on-GUS */
#define GUS_LEFT_RIGHT_OFFSET (sc->sc_nbufs * sc->sc_chanblocksize + GUS_MEM_OFFSET)
#define GUS_PREC_BYTES (sc->sc_precision >> 3) /* precision to bytes */
/* splgus() must be splaudio() */
#define splgus splaudio
extern struct audio_hw_if gus_hw_if;
extern struct audio_hw_if gusmax_hw_if;
extern struct audio_device gus_device;
#define FLIP_REV 5 /* This rev has flipped mixer chans */
void gus_subattach(struct gus_softc *, struct isa_attach_args *);